먼저 데이터 분석에 필요한 패키지를 불러오겠습니다.
import warnings
warnings.filterwarnings("ignore")
import os
from os.path import join
import pandas as pd
import numpy as np
import missingno as msno
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import KFold, cross_val_score
import xgboost as xgb
import lightgbm as lgb
import matplotlib.pyplot as plt
import seaborn as sns
import re
import glob
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
import os
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
from keras.callbacks import EarlyStopping
from keras.layers.normalization import BatchNormalization#정규화시켜줌
from keras.layers import Dropout
from keras import regularizers
아래 사이트에서 데이터 확인 및 다운 받으면 됩니다.
[https://www.kaggle.com/c/2019-2nd-ml-month-with-kakr/overview]
train_data_path = join('/data', 'train.csv')
test_data_path = join('/data', 'test.csv')
print(train_data_path)
print(test_data_path )
train = pd.read_csv(train_data_path)
test = pd.read_csv(test_data_path)
print(train.shape)
print(test.shape)
(15035, 21)
(6468, 20)
train 데이터는 라벨을 포함하고 있기 때문에 21열이고 test데이터는 라벨을 포함하고 있지 않기 때문에 20열입니다. 우리가 해야할 과제는 train데이터를 통해 데이터를 학습하고 test데이터를 기반으로 예측하여 나온 값으로 label을 찾는 것 입니다.
train.head()
train['date'] = train['date'].apply(lambda x :x[:6]).astype(int)
train.head()
y=train['price']
del train['price']
print(train.columns)
Index(['id', 'date', 'bedrooms', 'bathrooms', 'sqft_living', 'sqft_lot',
'floors', 'waterfront', 'view', 'condition', 'grade', 'sqft_above',
'sqft_basement', 'yr_built', 'yr_renovated', 'zipcode', 'lat', 'long',
'sqft_living15', 'sqft_lot15'],
dtype='object')
del train['id']
print(train.columns)
Index(['date', 'bedrooms', 'bathrooms', 'sqft_living', 'sqft_lot', 'floors',
'waterfront', 'view', 'condition', 'grade', 'sqft_above',
'sqft_basement', 'yr_built', 'yr_renovated', 'zipcode', 'lat', 'long',
'sqft_living15', 'sqft_lot15'],
dtype='object')
test['date'] = test['date'].apply(lambda x :x[:6]).astype(int)
del test['id']
print(test.columns)
sns.kdeplot(y)
plt.show()
y= np.log1p(y)
y
0 12.309987
1 12.100718
2 13.142168
.
.
sns.kdeplot(y)
plt.show()
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error
def rmse(y_test,y_pred):
return np.sqrt(mean_squared_error(np.expm1(y_test),np.expm1(y_pred)))
from xgboost import XGBRegressor
from lightgbm import LGBMRegressor
from sklearn.ensemble import GradientBoostingRegressor, RandomForestRegressor
random_state는 모델초기화 랜덤 시드값입니다.
random_state=2020
gboost = GradientBoostingRegressor(random_state=random_state)
xgboost = XGBRegressor(random_state=random_state)
lightgbm = LGBMRegressor(random_state=random_state)
rdforest = RandomForestRegressor(random_state=random_state)
models = [gboost, xgboost, lightgbm, rdforest]
df = {}
for model in models:
# 모델 이름 획득
model_name = model.__class__.__name__
# train, test 데이터셋 분리 - 여기에도 random_state를 고정합니다.
X_train, X_test, y_train, y_test = train_test_split(train, y, random_state=random_state, test_size=0.2)
# 모델 학습
model.fit(X_train, y_train)
# 예측
y_pred = model.predict(X_test)
# 예측 결과의 rmse값 저장
df[model_name] = rmse(y_test, y_pred)
# data frame에 저장
score_df = pd.DataFrame(df, index=['RMSE']).T.sort_values('RMSE', ascending=False)
df
{'GradientBoostingRegressor': 128360.19649691365,
'XGBRegressor': 110318.6704088949,
'LGBMRegressor': 111920.36735892233,
'RandomForestRegressor': 125367.2973747959}
def get_scores(models, train, y):
df = {}
for model in models:
model_name = model.__class__.__name__
X_train, X_test, y_train, y_test = train_test_split(train, y, random_state=random_state, test_size=0.2)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
df[model_name] = rmse(y_test, y_pred)
score_df = pd.DataFrame(df, index=['RMSE']).T.sort_values('RMSE', ascending=False)
get_scores(models, train, y)
from sklearn.model_selection import GridSearchCV
grid에 탐색을 할 xgboost관련 하이퍼 파라미터를 넣습니다.
param_grid = {'n_estimators':[50,100], 'max_depth' : [1,10],}
LGBMRegressor를 사용해서 적용해보겠습니다.
model = LGBMRegressor(random_state = random_state)
grid_model = GridSearchCV(model, param_grid=param_grid, \
scoring='neg_mean_squared_error', \
cv=5, verbose=1, n_jobs=5)
grid_model.fit(train, y)
grid를 통해 얻은 값은 gridmodel.cv_results에 저장이 됩니다., 그중에 우리는 params 중 테스트 점수 인 mean_test_score값만을 호출하겠습니다. 다른 정보보다는 우리가 보고 싶은 것이 params에 대한 점수니까요
params = grid_model.cv_results_['params']
params
[{'max_depth': 1, 'n_estimators': 50},
{'max_depth': 1, 'n_estimators': 100},
{'max_depth': 10, 'n_estimators': 50},
{'max_depth': 10, 'n_estimators': 100}]
score = grid_model.cv_results_['mean_test_score']
score
array([-0.17974603, -0.17912826, -0.03545062, -0.0352382 ])
results = pd.DataFrame(params)
results['score'] = score
results
호출한 score값이 음수이기 때문에 양수로 바꿔줍니다. 음수였던 이유는 MSE에 음수 값을 넣어 scoring을 하기 때문입니다.
results['RMSE'] = np.sqrt(-1 * results['score'])
results
앞에서 y에 log값을 취에 다듬었기 때문에 RMSE값도 log값이 취해진 결과로 나옵니다. 그렇기 때문에 이름을 변경해주겠습니다.
results = results.rename(columns={'RMSE': 'RMSLE'})
results
순서를 좋으 순으로 바꿉니다!
results = results.sort_values('RMSLE')
results
def my_GridSearch(model, train, y, param_grid, verbose=2, n_jobs=5):
# GridSearchCV 모델로 초기화
grid_model = GridSearchCV(model, param_grid=param_grid, scoring='neg_mean_squared_error', \
cv=5, verbose=verbose, n_jobs=n_jobs)
# 모델 fitting
grid_model.fit(train, y)
# 결과값 저장
params = grid_model.cv_results_['params']
score = grid_model.cv_results_['mean_test_score']
# 데이터 프레임 생성
results = pd.DataFrame(params)
results['score'] = score
# RMSLE 값 계산 후 정렬
results['RMSLE'] = np.sqrt(-1 * results['score'])
results = results.sort_values('RMSLE')
return results
param_grid = {
'n_estimators': [50, 100],
'max_depth': [1, 10],
}
model = LGBMRegressor(random_state=random_state)
my_GridSearch(model, train, y, param_grid, verbose=2, n_jobs=5)
아래 max_depth=20, n_estimators=300로 설정한 이유는 맨 아래 파라미터 값들을 여러번 수정하며 가장 좋은 값을 찾아서 적용했습니다. ㅎㅎ
model = LGBMRegressor(max_depth=20, n_estimators=300, random_state=random_state)
model.fit(train, y)
prediction = model.predict(test)
prediction
array([13.12160458, 13.10226918, 14.15043868, ..., 13.05037436,
12.67158278, 13.01735592])
prediction = np.expm1(prediction)
prediction
array([ 499619.74521686, 490052.17258291, 1397838.90879818, ...,
465269.55869982, 318564.30877008, 450157.90324192])
data_dir = 'C:/Users/hoo45/Desktop/PythonTech/kaggle-kakr-housing-data/data'
submission_path = join(data_dir, 'sample_submission.csv')
submission = pd.read_csv(submission_path)
submission.head()
submission['price'] = prediction
submission.head()
submission_csv_path = '{}/submission_{}_RMSLE_{}.csv'.format(data_dir, 'lgbm', '0.164399')
submission.to_csv(submission_csv_path, index=False)
print(submission_csv_path)
아래 코드를 통해 몇번 파라미터를 바꿔봤는데 LGBMRegressor 분석기법이 가장 좋았고 n_estimators, max_depth 를 수정하며 가장 좋은 파라미터 값을 찾아서 제출해보니 바로 통과했네요... 캐글에서 순위로는 45등 정도 합니다.
머신러닝 말고도 딥러닝을 이용해서 예측해 볼 수 있습니다.
from keras import backend as K
def root_mean_squared_error(y_true, y_pred):
return K.sqrt(K.mean(K.square(y_pred - y_true)))
keras의 dense레이어를 이용하여 분석해보겠습니다.
model=keras.models.Sequential()
model.add(keras.layers.Dense(64, activation='relu',input_shape=[len(X_train.keys())]))
model.add(keras.layers.Dense(128, activation='relu'))
model.add(keras.layers.Dense(64, activation='relu'))
#model.add(BatchNormalization())
model.add(keras.layers.Dense(1))
model.compile(loss=root_mean_squared_error,
optimizer='Adam')
model.summary()
s=EarlyStopping(monitor='val_loss',mode='min',verbose=1,patience=10)
model.fit(X_train,np.expm1(y_train), epochs=100, batch_size=10,callbacks=[es], validation_data=(X_test, np.expm1(y_test)))
y_pred=model.predict(test)
y_pred
array([[ 710453.75],
[ 536851.25],
[1279097. ],
...,
[ 435745.5 ],
[ 356353.44],
[ 479380.62]], dtype=float32)
data_dir = 'data/data'
submission_path = join(data_dir, 'sample_submission.csv')
submission = pd.read_csv(submission_path)
submission.head()
submission['price'] = y_pred
submission.head()
submission_csv_path = '{}/submission_{}_RMSE_{}.csv'.format(data_dir, 'dense', '')
submission.to_csv(submission_csv_path, index=False)
print(submission_csv_path)
매우 안.좋..;;