Notice
Recent Posts
Recent Comments
Link
«   2025/06   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

초보자의 빅데이터 정복기

22-08-24 chap15_LogisticRegression 본문

아이티월 수업일지(R)

22-08-24 chap15_LogisticRegression

서부남93 2022. 8. 24. 17:10

chap15_LogisticRegression


# 1. 로짓 변환 : y예측값을 0 ~ 1로 조정하는 과정 

# 단계1 : 오즈비(Odds ratio) : [실패(0)에 대한] 성공(1) 비율(0:fail, 1:success)
# ex) Odds of ten to one -> 10대 1의 배당률(성공 비율 1/10) 

p = 0.5 # 성공확률(success)
odds_ratio = p / (1-p) # 1


p = 1 # 성공확률(success)
odds_ratio = p / (1-p) # Inf

p = 0 # 성공확률(success)
odds_ratio = p / (1-p) # 0

# [정리] 오즈비 범위 : 0 ~ Inf


# 단계2 : 로짓변환 : 오즈비에 log 적용 = log(odds_ratio)
p = 0.5 # 성공 50%
odds_ratio = p / (1-p) 
logit1 = log(odds_ratio) # 0

p = 1 # 성공 100% 
odds_ratio = p / (1-p)  
logit2 = log(odds_ratio) # Inf

p = 0 # 성공 0% 
odds_ratio = p / (1-p)  
logit3 = log(odds_ratio) # -Inf

# [정리] 로짓변환 범위 : -Inf ~ Inf

# 단계3 : 시그모이드(sigmoid) 함수 
# sigmoid_function = (1 / (1 + exp(-로짓값)))
1 / (1 + exp(-(logit1))) # logit=  0   -> 0.5
1 / (1 + exp(-(logit2))) # logit=  Inf -> 1
1 / (1 + exp(-(logit3))) # logit= -Inf -> 0

# [정리] sigmoid 범위 : 0 ~ 1




# 로지스틱 회귀분석(Logistic Regression) 모델 

# 단계1. 데이터 가져오기 
setwd('C:/itwill/3_Rwork/data')
weather = read.csv("weather.csv") 
dim(weather)  # 366  15
head(weather)
str(weather)

#변수로 사용하기 힘든종류
# 1. date 2.ID 3.name

# chr 칼럼, Date, RainToday 칼럼 제거 
weather_df <- weather[, -c(1, 6, 8, 14)]
str(weather_df)

#결측치 제거
weather_df <- na.omit(weather_df)


# y변수(RainTomorrow) -> 로지스틱 회귀분석 결과(0,1)에 맞게 더미변수 생성      
weather_df$RainTomorrow <- as.factor(weather_df$RainTomorrow)# 요인형 변환
head(weather_df)

## as.factor(): 범주형(명목형) -> 요인형 변환
#독립변수: 선형/로지스틱 회귀분석 범주형 변수 -> 더미변수
#종속변수: 로지스틱/분류분석 범주형 변수 -> 분류변수 

#  단계2.  데이터 셈플링
idx <- sample(nrow(weather_df), nrow(weather_df)*0.7)
train <- weather_df[idx, ]
test <- weather_df[-idx, ]
dim(train)# 252 11 70%
dim(test)# 109 11  30%

#  단계3.  로지스틱  회귀모델 생성 (glm) : 학습데이터 
weater_model <- glm(RainTomorrow ~ ., data = train, family = 'binomial')
#family = 'gaussian'(기본) :종속변수가 정규분포(연속형 변수)
#family = 'binomial' :종속변수가 이항변수
weater_model 

summary(weater_model) # 모델의 통계적 유의성 검정(x), 설명력(x)


# 단계4. 로지스틱  회귀모델 예측치 생성 : 검정데이터 
# newdata=test : 새로운 데이터 셋, type="response" : 0~1 확률값으로 예측 
pred <- predict(weater_model, newdata=test, type="response") # sigmoid 함수
range(pred) #[1] 0.0006162502 0.9918287344

# cutoff = 0.5
y_pred <- ifelse(pred > 0.5, 1, 0) # 확률 -> 0 or 1
y_pred #예측치
y_true <- test$RainTomorrow # 관측치(정답)


# 단계5. model 평가 : 혼동 행렬 (confusion matrix)
tab <- table(y_true, y_pred)#( 관측치, 예측치 )
tab

#        y_pred
# y_true  0(N)  1(P)
#    No  82(Tn)  5(Fn) -> 82/87
#    Yes 12(Fp) 10(Tp) -> 10/22

no_rate <- tab[1,1]/sum(tab[1,]) # 0.9425287
yes_rate <- tab[2,2]/sum(tab[2,])# 0.4545455
acc <-  (tab[1,1]+tab[2,2]) / sum(tab)
cat('분류정확도=',acc)# 0.8440367 분류정확도



# 1) 분류정확도(accuracy) = (Tn + Tp)/ (전체관측치)

acc <-  (tab[1,1]+tab[2,2]) / sum(tab) #0.8440367

# 2) 정확률(precision) = TP / (FP +TP) 예측치 기준
p<- tab[2,2]/sum(tab[,2])  
p #0.6666667

# 3) 재현률(recall)= Tp/ (TP+Fn) 관측치 기준
r <- tab[2,2]/sum(tab[2,])
r <- # 0.4545455

#민감도 (tpr): 양성(감연 -> 양성예측비율

#4) 특이도 (tnr) = tn/(tn+fp)
s<- tab[1,1] / sum(tab[1,])
s #0.9425287

#5) F측정치 = 2* ((정활률*재현률)/(정확률+재현률))
# F측정치: 종속변수 비율이 불균형인 경우

f1 <- 2*((p* r) / (p+ r))
f1 # 0.7809524

# 단계6. 모델 유의성(적합도) 검정 
install.packages("ResourceSelection")
library(ResourceSelection)

weater_model$y # y변수 값 
weater_model$fitted.values # 예측치

hoslem.test(weater_model$y, weater_model$fitted.values)

#X-squared = 3.3325, df = 8, p-value = 0.9118


### ROC Curve를 이용한 모형평가(분류정확도)  ####
# Receiver Operating Characteristic

install.packages("ROCR")
library(ROCR)

# ROCR 패키지 제공 함수 : prediction() -> performance
pr <- prediction(pred, test$RainTomorrow)
prf <- performance(pr, measure = "tpr", x.measure = "fpr")
#measure = "tpr" : y축 - 민감도(TPR)
#x.measure = "fpr" : x축 = FPR = 1- 특이도(TNR)
plot(prf)



######################################
# 3. Logistic Regression example
######################################

# 대출 수락 or 거절 prediction
Data = read.csv('UniversalBank.csv')
str(Data)
#$ ID(x)             : int  1 2 3 4 5 6 7 8 9 10 ...
#$ Age               : 고객 나이
#$ Experience        : 은행 거래 가입기간
#$ Income            : 수입
#$ ZIP.Code(x)       : int  91107 90089 94720 94112 91330 ...
#$ Family            : 구성원
#$ CCAvg             : 카드지출 평균액
#$ Education         : 교육수준
#$ Mortgage          : 모기지-주택담보대출 
#$ Personal.Loan(y)  : 수락 or 거절 
#$ Securities.Account: 비밀계좌
#$ CD.Account        : CD계좌 
#$ Online            : 인터넷뱅킹
#$ CreditCard        : 신용카드 사용여부


# 더미변수 생성 : factor형 변환 
Data$Education <- as.factor(Data$Education)# 독립변수
Data$Personal.Loan <- as.factor(Data$Personal.Loan)# 종속변수: 분류 변수 y
Data$Securities.Account <- as.factor(Data$Securities.Account)# 독립변수
Data$CD.Account <- as.factor(Data$CD.Account)# 독립변수
Data$Online <- as.factor(Data$Online)# 독립변수
Data$CreditCard <- as.factor(Data$CreditCard)# 독립변수

str(Data)

#전처리과정: 결측치, 변수 제거

Data <- na.omit(Data)
dim(Data)

#사용불가 변수제거

Data <- Data[-c(1,5)]


# train/test 데이터셋 생성  
idx <- sample(1:nrow(Data), 0.7*nrow(Data), replace = FALSE)
# 전체 Data를 7:3으로 구분
train_bank <- Data[idx, ]
test_bank <- Data[-idx, ]


#formula = y(종속) ~ x(독립변수)
formula <- Personal.Loan ~.
Reg_Model <- glm(formula, data = train_bank, family = 'binomial')

summary(Reg_Model)

# 기여도가 낮은 변수(“Age”, “Mortgage”, “Experience” ) 제거 후 model 생성 
Reg_Model <- glm(formula, data = train_bank[-c(1,2,7)], family = 'binomial')
Reg_Model
summary(Reg_Model)

names(Reg_Model)

# 적합치 분포도 : histogram  생성
h <- hist(Reg_Model$fitted.values, main = "Regression_ Model Fitted Values", breaks = 10, col = "grey")
# count된 결과값 표시
text(h$mids,h$counts, labels=h$counts, adj=c(0.5, -0.5))

# cut-off 값 적용하여 검정데이터 예측 
pred <- predict(Reg_Model, newdata=test_bank[-c(1:2,7)], type="response")  # 검정데이터 예측치 
range(pred) # 6.334892e-07 9.995696e-01


# cut-off = 0.5
pred_result_0.5 <- ifelse(pred >= 0.5, 1, 0)

# 혼동행렬 
Pred_Table_0.5 <- table(test_bank$Personal.Loan, pred_result_0.5)

#     0    1
# 0 1333   17 
# 1   52   98
sum(diag(Pred_Table_0.5))/sum(Pred_Table_0.5) #0.954
Pred_Table_0.5[2,2] /sum(Pred_Table_0.5[2,])  #0.6533333

# cut-off = 0.3
pred_result_0.3 <- ifelse(pred >= 0.3, 1, 0)

Pred_Table_0.3 <- table(test_bank$Personal.Loan, pred_result_0.3)
pred_result_0.3
#     0    1
# 0 1306   44
# 1   35  115

sum(diag(Pred_Table_0.3))/sum(Pred_Table_0.3) #0.9473333
Pred_Table_0.3[2,2] /sum(Pred_Table_0.3[2,])  #0.7666667

###################################
# 최적의 cutoff값 정하기
###################################
# cut off=0.5 타당성 테스트 
cutOff_test <- function(prop, realdata){ #start
  cutOff_re <- c() # cutoff 누적 
  acc_re <- c() # 분류정확도 누적     
  cutOff <- seq(0.3, 0.7, by = 0.1) # 테스트 cutoff(0.3~0.7 : 5개) 
  
  for( cut in cutOff ){ # 5회 반복 
    cutOff_re <- c(cutOff_re, cut ) 
    pred <- ifelse(prop >= cut, 1, 0) 
    conf <- table(pred, realdata)      
    acc <- sum(diag(conf))/sum(conf) # 분류정확도 
    acc_re <- c(acc_re, acc) # 분류정확도 누적 
  }
  df <- data.frame(cutOff_re, acc_re) # df 생성 
  print(df) #  전체 : cutOff와 accuracy
  print(df[df$acc_re == max(df$acc_re), ]) # 가장 높은 cutOff와 accuracy
} #end

#함수호출
cutOff_test(pred, test_bank$Personal.Loan)#(예측확률,실제관측치)


'아이티월 수업일지(R)' 카테고리의 다른 글

22-08-26 chap17_RandomForest  (0) 2022.08.29
22-08-25 chap16_DecisionTree  (0) 2022.08.29
22-08-18 chap11_Parametric_test  (0) 2022.08.19
22-08-17 chap10_CrossTableChiSquare  (0) 2022.08.18
22-08-11 chap07_2 InForma  (0) 2022.08.12
Comments