본문 바로가기

데이터 분석 (Data Analysis)/R

분류 모델(Logistic, LDA, QDA, KNN) 및 혼동행렬(Confusion Matrix)로 모델 평가

이번 공부 내용은 시간이 부족해서 책보고 따라하는 것으로 공부를 마쳤습니다.

코드는 보고 따라할 수 있지만, 각 모델들에 대해 수학적인 이론과 어떻게 분류가 돌아가는지 파악하는데 많은 어려움이 있었음. 기존 라이브러리에 있는 쉬운 데이터로 사용해서 결과가 잘 나왔지만 실제 데이터를 분석하면서 책에서 나온대로 적용하는 것이 매우 어려웠음. 학부시절 기계학습 수업 들었을때 공부했던 내용을 다시 복습했습니다.

데이터 설명

2001년 초부터 2005년 말까지 1,250일 동안 S&P 500 주가지수에 대한 수익률로 구성

각 날짜에 대해

이전 거래일(5일)에 대한 수익률(Lag1 ~ Lag5)

또한 Volume(전일 거래된 주식 수, 수십억 달러),

Today(해당 날짜의 수익률),

Direction(이 날짜에 시장이 상승 또는 하강했는지 여부) 를 의미함.

library(ISLR) # 주식시장 데이터 가져오기 위해서
library(MASS) # LDA
library(dplyr)

# 데이터 파악

df <- Smarket

str(df)

df %>% head(10)

summary(df)

# 산점도 행렬을 통한 상관관계 파악
pairs(df)

# 반응변수 파악
table(df$Direction)

# 모형화
## 로지스틱 회귀
glm.fit=glm(Direction~Lag1+Lag2+Lag3+Lag4+Lag5+Volume,data=df,family=binomial)
summary(glm.fit)

summary(glm.fit)$coef

# 해당 모형에 대한 예측값 산출
glm.probs = predict(glm.fit, type = "response")
glm.probs %>% head(5) # 예측값 상위 5개값

# 더미변수 처리
contrasts(df$Direction)

glm.pred = rep("Down", 1250)
glm.pred[glm.probs > 0.5] = "Up" # 임계치 0.5로 조정
# confusion matrix
table(glm.pred, df$Direction)

mean(glm.pred == df$Direction) # 145+507/1250 하락을 하락으로, 상승을 상승으로 예측 했는지

# 훈련셋과 테스트셋으로 나눠서 접근

attach(df) 

train=(Year<2005) # 2001 ~ 2004 년은 훈련셋
Smarket.2005=Smarket[!train,]

Direction.2005=Direction[!train] # 2005년 테스트셋

glm.fit=glm(Direction~Lag1+Lag2+Lag3+Lag4+Lag5+Volume,data=Smarket,family=binomial,subset=train)
glm.probs=predict(glm.fit,Smarket.2005,type="response")

glm.pred=rep("Down",252)
glm.pred[glm.probs>.5]="Up"

table(glm.pred,Direction.2005)

mean(glm.pred==Direction.2005) # Test Error, (77+44) / 252

## 선형판별분석, LDA

lda.fit=lda(Direction~Lag1+Lag2,data=Smarket,subset=train)
lda.fit # summary() 안쓰고 직접 입력

plot(lda.fit)

lda.pred=predict(lda.fit, Smarket.2005)

lda.class=lda.pred$class
table(lda.class,Direction.2005)

mean(lda.class==Direction.2005) # (35+106)/252

# QDA

qda.fit=qda(Direction~Lag1+Lag2,data=Smarket,subset=train)
qda.fit

qda.class=predict(qda.fit,Smarket.2005)$class
table(qda.class,Direction.2005)

mean(qda.class==Direction.2005) # (30+121)/252

# kNN

library(class)

train.X=cbind(Lag1,Lag2)[train,]
test.X=cbind(Lag1,Lag2)[!train,]
train.Direction=Direction[train]


set.seed(123)

knn.pred=knn(train.X,test.X,train.Direction,k=1)
table(knn.pred,Direction.2005)

mean(knn.pred==Direction.2005) # (43+83)/252

# 로지스틱, LDA, QDA, KNN 의 분류 평가

mean(glm.pred==Direction.2005) # 0.4802
mean(lda.class==Direction.2005) # 0.5595
mean(qda.class==Direction.2005) # 0.5992
mean(knn.pred==Direction.2005) # 0.5

교차검증을 하지않고 훈련셋으로 학습 후 테스트셋으로 test error 값을 비교해 분류기 성능을 비교하였음.

 

결론)

모든 상황에서 우월한 분류기는 없고,

비교적 간단한 상황에서는 LDA나 로지스틱 모형이 우수함.

복잡한 상황에서는 KNN이나 QDA가 우수

KNN에서도 적절한 수의 K를 설정하는 것이 필요함.

 

확실히 모델링 과정을 여러번 돌려서 최적화된 값을 찾는 좋은 방법이지만, 모델 원리를 알고 통계적으로 접근해서 푸는 것도 꽤 중요하다고 느꼈습니다. 책에 나온 코드 그대로지만 이렇게도 접근할 수 있다는 점이 인상깊었습니다.

 

 

제가 참고하면서 공부했던 자료입니다.

https://www.statlearning.com/ 

 

An Introduction to Statistical Learning

Winner of the 2014 Eric Ziegel award from Technometrics. As the scale and scope of data collection continue to increase across virtually all fields, statistical learning has become a critical toolkit for anyone who wishes to understand data. An Introductio

www.statlearning.com

저자 : Gareth James, Daniela Witten, Trevor Hastie Robert Tibshirani