R 발표 소스 - 챕터 4
---
title: "R로 마스터하는 머신 러닝"
output: 챕터 4
---
install.packages('ElemStatLearn')
install.packages('car')
install.packages('corrplot')
install.packages('leaps')
install.packages('glmnet')
install.packages('caret')
library(ElemStatLearn) # 패키지에 원하는 데이터 존재
library(car) #분산 팽창 인수 계산하는데 사용
library(corrplot) #상관 관계를 도표로 보여준다 correlation plots
library(leaps) #최량 부분 집합 도표 best subsets regression
library(glmnet) #능형 회귀 분석 , LASSO , 일래스틱넷
library(caret) # 매개 변수 조절
data(prostate) # prostate 전립선 R의 내장되어 있는 데이터 세트의 리스트 출력
help(prostate) # 자료 설명 - 전립선 암 데이터
str(prostate)
##해석10개 변수와 97개의 관측치
plot(prostate)
#전체 데이터 산전도 행렬
##해석 lcavol 와 lpsa 사이의 관계는 선형 관계처럼 보임
plot(prostate$gleason)
#그리슨 데이터 보기 (종양 조직의 분화도)
##해석-8.0 ,9.0 분포
table(prostate$gleason)
#그리스 데이터 테이블 형식
##해석 8=1개 ,9=1개
#방법
#1.해당 피처를 완전히 뺀다
#2.점수 8,9만 뺀다
#3.이 피처를 지시 변수를 만든다
boxplot(prostate$lpsa~prostate$gleason,xlab="Gleason Score", ylab="Log of PSA")
# 해당 그래프로 판단한다 -최소값,최대값 사이의 값들을 알수 있다.
# 1,2 방식이 아닌 책에서는 코드로 전환 하는것으로 가이드
# 점수가 6일 때는 0, 7이상일 경우에는 1
prostate$gleason = ifelse(prostate$gleason == 6, 0, 1)
#Ifelse를 이요한 코드값으로 전환 format = ifelse(logicalmode, yes, no)
table(prostate$gleason)
# 정상 변환 확인
p.cor = cor(prostate)
corrplot.mixed(p.cor)
#cor()를 통해 두 변수간의 선형관계의 정도를 알수 있음
#상관 도표를 토해 피처 사이에 상관관계, 독립적인지 판단
##해석
##lpsa(psa의 log) 값과 lcavol(암 부피의 log)연관이 크다 값 0.73
##다중 공선성 문제 lcavol는 lcp, lcp(암세포 침투 log) 는 svi(정낭 침범)값 0.68,0.67
train = subset(prostate, train==TRUE)[,1:9]
str(train)
test = subset(prostate, train==FALSE)[,1:9]
str(test)
# train 데이터 와 test 데이터 생성
#####모형화와 평가 #####
#1.최량 부분 집합 (regsubser) 사용
subfit = regsubsets(lpsa~., data=train)
#최량 부분 집합 regsubser() 함수 사용
b.sum = summary(subfit)
which.min(b.sum$bic)
# summary 모형을 다른 객체로 전환
#베이지안 정보 기준(BIC, Bayesian Information Criteria)은 AIC와 마찬가지로 여러 모델이 주어졌을 때 최적의 모델을 선택하는 기준이다
##해석
#which.min()로 사용해 가장 좋은 것을 선택, sum을 이용
#3 이 나옴
plot(b.sum$bic, type="l", xlab="# of Features", ylab="BIC", main="BIC score by Feature Inclusion")
##해석 BIC를 이용해서 3개가 가장 적절한 피처라는것을 알아냄
plot(subfit, scale="bic", main="Best Subset Features")
##해석 BIC의 값이 가장 낮은 3개는 -52 의 값 lcavol, lweight,gleason
ols = lm(lpsa~lcavol+lweight+gleason, data=train)
plot(ols$fitted.values, train$lpsa, xlab="Predicted", ylab="Actual", main="Predicted vs Actual")
#학습과 데이터와 실제 값의 도표화(3가지만 가지고 비교)
##해석 대체적으로 선형으로 분표
pred.subfit = predict(ols, newdata=test)
#새로운 데이터 test 값을 넣어서 모형의 예측값 예측
plot(pred.subfit, test$lpsa , xlab="Predicted", ylab="Actual", main="Predicted vs Actual")
#예상값과 실제값 비교하는 도표화
##해석 대부분 선형이지만 , 2개 정도가 동떨어짐
resid.subfit = test$lpsa - pred.subfit
#예상 값과 실제값의 차이 =잔차
mean(resid.subfit^2)
#해당 값의 평균 제곱차이 = Mean Sqauared Error = MSE = 잔차제곱평균
#잔차제곱평균 - 회귀로도 설명할 수 없는 잔차
##결과 0.508
##정리##
#F통계량= MSR / MSE
#MSE는 회귀로도 좁힐 수 없는 예측 오차 대비, 회귀로 인해 좁혀진 예측 오차가 얼마나 큰가를 표현한 수치가 F-통계량이다. 이 통계량이 크면 클 수록 (우리가 증명하고 싶은) 이 회귀모델이 유용하다는 것을 증명하기에 좋다. 즉 분자인 MSE가 작을 수록 F통계량은 늘어난다.
### 능형 회귀 분석 (Ridge regression)
### glmnet를 활용
### input Format glment(x= 입력 데이터 행렬, y= 반응값 ,family= 분표방법 , alpha= 0)
x = as.matrix(train[,1:8])
y = train[ ,9]
#입력 데이터 행렬 x, 반응 값 y
ridge = glmnet(x, y, family="gaussian", alpha=0)
#설정 분포= guassian ,alpha =0
print(ridge)
#출력 계수의 숫자(df),편차의 백분율(%Dev), 람다(Labda)
#능형 회귀 분석의 특징은 계수의 숫자는 계속 8
##해석 마지막 100회 편차의 백분율 0.6971, 람다 0.08789
plot(ridge, label=TRUE)
# x축 L1 Norm ,y축 계수의 값
plot(ridge, xvar="lambda", label=TRUE)
# x축 lambda , y축 계수의 값
#해석 람다의 값이 줄어들면 축소 벌점이 줄고 , 계수의 절대값은 올라감
#ridge.coef = coef(ridge, s=0.1, exact = TRUE)
ridge.coef = coef(ridge, s=0.1)
#coef= 절편과 기울기를 보여주는 함수
ridge.coef
#해석 age, lcp ,pgg45에 관한 계수가 0에 가까워진다. (0은 아님)
plot(ridge, xvar="dev", label=TRUE)
#xvar설정 NORM(기본),lambda(로그-람다 값), dev(deviance-훈련 데이터에서의 편차의 백분률 )
##해석 람다가 감소할수록 계수의 값은 증가 , 편차의 백분율 증가 ,계수의 값이 증가
newx = as.matrix(test[,1:8])
ridge.y = predict(ridge, newx=newx, type="response", s=0.1)
# 테스트 데이터를 통한 ,predict를 이용한 예상값과 실제 값 도표
# type= link(log-odds값) , response(확율 $p$)
plot(ridge.y, test$lpsa, xlab="Predicted", ylab="Actual", main="Ridge Regression")
##해석 최량 부분 집합 방법을 이용해서 얻은 값과 비슷
ridge.resid = ridge.y - test$lpsa
mean(ridge.resid^2)
# MSE 값 비교 0.478 , 최량 부분 집합 = 0.50
###RASSO###
lasso = glmnet(x, y, family="gaussian", alpha=1)
#LASSO 모형 만들기 능형 회귀 분석 에서 alpht= 0 -> 1로 바꾸면 lasso
print(lasso)
##해석 모형을 자동으로 만들다 람다 값이 줄어드는 데 편차가 줄지 않아 69번째 에서 멈춤
#DF(피처) 값도 람다와 함께 변함
plot(lasso, xvar="lambda", label=TRUE)
##해석 8,3,5 라인
#lasso.coef = coef(lasso, s=0.045, exact=TRUE)
lasso.coef = coef(lasso, s=0.045)
lasso.coef
##해석 s=0.045 즉 람다가 0.045일 때 lcp 계수 0 으로 만듬
lasso.y = predict(lasso, newx=newx, type="response", s=0.045)
plot(lasso.y, test$lpsa, xlab="Predicted", ylab="Actual", main="LASSO")
lasso.resid = lasso.y - test$lpsa
mean(lasso.resid^2)
# Lasso MSE 값 0.443
# Ridge MSE 값 0.478 , 최량 부분 집합 값 0.50
###일래스틱 넷 ###
##람다와 일래스틱넷의 혼합 설정 인자인 알파의 가장 최적값을 찾는 방법
# 1. expand.grid() 함수 사용 모든 알파와 람다의 조합 벡터 만든다.
# 2. caret패키지에 있는 trainControl() 함수를 사용해 재샘플링 방법 사용 결정- LOOCV 사용
# 3. caret 패키지 train()함수인 glmnet()을 이용한 모형 학습시켜 알파와 람다를 선택
# alpla와 lambda 증가 시키지 expand.grid()
grid = expand.grid(.alpha=seq(0,1, by=.2), .lambda=seq(0.00,0.2, by=0.02))
#알파 값 0.2씩 증가, 0~1 사이, 람다 0.02씩 증가 0.0~0.2사이 설저으로 벡터 생성
table(grid)
##해석 66개의 조합 6*11
head(grid)
control = trainControl(method="LOOCV")
#leave- One - Out Cross Validataion
#k-fold의 k 숫자가 examples 수가 동일할 경우가된다. 가장 극단적이며 모델을 훈련시키는데 많은 데이터를 사용 할 수 있지만, 계산량이 많고 고비용이다.
#첨부파일 - 재샘플링.jpg 참고
#재샘플링 방법으로 LOOCV 선택, 그 외 bootstraping, k-겹 교차 검증 존재
#selectionFunction="best"
enet.train = train(lpsa~., data=train, method="glmnet", trControl=control, tuneGrid=grid)
#tran()함수를 통해 일래스틱넷의 최적 설정 인자를 찾는다
enet.train
# 가장 낮은 RMSE(Root Mean Square Error)값 알파 =0, 람다는 0.08
## 해석 glmnet s=0.08 지정한 능형 회귀 값과 비슷하다 , 참고 s=0.10 지정 R-squared 61%가 나옴
# 실험이나 관측에서 나타나는 오차의 제곱해서 평균한 값의 제곱근 뜻
enet = glmnet(x, y,family="gaussian", alpha=0, lambda=.08)
enet.coef = coef(enet, s=.08, exact=TRUE)
enet.coef
enet.y = predict(enet, newx=newx, type="response", s=.08)
plot(enet.y, test$lpsa, xlab="Predicted", ylab="Actual", main="Elastic Net")
#test 데이터를 이용해서 람다 값 0.08를 대입해서 검증
enet.resid = enet.y - test$lpsa
mean(enet.resid^2)
# MSE 계산 0.4795019
# MSE - 평균 제곱 오차
# RMSE - 제곱근평균제곱오차
#MSE 비교
# ElaticNET 값 0.479
# Lasso MSE 값 0.443
# Ridge MSE 값 0.478
# 최량 부분 집합 값 0.50
##추가 glnet을 이용한 교차 검증
#원리 = k-겹 교차 검증 -데이터를 같은 수의 집합(겹)으로 나누고 ,k-1개의 부분 집학을 이용햇 서로 다른 모형을 만드는 방법 , 따로 준비해둔 나머지 집합으로 테스트한 수 그 결과를 평균 내 최종적으로 설정 인자 설정
set.seed(317)
lasso.cv = cv.glmnet(x, y,nfolds =3)
#데이터 수가 적어서 3겹으로 처리
plot(lasso.cv)
# log(lambda)가 0으로 갈수로 MSE(Mean-Squared Error)가 증가 하는것을 볼수 있음
lasso.cv$lambda.min
#람다의 최소값. 좀 더 정확한 람다 값을 알기 위해
lasso.cv$lambda.1se
#람다의 최소에서 표준 오차만큼 떨어진곳 알기 위해
coef(lasso.cv, s ="lambda.1se")
##해석 age, lcp,pgg45를 뺸 5개의 피처를 사용한 모델
lasso.y.cv = predict(lasso.cv, newx=newx, type="response", s="lambda.1se")
lasso.cv.resid = lasso.y.cv - test$lpsa
mean(lasso.cv.resid^2)
#최종 MSE 구하기
#MSE 비교
# 최량 부분 집합 값 0.50
# 능형 회귀 Ridge MSE 값 0.478
# 랏쏘 Lasso MSE 값 0.443
# ElaticNET 값 0.479
# 교차 검증을 통한 랏쏘 LASSO 값 0.45
#현재 검증으로는 교찻검증을 이용한 LASSO 적합
#전문 지식 + 더 많은 데이터
#변수들 (난수 생성기 변경, Train ,Test 데이터 세트의 변경 )
# R의 함수 포맷알아보기 : https://www.rdocumentation.org/