def test_long_eval(self): model = ar_model.ARModel(periodicities=2, num_features=1, num_time_buckets=10, input_window_size=2, output_window_size=1) raw_features = { TrainEvalFeatures.TIMES: [[1, 3, 5, 7, 11]], TrainEvalFeatures.VALUES: [[[1.], [2.], [3.], [4.], [5.]]] } model.initialize_graph() with tf.compat.v1.variable_scope("armodel"): raw_evaluation = model.define_loss( raw_features, mode=estimator_lib.ModeKeys.EVAL) with tf.compat.v1.Session() as sess: tf.compat.v1.initializers.global_variables().run() raw_evaluation_evaled = sess.run(raw_evaluation) self.assertAllEqual([[5, 7, 11]], raw_evaluation_evaled.prediction_times) for feature_name in raw_evaluation.predictions: self.assertAllEqual( [1, 3, 1 ], # batch, window, num_features. The window size has 2 # cut off for the first input_window. raw_evaluation_evaled.predictions[feature_name].shape)
def test_long_eval_discard_indivisible(self): model = ar_model.ARModel(periodicities=2, num_features=1, num_time_buckets=10, input_window_size=2, output_window_size=2) raw_features = { TrainEvalFeatures.TIMES: [[1, 3, 5, 7, 11]], TrainEvalFeatures.VALUES: [[[1.], [2.], [3.], [4.], [5.]]] } model.initialize_graph() raw_evaluation = model.define_loss(raw_features, mode=estimator_lib.ModeKeys.EVAL) with tf.compat.v1.Session() as sess: tf.compat.v1.initializers.global_variables().run() raw_evaluation_evaled = sess.run(raw_evaluation) self.assertAllEqual([[7, 11]], raw_evaluation_evaled.prediction_times) for feature_name in raw_evaluation.predictions: self.assertAllEqual( [1, 2, 1 ], # batch, window, num_features. The window has two cut # off for the first input window and one discarded so # that the remainder is divisible into output windows. raw_evaluation_evaled.predictions[feature_name].shape)
def test_long_eval_discard_indivisible(self): g = ops.Graph() with g.as_default(): model = ar_model.ARModel(periodicities=2, num_features=1, num_time_buckets=10, input_window_size=2, output_window_size=2) raw_features = { TrainEvalFeatures.TIMES: [[1, 3, 5, 7, 11]], TrainEvalFeatures.VALUES: [[[1.], [2.], [3.], [4.], [5.]]] } model.initialize_graph() raw_evaluation = model.define_loss( raw_features, mode=estimator_lib.ModeKeys.EVAL) with session.Session() as sess: coordinator = coordinator_lib.Coordinator() queue_runner_impl.start_queue_runners(sess, coord=coordinator) variables.global_variables_initializer().run() raw_evaluation_evaled = sess.run(raw_evaluation) self.assertAllEqual([[7, 11]], raw_evaluation_evaled.prediction_times) for feature_name in raw_evaluation.predictions: self.assertAllEqual( [ 1, 2, 1 ], # batch, window, num_features. The window has two cut # off for the first input window and one discarded so # that the remainder is divisible into output windows. raw_evaluation_evaled.predictions[feature_name].shape) coordinator.request_stop() coordinator.join()
def test_long_eval(self): g = ops.Graph() with g.as_default(): model = ar_model.ARModel(periodicities=2, num_features=1, num_time_buckets=10, input_window_size=2, output_window_size=1) raw_features = { TrainEvalFeatures.TIMES: [[1, 3, 5, 7, 11]], TrainEvalFeatures.VALUES: [[[1.], [2.], [3.], [4.], [5.]]] } chunked_features, _ = test_utils.AllWindowInputFn( time_series_reader=input_pipeline.NumpyReader(raw_features), window_size=3)() model.initialize_graph() with variable_scope.variable_scope("armodel") as scope: raw_evaluation = model.define_loss( raw_features, mode=estimator_lib.ModeKeys.EVAL) with variable_scope.variable_scope(scope, reuse=True): chunked_evaluation = model.define_loss( chunked_features, mode=estimator_lib.ModeKeys.EVAL) with session.Session() as sess: coordinator = coordinator_lib.Coordinator() queue_runner_impl.start_queue_runners(sess, coord=coordinator) variables.global_variables_initializer().run() raw_evaluation_evaled, chunked_evaluation_evaled = sess.run( [raw_evaluation, chunked_evaluation]) self.assertAllClose(chunked_evaluation_evaled.loss, raw_evaluation_evaled.loss) last_chunk_evaluation_state = [ state[-1, None] for state in chunked_evaluation_evaled.end_state ] for last_chunk_state_member, raw_state_member in zip( last_chunk_evaluation_state, raw_evaluation_evaled.end_state): self.assertAllClose(last_chunk_state_member, raw_state_member) self.assertAllEqual([[5, 7, 11]], raw_evaluation_evaled.prediction_times) for feature_name in raw_evaluation.predictions: self.assertAllEqual( [ 1, 3, 1 ], # batch, window, num_features. The window size has 2 # cut off for the first input_window. raw_evaluation_evaled.predictions[feature_name].shape) self.assertAllClose( np.reshape( chunked_evaluation_evaled. predictions[feature_name], [-1]), np.reshape( raw_evaluation_evaled.predictions[feature_name], [-1])) coordinator.request_stop() coordinator.join()
def _estimator_fn(model_dir, exogenous_feature_columns): return estimators.TimeSeriesRegressor(model=ar_model.ARModel( periodicities=10, input_window_size=10, output_window_size=6, num_features=1, exogenous_feature_columns=exogenous_feature_columns, prediction_model_factory=functools.partial( ar_model.LSTMPredictionModel, num_units=10)), config=_SeedRunConfig(), model_dir=model_dir)
def test_predictions_direct_lstm(self): model = ar_model.ARModel(periodicities=2, num_features=1, num_time_buckets=10, input_window_size=2, output_window_size=2, prediction_model_factory=functools.partial( ar_model.LSTMPredictionModel, num_units=16)) with tf.compat.v1.Session(): predicted_values = model.predict({ PredictionFeatures.TIMES: [[4, 6, 10]], PredictionFeatures.STATE_TUPLE: ([[1, 2]], [[[1.], [2.]]], [[[], []]]) }) tf.compat.v1.initializers.global_variables().run() self.assertAllEqual(predicted_values["mean"].eval().shape, [1, 3, 1])
def __init__(self, periodicities, input_window_size, output_window_size, model_dir=None, num_features=1, extra_feature_columns=None, num_timesteps=10, loss=ar_model.ARModel.NORMAL_LIKELIHOOD_LOSS, num_units=128, optimizer="Adam", config=None): """Initialize the Estimator. Args: periodicities: periodicities of the input data, in the same units as the time feature (for example 24 if feeding hourly data with a daily periodicity, or 60 * 24 if feeding minute-level data with daily periodicity). Note this can be a single value or a list of values for multiple periodicities. input_window_size: Number of past time steps of data to look at when doing the regression. output_window_size: Number of future time steps to predict. Note that setting this value to > 1 empirically seems to give a better fit. model_dir: Directory to save model parameters, graph and etc. This can also be used to load checkpoints from the directory into a estimator to continue training a previously saved model. num_features: The dimensionality of the time series (default value is one for univariate, more than one for multivariate). extra_feature_columns: A list of `tf.feature_column`s (for example `tf.feature_column.embedding_column`) corresponding to features which provide extra information to the model but are not part of the series to be predicted. num_timesteps: Number of buckets into which to divide (time % periodicity). This value multiplied by the number of periodicities is the number of time features added to the model. loss: Loss function to use for training. Currently supported values are SQUARED_LOSS and NORMAL_LIKELIHOOD_LOSS. Note that for NORMAL_LIKELIHOOD_LOSS, we train the covariance term as well. For SQUARED_LOSS, the evaluation loss is reported based on un-scaled observations and predictions, while the training loss is computed on normalized data. num_units: The size of the hidden state in the encoder and decoder LSTM cells. optimizer: string, `tf.train.Optimizer` object, or callable that defines the optimizer algorithm to use for training. Defaults to the Adam optimizer with a learning rate of 0.01. config: Optional `estimator.RunConfig` object to configure the runtime settings. """ optimizer = optimizers.get_optimizer_instance(optimizer, learning_rate=0.01) model = ar_model.ARModel( periodicities=periodicities, input_window_size=input_window_size, output_window_size=output_window_size, num_features=num_features, exogenous_feature_columns=extra_feature_columns, num_time_buckets=num_timesteps, loss=loss, prediction_model_factory=functools.partial( ar_model.LSTMPredictionModel, num_units=num_units)) state_manager = state_management.FilteringOnlyStateManager() super(LSTMAutoRegressor, self).__init__(model=model, state_manager=state_manager, optimizer=optimizer, model_dir=model_dir, config=config, head_type=ts_head_lib.OneShotPredictionHead)
def test_one_shot_prediction_head_export(self): def _new_temp_dir(): return os.path.join(tf.compat.v1.test.get_temp_dir(), str(ops.uid())) model_dir = _new_temp_dir() categorical_column = tf.feature_column.categorical_column_with_hash_bucket( key="categorical_exogenous_feature", hash_bucket_size=16) exogenous_feature_columns = [ tf.feature_column.numeric_column( "2d_exogenous_feature", shape=(2,)), tf.feature_column.embedding_column( categorical_column=categorical_column, dimension=10)] estimator = ts_estimators.TimeSeriesRegressor( model=ar_model.ARModel( periodicities=10, input_window_size=10, output_window_size=6, num_features=5, exogenous_feature_columns=exogenous_feature_columns, prediction_model_factory=functools.partial( ar_model.LSTMPredictionModel, num_units=10)), head_type=ts_head_lib.OneShotPredictionHead, model_dir=model_dir) def train_input_fn(): num_range = tf.range(16, dtype=tf.dtypes.int64) features = { feature_keys.TrainEvalFeatures.TIMES: tf.compat.v1.expand_dims(num_range, axis=0), feature_keys.TrainEvalFeatures.VALUES: tf.compat.v1.expand_dims( tf.tile(num_range[:, None], [1, 5]), axis=0), "2d_exogenous_feature": tf.ones([1, 16, 2]), "categorical_exogenous_feature": tf.compat.v1.expand_dims( tf.tile(["strkey"], [16])[:, None], axis=0) } return features estimator.train(input_fn=train_input_fn, steps=5) result = estimator.evaluate(input_fn=train_input_fn, steps=1) self.assertIn("average_loss", result) self.assertNotIn(feature_keys.State.STATE_TUPLE, result) input_receiver_fn = estimator.build_raw_serving_input_receiver_fn() export_location = estimator.export_saved_model(_new_temp_dir(), input_receiver_fn) graph = tf.Graph() with graph.as_default(): with tf.compat.v1.Session() as session: signatures = tf.compat.v1.saved_model.load( session, [tf.saved_model.SERVING], export_location) self.assertEqual([feature_keys.SavedModelLabels.PREDICT], list(signatures.signature_def.keys())) predict_signature = signatures.signature_def[ feature_keys.SavedModelLabels.PREDICT] six.assertCountEqual( self, [feature_keys.FilteringFeatures.TIMES, feature_keys.FilteringFeatures.VALUES, "2d_exogenous_feature", "categorical_exogenous_feature"], predict_signature.inputs.keys()) features = { feature_keys.TrainEvalFeatures.TIMES: numpy.tile( numpy.arange(35, dtype=numpy.int64)[None, :], [2, 1]), feature_keys.TrainEvalFeatures.VALUES: numpy.tile(numpy.arange( 20, dtype=numpy.float32)[None, :, None], [2, 1, 5]), "2d_exogenous_feature": numpy.ones([2, 35, 2]), "categorical_exogenous_feature": numpy.tile(numpy.array( ["strkey"] * 35)[None, :, None], [2, 1, 1]) } feeds = { graph.as_graph_element(input_value.name): features[input_key] for input_key, input_value in predict_signature.inputs.items()} fetches = {output_key: graph.as_graph_element(output_value.name) for output_key, output_value in predict_signature.outputs.items()} output = session.run(fetches, feed_dict=feeds) self.assertEqual((2, 15, 5), output["mean"].shape) # Build a parsing input function, then make a tf.Example for it to parse. export_location = estimator.export_saved_model( _new_temp_dir(), estimator.build_one_shot_parsing_serving_input_receiver_fn( filtering_length=20, prediction_length=15)) graph = tf.Graph() with graph.as_default(): with tf.compat.v1.Session() as session: example = example_pb2.Example() times = example.features.feature[feature_keys.TrainEvalFeatures.TIMES] values = example.features.feature[feature_keys.TrainEvalFeatures.VALUES] times.int64_list.value.extend(range(35)) for i in range(20): values.float_list.value.extend( [float(i) * 2. + feature_number for feature_number in range(5)]) real_feature = example.features.feature["2d_exogenous_feature"] categortical_feature = example.features.feature[ "categorical_exogenous_feature"] for i in range(35): real_feature.float_list.value.extend([1, 1]) categortical_feature.bytes_list.value.append(b"strkey") # Serialize the tf.Example for feeding to the Session examples = [example.SerializeToString()] * 2 signatures = tf.compat.v1.saved_model.load( session, [tf.saved_model.SERVING], export_location) predict_signature = signatures.signature_def[ feature_keys.SavedModelLabels.PREDICT] ((_, input_value),) = predict_signature.inputs.items() feeds = {graph.as_graph_element(input_value.name): examples} fetches = {output_key: graph.as_graph_element(output_value.name) for output_key, output_value in predict_signature.outputs.items()} output = session.run(fetches, feed_dict=feeds) self.assertEqual((2, 15, 5), output["mean"].shape)