Bike sharind demand를 맞춰봅시다!
kaggle) bike sharing demand를 맞춰봅시다!
- 아주 행복하게도, missing value가 없습니다 개좋음!!
- Linear model로 했을때보다, randomforest를 넣었을때 훨씬 좋게 나옵니다. 사실 너무 당연한 거죠.
just do it.
- 보통 저는, benchmark model로 만만한, linear model을 만듭니다. 저는 randomforest를 주로 쓰구요.
- house price prediction을 할때는 gradient boosting method가 괜찮았는데, 여기서는 잘 먹히지 않아요. 흠.
- 일단은 randomforest를 이용해서, 0.65정도를 찍었습니다. 이후에도
MLPRegressor도 써보고, linear model과 gradientboosting도 써봤으나, 잘 안되는 관계로, scoring에 문제가 있는 것은 아닐까, 라는 생각을 해봤습니다. - kaggle의 다양한 kernel들을 확인해보니, rmsle(root mean squared log error)를 사용하는 경우가 많아서, scoring을 바꾸고, GridSearchCV에서 해당 scoring을 사용하여 적절한 GradientBoosting model을 만들어봤으나, 여전히 잘 되지 않네요 제기랄. kernel에서 만든 모델과 별 차이 없는데 왜 그럴까요 흠.
- 그만할래요. 후.
- 저의 경우는 RandomforestRegressor를 쓴 경우가 GradientBoosting보다 잘 나왔습니다.
import numpy as np
import pandas as pd
from sklearn.preprocessing import MinMaxScaler, RobustScaler
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.linear_model import LinearRegression, Lasso
from sklearn.metrics import make_scorer, mean_squared_error, make_scorer
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.neural_network import MLPRegressor
train_url = ""
test_url = ""
train_df = pd.read_csv(train_url)
test_df = pd.read_csv(test_url)
#train_df = train_df[train_df['count'] < (count_mean + 3* count_std)].reset_index(drop=True)
count_mean = train_df['count'].mean()
count_std = train_df['count'].std()
train_df = train_df[train_df['count'] < (count_mean + 3* count_std)]
print("reading data complete")
def rmsle(actual_values, predicted_values, convertExp=True):
"""
- root mean squared log error는 error를 로그화값으로 변환하고, 제곱하고, 평균을 내고, 루트를 씌웁니다.
- skewness를 해결하기 위해 np.log1p를 했기 때문에, 값을 예측할 때 이를 다시 변환해서 처리해주는 것이 필요합니다.
"""
if convertExp==True:
predicted_values = np.exp(predicted_values),
actual_values = np.exp(actual_values)
log_predicted_values = np.log(np.array(predicted_values)+1)
log_actual_values = np.log(np.array(actual_values)+1)
# 위에서 계산한 예측값에서 실제값을 빼주고 제곱을 해준다.
difference = np.square(log_predicted_values - log_actual_values)
return np.sqrt(difference.mean())
def preprocessingX(input_df):
r_df = input_df.copy()
r_df['datetime'] = pd.to_datetime(r_df['datetime'])
r_df['weekday'] = r_df['datetime'].apply(lambda d: d.weekday())
r_df['year'] = r_df['datetime'].apply(lambda dt: dt.year)
r_df['month'] = r_df['datetime'].apply(lambda dt: dt.month)
r_df['days'] = r_df['datetime'].apply(lambda dt: dt.day)
r_df['hour'] = r_df['datetime'].apply(lambda dt: dt.hour)
r_df['day_from_start'] = (r_df['datetime'] - r_df['datetime'][0]).apply(lambda td: td.days)
r_df['day_from_start//30'] = r_df['day_from_start']//30
r_df['day_from_start/180'] = r_df['day_from_start']//180
r_df['non_windspeed'] = r_df['windspeed'] ==0
try:
del r_df['registered']
del r_df['casual']
except:
pass
del r_df['datetime']
## making categorical colm
for col in ['holiday', 'season', 'workingday', 'hour']:
r_df = r_df.join(pd.get_dummies(r_df[col], prefix=col))
r_df_v = r_df.values
#r_df_v = RobustScaler().fit_transform(r_df_v)
##r_df_v = MinMaxScaler().fit_transform(r_df_v)
return pd.DataFrame(r_df_v, columns=r_df.columns)
# outlier removal
x = preprocessingX(train_df[list(set(train_df.columns)-set(['count']))])
y = train_df['count']
y_log = np.log1p(y)
x_train, x_test, y_train, y_test = train_test_split(x.values, y_log, train_size=0.8, test_size=0.2, random_state=42)
#reg = GradientBoostingRegressor(n_estimators=5000, alpha=0.01)
#reg = MLPRegressor(hidden_layer_sizes=[512, 64, 4], max_iter=1000, alpha=0.005, random_state=42)
#reg = GridSearchCV( Lasso(), { 'max_iter':[3000], 'alpha':1/np.array([0.1, 1, 2, 3, 4, 10, 30,100,200,300,400,800,900,1000])}, cv=5)
#reg = GridSearchCV(GradientBoostingRegressor(), {"n_estimators":[5, 500, 1000], 'alpha':[0.001, 0.01, 0.1, 0.5]}, scoring=make_scorer(rmsle))
reg = GridSearchCV(GradientBoostingRegressor(), {"n_estimators":[4000], 'alpha':[0.01]}, cv=3,
scoring=make_scorer(rmsle))
reg = GridSearchCV(RandomForestRegressor(), {"n_estimators":[5, 50, 100, 500]}, cv=3,
scoring=make_scorer(rmsle))
reg.fit(x.values, y_log)
## submission
submit_df = pd.DataFrame({'datetime':test_df['datetime'],
'count':[max(0, x) for x in np.exp(reg.predict(preprocessingX(test_df)))],
#'count':list(map(lambda x: round(x, 0), np.exp(reg.predict(preprocessingX(test_df)))))
})
submit_df.to_csv('bycicle.csv', index=False)
print("----complete----")
wrap-up
- 처음에는 시간에 따른 변화를 어떻게 트래킹할 수 있을까? 라고 생각했는데, 거시적으로 추정할 것이라면, 그냥 처음 시작부터 날짜를 하나의 변수로 집어넣으면 된다.
- 그렇게 만들면, 시간의 흐름에 따라 증가하는 것을 알 수있고, 요일 등의 변수를 이용해서 대략 적으로 추정할 수 있음.
- fitting할 때, param_grid에만 신경을 많이 쓰곤 하는데, scoring을 잘 이용하는 것 또한 매우 중요하다. 경우에 따라 적합한 scoring을 정의하여 주는 것이 필요하며, 이를 위해서 sklearn에 있는 make_score를 쓰는 것이 필요하다.
reference
GitHub에서 이 글의 마크다운 원본 보기 & 수정 제안src/content/posts/2018-06-11-kaggle-bike_sharing_demand