def evaluate_basin(model: nn.Module, loader: DataLoader) -> Tuple[np.ndarray, np.ndarray]: """Evaluate model on a single basin Parameters ---------- model : nn.Module The PyTorch model to train loader : DataLoader PyTorch DataLoader containing the basin data in batches. Returns ------- preds : np.ndarray Array containing the (rescaled) network prediction for the entire data period obs : np.ndarray Array containing the observed discharge for the entire data period """ model.eval() preds, obs = None, None with torch.no_grad(): for data in loader: if len(data) == 2: x, y = data x, y = x.to(DEVICE), y.to(DEVICE) p = model(x)[0] elif len(data) == 3: x_d, x_s, y = data x_d, x_s, y = x_d.to(DEVICE), x_s.to(DEVICE), y.to(DEVICE) p = model(x_d, x_s[:, 0, :])[0] if preds is None: preds = p.detach().cpu() obs = y.detach().cpu() else: preds = torch.cat((preds, p.detach().cpu()), 0) obs = torch.cat((obs, y.detach().cpu()), 0) preds = rescale_features(preds.numpy(), variable='output') obs = obs.numpy() # set discharges < 0 to zero preds[preds < 0] = 0 return preds, obs
def eval_with_added_noise(model: torch.nn.Module, loader: DataLoader, noise: torch.Tensor) -> float: """Evaluate model on a single basin with added noise Parameters ---------- model : nn.Module The PyTorch model to train loader : DataLoader PyTorch DataLoader containing the basin data in batches. noise : torch.Tensor Tensor containing the noise for this evaluation run. Returns ------- float Nash-Sutcliff-Efficiency of the simulations with added noise. """ model.eval() preds, obs = None, None with torch.no_grad(): for x_d, x_s, y in loader: x_d, x_s, y = x_d.to(DEVICE), x_s.to(DEVICE), y.to(DEVICE) batch_noise = noise.repeat(*x_s.size()[:2], 1) x_s = x_s.add(batch_noise) y_hat = model(x_d, x_s[:, 0, :])[0] if preds is None: preds = y_hat.detach().cpu() obs = y.detach().cpu() else: preds = torch.cat((preds, y_hat.detach().cpu()), 0) obs = torch.cat((obs, y.detach().cpu()), 0) obs = obs.numpy() preds = rescale_features(preds.numpy(), variable='output') # set discharges < 0 to zero preds[preds < 0] = 0 nse = calc_nse(obs[obs >= 0], preds[obs >= 0]) return nse
def eval_with_added_noise(model: xgb.XGBRegressor, ds_test: CamelsTXT, noise: torch.Tensor) -> float: """Evaluate model on a single basin with added noise Parameters ---------- model : xgb.XGBRegressor The XGBoost model to evaluate ds_test : CamelsTXT Dataset containing the basin data. noise : torch.Tensor Tensor containing the noise for this evaluation run. Returns ------- float Nash-Sutcliffe-Efficiency of the simulations with added noise. """ preds, obs = None, None x = ds_test.x.reshape(len(ds_test.x), -1).numpy() obs = ds_test.y.numpy() attributes = ds_test.attributes.repeat(len(x), 1).clone() batch_noise = noise.repeat(len(attributes), 1) attributes = attributes.add(batch_noise) x = np.concatenate([x, attributes.numpy()], axis=1) preds = model.predict(x) preds = rescale_features(preds, variable='output') # set discharges < 0 to zero preds[preds < 0] = 0 nse = calc_nse(obs[obs >= 0], preds[obs.reshape(-1) >= 0]) return nse
def evaluate_basin(model: xgb.XGBRegressor, ds_test: CamelsTXT, no_static: bool) -> Tuple[np.ndarray, np.ndarray]: """Evaluate model on a single basin Parameters ---------- model : xgb.XGBRegressor The XGBoost model to evaluate ds_test : CamelsTXT CAMELS dataset containing the basin data no_static: bool If True, will not include static attributes as input features Returns ------- preds : np.ndarray Array containing the (rescaled) prediction for the entire data period obs : np.ndarray Array containing the observed discharge for the entire data period """ preds, obs = None, None x = ds_test.x.reshape(len(ds_test.x), -1).numpy() obs = ds_test.y.numpy() if not no_static: x = np.concatenate([x, ds_test.attributes.repeat(len(x), 1).numpy()], axis=1) preds = model.predict(x) preds = rescale_features(preds, variable='output') # set discharges < 0 to zero preds[preds < 0] = 0 return preds, obs