Skip to content

Commit

Permalink
corrected quantile predictions, probabilistic loss kind passing, adde…
Browse files Browse the repository at this point in the history
…d crps as metric
  • Loading branch information
nepslor committed Dec 18, 2023
1 parent 706fc11 commit a37bd16
Show file tree
Hide file tree
Showing 3 changed files with 18 additions and 14 deletions.
17 changes: 9 additions & 8 deletions pyforecaster/forecasting_models/neural_forecasters.py
Original file line number Diff line number Diff line change
Expand Up @@ -381,16 +381,17 @@ def predict_quantiles(self, inputs, normalize=True, **kwargs):
x = inputs
y_hat = self.predict_batch(self.pars, x)
y_hat = np.array(y_hat)
if self.normalize_target:
if self.normalize_target and normalize:
y_hat[:, :y_hat.shape[1] // 2] = self.target_scaler.inverse_transform(y_hat[:, :y_hat.shape[1] // 2])
y_hat[:, y_hat.shape[1] // 2:] = self.target_scaler.inverse_transform(
(y_hat[:, y_hat.shape[1] // 2:]) ** 0.5)
(y_hat[:, y_hat.shape[1] // 2:]))
y_hat[:, y_hat.shape[1] // 2:] = (y_hat[:, y_hat.shape[1] // 2:])** 0.5
mu_hat = y_hat[:, :y_hat.shape[1]//2]
sigma_hat = y_hat[:, y_hat.shape[1]//2:]

preds = np.expand_dims(mu_hat, -1) * np.ones((1, 1, len(self.q_vect)))
for q in self.q_vect:
preds[:, :, int(q*len(self.q_vect))] += sigma_hat * np.sqrt(2) * erfinv(2*q-1)
for i, q in enumerate(self.q_vect):
preds[:, :, i] += sigma_hat * np.sqrt(2) * erfinv(2*q-1)
return preds

def get_normalized_inputs(self, inputs, target=None):
Expand Down Expand Up @@ -428,7 +429,7 @@ class PartiallyICNN(nn.Module):
probabilistic: bool = False
@nn.compact
def __call__(self, x, y):
u = x
u = x.copy()
z = jnp.zeros(self.features_out) # Initialize z_0 to be the same shape as y
for i in range(self.num_layers):
prediction_layer = i == self.num_layers -1
Expand All @@ -438,7 +439,7 @@ def __call__(self, x, y):
augment_ctrl_inputs=self.augment_ctrl_inputs,
layer_normalization=self.layer_normalization)(y, u, z)
if self.probabilistic:
u = x
u = x.copy()
sigma = jnp.zeros(self.features_out) # Initialize z_0 to be the same shape as y
for i in range(self.num_layers):
prediction_layer = i == self.num_layers - 1
Expand All @@ -448,7 +449,7 @@ def __call__(self, x, y):
rec_activation=self.rec_activation, init_type=self.init_type,
augment_ctrl_inputs=self.augment_ctrl_inputs,
layer_normalization=self.layer_normalization)(y, u, sigma)
return jnp.hstack([z, nn.softplus(sigma) + 1e-8])
return jnp.hstack([z, nn.softplus(sigma) + 1e-4])
return z


Expand Down Expand Up @@ -575,7 +576,7 @@ def __init__(self, learning_rate: float = 0.01, batch_size: int = None, load_pat
self.loss_fn = jitting_wrapper(causal_loss_fn, self.model, causal_matrix=causal_matrix, kind=probabilistic_loss_kind) \
if not self.probabilistic else jitting_wrapper(probabilistic_causal_loss_fn, self.model, causal_matrix=causal_matrix, kind=probabilistic_loss_kind)
else:
self.loss_fn = jitting_wrapper(loss_fn, self.predict_batch) if not self.probabilistic else jitting_wrapper(probabilistic_loss_fn, self.predict_batch)
self.loss_fn = jitting_wrapper(loss_fn, self.predict_batch) if not self.probabilistic else jitting_wrapper(probabilistic_loss_fn, self.predict_batch, kind=probabilistic_loss_kind)

self.train_step = jitting_wrapper(partial(train_step, loss_fn=self.loss_fn), self.optimizer)

Expand Down
11 changes: 7 additions & 4 deletions pyforecaster/metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,14 @@ def reliability(q_hat, t, alphas=None, agg_index=None, get_score=False, **kwargs

def make_scorer(metric):
def scorer(estimator, X, y):
y_hat = estimator.predict(X)
if not isinstance(y_hat, pd.DataFrame):
y_hat = pd.DataFrame(y_hat, index=y.index, columns=y.columns)
if metric in [crps, reliability]:
y_hat = estimator.predict_quantiles(X)
else:
y_hat.columns = y.columns
y_hat = estimator.predict(X)
if not isinstance(y_hat, pd.DataFrame):
y_hat = pd.DataFrame(y_hat, index=y.index, columns=y.columns)
else:
y_hat.columns = y.columns
# default behaviour is to reduce metric over forecasting horizon.
# If just one step ahead is forecasted, metric is reduced on samples
agg_index = np.zeros(len(y)) if len(y.shape)<2 else np.zeros(y.shape[1])
Expand Down
4 changes: 2 additions & 2 deletions tests/test_nns.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ def test_picnn(self):
optimization_vars = x_tr.columns[:100]


m_1 = PICNN(learning_rate=1e-3, batch_size=500, load_path=None, n_hidden_x=200, n_hidden_y=200,
m_1 = PICNN(learning_rate=1e-3, batch_size=500, load_path=None, n_hidden_x=20, n_hidden_y=20,
n_out=y_tr.shape[1], n_layers=3, optimization_vars=optimization_vars,probabilistic=True, probabilistic_loss_kind='crps', rel_tol=-1,
val_ratio=0.2).fit(x_tr, y_tr,n_epochs=1,stats_step=100,savepath_tr_plots=savepath_tr_plots)
val_ratio=0.2).fit(x_tr, y_tr,n_epochs=10,stats_step=50,savepath_tr_plots=savepath_tr_plots)

y_hat_1 = m_1.predict(x_te)
m_1.save('tests/results/ffnn_model.pk')
Expand Down

0 comments on commit a37bd16

Please sign in to comment.