BACK END/R

[R] R 정리 13 - 로지스틱 회귀

circle kim 2021. 2. 1. 11:29

13. Logistic Regrission

: 독립변수 : 연속형, 종속변수 : 범주형
: 정규분포가 아니라 이항분포를 따른다. 결과가 0과 1 출력 (sigmoid 함수 사용).

# 미국의 어느 대학원 입학여부 관련 데이터
getwd()
mydata <- read.csv("testdata/binary.csv")
head(mydata)
#     admit gre  gpa rank
# 1     0 380 3.61    3
# 2     1 660 3.67    3
# 3     1 800 4.00    1
# 4     1 640 3.19    4
# 5     0 520 2.93    4
# 6     1 760 3.00    2
str(mydata)
# 'data.frame':	400 obs. of  4 variables:
# $ admit: int  0 1 1 1 0 1 1 0 1 0 ...
# $ gre  : int  380 660 800 640 520 760 560 400 540 700 ...
# $ gpa  : num  3.61 3.67 4 3.19 2.93 3 2.98 3.08 3.39 3.92 ...
# $ rank : int  3 3 1 4 4 2 1 2 3 2 ...
dim(mydata) # 400   4
summary(mydata)
xtabs(formula = ~admit + rank, data = mydata) # xtabs() : 포뮬러를 이용한 분할표
table(mydata$admit, mydata$rank)
# rank
# admit  1  2  3  4
# 0 28 97 93 55
# 1 33 54 28 12

 

 - 데이터 분리 : train/test(7:3)

set.seed(1)
idx <- sample(1:nrow(mydata), nrow(mydata) * 0.7)
idx
length(idx) # 280
train <- mydata[idx,]
train
test <- mydata[-idx,]
dim(train); dim(test)

 

 - 로지스틱 회귀 모델작성

help(glm)
# lgmodel <- glm(formula = admit ~ ., data = train, family = "binomial")
lgmodel <- glm(formula = admit ~ ., data = train, family = binomial(link = "logit"))
# binomial(link = "logit")  : 이항분포, glgaussian(link = "identity") : 정규분포
lgmodel
# Coefficients:
#   (Intercept)          gre          gpa         rank  
# -3.552482           0.003548     0.604202    -0.651471  
# 
# Degrees of Freedom: 279 Total (i.e. Null);  276 Residual
# Null Deviance:	    338.6 
# Residual Deviance: 303.5 	AIC: 311.5
anova(lgmodel)
# Df Deviance Resid. Df Resid. Dev
# NULL                   279     338.63
# gre   1  15.0843       278     323.54
# gpa   1   2.3481       277     321.19
# rank  1  17.6445       276     303.55
summary(lgmodel)

 

 - 분류 예측 (test로 모형평가)

pred <- predict(lgmodel, newdata = test, type="response") # type="response" : 0 ~ 1
head(pred, 10)
head(ifelse(pred > 0.5, 1, 0), 10) #  예측값 : 1  0  1  1  1  0  1  0  0  1
head(test$admit, 10)               #  실제값 : 0  0  0  0  0  0  1  0  0  1

 

 - 분류 정확도 계산

result_pred <- ifelse(pred > 0.5, 1, 0)
t <- table(result_pred, test$admit)
t
# result_pred  0  1
# 0 71 36
# 1  4  9
(71+9) / nrow(test)          # 0.6666667
t[1,1] + t[2,2] / nrow(test) # 71.075
sum(diag(t)) / nrow(test)    # 0.6666667

 

 - 새로운 값으로 분류하기

m <- train[c(1:3),]
m
m <- edit(m)
new_pred <- predict(lgmodel, newdata = m, type="response") # type="response" : 0~1
new_pred
# 324        167        129 
# 0.63870435 0.44552481 0.02585893
ifelse(new_pred > 0.5, 1, 0)
ifelse(new_pred > 0.5, '합격', '불합격')
# 324      167      129 
# "합격" "불합격" "불합격"