로지스틱 회귀(Logistic Regression)
- 로지스틱 함수를 사용하여 두 개의 반응변수 클래스에 대해 Pr(Y=k|X=x)를 직접 모델링(설명변수X에 대해 반응변수Y의 조건부분포를 모델링)
- 최대가능도(maximum likelihood) 방법을 사용하여 모델 적합
- 모델을 적합하여 얻은 계수 추정치 beta1이 0.0055라면, X의 한 유닛 증가로 인해 로그 공산은 0.0055 유닛만큼 증가
선형판별분석(Linear Discriminant Analysis)
- 데이터 분포를 학습해 결정경계(Decision Boundary)를 만들어 데이터를 분류하는 모델
- 로지스틱 회귀보다 대안적인 기법을 사용하여 반응변수Y의 각 클래스에서 설명변수X의 분포를 모델링하고, 그 다음에 베이즈 정리를 사용하여 Pr(Y=k|X=x)에 대한 추정치를 얻음
- PCA와 같이 축소 방법 중 하나로 사용되기도 하지만, PCA는 데이터의 변동성이 최대가 되는 축을 찾아 주성분으로 정한다면 LDA는 데이터의 Target값끼리 최대한 분리할 수 있는 축을 찾음
- 클래스들이 잘 분리될 때 로지스틱 회귀모델에 대한 모수 추정치는 아주 불안정하지만, 선형판별분석은 이런 문제가 없음
- 만약 n이 작고 각 클래스에서 설명변수X의 분포가 근사적으로 정규분포이면 선형판별모델은 로지스틱 회귀모델보다 더 안정적
- 선형판별분석은 반응변수의 클래스 수가 2보다 클 때 일반적으로 사용
분류방법의 비교
- 로지스틱 회귀와 LDA는 선형의 결정경계를 만든다. 유일한 차이점은 로지스틱 회귀는 beta0과 beta1은 최대가능도를 사용하여 추정되는 반면 c0와 c1은 정규분포로부터 추정된 평균과 분산을 사용하여 계산된다는 것이다.
- LDA는 관측치들이 각 클래스에 공통인 공분산행렬을 갖는 가우스분포를 따른다고 가정한다. 따라서 이 가정이 근사적으로 성립하면 LDA는 로지스틱 회귀보다 더 나은 결과를 제공할 수 있다.
- KNN과 비교를 하자면, KNN은 완전히 비모수적인 방법이다. 즉, 결정경계의 형태에 대한 어떠한 가정도 하지 않는다. 그러므로 결정경계가 상당히 비선형적인 경우 LDA와 로지스틱 회귀보다 우수하다고 예상할 수 있다. 반면, KNN은 어느 설명변수가 중요한지 알수 없어 추정 계수들을 얻지 못한다.
- QDA(이차판별분석)은 비모수적 방법인 KNN과 선형의 LDA 및 로지스틱 회귀 사이에서 절충한 것이다.
R Code
주식시장자료
library(ISLR)
head(Smarket)
## Year Lag1 Lag2 Lag3 Lag4 Lag5 Volume Today Direction
##1 2001 0.381 -0.192 -2.624 -1.055 5.010 1.1913 0.959 Up
##2 2001 0.959 0.381 -0.192 -2.624 -1.055 1.2965 1.032 Up
##3 2001 1.032 0.959 0.381 -0.192 -2.624 1.4112 -0.623 Down
##4 2001 -0.623 1.032 0.959 0.381 -0.192 1.2760 0.614 Up
##5 2001 0.614 -0.623 1.032 0.959 0.381 1.2057 0.213 Up
##6 2001 0.213 0.614 -0.623 1.032 0.959 1.3491 1.392 Up
2001년에서 2005년까지 1,250일에 걸친 S&P500 주가지수의 수익률
- Lag1-Lag5: 각 날짜에 그날 이전 5일의 거래일 Lag1-Lag5에 대한 수익률
- Volumn: 전날에 거래된 주식 수를 10억 주 단위로 표시
- Today: 당일의 수익률
- Direction: 당일 주가지수가 상승인지 또는 하락인지의 여부
로지스틱 회귀
1. Full Model
glm.fit=glm(Direction~Lag1+Lag2+Lag3+Lag4+Lag5+Volume, data=Smarket, family=binomial)
summary(glm.fit)
##Call:
##glm(formula = Direction ~ Lag1 + Lag2 + Lag3 + Lag4 + Lag5 +
## Volume, family = binomial, data = Smarket)
##
##Deviance Residuals:
## Min 1Q Median 3Q Max
##-1.446 -1.203 1.065 1.145 1.326
##
##Coefficients:
## Estimate Std. Error z value Pr(>|z|)
##(Intercept) -0.126000 0.240736 -0.523 0.601
##Lag1 -0.073074 0.050167 -1.457 0.145
##Lag2 -0.042301 0.050086 -0.845 0.398
##Lag3 0.011085 0.049939 0.222 0.824
##Lag4 0.009359 0.049974 0.187 0.851
##Lag5 0.010313 0.049511 0.208 0.835
##Volume 0.135441 0.158360 0.855 0.392
##
##(Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 1731.2 on 1249 degrees of freedom
##Residual deviance: 1727.6 on 1243 degrees of freedom
##AIC: 1741.6
##
##Number of Fisher Scoring iterations: 3
p-값이 가장 작은 것은 Lag1이다.
이것이 시사하는 바는 어제의 수익률이 양수이면 오늘 주가지수가 상승할 가능성이 낮다는 것이다.
coef(glm.fit) #1)
## (Intercept) Lag1 Lag2 Lag3 Lag4
##-0.126000257 -0.073073746 -0.042301344 0.011085108 0.009358938
## Lag5 Volume
## 0.010313068 0.135440659
summary(glm.fit)$coef #2)
## Estimate Std. Error z value Pr(>|z|)
##(Intercept) -0.126000257 0.24073574 -0.5233966 0.6006983
##Lag1 -0.073073746 0.05016739 -1.4565986 0.1452272
##Lag2 -0.042301344 0.05008605 -0.8445733 0.3983491
##Lag3 0.011085108 0.04993854 0.2219750 0.8243333
##Lag4 0.009358938 0.04997413 0.1872757 0.8514445
##Lag5 0.010313068 0.04951146 0.2082966 0.8349974
##Volume 0.135440659 0.15835970 0.8552723 0.3924004
glm.probs=predict(glm.fit, type="response")
glm.probs[1:10] #3)
## 1 2 3 4 5 6 7
##0.5070841 0.4814679 0.4811388 0.5152224 0.5107812 0.5069565 0.4926509
## 8 9 10
##0.5092292 0.5176135 0.4888378
contrasts(Direction) #4)
## Up
##Down 0
##Up 1
coef 함수를 사용하여 적합된 모델에 대한 계수들을 액세스 할 수 있다. 또한 summary 함수를 사용하여 계수들의 p-값과 같은 적합된 모델의 특정 정보를 액세스할 수 있다.
predict 함수는 주어진 설명변수 값에 대해 주가지수가 상승할 확률을 예측하는 데 사용될 수 있다. type="response" 옵션을 사용하면 로짓과 같은 다른 정보가 아니라 P(Y=1|X)형태의 확률을 출력한다.
constrasts함수로 R이 생성한 가변수가 Up일 때 1이라는 것을 확인할 수 있다.
glm.pred=rep("Down", 1250)
glm.pred[glm.probs>.5]="UP"
table(glm.pred, Smarket$Direction)
##glm.pred Down Up
## Down 600 647
## UP 2 1
mean(glm.pred==Smarket$Direction)
##[1] 0.48
주가지수의 상승 예측확률이 0.5보다 큰지 작은지에 따라 클래스 예측 벡터를 생성하고 혼동행렬을 출력한다.
이 예에서 로지스틱 회귀는 주가지수의 움직임 방향을 52.2% 올바르게 예측하였다.
임의 추측보다 조금 더 나은 것처럼 보이지만, 훈련오차율은 보통 검정오차율을 과소평가하는 경향이 있다.
train=(Smarket$Year<2005)
Smarket.2005=Smarket[!train,]
Direction.2005=Smarket$Direction[!train]
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)
## Direction.2005
##glm.pred Down Up
## Down 77 97
## Up 34 44
mean(glm.pred==Direction.2005)
##[1] 0.4801587
2005년의 데이터를 test set으로 놓고, 모델을 구축하여 정확도를 산출했다.
48%로 임의 추측보다 더 못한 결과라는 것을 알 수 있다.
2. Sub Model
glm.fit=glm(Direction~Lag1+Lag2, 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)
## Direction.2005
##glm.pred Down Up
## Down 35 35
## Up 76 106
mean(glm.pred==Direction.2005)
##[1] 0.5595238
예측에 가장 도움이 되는 것 같은 Lag1와 Lag2만을 사용하여 로지스틱 회귀를 적합한 결과다.
결과가 약간 나아져 일별 주가지수 움직임의 56%를 올바르게 예측하였다.
주가지수 상승을 예측한 날에는 주식을 사고 주가지수 하락이 예측된 날에는 거래를 피하는 전략이 유효해보인다.
3. Prediction
predict(glm.fit, newdata=data.frame(Lag1=c(1.2, 1.5), Lag2=c(1.1, -0.8)),
type="response")
## 1 2
##0.4791462 0.4960939
Lag1와 Lag2의 특정값에 연관된 수익률을 다음과 같이 예측할 수 있다.
선형판별분석
library(MASS)
lda.fit=lda(Direction~Lag1+Lag2, data=Smarket, subset=train)
lda.fit
##Call:
##lda(Direction ~ Lag1 + Lag2, data = Smarket, subset = train)
##
##Prior probabilities of groups:
## Down Up
##0.491984 0.508016
##
##Group means:
## Lag1 Lag2
##Down 0.04279022 0.03389409
##Up -0.03954635 -0.03132544
##
##Coefficients of linear discriminants:
## LD1
##Lag1 -0.6420190
##Lag2 -0.5135293
plot(lda.fit)
LDA모델을 적합하는 데에는 MASS라이브러리의 lda함수를 사용한다.
- Prior probabilities of groups의 결과를 통해 그룹 평균들은 주가지수가 상승한 날 이전 이틀의 수익률은 음수이고 주가지수가 하락한 날 이전 이틀의 수익률은 양수인 경향이 있다는 것을 시사한다.
- 선형판별계수들은 LDA결정규칙을 형성하는 데 사용되는 Lag1과 Lag2의 선형결합을 제공한다. 만약, -0.642XLag1-0.514XLag2가 크면 LDA 분류기는 주가지수 상승을 예측할 것이고, 그렇지 않다면 LDA분류기는 주가지수 하락을 예측할 것이다.
- plot을 통해 훈련 관측치에 대해 -0.642XLag1-0.514XLag2를 계산하여 얻은 선형판별 그래프를 제공한다.
lda.pred=predict(lda.fit, Smarket.2005)
names(lda.pred)
##[1] "class" "posterior" "x"
lda.class=lda.pred$class
table(lda.class, Direction.2005)
## Direction.2005
##lda.class Down Up
## Down 35 35
## Up 76 106
mean(lda.class==Direction.2005)
##[1] 0.5595238
predict함수는 3개의 원소를 가진 리스트를 반환한다.
- class: 주가지수의 움직임에 대한 LDA의 예측을 포함한다.
- posterior: 사후확률을 포함하는 행렬로, k번째 열은 대응하는 관측치가 k번째 클래스에 속하는 사후확률이다.
- x: 선형판별을 포함한다.
이차판별분석
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)
## Direction.2005
##qda.class Down Up
## Down 30 20
## Up 81 121
mean(qda.class==Direction.2005)
##[1] 0.5992063
QDA 설명변수들은 거의 60%의 정확도를 보인다.
K-최근접이웃
library(class)
train.X=cbind(Lag1, Lag2)[train,]
test.X=cbind(Lag1, Lag2)[!train,]
train.Direction=Direction[train]
class라이브러리의 knn함수를 사용하여 KNN을 수행한다.
knn은 단일 명령어를 사용해 예측하며, 다음과 같은 4개의 입력이 필요하다.
- train.X: 훈련 데이터와 연관된 설명변수들을 포함하는 행렬
- test.X: 예측하고자 하는 데이터와 연관된 설명변수들을 포함하는 행렬
- train.Direction: 훈련 관측치들에 대한 클래스 라벨을 포함하는 벡터
- K: 분류기가 사용할 최근접 이웃의 수
set.seed(1)
knn.pred=knn(train.X, test.X, train.Direction, k=1)
table(knn.pred, Direction.2005)
## Direction.2005
##knn.pred Down Up
## Down 43 58
## Up 68 83
mean(knn.pred==Direction.2005)
##[1] 0.5
knn.pred=knn(train.X, test.X, train.Direction, k=3)
table(knn.pred, Direction.2005)
## Direction.2005
##knn.pred Down Up
## Down 48 54
## Up 63 87
mean(knn.pred==Direction.2005)
##[1] 0.5357143
K가 1일 때보다 3일 때 더 결과가 좋아졌지만, 이 자료의 경우 QDA가 가장 좋은 결과를 제공한다고 볼 수 있다.
Caravan 보험자료
attach(Caravan)
summary(Purchase)
## No Yes
##5474 348
348/5822
##[1] 0.05977327
standardized.X=scale(Caravan[,-86])
이 자료는 5,822명에 대한 인구통계적 특징을 측정하는 85개의 설명변수를 포함한다.
반응변수 Purchase는 개인이 이동식 주택 보험을 구매하는지의 여부를 나타낸다.
KNN분류기는 주어진 검정 관측치에 가장 가까운 관측치들을 식별하여 검정 관측치의 클래스를 예측하므로 변수들의 크기, 즉 스케일(scale)이 문제가 된다. 따라서 scale함수로 스케일을 조정해준다.
test=1:1000
train.X=standardized.X[-test,]
test.X=standardized.X[test,]
train.Y=Purchase[-test]
test.Y=Purchase[test]
set.seed(1)
knn.pred=knn(train.X, test.X, train.Y, k=1)
mean(test.Y!=knn.pred)
##[1] 0.118
mean(test.Y!='No')
##[1] 0.059
table(knn.pred, test.Y)
## test.Y
##knn.pred No Yes
## No 873 50
## Yes 68 9
9/(68+9)
##[1] 0.117
1,000개의 검정 관측치에 대한 KNN 오류율은 12%가 조금 안된다. 고객 중 6%만 보험을 구매하였으므로 좋지 않은 결과라고 할 수 있다.
하지만, KNN은 보험을 구입한다고 예측된 고객들 중에서는 임의 추측보다 훨씬 낫다. 77명의 고객 중 9명, 즉 11.7%가 실제로 보험을 구입했다.
knn.pred=knn(train.X, test.X, train.Y, k=3)
table(knn.pred, test.Y)
## test.Y
##knn.pred No Yes
## No 920 54
## Yes 21 5
4/26
##[1] 0.1538462
knn.pred=knn(train.X, test.X, train.Y, k=5)
table(knn.pred, test.Y)
## test.Y
##knn.pred No Yes
## No 930 55
## Yes 11 4
4/15
##[1] 0.2666667
K=5일 때는 26.7%까지 올라간다.
'머신러닝, 딥러닝' 카테고리의 다른 글
[머신러닝] 6. 선형성을 넘어서(비선형모델)- 다항식회귀, 계단함수, 스플라인, GAMs (feat. R Code) (0) | 2021.04.26 |
---|---|
[머신러닝] 5. 선형모델 선택 및 Regularization- Ridge, Lasso regression, PCR, PLS (feat. R Code) (0) | 2021.04.25 |
[머신러닝] 2. 선형회귀분석- 고려해야 할 요소, 잠재적 문제(feat. R Code) (0) | 2021.04.04 |
[머신러닝] 1. 통계학습 (0) | 2021.04.02 |
[머신러닝] 0. 책 소개 및 리뷰 시작 (0) | 2021.03.21 |