초보자의 빅데이터 정복기
22-08-24 chap15_LogisticRegression 본문
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 |