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
# "합격" "불합격" "불합격"