Slackbot
12/18/2023, 7:16 AMJosé Morales
12/18/2023, 4:27 PMlobbie lobbie
12/18/2023, 11:16 PM## Scaling by Item_ID
items = df_required['Item_ID'].unique()
item_scalers_x = {}
item_scalers_y = {}
# Select all numeric columns
ignore_qty = ['Qty']
numeric_cols = df_required_train.select_dtypes(include=['int8','int16','int32','int64','float16','float32','float64']).columns
numeric_cols = [col for col in numeric_cols if col not in ignore_qty]
for item in items:
item_filtered_fit = df_required_train[df_required_train['Item_ID'] == item].copy()
item_filtered_transform = df_required_full[df_required_full['Item_ID'] == item].copy()
scaler = MinMaxScaler()
scaler = scaler.fit(item_filtered_fit[numeric_cols])
item_filtered_transform[numeric_cols] = scaler.transform(item_filtered_transform[numeric_cols])
item_scalers_x[item] = scaler
scaler = MinMaxScaler()
scaler = scaler.fit(item_filtered_fit.loc[:, ['Qty']])
item_filtered_transform.loc[:, ['Qty']] = scaler.transform(item_filtered_transform.loc[:, ['Qty']])
item_scalers_y[item] = scaler
df_required_full.update(item_filtered_transform)
# Save the scalers as pkl files
scaler_feature_position = "Item__Scaler_feature_position.pkl"
scaler_x_file_name = "Item_Scaler_X.pkl"
scaler_y_file_name = "Item_Scaler_y.pkl"
if not os.path.exists(scalers_dir):
print("Path does not exist")
os.makedirs(scalers_dir)
else:
print("Path already exists")
# save scaler x
with open(scalers_dir + "/" + scaler_x_file_name, "wb") as file:
pkl.dump(item_scalers_x, file)
# save scaler y
with open(scalers_dir + "/" + scaler_y_file_name, "wb") as file:
pkl.dump(item_scalers_y, file)
# save the feature positions
with open(scalers_dir + "/" + scaler_feature_position, "wb") as file:
pkl.dump(numeric_cols, file)
Model Training and Predict with Unseen Data
# config for tunning etc. Most parameters taken of by the Auto models.
myconfig = {'input_size': tune.choice([horizon,horizon*2,horizon*3])
,'batch_size': tune.choice([32,64])
,'max_steps': tune.choice([500])
,'learning_rate': tune.loguniform(1e-4, 1e-2)
,'random_seed' : 666 # set a fixed seed for reproducibility but some randomness will exist
,'scaler_type': tune.choice([None]) # data is already scaled.
,'hist_exog_list' : myhist_exog_list
,'futr_exog_list' : myfutr_exog_list}
# model setup
model = [AutoNHITS(h=horizon, config=myconfig, loss=RMSE()
, search_alg=HyperOptSearch(), num_samples=3, cpus=1, verbose=False)]
# Fit the model
nf1 = NeuralForecast(models=model, freq='W-MON')
nf1.fit(df=historic_df)
# do predictions with model on unseen data
pred_df = nf1.predict(futr_df=future_df)
# Save the full data model
model_file_name = "NFC_AutoNHITS" + ".pkl"
if not os.path.exists(models_dir):
os.makedirs(models_dir)
with open(models_dir + "/" + model_file_name, "wb") as file:
pkl.dump(nf1, file)
Load the saved model and predict future rows
## Load saved model & scalers, predict and reverse scaled
# Open the pickle file and load the model
with open('./Models/NFC_AutoNHITS.pkl','rb') as f:
mymodel = pkl.load(f)
# Load scalers from pickle file for reverse scaling
with open('./Models/item_scalers_y.pkl', "rb") as file:
item_scalers_y = pkl.load(file)
# test predict mv
all_predictions = mymodel.predict(df=df_historic, futr_df=df_future)
columns = set(all_predictions.columns) - set(['Item_ID'])
for item in all_predictions['Item_ID'].unique():
# Filter the DataFrame
filtered_df = all_predictions[all_predictions['Item_ID'] == item].copy()
for column in columns:
# Reverse scale the Qty and all the predicitons
filtered_df.loc[filtered_df.index, column] = item_scalers_y[item].inverse_transform(filtered_df[[column]])
# Update the original DataFrame with the modified values
all_predictions.loc[filtered_df.index, column] = filtered_df[column]
José Morales
12/18/2023, 11:33 PMlobbie lobbie
12/18/2023, 11:35 PMJosé Morales
12/18/2023, 11:39 PMlobbie lobbie
12/18/2023, 11:41 PMJosé Morales
12/18/2023, 11:43 PMlobbie lobbie
12/18/2023, 11:45 PMJosé Morales
12/18/2023, 11:50 PMmymodel.models[0].scaler.scaler
should be the identity_scalerlobbie lobbie
12/18/2023, 11:52 PMJosé Morales
12/18/2023, 11:52 PMlobbie lobbie
12/19/2023, 12:26 AMJosé Morales
12/19/2023, 12:29 AMmymodel.models[0].model.scaler.scaler
lobbie lobbie
12/19/2023, 12:50 AM<function neuralforecast.common._scalers.identity_scaler(x, x_shift, x_scale)>
I found under Documentation - Time Series Scaling, there is a parameter local_scaler_type. Do the Auto models use this parameter? What is the default of this parameter? It seems that in addition to scaler type in config, NFC models also have a core scaler. Maybe this is causing my issue as my input data is already scaled and resulted in double scaling?
_Fit the model by instantiating a NeuralForecast
object and using the fit
method. The local_scaler_type
parameter is used to specify the type of scaling to be used. In this case, we will use standard
, which scales the data to have zero mean and unit variance.Other supported scalers are minmax
, robust
, robust-iqr
, minmax
, and boxcox
._Cristian (Nixtla)
12/19/2023, 3:26 PMdf
or futr_df
to keep the domain space constant for the model. So you would remove all the code before "Model Training and Predict with Unseen Data", and simply specify minmax
in the nf class.Cristian (Nixtla)
12/19/2023, 3:34 PMautonhits
to nhits
.
2. Remove future variables.lobbie lobbie
12/19/2023, 10:04 PMlobbie lobbie
12/21/2023, 1:10 AMFarzad E
03/15/2024, 10:31 PMlobbie lobbie
03/15/2024, 11:54 PMFarzad E
03/16/2024, 2:05 AMlobbie lobbie
03/21/2024, 10:27 PMFarzad E
03/21/2024, 11:01 PMlobbie lobbie
03/21/2024, 11:26 PM