def only_continuous_normalizer(feats, min_value=None, max_value=None): assert type(min_value) == type(max_value) and type(min_value) in ( int, float, list, np.ndarray, type(None), ) if type(min_value) in [int, float, type(None)]: min_value = [min_value] * len(feats) max_value = [max_value] * len(feats) normalization = collections.OrderedDict([( feats[i], NormalizationParameters( feature_type="CONTINUOUS", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value[i], max_value=max_value[i], ), ) for i in range(len(feats))]) return normalization
def only_continuous_normalizer_helper(feats, feature_type, min_value=None, max_value=None): assert feature_type in ( "CONTINUOUS", "CONTINUOUS_ACTION", ), f"invalid feature type: {feature_type}." assert type(min_value) == type(max_value) and type(min_value) in ( int, float, list, np.ndarray, type(None), ), f"invalid {type(min_value)}, {type(max_value)}" if type(min_value) in [int, float, type(None)]: min_value = [min_value] * len(feats) max_value = [max_value] * len(feats) normalization = collections.OrderedDict([( feats[i], NormalizationParameters( feature_type=feature_type, boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=float(min_value[i]) if min_value[i] is not None else None, max_value=float(max_value[i]) if max_value[i] is not None else None, ), ) for i in range(len(feats))]) return normalization
def test_normalize_dense_matrix_enum(self): normalization_parameters = { 1: NormalizationParameters( identify_types.ENUM, None, None, None, None, [12, 4, 2], None, None, None, ), 2: NormalizationParameters(identify_types.CONTINUOUS, None, 0, 0, 1, None, None, None, None), 3: NormalizationParameters(identify_types.ENUM, None, None, None, None, [15, 3], None, None, None), } preprocessor = Preprocessor(normalization_parameters, False) inputs = np.zeros([4, 3], dtype=np.float32) feature_ids = [2, 1, 3] # Sorted according to feature type inputs[:, feature_ids.index(1)] = [12, 4, 2, 2] inputs[:, feature_ids.index(2)] = [1.0, 2.0, 3.0, 3.0] inputs[:, feature_ids.index(3)] = [ 15, 3, 15, normalization.MISSING_VALUE ] inputs = torch.from_numpy(inputs) normalized_feature_matrix = preprocessor(inputs, (inputs != MISSING_VALUE)) np.testing.assert_allclose( np.array([ [1.0, 1, 0, 0, 1, 0], [2.0, 0, 1, 0, 0, 1], [3.0, 0, 0, 1, 1, 0], [3.0, 0, 0, 1, 0, 0], # Missing values should go to all 0 ]), normalized_feature_matrix, )
def test_do_not_preprocess(self): normalization_parameters = { i: NormalizationParameters(feature_type=DO_NOT_PREPROCESS) for i in range(1, 5) } preprocessor = Preprocessor(normalization_parameters, use_gpu=False) postprocessor = Postprocessor(normalization_parameters, use_gpu=False) x = torch.randn(3, 4) presence = torch.ones_like(x, dtype=torch.uint8) y = postprocessor(preprocessor(x, presence)) npt.assert_allclose(x, y)
def test_continuous_action(self): normalization_parameters = { i: NormalizationParameters(feature_type=CONTINUOUS_ACTION, min_value=-5.0 * i, max_value=10.0 * i) for i in range(1, 5) } preprocessor = Preprocessor(normalization_parameters, use_gpu=False) postprocessor = Postprocessor(normalization_parameters, use_gpu=False) x = torch.rand(3, 4) * torch.tensor([15, 30, 45, 60]) + torch.tensor( [-5, -10, -15, -20]) presence = torch.ones_like(x, dtype=torch.uint8) y = postprocessor(preprocessor(x, presence)) npt.assert_allclose(x, y, rtol=1e-4)
def only_continuous_action_normalizer(feats, min_value=None, max_value=None): normalization = collections.OrderedDict([( feats[i], NormalizationParameters( feature_type="CONTINUOUS_ACTION", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value, max_value=max_value, ), ) for i in range(len(feats))]) return normalization
def _test_seq2reward_with_preprocessor(self, plan_short_sequence): state_dim = 4 action_dim = 2 seq_len = 3 model = FakeSeq2RewardNetwork() state_normalization_parameters = { i: NormalizationParameters(feature_type=DO_NOT_PREPROCESS, mean=0.0, stddev=1.0) for i in range(1, state_dim) } state_preprocessor = Preprocessor(state_normalization_parameters, False) if plan_short_sequence: step_prediction_model = FakeStepPredictionNetwork(seq_len) model_with_preprocessor = Seq2RewardPlanShortSeqWithPreprocessor( model, step_prediction_model, state_preprocessor, seq_len, action_dim, ) else: model_with_preprocessor = Seq2RewardWithPreprocessor( model, state_preprocessor, seq_len, action_dim, ) input_prototype = rlt.ServingFeatureData( float_features_with_presence=state_preprocessor.input_prototype(), id_list_features=FAKE_STATE_ID_LIST_FEATURES, id_score_list_features=FAKE_STATE_ID_SCORE_LIST_FEATURES, ) q_values = model_with_preprocessor(input_prototype) if plan_short_sequence: # When planning for 1, 2, and 3 steps ahead, # the expected q values are respectively: # [0, 1], [1, 11], [11, 111] # Weighting the expected q values by predicted step # probabilities [0.33, 0.33, 0.33], we have [4, 41] expected_q_values = torch.tensor([[4.0, 41.0]]) else: expected_q_values = torch.tensor([[11.0, 111.0]]) assert torch.all(expected_q_values == q_values)
def test_quantile_boundary_logic(self): """Test quantile logic when feaure value == quantile boundary.""" input = torch.tensor([[0.0], [80.0], [100.0]]) norm_params = NormalizationParameters( feature_type="QUANTILE", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=[0.0, 80.0, 100.0], min_value=0.0, max_value=100.0, ) preprocessor = Preprocessor({1: norm_params}, False) output = preprocessor._preprocess_QUANTILE(0, input.float(), [norm_params]) expected_output = torch.tensor([[0.0], [0.5], [1.0]]) self.assertTrue(np.all(np.isclose(output, expected_output)))
def _cont_action_norm(): return NormalizationParameters(feature_type=CONTINUOUS_ACTION, min_value=-3.0, max_value=3.0)
def _cont_norm(): return NormalizationParameters(feature_type=CONTINUOUS, mean=0.0, stddev=1.0)
def default_normalizer(feats, min_value=None, max_value=None): normalization_types = [ NormalizationParameters( feature_type="BINARY", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value, max_value=max_value, ), NormalizationParameters( feature_type="PROBABILITY", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value, max_value=max_value, ), NormalizationParameters( feature_type="CONTINUOUS", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value, max_value=max_value, ), NormalizationParameters( feature_type="BOXCOX", boxcox_lambda=1, boxcox_shift=1, mean=0, stddev=1, possible_values=None, quantiles=None, min_value=min_value, max_value=max_value, ), NormalizationParameters( feature_type="QUANTILE", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=None, quantiles=[0, 1], min_value=min_value, max_value=max_value, ), NormalizationParameters( feature_type="ENUM", boxcox_lambda=None, boxcox_shift=None, mean=0, stddev=1, possible_values=[0, 1], quantiles=None, min_value=min_value, max_value=max_value, ), ] normalization = collections.OrderedDict([ (feats[i], normalization_types[i % len(normalization_types)]) for i in range(len(feats)) ]) return normalization
def test_seq2slate_scriptable(self): state_dim = 2 candidate_dim = 3 num_stacked_layers = 2 num_heads = 2 dim_model = 128 dim_feedforward = 128 candidate_size = 8 slate_size = 8 output_arch = Seq2SlateOutputArch.AUTOREGRESSIVE temperature = 1.0 greedy_serving = True # test the raw Seq2Slate model is script-able seq2slate = Seq2SlateTransformerModel( state_dim=state_dim, candidate_dim=candidate_dim, num_stacked_layers=num_stacked_layers, num_heads=num_heads, dim_model=dim_model, dim_feedforward=dim_feedforward, max_src_seq_len=candidate_size, max_tgt_seq_len=slate_size, output_arch=output_arch, temperature=temperature, ) seq2slate_scripted = torch.jit.script(seq2slate) seq2slate_net = Seq2SlateTransformerNet( state_dim=state_dim, candidate_dim=candidate_dim, num_stacked_layers=num_stacked_layers, num_heads=num_heads, dim_model=dim_model, dim_feedforward=dim_feedforward, max_src_seq_len=candidate_size, max_tgt_seq_len=slate_size, output_arch=output_arch, temperature=temperature, ) state_normalization_data = NormalizationData( dense_normalization_parameters={ 0: NormalizationParameters(feature_type=DO_NOT_PREPROCESS), 1: NormalizationParameters(feature_type=DO_NOT_PREPROCESS), }) candidate_normalization_data = NormalizationData( dense_normalization_parameters={ 5: NormalizationParameters(feature_type=DO_NOT_PREPROCESS), 6: NormalizationParameters(feature_type=DO_NOT_PREPROCESS), 7: NormalizationParameters(feature_type=DO_NOT_PREPROCESS), }) state_preprocessor = Preprocessor( state_normalization_data.dense_normalization_parameters, False) candidate_preprocessor = Preprocessor( candidate_normalization_data.dense_normalization_parameters, False) # test trace seq2slate_net.seq2slate = seq2slate seq2slate_with_preprocessor = Seq2SlateWithPreprocessor( seq2slate_net.eval(), state_preprocessor, candidate_preprocessor, greedy_serving, ) seq2slate_with_preprocessor( *seq2slate_with_preprocessor.input_prototype()) torch.jit.trace(seq2slate_with_preprocessor, seq2slate_with_preprocessor.input_prototype()) # test mix of script + trace seq2slate_net.seq2slate = seq2slate_scripted seq2slate_with_preprocessor = Seq2SlateWithPreprocessor( seq2slate_net.eval(), state_preprocessor, candidate_preprocessor, greedy_serving, ) seq2slate_with_preprocessor( *seq2slate_with_preprocessor.input_prototype()) torch.jit.trace(seq2slate_with_preprocessor, seq2slate_with_preprocessor.input_prototype())