본문 바로가기
카테고리 없음

R 발표 소스 - 챕터 4

by 정보장교 2018. 6. 12.
반응형

---

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/



반응형