def load(self, params: Iterable[Tuple[NBeatsParams, str]]): """ params: List((NBeatsParams, weight_path)) """ for p, d in params: mdl = NBeatsTF(p) if mdl.backcast_length > self.backcast_length: self.backcast_length = mdl.backcast_length mdl.load(d) self.sub_models.append(mdl) assert self.backcast_length > 0, 'Backast length not determined'
def create_components( self, submodel_params: Iterable[NBeatsParams]) -> keras.Model: """ Create ensemble components (submodels and mixer) submodel_params: Sequence of sub-model params """ # 1 - create sub-models self.backcast_length = -1 for param in submodel_params: mdl = NBeatsTF(param) if mdl.backcast_length > self.backcast_length: self.backcast_length = mdl.backcast_length self.sub_models[mdl.name] = mdl if self.submodel_names is None: self.submodel_names = sorted(self.sub_models.keys()) else: # Are these models what we were expecting ? assert self.submodel_names == sorted(self.sub_models.keys()) # 2 - create mixer model. backast length the largest backast of submodels self.mixer = Mixer(self.backcast_length, len(self.sub_models), self.hidden_layer_units, method=self.weighted_aggregation_method) return self
def train(config: dict, save_model: bool): name = '{}_{}H_{}'.format(config['model_type'], config['h_mult'], config['loss']) results_dir = mk_clear_dir(get_results_dir(config['load_subset']), False) model_dir = mk_clear_dir(get_model_dir(results_dir, name), False) m4 = M4Dataset(sources=M4Sources()).update_param(**config).read_source() config.update({ 'backcast_length': m4.H[Subset(config['load_subset'])] * m4.h_mult, 'forecast_length': m4.H[Subset(config['load_subset'])], 'name': name }) interpretable_mod(config) trainparms = TrainParams().update_param(**config) netparams = NBeatsParams().update_param(**config) train_data_fn = partial(m4.dataset, trainparms.epoch_sample_size, lh=config['lh']) model = NBeatsTF.create_model(netparams, trainparms) model_file_name = os.path.join(model_dir, f'model.mdl') model.train(train_data_fn, trainparms.epochs, trainparms.batch_size, save_model, model_file_name) with open(os.path.join(model_dir, 'config.yaml'), 'w') as f: yaml.dump(config, f)
def train(config: dict, save_model: bool, delete_existing: bool = False) -> tf.keras.models.Model: results_dir = mk_clear_dir(get_results_dir(config), delete_existing) model_dir = mk_clear_dir(get_model_dir(results_dir), delete_existing) m4 = M4Dataset(sources=M4Sources()).update_param(**config).read_source(config['test']) # Update backast and forecast lengths config.update({'backcast_length': m4.H[Subset(config['load_subset'])] * m4.h_mult, 'forecast_length': m4.H[Subset(config['load_subset'])]}) # For interpretable model, set seasonality theta dim to H if config['model_type'] == 'interpretable': th_dim = eval(config['thetas_dim']) assert eval(config['stack_types']) == (BlockType.TREND_BLOCK, BlockType.SEASONALITY_BLOCK) config['thetas_dim'] = str((th_dim[0], config['forecast_length'])) trainparms = TrainParams().update_param(**config) netparams = NBeatsParams().update_param(**config) train_data_fn = partial(m4.dataset, trainparms.epoch_sample_size, lh=config['lh']) model = NBeatsTF.create_model(netparams, trainparms) model_file_name = os.path.join(model_dir, f'model.mdl') model.train(train_data_fn, trainparms.epochs, trainparms.batch_size, save_model, model_file_name) with open(os.path.join(results_dir, 'config.yaml'), 'w') as f: yaml.dump(config, f) return model
def train(config: dict, save_model: bool, delete_existing: bool = False) -> tf.keras.models.Model: results_dir = mk_clear_dir(get_results_dir(config), delete_existing) model_dir = mk_clear_dir(get_model_dir(results_dir), delete_existing) m4 = M4Dataset(sources=M4SourcesLite()).update_param(**config).read_source(config['test']) # Update backast and forecast lengths config.update({'backcast_length': m4.H[Subset(config['load_subset'])] * m4.h_mult, 'forecast_length': m4.H[Subset(config['load_subset'])]}) trainparms = TrainParams().update_param(**config) netparams = NBeatsParams().update_param(**config) train_data_fn = partial(m4.dataset, trainparms.epoch_sample_size, lh=config['lh']) model = NBeatsTF.create_model(netparams, trainparms) model_file_name = os.path.join(model_dir, f'model.mdl') model.train(train_data_fn, trainparms.epochs, trainparms.batch_size, save_model, model_file_name) with open(os.path.join(results_dir, 'config.yaml'), 'w') as f: yaml.dump(config, f) return model
def test(config: dict, gen_plots: bool = False): results_dir = get_results_dir(config) plot_dir = mk_clear_dir(get_plot_dir(results_dir), True) if gen_plots else None model_dir = get_model_dir(results_dir) model_file_name = os.path.join(model_dir, f'model.mdl') m4 = M4Dataset(sources=M4SourcesLite()).update_param(**config).read_source(True) model = NBeatsTF.create_model(NBeatsParams().update_param(**config), TrainParams().update_param(**config)) model.load(model_file_name) test_dset = m4.test_dataset() x, y, w = next(test_dset.batch(len(test_dset)).as_numpy_iterator()) stack_coll = defaultdict(lambda: 0) yhat = model.call(x, False, stack_out=stack_coll).numpy() if gen_plots: samples2print = list(range(8)) try: if config['model_type'] == 'generic': labels = ['Stack1-Generic', 'Stack2-Generic'] elif config['model_type'] == 'interpretable': labels = ['Stack1-Interp', 'Stack2-Interp'] else: raise Exception() plot_stack(y, yhat, dict(stack_coll), samples2print, labels=labels, block_plot_cnt=2, plot_dir=plot_dir, show=False) plot_past_future(x[..., 0], yhat[..., 0], y[..., 0], plot_dir, n=samples2print, show=False) except: pass test_result = 'test smape: {:.3f}'.format(smape_simple(y, yhat, w)) print(test_result) with open(os.path.join(results_dir, 'results.txt'), 'w') as f: f.write(test_result)