Kaggle competition: Predice el futuro
path = ".. /input/m5-forecasting-accuracy"
calendar = pd.read_csv(os.path.join(path, "calendar.csv"))
selling_prices = pd.read_csv(os.path.join(path, "sell_prices.csv"))
sample_submission = pd.read_csv(os.path.join(path, "sample_submission.csv"))
sales = pd.read_csv(os.path.join(path, "sales_train_validation.csv"))<data_type_conversions>
train_data=pd.read_csv("/kaggle/input/predice-el-futuro/train_csv.csv")
 display(train_data.head())
 test_data=pd.read_csv("/kaggle/input/predice-el-futuro/test_csv.csv")
 display(test_data.head())
def prep_calendar(df):
df = df.drop(["date", "weekday", "event_type_1", "event_type_2"], axis=1)
 df = df.assign(d = df.d.str[2:].astype(int))
to_ordinal = ["event_name_1", "event_name_2"]
df[to_ordinal] = df[to_ordinal].fillna("1")
 df[to_ordinal] = OrdinalEncoder(dtype="int" ).fit_transform(df[to_ordinal])+ 1
to_int8 = ["wday", "month", "snap_CA", "snap_TX", "snap_WI"] + to_ordinal
df[to_int8] = df[to_int8].astype("int8")
 return df<drop_column>
train_data['time'] = pd.to_datetime(train_data['time'],format='%Y-%m-%d %H:%M:%S')
 train_data['year']=train_data['time'].dt.year
train_data['month']=train_data['time'].dt.month
train_data['day']=train_data['time'].dt.day
train_data['dayofweek_num']=train_data['time'].dt.dayofweek
train_data['dayofweek_name']=train_data['time'].dt.weekday_name
train_data['Hour'] = train_data['time'].dt.hour
train_data['minute'] = train_data['time'].dt.minute
train_data['second'] = train_data['time'].dt.second
train_data.head()
calendar = prep_calendar(calendar)
 calendar.head()<categorify>
train_data['lag_1'] = train_data['feature'].shift(1)
 train_data = train_data[['time', 'lag_1', 'feature']]
train_data.head()
LAGS = [7, 28]
WINDOWS = [7, 28]
FIRST = 1914
LENGTH = 28
def demand_features(df):

 for lag in LAGS:
df[f'lag_t{lag}'] = df.groupby('id')['demand'].transform(lambda x: x.shift(lag)).astype("float32")
 for w in WINDOWS:
df[f'rolling_mean_lag{lag}_w{w}'] = df.groupby('id')[f'lag_t{lag}'].transform(lambda x: x.rolling(w ).mean() ).astype("float32")
 return df<data_type_conversions>
train_data['lag_1'] = train_data['feature'].shift(1)
 train_data['lag_2'] = train_data['feature'].shift(2)
 train_data['lag_3'] = train_data['feature'].shift(3)
 train_data['lag_4'] = train_data['feature'].shift(4)
 train_data['lag_5'] = train_data['feature'].shift(5)
 train_data['lag_6'] = train_data['feature'].shift(6)
 train_data['lag_7'] = train_data['feature'].shift(7)
 data = train_data[['time', 'lag_1', 'lag_2', 'lag_3', 'lag_4', 'lag_5', 'lag_6', 'lag_7', 'feature']]
data.head(10 )
def demand_features_eval(df):

 out = df.groupby('id', sort=False ).last()
for lag in LAGS:
out[f'lag_t{lag}'] = df.groupby('id', sort=False)['demand'].nth(-lag-1 ).astype("float32")
 for w in WINDOWS:
out[f'rolling_mean_lag{lag}_w{w}'] = df.groupby('id', sort=False)['demand'].nth(list(range(-lag-w, -lag)) ).groupby('id', sort=False ).mean().astype("float32")
 return out.reset_index()<data_type_conversions>
model = Prophet()
model.fit(train_data.reset_index() \ 
.rename(columns={'time':'ds',
'feature':'y'}))
def prep_data(df, drop_d=1000):

 df = df.drop(["d_" + str(i+1)for i in range(drop_d)], axis=1)
 df = df.assign(id=df.id.str.replace("_validation", ""))
df = df.reindex(columns=df.columns.tolist() + ["d_" + str(FIRST + i)for i in range(2 * LENGTH)])
 df = df.melt(id_vars=["id", "item_id", "store_id", "state_id", "dept_id", "cat_id"], var_name='d', value_name='demand')
 df = df.assign(d=df.d.str[2:].astype("int64"),
demand=df.demand.astype("float32"))
df = demand_features(df)
 df = df[df.d >(drop_d + max(LAGS)+ max(WINDOWS)) ]
df = df.merge(calendar, how="left", on="d")
 df = df.merge(selling_prices, how="left", on=["store_id", "item_id", "wm_yr_wk"])
 df = df.drop(["wm_yr_wk"], axis=1)
 for v in ["item_id", "store_id", "state_id", "dept_id", "cat_id"]:
df[v] = OrdinalEncoder(dtype="int" ).fit_transform(df[[v]] ).astype("int16")+ 1
x = list(set(df.columns)- {'id', 'd', 'demand'})
 test = df[df.d >= FIRST - max(LAGS)- max(WINDOWS)]
df = df[df.d < FIRST]
xtrain, xvalid, ytrain, yvalid = train_test_split(df[x], df["demand"], test_size=0.1, shuffle=True, random_state=54)
 train = lgb.Dataset(xtrain, label = ytrain)
 valid = lgb.Dataset(xvalid, label = yvalid)
 return train, valid, test, x
def fit_model(train, valid):

 params = {
'metric': 'rmse',
'objective': 'poisson',
'seed': 200,
'force_row_wise' : True,
'learning_rate' : 0.09,
'lambda': 0.1,
'num_leaves': 63,
'sub_row' : 0.7,
'bagging_freq' : 1,
'colsample_bytree': 0.77
}
fit = lgb.train(params,
train,
num_boost_round = 2000,
valid_sets = [valid],
early_stopping_rounds = 200,
verbose_eval = 100)
 lgb.plot_importance(fit, importance_type="gain", precision=0, height=0.5, figsize=(6, 10)) ;
return fit
def pred_to_csv(fit, test, x, cols=sample_submission.columns, file="submission.csv"):

 for i, day in enumerate(np.arange(FIRST, FIRST + LENGTH)) :
test_day = demand_features_eval(test[(test.d <= day)&(test.d >= day - max(LAGS)- max(WINDOWS)) ])
 test.loc[test.d == day, "demand"] = fit.predict(test_day[x])*(1.025 + 0.01 *(day > 1928))
test = test.assign(id=test.id + "_" + np.where(test.d < FIRST + LENGTH, "validation", "evaluation"),
F="F" +(test.d - FIRST + 1 - LENGTH *(test.d >= FIRST + LENGTH)).astype("str"))
submission = test.pivot(index="id", columns="F", values="demand" ).reset_index() [cols].fillna(1)
 submission.to_csv(file, index=False)
 return True<save_to_csv>
test_fcst = model.predict(df=test_data.reset_index() \ 
.rename(columns={'time':'ds'}))
train, valid, test, x = prep_data(sales, 1000)
 fit = fit_model(train, valid)
 pred_to_csv(fit, test, x )<set_options>
data=test_fcst["yhat_upper"]
data.loc[1:40]
warnings.filterwarnings('ignore' )<randomize_order>
train_fcst = model.predict(df=train_data.reset_index() \ 
.rename(columns={'time':'ds'}))
def seed_everything(seed=0):
random.seed(seed)
 np.random.seed(seed)
 def df_parallelize_run(func, t_split):
num_cores = np.min([N_CORES,len(t_split)])
 pool = Pool(num_cores)
 df = pd.concat(pool.map(func, t_split), axis=1)
 pool.close()
pool.join()
return df<categorify>
def parserToTimeDatatype(time):
return datetime.strptime(time,"%Y-%m-%d %H:%M:%S" )
def get_data_by_store(store):
df = pd.concat([pd.read_pickle(BASE),
pd.read_pickle(PRICE ).iloc[:,2:],
pd.read_pickle(CALENDAR ).iloc[:,2:]],
axis=1)
 df = df[df['store_id']==store]
df2 = pd.read_pickle(MEAN_ENC)[mean_features]
df2 = df2[df2.index.isin(df.index)]
df3 = pd.read_pickle(LAGS ).iloc[:,3:]
df3 = df3[df3.index.isin(df.index)]
df = pd.concat([df, df2], axis=1)
 del df2
df = pd.concat([df, df3], axis=1)
 del df3
features = [col for col in list(df)if col not in remove_features]
df = df[['id','d',TARGET]+features]
df = df[df['d']>=START_TRAIN].reset_index(drop=True)
 return df, features
def get_base_test() :
base_test = pd.DataFrame()
for store_id in STORES_IDS:
temp_df = pd.read_pickle('test_'+store_id+'.pkl')
 temp_df['store_id'] = store_id
base_test = pd.concat([base_test, temp_df] ).reset_index(drop=True)
 return base_test
def make_lag(LAG_DAY):
lag_df = base_test[['id','d',TARGET]]
col_name = 'sales_lag_'+str(LAG_DAY)
 lag_df[col_name] = lag_df.groupby(['id'])[TARGET].transform(lambda x: x.shift(LAG_DAY)).astype(np.float16)
 return lag_df[[col_name]]
def make_lag_roll(LAG_DAY):
shift_day = LAG_DAY[0]
roll_wind = LAG_DAY[1]
lag_df = base_test[['id','d',TARGET]]
col_name = 'rolling_mean_tmp_'+str(shift_day)+'_'+str(roll_wind)
 lag_df[col_name] = lag_df.groupby(['id'])[TARGET].transform(lambda x: x.shift(shift_day ).rolling(roll_wind ).mean())
 return lag_df[[col_name]]<init_hyperparams>
df= pd.read_csv('/kaggle/input/predice-el-futuro/train_csv.csv',
parse_dates = [1],
index_col = 1,
date_parser=parserToTimeDatatype)
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'tweedie',
'tweedie_variance_power': 1.1,
'metric': 'rmse',
'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,
'boost_from_average': False,
'verbose': -1,
} 
<init_hyperparams>
df= df.iloc[:,[1]]
df
VER = 1
SEED = 42
seed_everything(SEED)
 lgb_params['seed'] = SEED
N_CORES = psutil.cpu_count()
TARGET = 'sales'
START_TRAIN = 0
END_TRAIN = 1913
P_HORIZON = 28
USE_AUX = True
remove_features = ['id','state_id','store_id',
'date','wm_yr_wk','d',TARGET]
mean_features = ['enc_cat_id_mean','enc_cat_id_std',
'enc_dept_id_mean','enc_dept_id_std',
'enc_item_id_mean','enc_item_id_std']
ORIGINAL = '.. /input/m5-forecasting-accuracy/'
BASE = '.. /input/m5-simple-fe/grid_part_1.pkl'
PRICE = '.. /input/m5-simple-fe/grid_part_2.pkl'
CALENDAR = '.. /input/m5-simple-fe/grid_part_3.pkl'
LAGS = '.. /input/m5-lags-features/lags_df_28.pkl'
MEAN_ENC = '.. /input/m5-custom-features/mean_encoding_df.pkl'
AUX_MODELS = '.. /input/m5-aux-models/'
STORES_IDS = pd.read_csv(ORIGINAL+'sales_train_validation.csv')['store_id']
STORES_IDS = list(STORES_IDS.unique())
 SHIFT_DAY = 28
N_LAGS = 15
LAGS_SPLIT = [col for col in range(SHIFT_DAY,SHIFT_DAY+N_LAGS)]
ROLS_SPLIT = []
for i in [1,7,14]:
for j in [7,14,30,60]:
ROLS_SPLIT.append([i,j] )<define_variables>
modifiedDF = df.diff(periods=1)
 modifiedDF.dropna(inplace=True)
 modifiedDF.head()
for store_id in STORES_IDS:
print('Train', store_id)
 grid_df, features_columns = get_data_by_store(store_id)
 train_mask = grid_df['d']<=END_TRAIN
valid_mask = train_mask&(grid_df['d']>(END_TRAIN-P_HORIZON))
preds_mask = grid_df['d']>(END_TRAIN-100)
 train_data = lgb.Dataset(grid_df[train_mask][features_columns],
label=grid_df[train_mask][TARGET])
 train_data.save_binary('train_data.bin')
 train_data = lgb.Dataset('train_data.bin')
 valid_data = lgb.Dataset(grid_df[valid_mask][features_columns],
label=grid_df[valid_mask][TARGET])
 grid_df = grid_df[preds_mask].reset_index(drop=True)
 keep_cols = [col for col in list(grid_df)if '_tmp_' not in col]
grid_df = grid_df[keep_cols]
grid_df.to_pickle('test_'+store_id+'.pkl')
 del grid_df
seed_everything(SEED)
 estimator = lgb.train(lgb_params,
train_data,
valid_sets = [valid_data],
verbose_eval = 100, 
)
 model_name = 'lgb_model_'+store_id+'_v'+str(VER)+'.bin'
pickle.dump(estimator, open(model_name, 'wb'))
!rm train_data.bin
del train_data, valid_data, estimator
gc.collect()
MODEL_FEATURES = features_columns<define_variables>
model = Prophet()
model.fit(modifiedDF.reset_index() \ 
.rename(columns={'time':'ds',
'feature':'y'}))
all_preds = pd.DataFrame()
base_test = get_base_test()
main_time = time.time()
for PREDICT_DAY in range(1,29):
print('Predict | Day:', PREDICT_DAY)
 start_time = time.time()
grid_df = base_test.copy()
grid_df = pd.concat([grid_df, df_parallelize_run(make_lag_roll, ROLS_SPLIT)], axis=1)
 for store_id in STORES_IDS:
model_path = 'lgb_model_'+store_id+'_v'+str(VER)+'.bin'
if USE_AUX:
model_path = AUX_MODELS + model_path
estimator = pickle.load(open(model_path, 'rb'))
day_mask = base_test['d']==(END_TRAIN+PREDICT_DAY)
 store_mask = base_test['store_id']==store_id
mask =(day_mask)&(store_mask)
 base_test[TARGET][mask] = estimator.predict(grid_df[mask][MODEL_FEATURES],num_iteration=1400)
 temp_df = base_test[day_mask][['id',TARGET]]
temp_df.columns = ['id','F'+str(PREDICT_DAY)]
if 'id' in list(all_preds):
all_preds = all_preds.merge(temp_df, on=['id'], how='left')
 else:
all_preds = temp_df.copy()
print('
' %0.2f min total |' %(( time.time() - main_time)/ 60),
' %0.2f day sales |' %(temp_df['F'+str(PREDICT_DAY)].sum()))
del temp_df
all_preds = all_preds.reset_index(drop=True)
 all_preds<save_to_csv>
train_data=train_data.drop(index = 79 )
submission = pd.read_csv(ORIGINAL+'sample_submission.csv')[['id']]
submission = submission.merge(all_preds, on=['id'], how='left' ).fillna(0)
 submission.to_csv('submission_v'+str(VER)+'.csv', index=False )<set_options>
test_fcst = model.predict(df=modifiedDF.reset_index() \ 
.rename(columns={'time':'ds'}))
warnings.filterwarnings('ignore' )<concatenate>
del test_data['time']
def seed_everything(seed=0):
random.seed(seed)
 np.random.seed(seed)
 def df_parallelize_run(func, t_split):
num_cores = np.min([N_CORES,len(t_split)])
 pool = Pool(num_cores)
 df = pd.concat(pool.map(func, t_split), axis=1)
 pool.close()
pool.join()
return df<categorify>
mean_squared_error(y_true=modifiedDF['feature'],
y_pred=test_fcst['yhat'] )
def get_data_by_store(store):
df = pd.concat([pd.read_pickle(BASE),
pd.read_pickle(PRICE ).iloc[:,2:],
pd.read_pickle(CALENDAR ).iloc[:,2:]],
axis=1)
 df = df[df['store_id']==store]
df2 = pd.read_pickle(MEAN_ENC)[mean_features]
df2 = df2[df2.index.isin(df.index)]
df3 = pd.read_pickle(LAGS ).iloc[:,3:]
df3 = df3[df3.index.isin(df.index)]
df = pd.concat([df, df2], axis=1)
 del df2
df = pd.concat([df, df3], axis=1)
 del df3
features = [col for col in list(df)if col not in remove_features]
df = df[['id','d',TARGET]+features]
df = df[df['d']>=START_TRAIN].reset_index(drop=True)
 return df, features
def get_base_test() :
base_test = pd.DataFrame()
for store_id in STORES_IDS:
temp_df = pd.read_pickle('test_'+store_id+'.pkl')
 temp_df['store_id'] = store_id
base_test = pd.concat([base_test, temp_df] ).reset_index(drop=True)
 return base_test
def make_lag(LAG_DAY):
lag_df = base_test[['id','d',TARGET]]
col_name = 'sales_lag_'+str(LAG_DAY)
 lag_df[col_name] = lag_df.groupby(['id'])[TARGET].transform(lambda x: x.shift(LAG_DAY)).astype(np.float16)
 return lag_df[[col_name]]
def make_lag_roll(LAG_DAY):
shift_day = LAG_DAY[0]
roll_wind = LAG_DAY[1]
lag_df = base_test[['id','d',TARGET]]
col_name = 'rolling_mean_tmp_'+str(shift_day)+'_'+str(roll_wind)
 lag_df[col_name] = lag_df.groupby(['id'])[TARGET].transform(lambda x: x.shift(shift_day ).rolling(roll_wind ).mean())
 return lag_df[[col_name]]<init_hyperparams>
mean_absolute_error(y_true=modifiedDF['feature'],
y_pred=test_fcst['yhat'] )
lgb_params = {
'boosting_type': 'gbdt',
'objective': 'tweedie',
'tweedie_variance_power': 1.1,
'metric': 'rmse',
'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,
'boost_from_average': False,
'verbose': -1,
} 
<init_hyperparams>
def mean_absolute_percentage_error(y_true, y_pred):
y_true, y_pred = np.array(y_true), np.array(y_pred)
 return np.mean(np.abs(( y_true - y_pred)/ y_true)) * 100
VER = 2
SEED = 42
seed_everything(SEED)
 lgb_params['seed'] = SEED
N_CORES = psutil.cpu_count()
TARGET = 'sales'
START_TRAIN = 0
END_TRAIN = 1913
P_HORIZON = 28
USE_AUX = True
remove_features = ['id','state_id','store_id',
'date','wm_yr_wk','d',TARGET]
mean_features = ['enc_cat_id_mean','enc_cat_id_std',
'enc_dept_id_mean','enc_dept_id_std',
'enc_item_id_mean','enc_item_id_std']
ORIGINAL = '.. /input/m5-forecasting-accuracy/'
BASE = '.. /input/featureextraction/grid_part_1.pkl'
PRICE = '.. /input/featureextraction/grid_part_2.pkl'
CALENDAR = '.. /input/featureextraction/grid_part_3.pkl'
LAGS = '.. /input/lag-rollingfeature/lags_df_28.pkl'
MEAN_ENC = '.. /input/other-features/mean_encoding_df.pkl'
AUX_MODELS = '.. /input/m5modelwithestimator1300/'
STORES_IDS = pd.read_csv(ORIGINAL+'sales_train_validation.csv')['store_id']
STORES_IDS = list(STORES_IDS.unique())
 SHIFT_DAY = 28
N_LAGS = 15
LAGS_SPLIT = [col for col in range(SHIFT_DAY,SHIFT_DAY+N_LAGS)]
ROLS_SPLIT = []
for i in [1,7,14]:
for j in [7,14,30,60]:
ROLS_SPLIT.append([i,j] )<set_options>
mean_absolute_percentage_error(y_true=modifiedDF['feature'],
y_pred=test_fcst['yhat'] )
gc.collect()<set_options>
y_true = np.random.randn(100)
 y_pred = y_true * 3.5
print(mean_absolute_percentage_error(y_true, y_pred))
if USE_AUX:
lgb_params['n_estimators'] = 2 
<define_variables>
print('rmse:', np.sqrt(mean_squared_error(y_true, y_pred)) )
for store_id in STORES_IDS:
print('Train', store_id)
 grid_df, features_columns = get_data_by_store(store_id)
 train_mask = grid_df['d']<=END_TRAIN
valid_mask = train_mask&(grid_df['d']>(END_TRAIN-P_HORIZON))
preds_mask = grid_df['d']>(END_TRAIN-100)
 train_data = lgb.Dataset(grid_df[train_mask][features_columns],
label=grid_df[train_mask][TARGET])
 train_data.save_binary('train_data.bin')
 train_data = lgb.Dataset('train_data.bin')
 valid_data = lgb.Dataset(grid_df[valid_mask][features_columns],
label=grid_df[valid_mask][TARGET])
 grid_df = grid_df[preds_mask].reset_index(drop=True)
 keep_cols = [col for col in list(grid_df)if '_tmp_' not in col]
grid_df = grid_df[keep_cols]
grid_df.to_pickle('test_'+store_id+'.pkl')
 del grid_df
seed_everything(SEED)
 estimator = lgb.train(lgb_params,
train_data,
valid_sets = [valid_data],
verbose_eval = 100, 
)
 model_name = 'lgb_model_'+store_id+'_v'+str(VER)+'.bin'
pickle.dump(estimator, open(model_name, 'wb'))
!rm train_data.bin
del train_data, valid_data, estimator
gc.collect()
MODEL_FEATURES = features_columns<define_variables>
test_data["feature"]=data
test_data.to_csv("submission.csv", index=None )