ADP (R)

[Adp 실기 기출 풀이] 21회 릿지 회귀

멋쟁이천재사자 2022. 8. 10. 19:29

지난 5월 21일 25회 ADP 필기를 합격하고, 9월 25일 26회 실기를 준비하고 있습니다.

후기에서 기출 문제 유형을 확인하여 나름의 방식으로 문제를 만들어 연습해 봅니다.

 

1. 문제 만들기

다음 후기 글을 참고하여 연습 문제를 만들었습니다.

2-2. 데이터 8:2로 분할하고 릿지 회귀 적용하시오.
alpha 값을 0부터 1까지 0.1단위로 모두 탐색해서 결정계수가 가장 높을때의 알파를 찾고, 해당 알파로 다시 모델을 학습해서 결정계수와 rmse를 계산
 
ADP 21회 (출처: https://cafe.naver.com/sqlpd/21090)

carData 패키지의 Prestige 데이터를 이용해서 문제를 만들었습니다.

 

2. 문제

carData::Prestige 데이터의 income 을 예측하려고 한다.

데이터를 8:2로 분할하고 릿지 회귀 적용하시오.
alpha 값을 0부터 1까지 0.1단위로 모두 탐색해서 결정계수가 가장 높을때의 알파를 찾고,

lambda 값을 100 부터1000 까지 10 단위로 모두 탐색해서 RMSE 가 가장 작을때의 lambda 를 찾고,

해당 값으로 다시 모델을 학습해서 결정계수와 rmse를 계산하라.

 

3. 답안

library(carData)
library(caret) 
library(recipes)
library(dplyr)

# EDA
str(Prestige)
sum(is.na(Prestige)) 
summary(Prestige)

# 8:2로 분할합니다.
set.seed(123) 
train <- createDataPartition(y=Prestige$income, p=0.8, list=F) 
Prestige.train <- Prestige[train,] 
Prestige.test <- Prestige[-train,] 

# 전처리
recipe = recipe(income ~ ., data = Prestige.train) %>%
  step_impute_knn(all_predictors()) %>%  # 결측치
  step_rm(census) %>% 
  #step_scale(all_numeric_predictors()) %>% 
  #step_normalize(all_numeric_predictors()) %>% 
  step_range(all_numeric_predictors()) %>% 
  step_dummy(type) %>% # 가변수
  prep()

finaltrain <- juice(recipe)  
finaltest <- bake(recipe, Prestige.test) 

# ridge regression
#lambda <- seq(0,1,by=0.1)
lambda <- seq(100,1000,by=10)

ridge <- train(form=income ~ ., data=finaltrain, 
               method="glmnet", 
               trControl=trainControl(method="cv",number=10), 
               tuneGrid=expand.grid(alpha=0,lambda=lambda)) 

# predict
pred <- predict(ridge,finaltest)     
postResample(pred=pred, obs=finaltest$income) 

 

4. 관련 댓글 참고

문제 만들기에서 언급한 참고 링크 댓글에 다음과 같은 유익한 내용이 있는데요, alpha 라는 표현이 파이선 관점의 표현이라 부적절함을 지적해주고 있습니다.

 

https://cafe.naver.com/sqlpd/21090

 

 

5. 풀이과정

 

try #1

 

 

cv.glmnet의 alpha=0 을 인자로 주어 Ridge 회귀분석을 합니다.

library(carData)
library(caret) 
library(glmnet) 
str(Prestige)

'data.frame': 102 obs. of  6 variables:
 $ education: num  13.1 12.3 12.8 11.4 14.6 ...
 $ income   : int  12351 25879 9271 8865 8403 11030 8258 14163 11377 11023 ...
 $ women    : num  11.16 4.02 15.7 9.11 11.68 ...
 $ prestige : num  68.8 69.1 63.4 56.8 73.5 77.6 72.6 78.1 73.1 68.8 ...
 $ census   : int  1113 1130 1171 1175 2111 2113 2133 2141 2143 2153 ...
 $ type     : Factor w/ 3 levels "bc","prof","wc": 2 2 2 2 2 2 2 2 2 2 ...

# 8:2로 분할합니다.

set.seed(123) 
train <- createDataPartition(y=Prestige$income, p=0.8, list=F) 
Prestige.train <- Prestige[train,] 
Prestige.test <- Prestige[-train,] 

nrow(Prestige.train) ;nrow(Prestige.test) 

[1] 82
[1] 20

# factor 변수의 인코딩을 합니다.
x <- model.matrix(income ~ ., Prestige.train) 
head(x)

 

                    (Intercept) education women prestige census typeprof typewc
gov.administrators            1     13.11 11.16     68.8   1113        1      0
general.managers              1     12.26  4.02     69.1   1130        1      0
accountants                   1     12.77 15.70     63.4   1171        1      0
purchasing.officers           1     11.42  9.11     56.8   1175        1      0
chemists                      1     14.62 11.68     73.5   2111        1      0
physicists                    1     15.64  5.13     77.6   2113        1      0

 

x <- model.matrix(income ~ ., Prestige.train)[,-1] 
y <- Prestige.train$income 

#ridge regresioon analysis 
set.seed(123) 
Prestige.cv <- cv.glmnet(x=x, y=y,family="gaussian",alpha=0) 

Error in glmnet(x, y, weights = weights, offset = offset, lambda = lambda,  : 
  number of observations in y (82) not equal to the number of rows of x (78)

 

 

특이한 오류

 

na.omit 처리후 재시도 과정에서 일시적으로 이상한 오류를 만났습니다.

R Studio 재시작으로 해소되었어요

 

 

try #2

 

 

cv.glmnet의 alpha=0 을 인자로 주어 Ridge 회귀분석을 합니다.

library(carData)
library(caret) 
library(glmnet) 
str(Prestige)

'data.frame': 102 obs. of  6 variables:
 $ education: num  13.1 12.3 12.8 11.4 14.6 ...
 $ income   : int  12351 25879 9271 8865 8403 11030 8258 14163 11377 11023 ...
 $ women    : num  11.16 4.02 15.7 9.11 11.68 ...
 $ prestige : num  68.8 69.1 63.4 56.8 73.5 77.6 72.6 78.1 73.1 68.8 ...
 $ census   : int  1113 1130 1171 1175 2111 2113 2133 2141 2143 2153 ...
 $ type     : Factor w/ 3 levels "bc","prof","wc": 2 2 2 2 2 2 2 2 2 2 ...

 

# 기초통계량을 확인합니다.

summary(Prestige)
   education          income          women           prestige    
 Min.   : 6.380   Min.   :  611   Min.   : 0.000   Min.   :14.80  
 1st Qu.: 8.445   1st Qu.: 4106   1st Qu.: 3.592   1st Qu.:35.23  
 Median :10.540   Median : 5930   Median :13.600   Median :43.60  
 Mean   :10.738   Mean   : 6798   Mean   :28.979   Mean   :46.83  
 3rd Qu.:12.648   3rd Qu.: 8187   3rd Qu.:52.203   3rd Qu.:59.27  
 Max.   :15.970   Max.   :25879   Max.   :97.510   Max.   :87.20  
     census       type   
 Min.   :1113   bc  :44  
 1st Qu.:3120   prof:31  
 Median :5135   wc  :23  
 Mean   :5402   NA's: 4  
 3rd Qu.:8312            
 Max.   :9517

# 결측치 4건이 있습니다.

# 나중에 knn 대치를 하기로 하고 일단은 간편하게 날리고 가겠습니다

Prestige <- na.omit(Prestige)


# 8:2로 분할합니다.

set.seed(123) 
train <- createDataPartition(y=Prestige$income, p=0.8, list=F) 
Prestige.train <- Prestige[train,] 
Prestige.test <- Prestige[-train,] 

nrow(Prestige.train) ;nrow(Prestige.test) 

[1] 80
[1] 18

# factor 변수의 인코딩을 합니다.
x <- model.matrix(income ~ ., Prestige.train) 
head(x)

 

                    (Intercept) education women prestige census typeprof typewc
gov.administrators            1     13.11 11.16     68.8   1113        1      0
general.managers              1     12.26  4.02     69.1   1130        1      0
accountants                   1     12.77 15.70     63.4   1171        1      0
purchasing.officers           1     11.42  9.11     56.8   1175        1      0
chemists                      1     14.62 11.68     73.5   2111        1      0
physicists                    1     15.64  5.13     77.6   2113        1      0

 

x <- model.matrix(income ~ ., Prestige.train)[,-1] 
y <- Prestige.train$income 

#ridge regresioon analysis 
set.seed(123) 
Prestige.cv <- cv.glmnet(x=x, y=y,family="gaussian",alpha=0) 
plot(Prestige.cv)

 

 

Prestige.cv$lambda.min 
log(Prestige.cv$lambda.min) 

Prestige.gnet <- glmnet(x=x, y=y, family="gaussian",alpha=0,
                        lambda=Prestige.cv$lambda.min
coef(Prestige.gnet) 
7 x 1 sparse Matrix of class "dgCMatrix"
                      s0
(Intercept) 1302.5550585
education    165.5028388
women        -49.8315601
prestige     124.7658577
census        -0.1047825
typeprof     283.7961464
typewc      -277.7588629
Prestige.test.x <- model.matrix(income ~ ., Prestige.test)[,-1] 
Prestige.pred <- predict(Prestige.gnet, newx=Prestige.test.x) 
head(Prestige.pred) 
                           s0
mining.engineers    12320.765
surveyors           11050.801
psychologists       10659.495
social.workers       7839.223
university.teachers 13524.357
medical.technicians  7443.387
postResample(pred=Prestige.pred, obs=Prestige.test$income) 

 

       RMSE    Rsquared         MAE 
1910.079857    0.693152 1460.461730

결정계수는 0.693152 이며 rmse는 1910.079857

 

try #3

 

cv.glmnet의 alpha=0 을 인자로 주어 Ridge 회귀분석을 합니다.

library(carData)
library(caret) 
library(glmnet) 
str(Prestige)

'data.frame': 102 obs. of  6 variables:
 $ education: num  13.1 12.3 12.8 11.4 14.6 ...
 $ income   : int  12351 25879 9271 8865 8403 11030 8258 14163 11377 11023 ...
 $ women    : num  11.16 4.02 15.7 9.11 11.68 ...
 $ prestige : num  68.8 69.1 63.4 56.8 73.5 77.6 72.6 78.1 73.1 68.8 ...
 $ census   : int  1113 1130 1171 1175 2111 2113 2133 2141 2143 2153 ...
 $ type     : Factor w/ 3 levels "bc","prof","wc": 2 2 2 2 2 2 2 2 2 2 ...

 

# 기초통계량을 확인합니다.

summary(Prestige)
   education          income          women           prestige    
 Min.   : 6.380   Min.   :  611   Min.   : 0.000   Min.   :14.80  
 1st Qu.: 8.445   1st Qu.: 4106   1st Qu.: 3.592   1st Qu.:35.23  
 Median :10.540   Median : 5930   Median :13.600   Median :43.60  
 Mean   :10.738   Mean   : 6798   Mean   :28.979   Mean   :46.83  
 3rd Qu.:12.648   3rd Qu.: 8187   3rd Qu.:52.203   3rd Qu.:59.27  
 Max.   :15.970   Max.   :25879   Max.   :97.510   Max.   :87.20  
     census       type   
 Min.   :1113   bc  :44  
 1st Qu.:3120   prof:31  
 Median :5135   wc  :23  
 Mean   :5402   NA's: 4  
 3rd Qu.:8312            
 Max.   :9517

# 결측치 4건이 있습니다.

# 나중에 knn 대치를 하기로 하고 일단은 간편하게 날리고 가겠습니다

Prestige <- na.omit(Prestige)


# 8:2로 분할합니다.

set.seed(123) 
train <- createDataPartition(y=Prestige$income, p=0.8, list=F) 
Prestige.train <- Prestige[train,] 
Prestige.test <- Prestige[-train,] 

nrow(Prestige.train) ;nrow(Prestige.test) 

[1] 80
[1] 18

# factor 변수의 인코딩을 합니다.
x <- model.matrix(income ~ ., Prestige.train) 
head(x)

 

                    (Intercept) education women prestige census typeprof typewc
gov.administrators            1     13.11 11.16     68.8   1113        1      0
general.managers              1     12.26  4.02     69.1   1130        1      0
accountants                   1     12.77 15.70     63.4   1171        1      0
purchasing.officers           1     11.42  9.11     56.8   1175        1      0
chemists                      1     14.62 11.68     73.5   2111        1      0
physicists                    1     15.64  5.13     77.6   2113        1      0

 

x <- model.matrix(income ~ ., Prestige.train)[,-1] 
y <- Prestige.train$income 

#ridge regresioon analysis 
set.seed(123) 
# lamda 튜닝 (문제와 무관하게 일단 진행)
Prestige.cv <- cv.glmnet(x=x, y=y,family="gaussian",alpha=0) 
plot(Prestige.cv)

 

 

Prestige.cv$lambda.min 
log(Prestige.cv$lambda.min) 

Prestige.gnet <- glmnet(x=x, y=y, family="gaussian",alpha=0,
                        lambda=Prestige.cv$lambda.min) 
coef(Prestige.gnet) 
7 x 1 sparse Matrix of class "dgCMatrix"
                      s0
(Intercept) 1302.5550585
education    165.5028388
women        -49.8315601
prestige     124.7658577
census        -0.1047825
typeprof     283.7961464
typewc      -277.7588629
Prestige.test.x <- model.matrix(income ~ ., Prestige.test)[,-1] 
Prestige.pred <- predict(Prestige.gnet, newx=Prestige.test.x) 
head(Prestige.pred) 
                           s0
mining.engineers    12320.765
surveyors           11050.801
psychologists       10659.495
social.workers       7839.223
university.teachers 13524.357
medical.technicians  7443.387

 

postResample(pred=Prestige.pred, obs=Prestige.test$income) 

 

       RMSE    Rsquared         MAE 
1910.079857    0.693152 1460.461730

결정계수는 0.693152 이며 rmse는 1910.079857

 

try #4

library(carData)
library(caret) 
library(glmnet) 
library(recipes)
library(dplyr)

# EDA
str(Prestige)
sum(is.na(Prestige)) 
summary(Prestige)

# 8:2로 분할합니다.
set.seed(123) 
train <- createDataPartition(y=Prestige$income, p=0.8, list=F) 
Prestige.train <- Prestige[train,] 
Prestige.test <- Prestige[-train,] 

nrow(Prestige.train) ;nrow(Prestige.test) 


# 전처리
recipe = recipe(income ~ ., data = Prestige.train) %>%
  step_impute_knn(all_predictors()) %>%  # 결측치
  step_dummy(type) %>% # 가변수
  prep()

finaltrain <- juice(recipe)  
finaltest <- bake(recipe, Prestige.test) 


#ridge regresioon analysis 
set.seed(123) 

# lamda 튜닝
Prestige.cv <- cv.glmnet(x=as.matrix(finaltrain[,c(-5)]), 
                         y=finaltrain$income,
                         family="gaussian",alpha=0) 

#?cv.glmnet
plot(Prestige.cv)
Prestige.cv$lambda.min 
log(Prestige.cv$lambda.min) 

# 모델 생성
Prestige.gnet <- glmnet(x=as.matrix(finaltrain[,c(-5)]), 
                        finaltrain$income, 
                        family="gaussian",alpha=0,
                        lambda=Prestige.cv$lambda.min) 
                        
coef(Prestige.gnet) 

# 예측
Prestige.pred <- predict(Prestige.gnet, 
                         newx=as.matrix(finaltest[,c(-5)])) 
head(Prestige.pred) 
postResample(pred=Prestige.pred, obs=finaltest$income)