예제 #1
0
    def get_train_step(self, columns_to_variables, weight_column_name,
                       loss_type, features, targets, global_step):
        """Returns the training operation of an SdcaModel optimizer."""
        def _dense_tensor_to_sparse_feature_column(dense_tensor):
            """Returns SparseFeatureColumn for the input dense_tensor."""
            ignore_value = 0.0
            sparse_indices = array_ops.where(
                math_ops.not_equal(
                    dense_tensor,
                    math_ops.cast(ignore_value, dense_tensor.dtype)))
            sparse_values = array_ops.gather_nd(dense_tensor, sparse_indices)
            # TODO(sibyl-Aix6ihai, sibyl-vie3Poto): Makes this efficient, as now SDCA supports
            # very sparse features with weights and not weights.
            return SparseFeatureColumn(
                array_ops.reshape(
                    array_ops.split(value=sparse_indices,
                                    num_or_size_splits=2,
                                    axis=1)[0], [-1]),
                array_ops.reshape(
                    array_ops.split(value=sparse_indices,
                                    num_or_size_splits=2,
                                    axis=1)[1], [-1]),
                array_ops.reshape(math_ops.to_float(sparse_values), [-1]))

        def _training_examples_and_variables():
            """Returns dictionaries for training examples and variables."""
            batch_size = targets.get_shape()[0]

            # Iterate over all feature columns and create appropriate lists for dense
            # and sparse features as well as dense and sparse weights (variables) for
            # SDCA.
            # TODO(sibyl-vie3Poto): Reshape variables stored as values in column_to_variables
            # dict as 1-dimensional tensors.
            dense_features, sparse_features, sparse_feature_with_values = [], [], []
            dense_feature_weights = []
            sparse_feature_weights, sparse_feature_with_values_weights = [], []
            for column in sorted(columns_to_variables.keys(),
                                 key=lambda x: x.key):
                transformed_tensor = features[column]
                if isinstance(column, layers.feature_column._RealValuedColumn):  # pylint: disable=protected-access
                    # A real-valued column corresponds to a dense feature in SDCA. A
                    # transformed tensor corresponding to a RealValuedColumn should have
                    # rank at most 2. In order to be passed to SDCA, its rank needs to be
                    # exactly 2 (i.e., its shape should be [batch_size, column.dim]).
                    check_rank_op = control_flow_ops.Assert(
                        math_ops.less_equal(array_ops.rank(transformed_tensor),
                                            2),
                        ['transformed_tensor shouls have rank at most 2.'])
                    # Reshape to [batch_size, dense_column_dimension].
                    with ops.control_dependencies([check_rank_op]):
                        transformed_tensor = array_ops.reshape(
                            transformed_tensor,
                            [array_ops.shape(transformed_tensor)[0], -1])

                    dense_features.append(transformed_tensor)
                    # For real valued columns, the variables list contains exactly one
                    # element.
                    dense_feature_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column,
                                layers.feature_column._BucketizedColumn):  # pylint: disable=protected-access
                    # A bucketized column corresponds to a sparse feature in SDCA. The
                    # bucketized feature is "sparsified" for SDCA by converting it to a
                    # SparseFeatureColumn respresenting the one-hot encoding of the
                    # bucketized feature.
                    #
                    # TODO(sibyl-vie3Poto): Explore whether it is more efficient to translate a
                    # bucketized feature column to a dense feature in SDCA. This will
                    # likely depend on the number of buckets.
                    dense_bucket_tensor = column._to_dnn_input_layer(
                        transformed_tensor)  # pylint: disable=protected-access
                    sparse_feature_column = _dense_tensor_to_sparse_feature_column(
                        dense_bucket_tensor)
                    sparse_feature_with_values.append(sparse_feature_column)
                    # For bucketized columns, the variables list contains exactly one
                    # element.
                    sparse_feature_with_values_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(
                        column,
                    (
                        layers.feature_column._WeightedSparseColumn,  # pylint: disable=protected-access
                        layers.feature_column._CrossedColumn,  # pylint: disable=protected-access
                        layers.feature_column._SparseColumn)):  # pylint: disable=protected-access

                    if isinstance(column,
                                  layers.feature_column._WeightedSparseColumn):  # pylint: disable=protected-access
                        id_tensor = column.id_tensor(transformed_tensor)
                        weight_tensor = array_ops.reshape(
                            column.weight_tensor(transformed_tensor).values,
                            [-1])
                    else:
                        id_tensor = transformed_tensor
                        weight_tensor = array_ops.ones(
                            [array_ops.shape(id_tensor.indices)[0]],
                            dtypes.float32)

                    example_ids = array_ops.reshape(id_tensor.indices[:, 0],
                                                    [-1])

                    flat_ids = array_ops.reshape(id_tensor.values, [-1])
                    # Prune invalid IDs (< 0) from the flat_ids, example_ids, and
                    # weight_tensor.  These can come from looking up an OOV entry in the
                    # vocabulary (default value being -1).
                    is_id_valid = math_ops.greater_equal(flat_ids, 0)
                    flat_ids = array_ops.boolean_mask(flat_ids, is_id_valid)
                    example_ids = array_ops.boolean_mask(
                        example_ids, is_id_valid)
                    weight_tensor = array_ops.boolean_mask(
                        weight_tensor, is_id_valid)

                    projection_length = math_ops.reduce_max(flat_ids) + 1
                    # project ids based on example ids so that we can dedup ids that
                    # occur multiple times for a single example.
                    projected_ids = projection_length * example_ids + flat_ids

                    # Remove any redudant ids.
                    ids, idx = array_ops.unique(projected_ids)
                    # Keep only one example id per duplicated ids.
                    example_ids_filtered = math_ops.unsorted_segment_min(
                        example_ids, idx,
                        array_ops.shape(ids)[0])

                    # reproject ids back feature id space.
                    reproject_ids = (ids -
                                     projection_length * example_ids_filtered)

                    weights = array_ops.reshape(
                        math_ops.unsorted_segment_sum(weight_tensor, idx,
                                                      array_ops.shape(ids)[0]),
                        [-1])
                    sparse_feature_with_values.append(
                        SparseFeatureColumn(example_ids_filtered,
                                            reproject_ids, weights))
                    sparse_feature_with_values_weights.append(
                        columns_to_variables[column][0])
                else:
                    raise ValueError(
                        'SDCAOptimizer does not support column type %s.' %
                        type(column).__name__)

            example_weights = array_ops.reshape(
                features[weight_column_name], shape=[
                    -1
                ]) if weight_column_name else array_ops.ones([batch_size])
            example_ids = features[self._example_id_column]
            sparse_feature_with_values.extend(sparse_features)
            sparse_feature_with_values_weights.extend(sparse_feature_weights)
            examples = dict(sparse_features=sparse_feature_with_values,
                            dense_features=dense_features,
                            example_labels=math_ops.to_float(
                                array_ops.reshape(targets, shape=[-1])),
                            example_weights=example_weights,
                            example_ids=example_ids)
            sdca_variables = dict(
                sparse_features_weights=sparse_feature_with_values_weights,
                dense_features_weights=dense_feature_weights)
            return examples, sdca_variables

        training_examples, training_variables = _training_examples_and_variables(
        )
        sdca_model = sdca_ops.SdcaModel(
            examples=training_examples,
            variables=training_variables,
            options=dict(
                symmetric_l1_regularization=self._symmetric_l1_regularization,
                symmetric_l2_regularization=self._symmetric_l2_regularization,
                adaptive=self._adaptive,
                num_loss_partitions=self._num_loss_partitions,
                num_table_shards=self._num_table_shards,
                loss_type=loss_type))
        train_op = sdca_model.minimize(global_step=global_step)
        return sdca_model, train_op
예제 #2
0
    def get_train_step(self, linear_feature_columns, weight_column_name,
                       loss_type, features, targets, columns_to_variables,
                       global_step):
        """Returns the training operation of an SdcaModel optimizer."""

        # TODO(sibyl-vie3Poto): Rename this method to convert_to_sparse_tensor and move under
        # contrib/framework.
        def _dense_to_sparse_tensor(dense_tensor):
            """Returns a SparseTensor for the input dense_tensor."""
            ignore_value = 0.0
            sparse_indices = array_ops.where(
                math_ops.not_equal(
                    dense_tensor,
                    math_ops.cast(ignore_value, dense_tensor.dtype)))
            sparse_values = array_ops.gather_nd(dense_tensor, sparse_indices)
            # SparseTensor needs the shape to be converted to int64.
            int64_shape = math_ops.to_int64(array_ops.shape(dense_tensor))
            return ops.SparseTensor(sparse_indices,
                                    sparse_values,
                                    shape=int64_shape)

        def _training_examples_and_variables():
            """Returns dictionaries for training examples and variables."""
            batch_size = targets.get_shape()[0]

            # Iterate over all feature columns and create appropriate lists for dense
            # and sparse features as well as dense and sparse weights (variables) for
            # SDCA.
            # TODO(sibyl-vie3Poto): Reshape variables stored as values in column_to_variables
            # dict as 1-dimensional tensors.
            dense_features, sparse_features = [], []
            dense_features_weights, sparse_features_weights = [], []
            # pylint: disable=protected-access
            for column in sorted(set(linear_feature_columns),
                                 key=lambda x: x.key):
                transformed_tensor = features[column]
                if isinstance(column, layers.feature_column._RealValuedColumn):
                    # A real-valued column corresponds to a dense feature in SDCA.
                    if column.dimension != 1:
                        raise ValueError(
                            "Invalid column dimension %d for column %s. SDCAOptimizer "
                            "supports only 1-dimensional dense feature columns."
                            % (column.dimension, column.name))

                    dense_features.append(
                        array_ops.reshape(transformed_tensor, shape=[-1]))
                    # For real valued columns, the variables list contains exactly one
                    # element.
                    dense_features_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column,
                                layers.feature_column._BucketizedColumn):
                    # A bucketized column corresponds to a sparse feature in SDCA. The
                    # bucketized feature is "sparsified" for SDCA by converting it to a
                    # SparseTensor respresenting the one-hot encoding of the bucketized
                    # feature.
                    dense_bucket_tensor = column.to_dnn_input_layer(
                        transformed_tensor)
                    sparse_bucket_tensor = _dense_to_sparse_tensor(
                        dense_bucket_tensor)
                    sparse_features.append(sparse_bucket_tensor)
                    # For bucketized columns, the variables list contains exactly one
                    # element.
                    sparse_features_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column, (layers.feature_column._CrossedColumn,
                                         layers.feature_column._SparseColumn)):
                    weights_tensor = ops.SparseTensor(
                        indices=transformed_tensor.indices,
                        values=array_ops.ones_like(transformed_tensor.values),
                        shape=transformed_tensor.shape)
                    sparse_features_tensor = sparse_ops.sparse_merge(
                        transformed_tensor, weights_tensor, column.length)
                    sparse_features.append(
                        math_ops.to_float(sparse_features_tensor))
                    sparse_features_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column,
                                layers.feature_column._WeightedSparseColumn):
                    id_tensor = column.id_tensor(transformed_tensor)
                    weight_tensor = column.weight_tensor(transformed_tensor)
                    sparse_features_tensor = sparse_ops.sparse_merge(
                        id_tensor,
                        weight_tensor,
                        column.length,
                        name="{}_sparse_merge".format(column.name))
                    sparse_features.append(
                        math_ops.to_float(sparse_features_tensor,
                                          name="{}_to_float".format(
                                              column.name)))
                    sparse_features_weights.append(
                        columns_to_variables[column][0])
                else:
                    raise ValueError(
                        "SDCAOptimizer does not support column type %s." %
                        type(column).__name__)
            # pylint: enable=protected-access

            example_weights = array_ops.reshape(
                features[weight_column_name], shape=[
                    -1
                ]) if weight_column_name else array_ops.ones([batch_size])
            example_ids = features[self._example_id_column]
            examples = dict(sparse_features=sparse_features,
                            dense_features=dense_features,
                            example_labels=math_ops.to_float(
                                array_ops.reshape(targets, shape=[-1])),
                            example_weights=example_weights,
                            example_ids=example_ids)
            sdca_variables = dict(
                sparse_features_weights=sparse_features_weights,
                dense_features_weights=dense_features_weights)
            return examples, sdca_variables

        options = dict(
            symmetric_l1_regularization=self._symmetric_l1_regularization,
            symmetric_l2_regularization=self._symmetric_l2_regularization,
            loss_type=loss_type)
        training_examples, training_variables = _training_examples_and_variables(
        )
        sdca_model = sdca_ops.SdcaModel(container=uuid.uuid4().hex,
                                        examples=training_examples,
                                        variables=training_variables,
                                        options=options)
        return sdca_model.minimize(global_step=global_step)
예제 #3
0
  def get_train_step(self, columns_to_variables,
                     weight_column_name, loss_type, features, targets,
                     global_step):
    """Returns the training operation of an SdcaModel optimizer."""

    def _tensor_to_sparse_feature_column(dense_tensor):
      """Returns SparseFeatureColumn for the input dense_tensor."""
      ignore_value = 0.0
      sparse_indices = array_ops.where(math_ops.not_equal(
          dense_tensor, math_ops.cast(ignore_value, dense_tensor.dtype)))
      sparse_values = array_ops.gather_nd(dense_tensor, sparse_indices)
      # TODO(sibyl-Aix6ihai, sibyl-vie3Poto): Makes this efficient, as now SDCA supports
      # very sparse features with weights and not weights.
      return sdca_ops.SparseFeatureColumn(
          array_ops.reshape(
              array_ops.split(1, 2, sparse_indices)[0], [-1]),
          array_ops.reshape(
              array_ops.split(1, 2, sparse_indices)[1], [-1]),
          array_ops.reshape(
              math_ops.to_float(sparse_values), [-1]))

    def _training_examples_and_variables():
      """Returns dictionaries for training examples and variables."""
      batch_size = targets.get_shape()[0]

      # Iterate over all feature columns and create appropriate lists for dense
      # and sparse features as well as dense and sparse weights (variables) for
      # SDCA.
      # TODO(sibyl-vie3Poto): Reshape variables stored as values in column_to_variables
      # dict as 1-dimensional tensors.
      dense_features, sparse_features, sparse_feature_with_values = [], [], []
      dense_feature_weights = []
      sparse_feature_weights, sparse_feature_with_values_weights = [], []
      # pylint: disable=protected-access
      for column in sorted(columns_to_variables.keys(), key=lambda x: x.key):
        transformed_tensor = features[column]
        if isinstance(column, layers.feature_column._RealValuedColumn):
          # A real-valued column corresponds to a dense feature in SDCA. A
          # transformed tensor corresponding to a RealValuedColumn has rank 2
          # (its shape is typically [batch_size, column.dimension]) and so it
          # can be passed to SDCA as is.
          dense_features.append(transformed_tensor)
          # For real valued columns, the variables list contains exactly one
          # element.
          dense_feature_weights.append(columns_to_variables[column][0])
        elif isinstance(column, layers.feature_column._BucketizedColumn):
          # A bucketized column corresponds to a sparse feature in SDCA. The
          # bucketized feature is "sparsified" for SDCA by converting it to a
          # SparseFeatureColumn respresenting the one-hot encoding of the
          # bucketized feature.
          dense_bucket_tensor = layers.input_from_feature_columns(
              {column: transformed_tensor}, [column])
          sparse_feature_column = _tensor_to_sparse_feature_column(
              dense_bucket_tensor)
          sparse_feature_with_values.append(sparse_feature_column)
          # For bucketized columns, the variables list contains exactly one
          # element.
          sparse_feature_with_values_weights.append(
              columns_to_variables[column][0])
        elif isinstance(column, (layers.feature_column._CrossedColumn,
                                 layers.feature_column._SparseColumn)):
          sparse_features.append(sdca_ops.SparseFeatureColumn(
              array_ops.reshape(
                  array_ops.split(1, 2, transformed_tensor.indices)[0], [-1]),
              array_ops.reshape(transformed_tensor.values, [-1]), None))
          sparse_feature_weights.append(columns_to_variables[column][0])
        elif isinstance(column, layers.feature_column._WeightedSparseColumn):
          id_tensor = column.id_tensor(transformed_tensor)
          weight_tensor = column.weight_tensor(transformed_tensor)
          sparse_feature_with_values.append(sdca_ops.SparseFeatureColumn(
              array_ops.reshape(
                  array_ops.split(1, 2, id_tensor.indices)[0], [-1]),
              array_ops.reshape(id_tensor.values, [-1]), array_ops.reshape(
                  weight_tensor.values, [-1])))
          sparse_feature_with_values_weights.append(
            columns_to_variables[column][0])
        else:
          raise ValueError('SDCAOptimizer does not support column type %s.' %
                           type(column).__name__)
      # pylint: enable=protected-access

      example_weights = array_ops.reshape(
          features[weight_column_name],
          shape=[-1]) if weight_column_name else array_ops.ones([batch_size])
      example_ids = features[self._example_id_column]
      sparse_feature_with_values.extend(sparse_features)
      sparse_feature_with_values_weights.extend(sparse_feature_weights)
      examples = dict(sparse_features=sparse_feature_with_values,
                      dense_features=dense_features,
                      example_labels=math_ops.to_float(array_ops.reshape(
                          targets, shape=[-1])),
                      example_weights=example_weights,
                      example_ids=example_ids)
      sdca_variables = dict(
          sparse_features_weights=sparse_feature_with_values_weights,
          dense_features_weights=dense_feature_weights)
      return examples, sdca_variables

    training_examples, training_variables = _training_examples_and_variables()
    sdca_model = sdca_ops.SdcaModel(
        examples=training_examples,
        variables=training_variables,
        options=dict(
            symmetric_l1_regularization=self._symmetric_l1_regularization,
            symmetric_l2_regularization=self._symmetric_l2_regularization,
            num_loss_partitions=self._num_loss_partitions,
            num_table_shards=self._num_table_shards,
            loss_type=loss_type))
    train_op = sdca_model.minimize(global_step=global_step)
    return sdca_model, train_op
예제 #4
0
    def get_train_step(self, columns_to_variables, weight_column_name,
                       loss_type, features, targets, global_step):
        """Returns the training operation of an SdcaModel optimizer."""
        def _dense_tensor_to_sparse_feature_column(dense_tensor):
            """Returns SparseFeatureColumn for the input dense_tensor."""
            ignore_value = 0.0
            sparse_indices = array_ops.where(
                math_ops.not_equal(
                    dense_tensor,
                    math_ops.cast(ignore_value, dense_tensor.dtype)))
            sparse_values = array_ops.gather_nd(dense_tensor, sparse_indices)
            # TODO (sibyl-Aix6ihai, sibyl-vie3Poto): Makes this efficient, as now SDCA supports id:1146 gh:1147
            # very sparse features with weights and not weights.
            return SparseFeatureColumn(
                array_ops.reshape(
                    array_ops.split(value=sparse_indices,
                                    num_or_size_splits=2,
                                    axis=1)[0], [-1]),
                array_ops.reshape(
                    array_ops.split(value=sparse_indices,
                                    num_or_size_splits=2,
                                    axis=1)[1], [-1]),
                array_ops.reshape(math_ops.to_float(sparse_values), [-1]))

        def _training_examples_and_variables():
            """Returns dictionaries for training examples and variables."""
            batch_size = targets.get_shape()[0]

            # Iterate over all feature columns and create appropriate lists for dense
            # and sparse features as well as dense and sparse weights (variables) for
            # SDCA.
            # TODO (sibyl-vie3Poto): Reshape variables stored as values in column_to_variables id:814 gh:815
            # dict as 1-dimensional tensors.
            dense_features, sparse_features, sparse_feature_with_values = [], [], []
            dense_feature_weights = []
            sparse_feature_weights, sparse_feature_with_values_weights = [], []
            for column in sorted(columns_to_variables.keys(),
                                 key=lambda x: x.key):
                transformed_tensor = features[column]
                if isinstance(column, layers.feature_column._RealValuedColumn):  # pylint: disable=protected-access
                    # A real-valued column corresponds to a dense feature in SDCA. A
                    # transformed tensor corresponding to a RealValuedColumn should have
                    # rank at most 2. In order to be passed to SDCA, its rank needs to be
                    # exactly 2 (i.e., its shape should be [batch_size, column.dim]).
                    check_rank_op = control_flow_ops.Assert(
                        math_ops.less_equal(array_ops.rank(transformed_tensor),
                                            2),
                        ['transformed_tensor shouls have rank at most 2.'])
                    # Reshape to [batch_size, dense_column_dimension].
                    with ops.control_dependencies([check_rank_op]):
                        transformed_tensor = array_ops.reshape(
                            transformed_tensor,
                            [array_ops.shape(transformed_tensor)[0], -1])

                    dense_features.append(transformed_tensor)
                    # For real valued columns, the variables list contains exactly one
                    # element.
                    dense_feature_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column,
                                layers.feature_column._BucketizedColumn):  # pylint: disable=protected-access
                    # A bucketized column corresponds to a sparse feature in SDCA. The
                    # bucketized feature is "sparsified" for SDCA by converting it to a
                    # SparseFeatureColumn respresenting the one-hot encoding of the
                    # bucketized feature.
                    #
                    # TODO (sibyl-vie3Poto): Explore whether it is more efficient to translate a id:755 gh:756
                    # bucketized feature column to a dense feature in SDCA. This will
                    # likely depend on the number of buckets.
                    dense_bucket_tensor = column._to_dnn_input_layer(
                        transformed_tensor)  # pylint: disable=protected-access
                    sparse_feature_column = _dense_tensor_to_sparse_feature_column(
                        dense_bucket_tensor)
                    sparse_feature_with_values.append(sparse_feature_column)
                    # For bucketized columns, the variables list contains exactly one
                    # element.
                    sparse_feature_with_values_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(
                        column,
                    (
                        layers.feature_column._CrossedColumn,  # pylint: disable=protected-access
                        layers.feature_column._SparseColumn)):  # pylint: disable=protected-access
                    sparse_features.append(
                        SparseFeatureColumn(
                            array_ops.reshape(
                                array_ops.split(
                                    value=transformed_tensor.indices,
                                    num_or_size_splits=2,
                                    axis=1)[0], [-1]),
                            array_ops.reshape(transformed_tensor.values, [-1]),
                            None))
                    sparse_feature_weights.append(
                        columns_to_variables[column][0])
                elif isinstance(column,
                                layers.feature_column._WeightedSparseColumn):  # pylint: disable=protected-access
                    id_tensor = column.id_tensor(transformed_tensor)
                    weight_tensor = column.weight_tensor(transformed_tensor)
                    sparse_feature_with_values.append(
                        SparseFeatureColumn(
                            array_ops.reshape(
                                array_ops.split(value=id_tensor.indices,
                                                num_or_size_splits=2,
                                                axis=1)[0], [-1]),
                            array_ops.reshape(id_tensor.values, [-1]),
                            array_ops.reshape(weight_tensor.values, [-1])))
                    sparse_feature_with_values_weights.append(
                        columns_to_variables[column][0])
                else:
                    raise ValueError(
                        'SDCAOptimizer does not support column type %s.' %
                        type(column).__name__)

            example_weights = array_ops.reshape(
                features[weight_column_name], shape=[
                    -1
                ]) if weight_column_name else array_ops.ones([batch_size])
            example_ids = features[self._example_id_column]
            sparse_feature_with_values.extend(sparse_features)
            sparse_feature_with_values_weights.extend(sparse_feature_weights)
            examples = dict(sparse_features=sparse_feature_with_values,
                            dense_features=dense_features,
                            example_labels=math_ops.to_float(
                                array_ops.reshape(targets, shape=[-1])),
                            example_weights=example_weights,
                            example_ids=example_ids)
            sdca_variables = dict(
                sparse_features_weights=sparse_feature_with_values_weights,
                dense_features_weights=dense_feature_weights)
            return examples, sdca_variables

        training_examples, training_variables = _training_examples_and_variables(
        )
        sdca_model = sdca_ops.SdcaModel(
            examples=training_examples,
            variables=training_variables,
            options=dict(
                symmetric_l1_regularization=self._symmetric_l1_regularization,
                symmetric_l2_regularization=self._symmetric_l2_regularization,
                num_loss_partitions=self._num_loss_partitions,
                num_table_shards=self._num_table_shards,
                loss_type=loss_type))
        train_op = sdca_model.minimize(global_step=global_step)
        return sdca_model, train_op