Kaggle competition: M5 Forecasting - Accuracy
<SOS> metric: M5_WRMSSE Kaggle data source: m5-forecasting-accuracy<correct_missing_values>
pd.set_option('display.max_columns', 500)
 pd.set_option('display.max_rows', 500)
 warnings.filterwarnings('ignore')
df_train.dropna(axis='columns', inplace=True )<drop_column>
INPUT_DIR_PATH = '.. /input/mlip-daemencloudt-feature-computation-notebook/'
df_train.drop(['Temperature', 'Fuel_Price', 'Unemployment', 'CPI'], axis=1, inplace=True )<feature_engineering>
def train_test_split(data):
x_train = data[data['date'] <= '2016-03-27']
y_train = x_train['demand']
x_val = data[(data['date'] > '2016-03-27')&(data['date'] <= '2016-04-24')]
y_val = x_val['demand']
test = data[(data['date'] > '2016-04-24')]
del data
gc.collect()
return x_train, y_train, x_val, y_val, test
def create_features(df):

 def create_holiday_type_column(df, dates, holiday_type, name):
df.loc[
df['Date'].isin(dates),
'HolidayType'
] = holiday_type
df['HolidayType'] = -1
holiday_list = [ 
(['2010-02-12', '2011-02-11', '2012-02-10', '2013-02-08'], 'Super_Bowl'), 
(['2010-09-10','2011-09-09', '2012-09-07', '2013-09-06'], 'Labor_Day'), 
(['2010-11-26', '2011-11-25', '2012-11-23', '2013-11-29'], 'Thanksgiving'), 
(['2010-12-31', '2011-12-30', '2012-12-28', '2013-12-27'], 'Christmas')
 ]
for index in range(0, len(holiday_list)) :
holiday = holiday_list[index]
create_holiday_type_column(df, holiday[0], index, holiday[1])
 df.Date = pd.to_datetime(df.Date)
 df['Week'] = df.Date.dt.week
df['Year'] = df.Date.dt.year
df['Month'] = df.Date.dt.month
for x in df:
if df[x].dtypes == "int64":
df[x] = df[x].astype(float )<feature_engineering>
def run_lgb(x_train, y_train, x_val, y_val, test):
paramstweedie= {
'boosting_type': 'gbdt',
'metric': 'custom',
'objective': 'tweedie',
'tweedie_variance_power': 1.1,
'n_jobs': -1,
'subsample': 0.5,
'subsample_freq': 1,
'learning_rate': 0.03,
'num_leaves': 2**11-1,
'min_data_in_leaf': 2**12-1,
'feature_fraction': 0.5,
'max_bin': 100,
'n_estimators': 1400,
'num_iterations' : 2000,
'boost_from_average': False,
'verbose': -1,
}
params = {
'metric': 'custom',
'objective': 'tweedie',
'tweedie_variance_power': 1.1,
'seed': 20,
'learning_rate': 0.1,
'num_iterations':2000,
'max_bin':500,
'feature fraction': 0.6,
'num_leaves': 100,
}
evals_result = {}
train_set = lgb.Dataset(x_train[features], y_train)
 val_set = lgb.Dataset(x_val[features], y_val)
 del x_train, y_train
model = lgb.train(params, train_set,early_stopping_rounds = 250, valid_sets = [train_set, val_set], verbose_eval = 10, feval= wrmsse,\
evals_result=evals_result)
 ax = lgb.plot_metric(evals_result)
 plt.show()
val_pred = model.predict(x_val[features], num_iteration=model.best_iteration)
 y_pred = model.predict(test[features], num_iteration=model.best_iteration)
 test['demand'] = y_pred
del y_pred
gc.collect()
return test, model
create_features(df_train )<prepare_x_and_y>
def rmse(predictions, y):
return np.sqrt(mean_squared_error(y, predictions))
X = df_train.drop(['Weekly_Sales', 'Date'], axis=1)
 y = df_train['Weekly_Sales']<categorify>
def predict(test, submission):
predictions = test[['id', 'date', 'demand']]
predictions = pd.pivot(predictions, index = 'id', columns = 'date', values = 'demand' ).reset_index()
predictions.columns = ['id'] + ['F' + str(i + 1)for i in range(28)]
evaluation_rows = [row for row in submission['id'] if 'evaluation' in row]
evaluation = submission[submission['id'].isin(evaluation_rows)]
validation = submission[['id']].merge(predictions, on = 'id')
 final = pd.concat([validation, evaluation])
 final.to_csv('submission_new.csv', index = False)
categorical_features = X.columns[X.dtypes == 'O']
numeric_features = X.columns[X.dtypes == 'float64']
categories = [X[column].unique() for column in X[categorical_features]]
for cat in categories:
cat[cat == None] = 'missing'
transform_categorical_features = make_pipeline(
 SimpleImputer(missing_values=None,
strategy='constant',
fill_value='missing'),
OrdinalEncoder(categories=categories)
)
 transform_numeric_features = make_pipeline(
 SimpleImputer(strategy='constant', fill_value=-9999),
StandardScaler() 
)
 preprocessing_step = make_column_transformer(
(transform_categorical_features, categorical_features), 
(transform_numeric_features, numeric_features),
remainder='passthrough'
)<split>
features = [
"item_id", "dept_id", "cat_id", "store_id", "state_id", "event_name_1", "event_type_1", "snap_CA", "snap_TX", \
"snap_WI", "sell_price", \
"shift_t28", \
"rolling_mean_28_7","rolling_mean_28_28", \
"price_change_t1",
"year", "month", "dayofweek", "before_holiday", "after_holiday"
]
print(f'length: {len(features)}')
 print(features )
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2 )<define_variables>
data = pd.read_pickle(f'{INPUT_DIR_PATH}Features{1}.pkl')
 for i in range(2,6):
data = pd.concat([data, pd.read_pickle(f'{INPUT_DIR_PATH}Features{i}.pkl')])
 data.shape
regression_models = [
'LinearRegression',
'KNN',
'Ridge',
'Lasso',
'XGBRegressor',
'RandomForestRegressor',
'ExtraTreesRegressor'
]
best_model = None
best_error = math.inf<choose_model_class>
sales_train_val = pd.read_csv('/kaggle/input/m5-forecasting-accuracy/sales_train_validation.csv')
 NUM_ITEMS = sales_train_val.shape[0]
submission = pd.read_csv('/kaggle/input/m5-forecasting-accuracy/sample_submission.csv')
 DAYS_PRED = submission.shape[1] - 1
product = sales_train_val[['id', 'item_id', 'dept_id', 'cat_id', 'store_id', 'state_id']].drop_duplicates()
print('-' * 50)
 print('Training evaluation')
 print('-' * 50)
 for name in regression_models:
print(f':: {name} - Training Pipeline')
 regressor = model_factory(name)
 training_pipeline = make_pipeline(
 preprocessing_step,
regressor 
)
 kfold = KFold(n_splits=3)
 y_pred = cross_val_predict(
 training_pipeline,
X_train,
y_train,
cv = kfold,
n_jobs = -1,
verbose = 1 
)
 wmae_metric = WMAE(X_train, y_train, y_pred)
 if wmae_metric < best_error:
best_error = wmae_metric
best_model = name
plot_regression_results(
 y_train,
y_pred,
name, 
(r'$WMAE ={:.2f}$' ).format(wmae_metric)
)
 print('-' * 50 )<compute_test_metric>
weight_mat = np.c_[np.ones([NUM_ITEMS,1] ).astype(np.int8),
pd.get_dummies(product.state_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.store_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.cat_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.dept_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.state_id.astype(str)+ product.cat_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.state_id.astype(str)+ product.dept_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.store_id.astype(str)+ product.cat_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.store_id.astype(str)+ product.dept_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.item_id.astype(str),drop_first=False ).astype('int8' ).values,
pd.get_dummies(product.state_id.astype(str)+ product.item_id.astype(str),drop_first=False ).astype('int8' ).values,
np.identity(NUM_ITEMS ).astype(np.int8)
 ].T
weight_mat_csr = csr_matrix(weight_mat)
 del weight_mat; gc.collect()
def weight_calc(data, product, sales_train_val):
d_name = ['d_' + str(i+1)for i in range(1913)]
sales_train_val = weight_mat_csr * sales_train_val[d_name].values
df_tmp =(( sales_train_val>0)* np.tile(np.arange(1,1914),(weight_mat_csr.shape[0],1)))
 start_no = np.min(np.where(df_tmp==0,9999,df_tmp),axis=1)-1
flag = np.dot(np.diag(1/(start_no+1)) , np.tile(np.arange(1,1914),(weight_mat_csr.shape[0],1)))<1
sales_train_val = np.where(flag,np.nan,sales_train_val)
 weight1 = np.nansum(np.diff(sales_train_val,axis=1)**2,axis=1)/(1913-start_no)
 df_tmp = data[(data['date'] > '2016-03-27')&(data['date'] <= '2016-04-24')]
df_tmp['amount'] = df_tmp['demand'] * df_tmp['sell_price']
df_tmp =df_tmp.groupby(['id'])['amount'].apply(np.sum)
 df_tmp = df_tmp[product.id].values
weight2 = weight_mat_csr * df_tmp
weight2 = weight2/np.sum(weight2)
 del sales_train_val
gc.collect()
return weight1, weight2
weight1, weight2 = weight_calc(data,product,sales_train_val)
 def wrmsse(preds, data):
y_true = data.get_label()
y_true = y_true[-(NUM_ITEMS * DAYS_PRED):]
preds = preds[-(NUM_ITEMS * DAYS_PRED):]
num_col = DAYS_PRED
reshaped_preds = preds.reshape(num_col, NUM_ITEMS ).T
reshaped_true = y_true.reshape(num_col, NUM_ITEMS ).T
train = weight_mat_csr*np.c_[reshaped_preds, reshaped_true]
score = np.sum(
 np.sqrt(
 np.mean(
 np.square(
 train[:,:num_col] - train[:,num_col:])
 ,axis=1)/ weight1)* weight2)
 return 'wrmsse', score, False
def wrmsse_simple(preds, data):
y_true = data.get_label()
y_true = y_true[-(NUM_ITEMS * DAYS_PRED):]
preds = preds[-(NUM_ITEMS * DAYS_PRED):]
num_col = DAYS_PRED
reshaped_preds = preds.reshape(num_col, NUM_ITEMS ).T
reshaped_true = y_true.reshape(num_col, NUM_ITEMS ).T
train = np.c_[reshaped_preds, reshaped_true]
weight2_2 = weight2[:NUM_ITEMS]
weight2_2 = weight2_2/np.sum(weight2_2)
 score = np.sum(
 np.sqrt(
 np.mean(
 np.square(
 train[:,:num_col] - train[:,num_col:])
 ,axis=1)/ weight1[:NUM_ITEMS])*weight2_2)
 return 'wrmsse', score, False
print(f'Best model is {best_model}')
 print(f'Best score is {best_error}' )<define_search_space>
x_train, y_train, x_val, y_val, test = train_test_split(data)
 del data
n_estimators = [x for x in range(50, 250, 50)]
random_grid = {
'model__n_estimators': n_estimators
}
random_grid<choose_model_class>
test, model = run_lgb(x_train, y_train, x_val, y_val, test )
def get_best_model_parameters(random_grid, X, y):
if best_model in ['ExtraTreesRegressor', 'RandomForestRegressor']:
model = model_factory(best_model)
 else:
return {'model__n_estimators': None}
grid_pipeline = Pipeline(
 [("preprocessing", preprocessing_step), 
("model", model)] 
)
 kfold = KFold(n_splits=3)
 model_random = GridSearchCV(
 grid_pipeline,
param_grid = random_grid,
cv = kfold,
verbose = 2,
n_jobs = -1 
)
 X_sample, _, y_sample, _ = train_test_split(X, y, test_size=0.9)
 return model_random.fit(X_sample, y_sample ).best_params_
best_params = get_best_model_parameters(random_grid, X, y)
 best_params<train_model>
print('-' * 70)
 print(f'Best Model: {best_model}: {best_params}
')
 print('Tip: click on the Pipeline diagram below to have a better view of each step.')
 print('-' * 70)
 model = model_factory(
 best_model,
n_estimators = best_params['model__n_estimators'],
verbose = 1,
n_jobs = -1 
)
 best_model_pipeline = Pipeline(
 [ 
("preprocessing", preprocessing_step), 
("model", model)
 ] 
)
 set_config(display='diagram')
 best_model_pipeline.fit(X_train, y_train )<merge>
del x_train, y_train, x_val, y_val
del weight_mat_csr
gc.collect()
<predict_on_test><EOS> 
predict(test, submission )