def testBinarySVMWithCenteredBias(self): head = head_lib._binary_svm_head(enable_centered_bias=True) with ops.Graph().as_default(), session.Session(): model_fn_ops = head.create_model_fn_ops( {}, model_fn.ModeKeys.TRAIN, self._labels, _noop_train_op, logits=self._predictions) self._assert_output_alternatives(model_fn_ops) _assert_variables( self, expected_global=( "binary_logistic_head/centered_bias_weight:0", ("binary_logistic_head/binary_logistic_head/centered_bias_weight/" "Adagrad:0"), ), expected_trainable=("binary_logistic_head/centered_bias_weight:0",)) variables.global_variables_initializer().run() _assert_summary_tags( self, ["loss", "binary_logistic_head/centered_bias/bias_0"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithInvalidLogits(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): with self.assertRaisesRegexp(ValueError, "Dimensions.*not compatible"): head.create_model_fn_ops( {}, self._labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits=np.ones((2, 2)))
def testBinarySVMWithInvalidLogits(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): with self.assertRaisesRegexp(ValueError, "Dimensions.*not compatible"): head.create_model_fn_ops( {}, model_fn.ModeKeys.TRAIN, self._labels, _noop_train_op, logits=np.ones((2, 2)))
def testBinarySVMDefaultWeights(self): head = head_lib._binary_svm_head() predictions = tf.constant([[-0.5], [1.2]]) labels = tf.constant([0, 1]) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) # Prediction for first example is in the right side of the hyperplane (i.e., # < 0) but it is within the [-1,1] margin. There is a 0.5 loss incurred by # this example. The 2nd prediction is outside the margin so it incurs no # loss at all. The overall (normalized) loss is therefore 0.5/(1+1) = 0.25. with tf.Session() as sess: self.assertAlmostEqual(0.25, sess.run(model_fn_ops.loss))
def testBinarySVMWithLogitsAndLogitsInput(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): with self.assertRaisesRegexp( ValueError, "Both logits and logits_input supplied"): head.create_model_fn_ops( {}, self._labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits_input=((0., 0.), (0., 0.)), logits=self._predictions)
def testBinarySVMWithLogitsAndLogitsInput(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): with self.assertRaisesRegexp( ValueError, "Both logits and logits_input supplied"): head.create_model_fn_ops( {}, model_fn.ModeKeys.TRAIN, self._labels, _noop_train_op, logits_input=((0., 0.), (0., 0.)), logits=self._predictions)
def testBinarySVMWithWeights(self): head = head_lib._binary_svm_head(weight_column_name="weights") predictions = tf.constant([[-0.7], [0.2]]) labels = tf.constant([0, 1]) features = {"weights": tf.constant([2.0, 10.0])} model_fn_ops = head.head_ops( features, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions ) # Prediction for both examples are in the right side of the hyperplane but # within the margin. The (weighted) loss incurred is 2*0.3=0.6 and 10*0.8=8 # respectively. The overall (normalized) loss is therefore 8.6/12. with tf.Session() as sess: self.assertAlmostEqual(8.6 / 2, sess.run(model_fn_ops.loss), places=3)
def testBinarySVMDefaultWeights(self): head = head_lib._binary_svm_head() with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_no_variables(self) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithWeights(self): head = head_lib._binary_svm_head( weight_column_name="weights") predictions = tf.constant([[-0.7], [0.2]]) labels = tf.constant([0, 1]) features = {"weights": tf.constant([2.0, 10.0])} model_fn_ops = head.head_ops(features, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) # Prediction for both examples are in the right side of the hyperplane but # within the margin. The (weighted) loss incurred is 2*0.3=0.6 and 10*0.8=8 # respectively. The overall (normalized) loss is therefore 8.6/12. with tf.Session() as sess: self.assertAlmostEqual(8.6 / 2, sess.run(model_fn_ops.loss), places=3)
def testBinarySVMWithWeights(self): head = head_lib._binary_svm_head(weight_column_name="weights") with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) weights = (7.0, 11.0) features = {"weights": tf.constant(weights)} model_fn_ops = head.head_ops(features, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) self._assert_metrics(model_fn_ops) _assert_no_variables(self) self.assertAlmostEqual( np.sum(np.multiply(weights, self._expected_losses)) / 2.0, model_fn_ops.loss.eval())
def testBinarySVMWithLabelName(self): label_name = "my_label" head = head_lib._binary_svm_head(label_name=label_name) with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = {label_name: tf.constant(self._labels)} model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithLogits(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): model_fn_ops = head.create_model_fn_ops( {}, self._labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits=self._predictions) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithWeights(self): head = head_lib._binary_svm_head(weight_column_name="weights") with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) weights = (7., 11.) features = {"weights": tf.constant(weights)} model_fn_ops = head.head_ops(features, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_no_variables(self) expected_weighted_sum = np.sum(np.multiply( weights, self._expected_losses)) _assert_metrics(self, expected_weighted_sum / len(weights), { "accuracy": 1., "loss": expected_weighted_sum / np.sum(weights), }, model_fn_ops)
def testBinarySVMDefaultWeights(self): head = head_lib._binary_svm_head() with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) self._assert_metrics(model_fn_ops) _assert_no_variables(self) self.assertAlmostEqual( np.average(self._expected_losses), model_fn_ops.loss.eval()) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.EVAL, _noop_train_op, logits=predictions) self.assertIsNone(model_fn_ops.train_op)
def testBinarySVMWithLabelName(self): label_name = "my_label" head = head_lib._binary_svm_head(label_name=label_name) with ops.Graph().as_default(), session.Session(): model_fn_ops = head.create_model_fn_ops( {}, model_fn.ModeKeys.TRAIN, {label_name: self._labels}, _noop_train_op, logits=self._predictions) self._assert_output_alternatives(model_fn_ops) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithLabelName(self): label_name = "my_label" head = head_lib._binary_svm_head(label_name=label_name) with ops.Graph().as_default(), session.Session(): predictions = constant_op.constant(self._predictions) labels = {label_name: constant_op.constant(self._labels)} model_fn_ops = head.head_ops({}, labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithCenteredBias(self): head = head_lib._binary_svm_head(enable_centered_bias=True) with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) self._assert_metrics(model_fn_ops) _assert_variables(self, expected_global=( "centered_bias_weight:0", "centered_bias_weight/Adagrad:0", ), expected_trainable=( "centered_bias_weight:0", )) tf.global_variables_initializer().run() self.assertAlmostEqual( np.average(self._expected_losses), model_fn_ops.loss.eval())
def testBinarySVMWithWeights(self): head = head_lib._binary_svm_head(weight_column_name="weights") with ops.Graph().as_default(), session.Session(): weights = (7., 11.) model_fn_ops = head.create_model_fn_ops( features={"weights": weights}, labels=self._labels, mode=model_fn.ModeKeys.TRAIN, train_op_fn=_noop_train_op, logits=self._predictions) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_weighted_sum = np.sum( np.multiply(weights, self._expected_losses)) _assert_metrics(self, expected_weighted_sum / len(weights), { "accuracy": 1., "loss": expected_weighted_sum / np.sum(weights), }, model_fn_ops)
def testBinarySVMEvalMode(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): predictions = constant_op.constant(self._predictions) labels = constant_op.constant(self._labels) model_fn_ops = head.head_ops({}, labels, model_fn.ModeKeys.EVAL, _noop_train_op, logits=predictions) self.assertIsNone(model_fn_ops.train_op) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithLogitsInput(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): model_fn_ops = head.create_model_fn_ops( {}, self._labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits_input=((0., 0.), (0., 0.))) w = ("logits/weights:0", "logits/biases:0") _assert_variables( self, expected_global=w, expected_model=w, expected_trainable=w) variables.global_variables_initializer().run() _assert_summary_tags(self, ["loss"]) expected_loss = 1. _assert_metrics(self, expected_loss, { "accuracy": .5, "loss": expected_loss, }, model_fn_ops)
def testBinarySVMEvalMode(self): head = head_lib._binary_svm_head() with ops.Graph().as_default(), session.Session(): predictions = constant_op.constant(self._predictions) labels = constant_op.constant(self._labels) model_fn_ops = head.head_ops( {}, labels, model_fn.ModeKeys.EVAL, _noop_train_op, logits=predictions) self.assertIsNone(model_fn_ops.train_op) _assert_no_variables(self) _assert_summary_tags(self, ["loss"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithCenteredBias(self): head = head_lib._binary_svm_head(enable_centered_bias=True) with tf.Graph().as_default(), tf.Session(): predictions = tf.constant(self._predictions) labels = tf.constant(self._labels) model_fn_ops = head.head_ops({}, labels, tf.contrib.learn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_variables(self, expected_global=( "centered_bias_weight:0", "centered_bias_weight/Adagrad:0", ), expected_trainable=( "centered_bias_weight:0", )) tf.global_variables_initializer().run() _assert_summary_tags(self, ["loss", "centered_bias/bias_0"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def testBinarySVMWithCenteredBias(self): head = head_lib._binary_svm_head(enable_centered_bias=True) with ops.Graph().as_default(), session.Session(): predictions = constant_op.constant(self._predictions) labels = constant_op.constant(self._labels) model_fn_ops = head.head_ops({}, labels, model_fn.ModeKeys.TRAIN, _noop_train_op, logits=predictions) _assert_variables(self, expected_global=( "centered_bias_weight:0", "centered_bias_weight/Adagrad:0", ), expected_trainable=("centered_bias_weight:0", )) variables.global_variables_initializer().run() _assert_summary_tags(self, ["loss", "centered_bias/bias_0"]) expected_loss = np.average(self._expected_losses) _assert_metrics(self, expected_loss, { "accuracy": 1., "loss": expected_loss, }, model_fn_ops)
def __init__(self, example_id_column, feature_columns, weight_column_name=None, model_dir=None, l1_regularization=0.0, l2_regularization=0.0, num_loss_partitions=1, kernels=None, config=None, feature_engineering_fn=None): """Constructs a `SVM~ estimator object. Args: example_id_column: A string defining the feature column name representing example ids. Used to initialize the underlying optimizer. feature_columns: An iterable containing all the feature columns used by the model. All items in the set should be instances of classes derived from `FeatureColumn`. weight_column_name: A string defining feature column name representing weights. It is used to down weight or boost examples during training. It will be multiplied by the loss of the example. 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. l1_regularization: L1-regularization parameter. Refers to global L1 regularization (across all examples). l2_regularization: L2-regularization parameter. Refers to global L2 regularization (across all examples). num_loss_partitions: number of partitions of the (global) loss function optimized by the underlying optimizer (SDCAOptimizer). kernels: A list of kernels for the SVM. Currently, no kernels are supported. Reserved for future use for non-linear SVMs. config: RunConfig object to configure the runtime settings. feature_engineering_fn: Feature engineering function. Takes features and labels which are the output of `input_fn` and returns features and labels which will be fed into the model. Raises: ValueError: if kernels passed is not None. """ if kernels is not None: raise ValueError("Kernel SVMs are not currently supported.") self._optimizer = sdca_optimizer.SDCAOptimizer( example_id_column=example_id_column, num_loss_partitions=num_loss_partitions, symmetric_l1_regularization=l1_regularization, symmetric_l2_regularization=l2_regularization) self._feature_columns = feature_columns self._model_dir = model_dir or tempfile.mkdtemp() self._chief_hook = linear._SdcaUpdateWeightsHook() # pylint: disable=protected-access self._estimator = estimator.Estimator( model_fn=linear.sdca_model_fn, model_dir=self._model_dir, config=config, params={ "head": head_lib._binary_svm_head( # pylint: disable=protected-access weight_column_name=weight_column_name, enable_centered_bias=False), "feature_columns": feature_columns, "optimizer": self._optimizer, "weight_column_name": weight_column_name, "update_weights_hook": self._chief_hook, }, feature_engineering_fn=feature_engineering_fn) if not self._estimator.config.is_chief: self._chief_hook = None
def sdca_classifier_model_fn(features, targets, mode, params): """Linear classifier model_fn that uses the SDCA optimizer. Args: features: A dict of `Tensor` keyed by column name. targets: `Tensor` of shape [batch_size, 1] or [batch_size] target labels of dtype `int32` or `int64` in the range `[0, n_classes)`. mode: Defines whether this is training, evaluation or prediction. See `ModeKeys`. params: A dict of hyperparameters. The following hyperparameters are expected: * feature_columns: An iterable containing all the feature columns used by the model. * optimizer: An `SDCAOptimizer` instance. * weight_column_name: A string defining the weight feature column, or None if there are no weights. * loss_type: A string. Must be either "logistic_loss" or "hinge_loss". * update_weights_hook: A `SessionRunHook` object or None. Used to update model weights. Returns: predictions: A dict of `Tensor` objects. loss: A scalar containing the loss of the step. train_op: The op for training. Raises: ValueError: If `optimizer` is not an `SDCAOptimizer` instance. ValueError: If mode is not any of the `ModeKeys`. """ feature_columns = params["feature_columns"] optimizer = params["optimizer"] weight_column_name = params["weight_column_name"] loss_type = params.get("loss_type", None) update_weights_hook = params.get("update_weights_hook") if not isinstance(optimizer, sdca_optimizer.SDCAOptimizer): raise ValueError("Optimizer must be of type SDCAOptimizer") logits, columns_to_variables, bias = ( layers.weighted_sum_from_feature_columns( columns_to_tensors=features, feature_columns=feature_columns, num_outputs=1)) _add_bias_column(feature_columns, features, bias, targets, columns_to_variables) if loss_type is "hinge_loss": head = head_lib._binary_svm_head( # pylint: disable=protected-access weight_column_name=weight_column_name, enable_centered_bias=False) else: # pylint: disable=protected-access head = head_lib._multi_class_head(2, # pylint: disable=protected-access weight_column_name=weight_column_name, enable_centered_bias=False) def _train_op_fn(unused_loss): global_step = contrib_variables.get_global_step() sdca_model, train_op = optimizer.get_train_step(columns_to_variables, weight_column_name, loss_type, features, targets, global_step) if update_weights_hook is not None: update_weights_hook.set_parameters(sdca_model, train_op) return train_op return head.head_ops(features, targets, mode, _train_op_fn, logits)
def sdca_classifier_model_fn(features, targets, mode, params): """Linear classifier model_fn that uses the SDCA optimizer. Args: features: A dict of `Tensor` keyed by column name. targets: `Tensor` of shape [batch_size, 1] or [batch_size] target labels of dtype `int32` or `int64` in the range `[0, n_classes)`. mode: Defines whether this is training, evaluation or prediction. See `ModeKeys`. params: A dict of hyperparameters. The following hyperparameters are expected: * feature_columns: An iterable containing all the feature columns used by the model. * optimizer: An `SDCAOptimizer` instance. * weight_column_name: A string defining the weight feature column, or None if there are no weights. * loss_type: A string. Must be either "logistic_loss" or "hinge_loss". * update_weights_hook: A `SessionRunHook` object or None. Used to update model weights. Returns: predictions: A dict of `Tensor` objects. loss: A scalar containing the loss of the step. train_op: The op for training. Raises: ValueError: If `optimizer` is not an `SDCAOptimizer` instance. ValueError: If mode is not any of the `ModeKeys`. """ feature_columns = params["feature_columns"] optimizer = params["optimizer"] weight_column_name = params["weight_column_name"] loss_type = params.get("loss_type", None) update_weights_hook = params.get("update_weights_hook") if not isinstance(optimizer, sdca_optimizer.SDCAOptimizer): raise ValueError("Optimizer must be of type SDCAOptimizer") logits, columns_to_variables, bias = ( layers.weighted_sum_from_feature_columns( columns_to_tensors=features, feature_columns=feature_columns, num_outputs=1)) _add_bias_column(feature_columns, features, bias, targets, columns_to_variables) if loss_type is "hinge_loss": head = head_lib._binary_svm_head( # pylint: disable=protected-access weight_column_name=weight_column_name, enable_centered_bias=False) else: # pylint: disable=protected-access head = head_lib._multi_class_head( 2, # pylint: disable=protected-access weight_column_name=weight_column_name, enable_centered_bias=False) def _train_op_fn(unused_loss): global_step = contrib_variables.get_global_step() sdca_model, train_op = optimizer.get_train_step( columns_to_variables, weight_column_name, loss_type, features, targets, global_step) if update_weights_hook is not None: update_weights_hook.set_parameters(sdca_model, train_op) return train_op return head.head_ops(features, targets, mode, _train_op_fn, logits)