펭귄 몸무게 예측-submission

kim 개인기록용·2021년 12월 29일
0

학습 데이터 불러오기 및 초기화

import pandas as pd
import numpy as np
from sklearn import preprocessing
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split

df_train = pd.read_csv('C:/workspace/py_dacon/data/penguin/train.csv')

#EDA를 거쳐 안쓰기로 결정한 컬럼들 drop
df_train_drop = df_train.drop(['id','Delta 15 N (o/oo)','Delta 13 C (o/oo)','Clutch Completion'], axis=1, inplace=False)

#범주형, 연속형 변수명들 지정
discrete_names_drop = ['Species', 'Island', 'Sex']
continuous_names_drop = ['Culmen Length (mm)', 'Culmen Depth (mm)', 'Flipper Length (mm)']

전처리

#범주형 변수의 one-hot 인코딩
df_train_after=pd.get_dummies(data=df_train_drop, columns=discrete_names_drop, drop_first=True)

#학습과 검증에 쓸 train, test 셋으로 분리
y_train = df_train_after['Body Mass (g)']
x_train = df_train_after.drop('Body Mass (g)', axis=1, inplace=False)

x_train, x_test, y_train, y_test = train_test_split(x_train, y_train, test_size=0.2, random_state=100)

#다음 단계에서 연속형 변수의 스케일링을 진행할 건데, 인덱스 리셋을 안해주면  NaN 값이 반환될 수 있으므로 반드시 인덱스를 리셋
x_train.reset_index(drop=True, inplace=True)
x_test.reset_index(drop=True, inplace=True)

#스케일링을 할 때는 훈련 데이터는 fit_transform으로 훈련-적용, 검증 데이터는 transform만 진행
scaler = StandardScaler()

train_scaler = scaler.fit_transform(x_train[continuous_names_drop])
x_train[continuous_names_drop] = pd.DataFrame(data=train_scaler, columns=continuous_names_drop)

test_scaler = scaler.transform(x_test[continuous_names_drop])
x_test[continuous_names_drop] = pd.DataFrame(data=test_scaler, columns=continuous_names_drop)

#전처리 완료된 데이터 확인
x_train.head()

모델학습

from sklearn.linear_model import LinearRegression, Ridge, Lasso
from sklearn.metrics import mean_squared_error
from sklearn.model_selection import GridSearchCV

#평가기준인 rmse 값을 리턴하는 함수
def get_rmse(model):
    pred = model.predict(x_test)
    score = np.sqrt(np.mean(np.square(y_test - pred)))
    
    print(model.__class__.__name__, 'RMSE : ',np.round(score, 3))
    
    return score
    
#여러 모델의 rmse 값들을 한번에 리턴하는 함수 -> 모델 비교를 통해 어떤 모델을 쓸지 확인
def get_rmses(models):
    rmses = []
    
    for model in models:
        rmse = get_rmse(model)
        rmses.append(rmse)
    
    return rmses
    
#릿지와 라쏘 모델에 대해 alpha 파라미터 변화를 통해 최적 값을 도출해내기 위한 함수
def print_best_params(model, params):
    grid_model = GridSearchCV(model, param_grid=params, scoring='neg_mean_squared_error', cv=5)
    grid_model.fit(x_test, y_test)
    rmse = np.sqrt(-1*grid_model.best_score_)
    
    print('{0} 5 CV 시 최적 평균 RMSE 값 : {1}, 최적 alpha : {2}'.format(model.__class__.__name__,
                                                                np.round(rmse,4),grid_model.best_params_))
                                                                
#모델에 검증 데이터로 예측 후, 해당 모델의 RMSE 값을 리턴하는 함수
def get_rmse_pred(preds):
    for key in preds.keys():
        pred_value = preds[key]
        mse = mean_squared_error(y_test, pred_value)
        rmse = np.sqrt(mse)
        
        print('{0} 모델의 RMSE: {1}'.format(key,rmse))

우선 학습에 쓰일 함수를 4가지 정의하고 밑에서 계속 불러서 쓸 예정

선형회귀, 릿지, 라쏘

lr = LinearRegression()
lr.fit(x_train,y_train)

rid = Ridge()
rid.fit(x_train, y_train)

las = Lasso()
las.fit(x_train,y_train)

models = [lr, rid, las]
get_rmses(models)

LinearRegression RMSE : 299.574
Ridge RMSE : 282.328
Lasso RMSE : 297.308

릿지와 라쏘가 선형회귀보다 잘 나와서 이 두 개의 알파 값을 임의로 변경해보고 최적의 알파 값을 찾도록 해본다.
변화시킬 알파 값은 맘대로 정한 것임.

rid_params = {'alpha':[0.05, 0.1, 1,2,3,4, 5,8,10,11,12,15,20]}
las_params = {'alpha':[0.001,0.005,0.008,0.05,0.03,0.1,0.5,1,2,3,4,5,10]}

print_best_params(rid, rid_params)
print_best_params(las, las_params)

Ridge 5 CV 시 최적 평균 RMSE 값 : 247.8067, 최적 alpha : {'alpha': 2}
Lasso 5 CV 시 최적 평균 RMSE 값 : 267.6843, 최적 alpha : {'alpha': 10}

나온 대로 알파 값을 적용해서 다시 해보겠다.

rid = Ridge(alpha=2)
rid.fit(x_train, y_train)

las = Lasso(alpha=10)
las.fit(x_train,y_train)

models = [lr, rid, las]
get_rmses(models)

Ridge RMSE : 272.335
Lasso RMSE : 274.737

쪼끔 나아짐.
다른 알고리즘들도 적용시켜보자.

from xgboost import XGBRegressor
from lightgbm import LGBMRegressor

xgb_params = {'n_estimators':[1000]}
xgb = XGBRegressor(n_estimators=1000, learning_rate=0.05, colsample_bytree=0.5, subsample=0.8)
xgb.fit(x_train, y_train)

lgbm_params = {'n_estimators':[1000]}
lgbm_reg = LGBMRegressor(n_estimators=1000, learning_rate=0.05, num_leaves=4, subsample=0.6, colsample_bytree=0.4, reg_lambda=10, n_jobs=-1)
lgbm_reg.fit(x_train,y_train)

models = [xgb, lgbm_reg]
get_rmses(models)

XGBRegressor RMSE : 398.254
LGBMRegressor RMSE : 316.298

두 알고리즘의 파람들이 뭘 의미하는지 세부적으론 모른다.
책 예시 소스 긁어온 것임. 나중에 공부해보자.

위 두 모델은 "회귀 트리" 모델인데 릿지랑 라쏘보다는 별로인 것으로 나왔다.

이번엔 강력한 알고리즘인 svm을 써보자.
3개 다 써보기로 함

from sklearn.svm import SVR

svr_lin = SVR(kernel='linear',C=1000)
svr_lin.fit(x_train, y_train)

svr_po = SVR(kernel='poly',C=1000)
svr_po.fit(x_train, y_train)

svr_rbf = SVR(kernel='rbf',C=1000)
svr_rbf.fit(x_train, y_train)

models = [svr_lin, svr_po, svr_rbf]
get_rmses(models)

SVR RMSE : 251.619
SVR RMSE : 363.021
SVR RMSE : 337.717

오 리니어가 제일 좋게 나왔다.
이걸로 실제 데이콘에서 준 test데이터로 만들어서 제출 완료함.

12/29 13시 37분 현재 기준
점수 : 304.79544
순위 : 28

더 고칠 수 있을 것 같긴 한데, 귀찮아서 안한다.

profile
java, python, siebel, nexacro, oracle, postgresql

0개의 댓글