def testRandomFourierFeatures(self, batch_size, input_dims, output_dims, bandwidth): def _rff_hypothesis_test(rff_output, X, W, b, scale): """ Runs hypothesis test for Semi Random Features layer. Inputs: rff_output -- output of net after running random fourier features layer X -- input data W -- weight parameter from train_init_net b -- bias parameter from train_init_net scale -- value by which to scale the output vector """ output = workspace.FetchBlob(rff_output) output_ref = scale * np.cos(np.dot(X, np.transpose(W)) + b) npt.assert_allclose(output, output_ref, rtol=1e-3, atol=1e-3) X = np.random.random((batch_size, input_dims)).astype(np.float32) scale = np.sqrt(2.0 / output_dims) input_record = self.new_record( schema.Scalar((np.float32, (input_dims, )))) schema.FeedRecord(input_record, [X]) input_blob = input_record.field_blobs()[0] rff_output = self.model.RandomFourierFeatures(input_record, output_dims, bandwidth) self.model.output_schema = schema.Struct() self.assertEqual(schema.Scalar((np.float32, (output_dims, ))), rff_output) train_init_net, train_net = self.get_training_nets() # Init net assertions init_ops_list = [ OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), ] init_ops = self._test_net(train_init_net, init_ops_list) W = workspace.FetchBlob(self.model.layers[0].w) b = workspace.FetchBlob(self.model.layers[0].b) # Operation specifications fc_spec = OpSpec( "FC", [input_blob, init_ops[0].output[0], init_ops[1].output[0]], None) cosine_spec = OpSpec("Cos", None, None) scale_spec = OpSpec("Scale", None, rff_output.field_blobs(), {'scale': scale}) ops_list = [fc_spec, cosine_spec, scale_spec] # Train net assertions self._test_net(train_net, ops_list) _rff_hypothesis_test(rff_output(), X, W, b, scale) # Eval net assertions eval_net = self.get_eval_net() self._test_net(eval_net, ops_list) _rff_hypothesis_test(rff_output(), X, W, b, scale) # Predict net assertions predict_net = self.get_predict_net() self._test_net(predict_net, ops_list) _rff_hypothesis_test(rff_output(), X, W, b, scale)
def create_net(self): net = core.Net("feature_extractor") init_net = core.Net("feature_extractor_init") missing_scalar = self.create_const(init_net, "MISSING_SCALAR", MISSING_VALUE) input_schema = schema.Struct(( "float_features", schema.Map( keys=core.BlobReference("input/float_features.keys"), values=core.BlobReference("input/float_features.values"), lengths_blob=core.BlobReference( "input/float_features.lengths"), ), )) input_record = net.set_input_record(input_schema) state = self.extract_float_features( net, "state", input_record.float_features, self.sorted_state_features, missing_scalar, ) if self.sorted_action_features: action = self.extract_float_features( net, "action", input_record.float_features, self.sorted_action_features, missing_scalar, ) if self.normalize: C2.set_net_and_init_net(net, init_net) state, _ = PreprocessorNet().normalize_dense_matrix( state, self.sorted_state_features, self.state_normalization_parameters, blobname_prefix="state", split_expensive_feature_groups=True, ) if self.sorted_action_features: action, _ = PreprocessorNet().normalize_dense_matrix( action, self.sorted_action_features, self.action_normalization_parameters, blobname_prefix="action", split_expensive_feature_groups=True, ) C2.set_net_and_init_net(None, None) output_record = schema.Struct(("state", state)) if self.sorted_action_features: output_record += schema.Struct(("action", action)) net.set_output_record(output_record) return FeatureExtractorNet(net, init_net)
def testSemiRandomFeatures(self, batch_size, input_dims, output_dims, s, scale, set_weight_as_global_constant): X = np.random.normal(size=(batch_size, input_dims)).astype(np.float32) input_record = self.new_record(schema.Scalar((np.float32, (input_dims,)))) schema.FeedRecord(input_record, [X]) input_blob = input_record.field_blobs()[0] srf_output = self.model.SemiRandomFeatures( input_record, output_dims, s=s, scale=scale, set_weight_as_global_constant=set_weight_as_global_constant ) self.model.output_schema = schema.Struct() self.assertEqual( schema.Scalar((np.float32, (output_dims, ))), srf_output ) init_ops_list = [ OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), ] train_init_net, train_net = self.get_training_nets() # Need to run to initialize the global constants for layer workspace.RunNetOnce(self.model.create_init_net(name='init_net')) if set_weight_as_global_constant: # If weight params are global constants, they won't be in train_init_net init_ops = self._test_net(train_init_net, init_ops_list[:2]) rand_w = workspace.FetchBlob( self.model.global_constants['semi_random_features_fixed_rand_W'] ) rand_b = workspace.FetchBlob( self.model.global_constants['semi_random_features_fixed_rand_b'] ) # Operation specifications fc_random_spec = OpSpec("FC", [input_blob, None, None], None) fc_learned_spec = OpSpec("FC", [input_blob, init_ops[0].output[0], init_ops[1].output[0]], None) else: init_ops = self._test_net(train_init_net, init_ops_list) rand_w = workspace.FetchBlob(self.model.layers[0].random_w) rand_b = workspace.FetchBlob(self.model.layers[0].random_b) # Operation specifications fc_random_spec = OpSpec("FC", [input_blob, init_ops[0].output[0], init_ops[1].output[0]], None) fc_learned_spec = OpSpec("FC", [input_blob, init_ops[2].output[0], init_ops[3].output[0]], None) gt_spec = OpSpec("GT", None, None) cast_spec = OpSpec("Cast", None, None) relu_spec = OpSpec("Relu", None, None) pow_spec = OpSpec("Pow", None, None, {'exponent': float(s - 1)}) mul_interim_spec = OpSpec("Mul", None, None) mul_spec = OpSpec("Mul", None, srf_output.field_blobs()) if s == 0: ops_list = [ fc_random_spec, fc_learned_spec, gt_spec, cast_spec, mul_spec, ] elif s == 1: ops_list = [ fc_random_spec, fc_learned_spec, relu_spec, mul_spec, ] else: ops_list = [ fc_random_spec, fc_learned_spec, relu_spec, pow_spec, mul_interim_spec, mul_spec, ] # Train net assertions self._test_net(train_net, ops_list) self._semi_random_hypothesis_test(srf_output(), X, rand_w, rand_b, s) # Eval net assertions eval_net = self.get_eval_net() self._test_net(eval_net, ops_list) self._semi_random_hypothesis_test(srf_output(), X, rand_w, rand_b, s) # Predict net assertions predict_net = self.get_predict_net() self._test_net(predict_net, ops_list) self._semi_random_hypothesis_test(srf_output(), X, rand_w, rand_b, s)
def init_adjoint_model_with_schemas(model_name, sig_input_dim, tanh_input_dim, pred_dim, train_target=TrainTarget.ADJOINT): ''' output_records have to filled with existing blobs. ''' workspace.ResetWorkspace() print('>>> Training Target: ' + train_target) if train_target == TrainTarget.ADJOINT: # When training the adjoint network, we also need to forward pass # through the origin network input_record_schema = schema.Struct( ('sig_input', schema.Scalar( (np.float32, (sig_input_dim, )))), # sig ('tanh_input', schema.Scalar( (np.float32, (tanh_input_dim, )))), # tanh ('adjoint_input', schema.Scalar((np.float32, (pred_dim, ))))) output_record_schema = schema.Struct( ('loss', schema.Scalar((np.float32, (1, )))), ('origin_pred', schema.Scalar((np.float32, (pred_dim, )))), ('sig_adjoint_pred', schema.Scalar( (np.float32, (sig_input_dim, )))), ('tanh_adjoint_pred', schema.Scalar((np.float32, (tanh_input_dim, )))), ) # use trainer_extra_schema as the loss input record trainer_extra_schema = schema.Struct( ('sig_loss_record', schema.Struct( ('label', schema.Scalar((np.float32, (sig_input_dim, )))), ('prediction', schema.Scalar( (np.float32, (sig_input_dim, )))))), ('tanh_loss_record', schema.Struct( ('label', schema.Scalar((np.float32, (tanh_input_dim, )))), ('prediction', schema.Scalar( (np.float32, (tanh_input_dim, )))))), ('origin_loss_record', schema.Struct( ('label', schema.Scalar((np.float32, (pred_dim, )))), ('prediction', schema.Scalar((np.float32, (pred_dim, )))))), ) if train_target == TrainTarget.ORIGIN: # When training the origin network, no need of the adjoint network input_record_schema = schema.Struct( ('sig_input', schema.Scalar( (np.float32, (sig_input_dim, )))), # sig ('tanh_input', schema.Scalar( (np.float32, (tanh_input_dim, )))), # tanh ('adjoint_input', schema.Scalar((np.float32, (pred_dim, ))))) output_record_schema = schema.Struct( ('loss', schema.Scalar((np.float32, (1, )))), ('origin_pred', schema.Scalar((np.float32, (pred_dim, )))), ) # use trainer_extra_schema as the loss input record trainer_extra_schema = schema.Struct( ('origin_loss_record', schema.Struct( ('label', schema.Scalar((np.float32, (pred_dim, )))), ('prediction', schema.Scalar((np.float32, (pred_dim, )))))), ) model = layer_model_helper.LayerModelHelper(model_name, input_record_schema, trainer_extra_schema) model.output_schema = output_record_schema return model
def __init__(self, model, input_record, output_names_or_num, function, name='functional', output_dtypes=None, **kwargs): # allow coercion input_record = schema.as_record(input_record) super(Functional, self).__init__(model, name, input_record, **kwargs) self._function = function self._kwargs = kwargs return_struct = ( isinstance(output_names_or_num, list) or (isinstance(output_names_or_num, six.integer_types) and output_names_or_num != 1) ) with scope.NameScope(self.name, reset=True): if isinstance(output_names_or_num, int): struct_output_schema = schema.NewRecord( model.net, schema.RawTuple(output_names_or_num)) elif isinstance(output_names_or_num, schema.Field): self.output_schema = output_names_or_num.clone(keep_blobs=True) return else: if not isinstance(output_names_or_num, list): output_names_or_num = [output_names_or_num] out_tuple = [(out, np.void) for out in output_names_or_num] struct_output_schema = schema.NewRecord( model.net, schema.Struct(*out_tuple)) num_outputs = len(struct_output_schema.field_blobs()) # functional layer returns Struct if more than one outputs or output is # a list, otherwise Scalar if return_struct: self.output_schema = struct_output_schema else: self.output_schema = struct_output_schema[0] # If output_dtypes is provided, use it for output schema. Otherwise # the shape and type will be inferred. if output_dtypes is not None: if not isinstance(output_dtypes, list): output_dtypes = [output_dtypes] * num_outputs assert len(output_dtypes) == num_outputs for dtype, scalar in zip(output_dtypes, self.output_schema.all_scalars()): scalar.set_type(dtype) return # Fake execution of the function to infer shapes and types automatically had_issues = False try: type_net = core.Net('_temp_type_and_shape_inference_net') schema.InitEmptyRecord(type_net, input_record, enforce_types=True) function(type_net, self.input_record, self.output_schema, **kwargs) (shapes, types) = workspace.InferShapesAndTypes([type_net], {}) for i in range(num_outputs): scalar_schema = (self.output_schema[i] if return_struct else self.output_schema) blob = scalar_schema() if blob not in types or blob not in shapes: had_issues = True continue if shapes[blob] == []: # Scalar type shape = tuple() elif shapes[blob][0] == 0: shape = tuple(shapes[blob][1:]) else: logger.warning("unexpeced shape: {}".format(shapes[blob])) # If batch dimension is not first - give up on shape # inference for that blob had_issues = True continue # TODO(amalevich): Move it to some shared library dtype = None if types[blob] == caffe2_pb2.TensorProto.DOUBLE: dtype = (np.float64, shape) elif types[blob] == caffe2_pb2.TensorProto.FLOAT: dtype = (np.float32, shape) elif types[blob] == caffe2_pb2.TensorProto.INT32: dtype = (np.int32, shape) elif types[blob] == caffe2_pb2.TensorProto.INT64: dtype = (np.int64, shape) if dtype is not None: scalar_schema.set_type(dtype) except TypeError as ex: had_issues = True logger.warning(str(ex)) if had_issues: logger.warning( "Type inference had problems for layer: {}".format(self.name))
def run_train_net(self): self.model.output_schema = schema.Struct() train_init_net, train_net = \ layer_model_instantiator.generate_training_nets(self.model) workspace.RunNetOnce(train_init_net) workspace.RunNetOnce(train_net)
def testBatchSigmoidCrossEntropyLoss(self): input_record = self.new_record( schema.Struct(('label', schema.Scalar((np.float32, (32, )))), ('prediction', schema.Scalar((np.float32, (32, )))))) loss = self.model.BatchSigmoidCrossEntropyLoss(input_record) self.assertEqual(schema.Scalar((np.float32, tuple())), loss)
def testArcCosineFeatureMap(self, batch_size, input_dims, output_dims, s, scale): X = np.random.normal(size=(batch_size, input_dims)).astype(np.float32) input_record = self.new_record( schema.Scalar((np.float32, (input_dims, )))) schema.FeedRecord(input_record, [X]) input_blob = input_record.field_blobs()[0] ac_output = self.model.ArcCosineFeatureMap(input_record, output_dims, s=s, scale=scale) self.model.output_schema = schema.Struct() self.assertEqual(schema.Scalar((np.float32, (output_dims, ))), ac_output) init_ops_list = [ OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), ] train_init_net, train_net = self.get_training_nets() # Init net assertions init_ops = self._test_net(train_init_net, init_ops_list) workspace.RunNetOnce(self.model.param_init_net) W = workspace.FetchBlob(self.model.layers[0].random_w) b = workspace.FetchBlob(self.model.layers[0].random_b) # Operation specifications fc_spec = OpSpec( "FC", [input_blob, init_ops[0].output[0], init_ops[1].output[0]], None) gt_spec = OpSpec("GT", None, None, {'broadcast': 1}) cast_spec = OpSpec("Cast", None, ac_output.field_blobs()) relu_spec = OpSpec("Relu", None, None) relu_spec_output = OpSpec("Relu", None, ac_output.field_blobs()) pow_spec = OpSpec("Pow", None, None, {'exponent': float(s - 1)}) mul_spec = OpSpec("Mul", None, ac_output.field_blobs()) if s == 0: ops_list = [ fc_spec, gt_spec, cast_spec, ] elif s == 1: ops_list = [ fc_spec, relu_spec_output, ] else: ops_list = [ fc_spec, relu_spec, pow_spec, mul_spec, ] # Train net assertions self._test_net(train_net, ops_list) self._arc_cosine_hypothesis_test(ac_output(), X, W, b, s) # Eval net assertions eval_net = self.get_eval_net() self._test_net(eval_net, ops_list) self._arc_cosine_hypothesis_test(ac_output(), X, W, b, s) # Predict net assertions predict_net = self.get_predict_net() self._test_net(predict_net, ops_list) self._arc_cosine_hypothesis_test(ac_output(), X, W, b, s)
def testBatchNormalization(self, X): input_record = self.new_record(schema.Scalar((np.float32, (5,)))) schema.FeedRecord(input_record, [X]) bn_output = self.model.BatchNormalization(input_record) self.assertEqual(schema.Scalar((np.float32, (5,))), bn_output) self.model.output_schema = schema.Struct() train_init_net, train_net = self.get_training_nets() init_ops = self.assertNetContainOps( train_init_net, [ OpSpec("ConstantFill", None, None), OpSpec("ConstantFill", None, None), OpSpec("ConstantFill", None, None), OpSpec("ConstantFill", None, None), ] ) input_blob = input_record.field_blobs()[0] output_blob = bn_output.field_blobs()[0] expand_dims_spec = OpSpec( "ExpandDims", [input_blob], [input_blob], ) train_bn_spec = OpSpec( "SpatialBN", [input_blob, init_ops[0].output[0], init_ops[1].output[0], init_ops[2].output[0], init_ops[3].output[0]], [output_blob, init_ops[2].output[0], init_ops[3].output[0], None, None], {'is_test': 0, 'order': 'NCHW', 'momentum': 0.9}, ) test_bn_spec = OpSpec( "SpatialBN", [input_blob, init_ops[0].output[0], init_ops[1].output[0], init_ops[2].output[0], init_ops[3].output[0]], [output_blob], {'is_test': 1, 'order': 'NCHW', 'momentum': 0.9}, ) squeeze_spec = OpSpec( "Squeeze", [output_blob], [output_blob], ) self.assertNetContainOps( train_net, [expand_dims_spec, train_bn_spec, squeeze_spec] ) eval_net = self.get_eval_net() self.assertNetContainOps( eval_net, [expand_dims_spec, test_bn_spec, squeeze_spec] ) predict_net = self.get_predict_net() self.assertNetContainOps( predict_net, [expand_dims_spec, test_bn_spec, squeeze_spec] ) workspace.RunNetOnce(train_init_net) workspace.RunNetOnce(train_net) schema.FeedRecord(input_record, [X]) workspace.RunNetOnce(eval_net) schema.FeedRecord(input_record, [X]) workspace.RunNetOnce(predict_net)
def __init__(self, model, input_record, name='batch_lr_loss', average_loss=True, jsd_weight=0.0, pos_label_target=1.0, neg_label_target=0.0, homotopy_weighting=False, log_D_trick=False, unjoined_lr_loss=False, uncertainty_penalty=1.0, focal_gamma=0.0, stop_grad_in_focal_factor=False, task_gamma=1.0, task_gamma_lb=0.1, **kwargs): super(BatchLRLoss, self).__init__(model, name, input_record, **kwargs) self.average_loss = average_loss assert (schema.is_schema_subset( schema.Struct(('label', schema.Scalar()), ('logit', schema.Scalar())), input_record)) self.jsd_fuse = False assert jsd_weight >= 0 and jsd_weight <= 1 if jsd_weight > 0 or homotopy_weighting: assert 'prediction' in input_record self.init_weight(jsd_weight, homotopy_weighting) self.jsd_fuse = True self.homotopy_weighting = homotopy_weighting assert pos_label_target <= 1 and pos_label_target >= 0 assert neg_label_target <= 1 and neg_label_target >= 0 assert pos_label_target >= neg_label_target self.pos_label_target = pos_label_target self.neg_label_target = neg_label_target assert not (log_D_trick and unjoined_lr_loss) self.log_D_trick = log_D_trick self.unjoined_lr_loss = unjoined_lr_loss assert uncertainty_penalty >= 0 self.uncertainty_penalty = uncertainty_penalty self.tags.update([Tags.EXCLUDE_FROM_PREDICTION]) self.output_schema = schema.Scalar( np.float32, self.get_next_blob_reference('output')) self.focal_gamma = focal_gamma self.stop_grad_in_focal_factor = stop_grad_in_focal_factor self.apply_exp_decay = False if task_gamma < 1.0: self.apply_exp_decay = True self.task_gamma_cur = self.create_param( param_name=('%s_task_gamma_cur' % self.name), shape=[1], initializer=('ConstantFill', { 'value': 1.0, 'dtype': core.DataType.FLOAT }), optimizer=self.model.NoOptim, ) self.task_gamma = self.create_param( param_name=('%s_task_gamma' % self.name), shape=[1], initializer=('ConstantFill', { 'value': task_gamma, 'dtype': core.DataType.FLOAT }), optimizer=self.model.NoOptim, ) self.task_gamma_lb = self.create_param( param_name=('%s_task_gamma_lb' % self.name), shape=[1], initializer=('ConstantFill', { 'value': task_gamma_lb, 'dtype': core.DataType.FLOAT }), optimizer=self.model.NoOptim, )
def __init__(self, model, input_record, output_names_or_num, function, name='functional', **kwargs): super(Functional, self).__init__(model, name, input_record, **kwargs) self._function = function with scope.NameScope(self.name): if isinstance(output_names_or_num, int): self.output_schema = schema.NewRecord( model.net, schema.RawTuple(output_names_or_num)) else: if not isinstance(output_names_or_num, list): output_names_or_num = [output_names_or_num] out_tuple = [(out, np.void) for out in output_names_or_num] self.output_schema = schema.NewRecord( model.net, schema.Struct(*out_tuple)) num_outputs = len(self.output_schema.field_blobs()) # Fake execution of the function to infer shapes and types automatically had_issues = False try: type_net = core.Net('_temp_type_and_shape_inference_net') schema.InitEmptyRecord(type_net, input_record, enforce_types=True) function(type_net, self.input_record, self.output_schema) (shapes, types) = workspace.InferShapesAndTypes([type_net], {}) for i in range(num_outputs): blob = self.output_schema[i]() if blob not in types or blob not in shapes: had_issues = True continue if shapes[blob] == []: # Scalar type shape = tuple() elif shapes[blob][0] == 0: shape = tuple(shapes[blob][1:]) else: # If batch dimension is not first - give up on shape # inference for that blob had_issues = True continue # TODO(amalevich): Move it to some shared library dtype = None if types[blob] == caffe2_pb2.TensorProto.DOUBLE: dtype = (np.float64, shape) elif types[blob] == caffe2_pb2.TensorProto.FLOAT: dtype = (np.float32, shape) elif types[blob] == caffe2_pb2.TensorProto.INT32: dtype = (np.int32, shape) elif types[blob] == caffe2_pb2.TensorProto.INT64: dtype = (np.int64, shape) if dtype is not None: self.output_schema[i].set_type(dtype) except TypeError as ex: had_issues = True logger.warning(str(ex)) if had_issues: logger.warning("Type inference had problems for layer: {}".format( self.name))
def __init__(self, model, input_record, input_specs, name='sparse_to_dense', **kwargs): """ `input_specs` follows the format of FeatureSpec from schema. To be more precise it's a namedtuple that should have: 'feature_type', 'feature_names', 'feature_ids' """ super(SparseToDense, self).__init__(model, name, input_record, **kwargs) self.input_specs = input_specs outputs = [] for field, feature_specs in self.input_specs: assert len(feature_specs.feature_names) ==\ len(feature_specs.feature_ids) if feature_specs.feature_type == 'FLOAT': outputs.append( (field, schema.Scalar( (np.float32, len(feature_specs.feature_ids)), core.ScopedBlobReference( model.net.NextName(self.name + field + '_output'))))) elif feature_specs.feature_type == 'ID_LIST': outputs.append( (field, schema.Struct( ( 'ranges', schema.Scalar( (np.int32, (len(feature_specs.feature_ids), 2)), core.ScopedBlobReference( model.net.NextName(self.name + field + '_ranges'))), ), ('values', input_record[field].values.items), ))) else: raise TypeError("Unsupported input type: {0}".format( feature_specs.feature_type)) # TODO(amalevich): This schema is producing ranges. And thus if there is # something using it it should support ranges as well. It might be # confusing, if we don't add better support for ranges/have it as a # first layer self.output_schema = schema.Struct(*outputs) # TODO(amalevich): Consider moving this data to schema, instead # Structs doens't support attaching metadata to them and clonning # will break things badly, but this is the most elegant way to pass # this info around. Should we change it or it'll be too much work and # not worse it? for field, feature_specs in input_specs: schema.attach_metadata_to_scalars( self.output_schema[field], schema.Metadata(feature_specs=feature_specs)) self.zero = model.global_constants['ZERO'] self.zero_range = model.global_constants['ZERO_RANGE']
def testSemiRandomFeatures(self, batch_size, input_dims, output_dims, s, scale, set_weight_as_global_constant, use_struct_input): def _semi_random_hypothesis_test(srf_output, X_full, X_random, rand_w, rand_b, s): """ Runs hypothesis test for Semi Random Features layer. Inputs: srf_output -- output of net after running semi random features layer X_full -- full input data X_random -- random-output input data rand_w -- random-initialized weight parameter from train_init_net rand_b -- random-initialized bias parameter from train_init_net s -- degree parameter """ # Get output from net net_output = workspace.FetchBlob(srf_output) # Fetch learned parameter blobs learned_w = workspace.FetchBlob(self.model.layers[0].learned_w) learned_b = workspace.FetchBlob(self.model.layers[0].learned_b) # Computing output directly x_rand = np.matmul(X_random, np.transpose(rand_w)) + rand_b x_learn = np.matmul(X_full, np.transpose(learned_w)) + learned_b x_pow = np.power(x_rand, s) if s > 0: h_rand_features = np.piecewise(x_rand, [x_rand <= 0, x_rand > 0], [0, 1]) else: h_rand_features = np.piecewise(x_rand, [x_rand <= 0, x_rand > 0], [0, lambda x: x / (1 + x)]) output_ref = np.multiply(np.multiply(x_pow, h_rand_features), x_learn) # Comparing net output and computed output npt.assert_allclose(net_output, output_ref, rtol=1e-3, atol=1e-3) X_full = np.random.normal(size=(batch_size, input_dims)).astype(np.float32) if use_struct_input: X_random = np.random.normal(size=(batch_size, input_dims)).\ astype(np.float32) input_data = [X_full, X_random] input_record = self.new_record( schema.Struct( ('full', schema.Scalar((np.float32, (input_dims, )))), ('random', schema.Scalar((np.float32, (input_dims, )))))) else: X_random = X_full input_data = [X_full] input_record = self.new_record( schema.Scalar((np.float32, (input_dims, )))) schema.FeedRecord(input_record, input_data) srf_output = self.model.SemiRandomFeatures( input_record, output_dims, s=s, scale_random=scale, scale_learned=scale, set_weight_as_global_constant=set_weight_as_global_constant) self.model.output_schema = schema.Struct() self.assertEqual( schema.Struct( ('full', schema.Scalar((np.float32, (output_dims, )))), ('random', schema.Scalar((np.float32, (output_dims, ))))), srf_output) init_ops_list = [ OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), OpSpec("GaussianFill", None, None), OpSpec("UniformFill", None, None), ] train_init_net, train_net = self.get_training_nets() # Need to run to initialize the global constants for layer workspace.RunNetOnce(self.model.create_init_net(name='init_net')) if set_weight_as_global_constant: # If weight params are global constants, they won't be in train_init_net init_ops = self._test_net(train_init_net, init_ops_list[:2]) rand_w = workspace.FetchBlob( self.model. global_constants['semi_random_features_fixed_rand_W']) rand_b = workspace.FetchBlob( self.model. global_constants['semi_random_features_fixed_rand_b']) # Operation specifications fc_random_spec = OpSpec("FC", [None, None, None], None) fc_learned_spec = OpSpec( "FC", [None, init_ops[0].output[0], init_ops[1].output[0]], None) else: init_ops = self._test_net(train_init_net, init_ops_list) rand_w = workspace.FetchBlob(self.model.layers[0].random_w) rand_b = workspace.FetchBlob(self.model.layers[0].random_b) # Operation specifications fc_random_spec = OpSpec( "FC", [None, init_ops[0].output[0], init_ops[1].output[0]], None) fc_learned_spec = OpSpec( "FC", [None, init_ops[2].output[0], init_ops[3].output[0]], None) softsign_spec = OpSpec("Softsign", None, None) relu_spec = OpSpec("Relu", None, None) relu_output_spec = OpSpec("Relu", None, srf_output.random.field_blobs()) pow_spec = OpSpec("Pow", None, None, {'exponent': float(s - 1)}) mul_interim_spec = OpSpec("Mul", None, srf_output.random.field_blobs()) mul_spec = OpSpec("Mul", None, srf_output.full.field_blobs()) if s == 0: ops_list = [ fc_learned_spec, fc_random_spec, softsign_spec, relu_output_spec, mul_spec, ] elif s == 1: ops_list = [ fc_learned_spec, fc_random_spec, relu_output_spec, mul_spec, ] else: ops_list = [ fc_learned_spec, fc_random_spec, relu_spec, pow_spec, mul_interim_spec, mul_spec, ] # Train net assertions self._test_net(train_net, ops_list) _semi_random_hypothesis_test(srf_output.full(), X_full, X_random, rand_w, rand_b, s) # Eval net assertions eval_net = self.get_eval_net() self._test_net(eval_net, ops_list) _semi_random_hypothesis_test(srf_output.full(), X_full, X_random, rand_w, rand_b, s) # Predict net assertions predict_net = self.get_predict_net() self._test_net(predict_net, ops_list) _semi_random_hypothesis_test(srf_output.full(), X_full, X_random, rand_w, rand_b, s)
def testArcCosineFeatureMap(self, batch_size, input_dims, output_dims, s, scale, set_weight_as_global_constant): def _arc_cosine_hypothesis_test(ac_output, X, W, b, s): """ Runs hypothesis test for Arc Cosine layer. Inputs: ac_output -- output of net after running arc cosine layer X -- input data W -- weight parameter from train_init_net b -- bias parameter from train_init_net s -- degree parameter """ # Get output from net net_output = workspace.FetchBlob(ac_output) # Computing output directly x_rand = np.matmul(X, np.transpose(W)) + b x_pow = np.power(x_rand, s) if s > 0: h_rand_features = np.piecewise(x_rand, [x_rand <= 0, x_rand > 0], [0, 1]) else: h_rand_features = np.piecewise(x_rand, [x_rand <= 0, x_rand > 0], [0, lambda x: x / (1 + x)]) output_ref = np.multiply(x_pow, h_rand_features) # Comparing net output and computed output npt.assert_allclose(net_output, output_ref, rtol=1e-3, atol=1e-3) X = np.random.normal(size=(batch_size, input_dims)).astype(np.float32) input_record = self.new_record( schema.Scalar((np.float32, (input_dims, )))) schema.FeedRecord(input_record, [X]) input_blob = input_record.field_blobs()[0] ac_output = self.model.ArcCosineFeatureMap( input_record, output_dims, s=s, scale=scale, set_weight_as_global_constant=set_weight_as_global_constant) self.model.output_schema = schema.Struct() self.assertEqual(schema.Scalar((np.float32, (output_dims, ))), ac_output) train_init_net, train_net = self.get_training_nets() # Run create_init_net to initialize the global constants, and W and b workspace.RunNetOnce(train_init_net) workspace.RunNetOnce(self.model.create_init_net(name='init_net')) if set_weight_as_global_constant: W = workspace.FetchBlob( self.model. global_constants['arc_cosine_feature_map_fixed_rand_W']) b = workspace.FetchBlob( self.model. global_constants['arc_cosine_feature_map_fixed_rand_b']) else: W = workspace.FetchBlob(self.model.layers[0].random_w) b = workspace.FetchBlob(self.model.layers[0].random_b) # Operation specifications fc_spec = OpSpec("FC", [input_blob, None, None], None) softsign_spec = OpSpec("Softsign", None, None) relu_spec = OpSpec("Relu", None, None) relu_spec_output = OpSpec("Relu", None, ac_output.field_blobs()) pow_spec = OpSpec("Pow", None, None, {'exponent': float(s - 1)}) mul_spec = OpSpec("Mul", None, ac_output.field_blobs()) if s == 0: ops_list = [ fc_spec, softsign_spec, relu_spec_output, ] elif s == 1: ops_list = [ fc_spec, relu_spec_output, ] else: ops_list = [ fc_spec, relu_spec, pow_spec, mul_spec, ] # Train net assertions self._test_net(train_net, ops_list) _arc_cosine_hypothesis_test(ac_output(), X, W, b, s) # Eval net assertions eval_net = self.get_eval_net() self._test_net(eval_net, ops_list) _arc_cosine_hypothesis_test(ac_output(), X, W, b, s) # Predict net assertions predict_net = self.get_predict_net() self._test_net(predict_net, ops_list) _arc_cosine_hypothesis_test(ac_output(), X, W, b, s)
def testAssignToField(self): with self.assertRaises(TypeError): s = schema.Struct(('a', schema.Scalar())) s.a = schema.Scalar()
def testMapToRange(self): input_record = self.new_record(schema.Scalar(np.int32)) map_to_range_output = self.model.MapToRange(input_record, max_index=100) self.model.output_schema = schema.Struct() train_init_net, train_net = self.get_training_nets() schema.FeedRecord( input_record, [np.array([10, 3, 20, 99, 15, 11, 3, 11], dtype=np.int32)] ) workspace.RunNetOnce(train_init_net) workspace.RunNetOnce(train_net) indices = workspace.FetchBlob(map_to_range_output()) np.testing.assert_array_equal( np.array([1, 2, 3, 4, 5, 6, 2, 6], dtype=np.int32), indices ) schema.FeedRecord( input_record, [np.array([10, 3, 23, 35, 60, 15, 10, 15], dtype=np.int32)] ) workspace.RunNetOnce(train_net) indices = workspace.FetchBlob(map_to_range_output()) np.testing.assert_array_equal( np.array([1, 2, 7, 8, 9, 5, 1, 5], dtype=np.int32), indices ) eval_net = self.get_eval_net() schema.FeedRecord( input_record, [np.array([10, 3, 23, 35, 60, 15, 200], dtype=np.int32)] ) workspace.RunNetOnce(eval_net) indices = workspace.FetchBlob(map_to_range_output()) np.testing.assert_array_equal( np.array([1, 2, 7, 8, 9, 5, 0], dtype=np.int32), indices ) schema.FeedRecord( input_record, [np.array([10, 3, 23, 15, 101, 115], dtype=np.int32)] ) workspace.RunNetOnce(eval_net) indices = workspace.FetchBlob(map_to_range_output()) np.testing.assert_array_equal( np.array([1, 2, 7, 5, 0, 0], dtype=np.int32), indices ) predict_net = self.get_predict_net() schema.FeedRecord( input_record, [np.array([3, 3, 20, 23, 151, 35, 60, 15, 200], dtype=np.int32)] ) workspace.RunNetOnce(predict_net) indices = workspace.FetchBlob(map_to_range_output()) np.testing.assert_array_equal( np.array([2, 2, 3, 7, 0, 8, 9, 5, 0], dtype=np.int32), indices )
def testFromEmptyColumnList(self): st = schema.Struct() columns = st.field_names() rec = schema.from_column_list(col_names=columns) self.assertEqual(rec, schema.Struct())
def filter_metrics_schema(self, white_set): logger.info("Filter metric schema with white_set {}".format(white_set)) field_names = self._metrics_schema.field_names() for name in field_names: if name not in white_set: self._metrics_schema = self._metrics_schema - schema.Struct((name, schema.Scalar()))
def __init__(self, model, input_record, num_to_collect, name='reservoir_sampling', **kwargs): super(ReservoirSampling, self).__init__( model, name, input_record, **kwargs) assert num_to_collect > 0 self.num_to_collect = num_to_collect self.reservoir = self.create_param( param_name='reservoir', shape=[0], initializer=('ConstantFill',), optimizer=model.NoOptim, ) self.num_visited_blob = self.create_param( param_name='num_visited', shape=[], initializer=('ConstantFill', { 'value': 0, 'dtype': core.DataType.INT64, }), optimizer=model.NoOptim, ) self.mutex = self.create_param( param_name='mutex', shape=None, initializer=('CreateMutex',), optimizer=model.NoOptim, ) self.extra_input_blobs = [] self.extra_output_blobs = [] if 'object_id' in input_record: object_to_pos = self.create_param( param_name='object_to_pos', initializer=('CreateMap', { 'key_dtype': core.DataType.INT64, 'valued_dtype': core.DataType.INT32, }), optimizer=model.NoOptim, ) pos_to_object = self.create_param( param_name='pos_to_object', shape=[0], initializer=('ConstantFill', { 'value': 0, 'dtype': core.DataType.INT64, }), optimizer=model.NoOptim, ) self.extra_input_blobs.append(input_record.object_id()) self.extra_input_blobs.extend([object_to_pos, pos_to_object]) self.extra_output_blobs.extend([object_to_pos, pos_to_object]) self.output_schema = schema.Struct( ( 'reservoir', schema.from_blob_list(input_record.data, [self.reservoir]) ), ('num_visited', schema.Scalar(blob=self.num_visited_blob)), ('mutex', schema.Scalar(blob=self.mutex)), )
def __init__( self, model, input_record, output_dims, s=1, scale_random=1.0, scale_learned=1.0, weight_init_random=None, bias_init_random=None, weight_init_learned=None, bias_init_learned=None, weight_optim=None, bias_optim=None, set_weight_as_global_constant=False, name='semi_random_features', **kwargs): if isinstance(input_record, schema.Struct): schema.is_schema_subset( schema.Struct( ('full', schema.Scalar()), ('random', schema.Scalar()), ), input_record ) self.input_record_full = input_record.full self.input_record_random = input_record.random elif isinstance(input_record, schema.Scalar): self.input_record_full = input_record self.input_record_random = input_record super(SemiRandomFeatures, self).__init__( model, self.input_record_full, output_dims, s=s, scale=scale_random, # To initialize the random parameters weight_init=weight_init_random, bias_init=bias_init_random, weight_optim=None, bias_optim=None, set_weight_as_global_constant=set_weight_as_global_constant, initialize_output_schema=False, name=name, **kwargs) self.output_schema = schema.Struct( ('full', schema.Scalar( (np.float32, output_dims), model.net.NextScopedBlob(name + '_full_output') ),), ('random', schema.Scalar( (np.float32, output_dims), model.net.NextScopedBlob(name + '_random_output') ),), ) # To initialize the learnable parameters assert (scale_learned > 0.0), \ "Expected scale (learned) > 0, got %s" % scale_learned self.stddev = scale_learned * np.sqrt(1.0 / self.input_dims) # Learned Parameters (self.learned_w, self.learned_b) = self._initialize_params( 'learned_w', 'learned_b', w_init=weight_init_learned, b_init=bias_init_learned, w_optim=weight_optim, b_optim=bias_optim )
def testGatherRecord(self): indices = np.array([1, 3, 4], dtype=np.int32) dense = np.array(range(20), dtype=np.float32).reshape(10, 2) lengths = np.array(range(10), dtype=np.int32) items = np.array(range(lengths.sum()), dtype=np.int64) items_lengths = np.array(range(lengths.sum()), dtype=np.int32) items_items = np.array(range(items_lengths.sum()), dtype=np.int64) record = self.new_record( schema.Struct( ('dense', schema.Scalar(np.float32)), ('sparse', schema.Struct( ('list', schema.List(np.int64)), ('list_of_list', schema.List(schema.List(np.int64))), )), ('empty_struct', schema.Struct()))) indices_record = self.new_record(schema.Scalar(np.int32)) input_record = schema.Struct( ('indices', indices_record), ('record', record), ) schema.FeedRecord(input_record, [ indices, dense, lengths, items, lengths, items_lengths, items_items ]) gathered_record = self.model.GatherRecord(input_record) self.assertTrue(schema.equal_schemas(gathered_record, record)) self.run_train_net_forward_only() gathered_dense = workspace.FetchBlob(gathered_record.dense()) np.testing.assert_array_equal( np.concatenate([dense[i:i + 1] for i in indices]), gathered_dense) gathered_lengths = workspace.FetchBlob( gathered_record.sparse.list.lengths()) np.testing.assert_array_equal( np.concatenate([lengths[i:i + 1] for i in indices]), gathered_lengths) gathered_items = workspace.FetchBlob( gathered_record.sparse.list.items()) offsets = lengths.cumsum() - lengths np.testing.assert_array_equal( np.concatenate( [items[offsets[i]:offsets[i] + lengths[i]] for i in indices]), gathered_items) gathered_items_lengths = workspace.FetchBlob( gathered_record.sparse.list_of_list.items.lengths()) np.testing.assert_array_equal( np.concatenate([ items_lengths[offsets[i]:offsets[i] + lengths[i]] for i in indices ]), gathered_items_lengths) nested_offsets = [] nested_lengths = [] nested_offset = 0 j = 0 for l in lengths: nested_offsets.append(nested_offset) nested_length = 0 for _i in range(l): nested_offset += items_lengths[j] nested_length += items_lengths[j] j += 1 nested_lengths.append(nested_length) gathered_items_items = workspace.FetchBlob( gathered_record.sparse.list_of_list.items.items()) np.testing.assert_array_equal( np.concatenate([ items_items[nested_offsets[i]:nested_offsets[i] + nested_lengths[i]] for i in indices ]), gathered_items_items)
def testSetInputRecordWithoutBlobs(self): net = core.Net("test") record = schema.Struct(("x", schema.Scalar(np.float))) input_record = net.set_input_record(record) self.assertTrue(net.BlobIsDefined(input_record.x())) self.assertIn(input_record.x(), net.external_inputs)
def __init__(self, model, input_record, input_specs, name="feature_sparse_to_dense", **kwargs): """ `input_specs` follows the format of FeatureSpec from schema. To be more precise it's a namedtuple that should have: 'feature_type', 'feature_names', 'feature_ids' """ super(FeatureSparseToDense, self).__init__(model, name, input_record, **kwargs) self.input_specs = input_specs outputs = [] for field, feature_specs in self.input_specs: assert len(feature_specs.feature_names) == len( feature_specs.feature_ids) if feature_specs.feature_type == "FLOAT": outputs.append(( field, schema.Scalar( (np.float32, (len(feature_specs.feature_ids), )), self.get_next_blob_reference(field + "_output"), ), )) elif feature_specs.feature_type == "ID_LIST": outputs.append(( field, schema.Struct( ( "ranges", schema.Scalar( (np.int32, (len(feature_specs.feature_ids), 2)), self.get_next_blob_reference(field + "_ranges"), ), ), ( "values", schema.Scalar( np.int64, self.get_next_blob_reference(field + "_values"), ), ), ), )) elif feature_specs.feature_type == "ID_SCORE_LIST": outputs.append(( field, schema.Struct( ( "ranges", schema.Scalar( (np.int32, (len(feature_specs.feature_ids), 2)), self.get_next_blob_reference(field + "_ranges"), ), ), ( "ids", schema.Scalar( np.int64, self.get_next_blob_reference(field + "_ids"), ), ), ( "scores", schema.Scalar( np.float32, self.get_next_blob_reference(field + "_scores"), ), ), ), )) elif feature_specs.feature_type == "EMBEDDING": # We don't know dimensions of embeddings in input data. # Even though they should match dimensions from feature config, # we keep ranges blob to check input data later. outputs.append(( field, schema.Struct( ( "ranges", schema.Scalar( (np.int32, (len(feature_specs.feature_ids), 2)), self.get_next_blob_reference(field + "_ranges"), ), ), ( "values", schema.Scalar( np.float32, self.get_next_blob_reference(field + "_values"), ), ), ), )) elif feature_specs.feature_type == "GENERIC_FEATURE": # We don't know dimensions of embeddings in input data. # Even though they should match dimensions from feature config, # we keep ranges blob to check input data later. # Currently this schema with ranges and values is only for # generic type enum 1. If new types are implemented, we need to # modify the ParseGeneric operator, and this part accordinly outputs.append(( field, schema.Struct( ( "ranges", schema.Scalar( (np.int32, (len(feature_specs.feature_ids), 2)), self.get_next_blob_reference(field + "_ranges"), ), ), ( "values", schema.Scalar( np.float32, self.get_next_blob_reference(field + "_values"), ), ), ), )) else: raise TypeError("Unsupported input type: {0}".format( feature_specs.feature_type)) # TODO(amalevich): This schema is producing ranges. And thus if there is # something using it it should support ranges as well. It might be # confusing, if we don't add better support for ranges/have it as a # first layer self.output_schema = schema.Struct(*outputs) # TODO(amalevich): Consider moving this data to schema, instead # Structs doens't support attaching metadata to them and clonning # will break things badly, but this is the most elegant way to pass # this info around. Should we change it or it'll be too much work and # not worse it? for field, feature_specs in input_specs: schema.attach_metadata_to_scalars( self.output_schema[field], schema.Metadata(feature_specs=feature_specs)) self.zero = model.global_constants["ZERO"] self.zero_range = model.global_constants["ZERO_RANGE"]
def __init__( self, model, input_record, output_dims, s=0, scale=None, weight_init=None, bias_init=None, weight_optim=None, bias_optim=None, set_weight_as_global_constant=False, name='semi_random_features', **kwargs): if isinstance(input_record, schema.Struct): schema.is_schema_subset( schema.Struct( ('full', schema.Scalar()), ('random', schema.Scalar()), ), input_record ) self.input_record_full = input_record.full self.input_record_random = input_record.random elif isinstance(input_record, schema.Scalar): self.input_record_full = input_record self.input_record_random = input_record super(SemiRandomFeatures, self).__init__( model, self.input_record_full, output_dims, s=s, scale=scale, weight_init=weight_init, bias_init=bias_init, weight_optim=None, bias_optim=None, set_weight_as_global_constant=set_weight_as_global_constant, initialize_output_schema=False, name=name, **kwargs) self.output_schema = schema.Struct( ('full', schema.Scalar( (np.float32, output_dims), model.net.NextScopedBlob(name + '_full_output') ),), ('random', schema.Scalar( (np.float32, output_dims), model.net.NextScopedBlob(name + '_random_output') ),), ) # Learned Parameters self.learned_w = self.model.net.NextScopedBlob(self.name + "_learned_w") self.learned_b = self.model.net.NextScopedBlob(self.name + "_learned_b") self.params += self._initialize_params(self.learned_w, self.learned_b, w_init=weight_init, b_init=bias_init, w_optim=weight_optim, b_optim=bias_optim)
def create_net(self): net = core.Net("feature_extractor") init_net = core.Net("feature_extractor_init") missing_scalar = self.create_const(init_net, "MISSING_SCALAR", MISSING_VALUE) action_schema = map_schema( ) if self.sorted_action_features else schema.Scalar() input_schema = schema.Struct( (InputColumn.STATE_FEATURES, map_schema()), (InputColumn.NEXT_STATE_FEATURES, map_schema()), (InputColumn.ACTION, action_schema), (InputColumn.NEXT_ACTION, action_schema), (InputColumn.NOT_TERMINAL, schema.Scalar()), ) if self.include_possible_actions: input_schema += schema.Struct( (InputColumn.POSSIBLE_ACTIONS_MASK, schema.List( schema.Scalar())), (InputColumn.POSSIBLE_NEXT_ACTIONS_MASK, schema.List(schema.Scalar())), ) if self.sorted_action_features is not None: input_schema += schema.Struct( (InputColumn.POSSIBLE_ACTIONS, schema.List(map_schema())), (InputColumn.POSSIBLE_NEXT_ACTIONS, schema.List(map_schema())), ) input_record = net.set_input_record(input_schema) state = self.extract_float_features( net, "state", input_record[InputColumn.STATE_FEATURES], self.sorted_state_features, missing_scalar, ) next_state = self.extract_float_features( net, "next_state", input_record[InputColumn.NEXT_STATE_FEATURES], self.sorted_state_features, missing_scalar, ) if self.sorted_action_features: action = self.extract_float_features( net, InputColumn.ACTION, input_record[InputColumn.ACTION], self.sorted_action_features, missing_scalar, ) next_action = self.extract_float_features( net, InputColumn.NEXT_ACTION, input_record[InputColumn.NEXT_ACTION], self.sorted_action_features, missing_scalar, ) if self.include_possible_actions: possible_action_features = self.extract_float_features( net, InputColumn.POSSIBLE_ACTIONS, input_record[InputColumn.POSSIBLE_ACTIONS]["values"], self.sorted_action_features, missing_scalar, ) possible_next_action_features = self.extract_float_features( net, InputColumn.POSSIBLE_NEXT_ACTIONS, input_record[InputColumn.POSSIBLE_NEXT_ACTIONS]["values"], self.sorted_action_features, missing_scalar, ) else: action = input_record[InputColumn.ACTION] next_action = input_record[InputColumn.NEXT_ACTION] if self.normalize: C2.set_net_and_init_net(net, init_net) state, _ = PreprocessorNet().normalize_dense_matrix( state, self.sorted_state_features, self.state_normalization_parameters, blobname_prefix="state", split_expensive_feature_groups=True, ) next_state, _ = PreprocessorNet().normalize_dense_matrix( next_state, self.sorted_state_features, self.state_normalization_parameters, blobname_prefix="next_state", split_expensive_feature_groups=True, ) if self.sorted_action_features is not None: action, _ = PreprocessorNet().normalize_dense_matrix( action, self.sorted_action_features, self.action_normalization_parameters, blobname_prefix="action", split_expensive_feature_groups=True, ) next_action, _ = PreprocessorNet().normalize_dense_matrix( next_action, self.sorted_action_features, self.action_normalization_parameters, blobname_prefix="next_action", split_expensive_feature_groups=True, ) if self.include_possible_actions: possible_action_features, _ = PreprocessorNet( ).normalize_dense_matrix( possible_action_features, self.sorted_action_features, self.action_normalization_parameters, blobname_prefix="possible_action", split_expensive_feature_groups=True, ) possible_next_action_features, _ = PreprocessorNet( ).normalize_dense_matrix( possible_next_action_features, self.sorted_action_features, self.action_normalization_parameters, blobname_prefix="possible_next_action", split_expensive_feature_groups=True, ) C2.set_net_and_init_net(None, None) output_schema = schema.Struct( (InputColumn.STATE_FEATURES, state), (InputColumn.NEXT_STATE_FEATURES, next_state), (InputColumn.ACTION, action), (InputColumn.NEXT_ACTION, next_action), (InputColumn.NOT_TERMINAL, input_record[InputColumn.NOT_TERMINAL]), ) if self.include_possible_actions: # Drop the "lengths" blob from possible_actions_mask since we know # it's just a list of [max_num_actions, max_num_actions, ...] output_schema += schema.Struct( ( InputColumn.POSSIBLE_ACTIONS_MASK, input_record[InputColumn.POSSIBLE_ACTIONS_MASK]["values"], ), ( InputColumn.POSSIBLE_NEXT_ACTIONS_MASK, input_record[InputColumn.POSSIBLE_NEXT_ACTIONS_MASK] ["values"], ), ) if self.sorted_action_features is not None: output_schema += schema.Struct( (InputColumn.POSSIBLE_ACTIONS, possible_action_features), (InputColumn.POSSIBLE_NEXT_ACTIONS, possible_next_action_features), ) net.set_output_record(output_schema) return FeatureExtractorNet(net, init_net)
def __init__(self, name, input_feature_schema, trainer_extra_schema, keep_blobs=False, use_attribution=True): ''' TODO(amalevich): more documnetation on input args use_attribution: if True, will generate the atrribution net for feature importance calculation; Need to turn it to false when FC is quantized as FP16 This attribute access will be consistent with MTML model. ''' super(LayerModelHelper, self).__init__(name=name) self._layer_names = set() self._layers = [] self._param_to_shape = {} # seed default self._seed = None self._sequence_seed = True # optimizer bookkeeping self.param_to_optim = {} self.param_to_reg = {} self._default_optimizer = None self._loss = None self._prediction = [] self._output_schema = None self._post_grad_net_modifiers = [] self._final_net_modifiers = [] # breakdown map; breakdown features are categorical (like dense) but not # necessarily used to represent data for training self._breakdown_map = None # Connect Schema to self.net. That particular instance of schmea will be # use for generation of the Layers across the network and would be used # for connection with Readers. self._input_feature_schema = schema.NewRecord( self.net, input_feature_schema ) if not keep_blobs else input_feature_schema.clone() self._trainer_extra_schema = schema.NewRecord( self.net, trainer_extra_schema ) if not keep_blobs else trainer_extra_schema.clone() self._metrics_schema = schema.Struct() self._preproc_output_schema = None self._init_global_constants() self.param_init_net = self.create_init_net('param_init_net') self._initialize_params = True self._transfer_learning_blob_name_mappings = None # additional (hard-coded) diagnose_options to report based on the model # TODO(xlwang): it's hack! self.ad_hoc_diagnose_blobs_and_operations = [] self.ad_hoc_plot_blobs = [] self.use_attribution = use_attribution
def add_metric_field(self, name, value): assert name not in self._metrics_schema.fields, ( "Try to add metric field twice: {}".format(name)) self._metrics_schema = self._metrics_schema + schema.Struct( (name, value))
def testDupField(self): with self.assertRaises(ValueError): schema.Struct( ('a', schema.Scalar()), ('a', schema.Scalar()))
def testSamplingTrain(self): output_dims = 1000 indices = self.new_record(schema.Scalar((np.int32, (10,)))) sampling_prob = self.new_record(schema.Scalar((np.float32, (10, )))) sampled_fc = self.model.SamplingTrain( schema.Struct( ('input', self.model.input_feature_schema.float_features), ('indices', indices), ('sampling_prob', sampling_prob), ), "FC", output_dims, ) self.model.output_schema = sampled_fc # Check that we don't add prediction layer into the model self.assertEqual(1, len(self.model.layers)) self.assertEqual( schema.Scalar((np.float32, (output_dims, ))), sampled_fc ) train_init_net, train_net = self.get_training_nets() init_ops = self.assertNetContainOps( train_init_net, [ OpSpec("UniformFill", None, None), OpSpec("UniformFill", None, None), ] ) sampled_fc_layer = self.model.layers[0] gather_w_spec = OpSpec( "Gather", [ init_ops[0].output[0], indices(), ], [ sampled_fc_layer._prediction_layer.train_param_blobs[0] ] ) gather_b_spec = OpSpec( "Gather", [ init_ops[1].output[0], indices(), ], [ sampled_fc_layer._prediction_layer.train_param_blobs[1] ] ) train_fc_spec = OpSpec( "FC", [ self.model.input_feature_schema.float_features(), ] + sampled_fc_layer._prediction_layer.train_param_blobs, sampled_fc.field_blobs() ) log_spec = OpSpec("Log", [sampling_prob()], [None]) sub_spec = OpSpec( "Sub", [sampled_fc.field_blobs()[0], None], sampled_fc.field_blobs() ) train_ops = self.assertNetContainOps( train_net, [gather_w_spec, gather_b_spec, train_fc_spec, log_spec, sub_spec]) self.assertEqual(train_ops[3].output[0], train_ops[4].input[1]) predict_net = self.get_predict_net() self.assertNetContainOps( predict_net, [ OpSpec( "FC", [ self.model.input_feature_schema.float_features(), init_ops[0].output[0], init_ops[1].output[0], ], sampled_fc.field_blobs() ) ] )
def testNormalizeField(self): s = schema.Struct(('field1', np.int32), ('field2', str)) self.assertEquals( s, schema.Struct(('field1', schema.Scalar(dtype=np.int32)), ('field2', schema.Scalar(dtype=str))))