【问题标题】:Tensorflow One Hot Encoder?TensorFlow One 热编码器?
【发布时间】:2016-02-14 08:55:45
【问题描述】:

tensorflow 是否有类似于 scikit learn 的 one hot encoder 的东西来处理分类数据?使用 tf.string 的占位符会表现为分类数据吗?

我意识到我可以在将数据发送到 tensorflow 之前手动对其进行预处理,但是内置它非常方便。

【问题讨论】:

  • 想知道...是否可以训练分类器层来执行此操作?

标签: python machine-learning neural-network tensorflow


【解决方案1】:

从 TensorFlow 0.8 开始,现在有一个 native one-hot op, tf.one_hot 可以将一组稀疏标签转换为密集的 one-hot 表示。这是对 tf.nn.sparse_softmax_cross_entropy_with_logits 的补充,在某些情况下,它可以让您直接在稀疏标签上计算交叉熵,而不是将它们转换为 one-hot。

以前的答案,如果你想用旧方法做的话: @Salvador 的答案是正确的 - (曾经)没有本地操作可以做到这一点。但是,您可以使用 sparse-to-dense 运算符在 tensorflow 中本地执行,而不是在 numpy 中执行此操作:

num_labels = 10

# label_batch is a tensor of numeric labels to process
# 0 <= label < num_labels

sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(label_batch)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.pack([derived_size, num_labels])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)

输出标签是 batch_size x num_labels 的 one-hot 矩阵。

另请注意,截至 2016 年 2 月 12 日(我认为最终将成为 0.7 版本的一部分),TensorFlow 还具有 tf.nn.sparse_softmax_cross_entropy_with_logits 操作,在某些情况下可以让您进行训练而无需转换为one-hot 编码。

编辑添加:最后,您可能需要明确设置标签的形状。形状推断无法识别 num_labels 组件的大小。如果您不需要带 derived_size 的动态批量大小,可以简化。

于 2016 年 2 月 12 日编辑,以更改下面每条评论的 outshape 分配。

【讨论】:

  • 就像@CFB 下面已经提到的那样,由于 TensorFlow 的变化,这可能不再有效。抛出IndexError: list index out of range。分配 outshape = tf.pack([derived_size, num_labels]) 对我有用。
  • 代码对我有用。使用tf.nn.sparse_softmax_cross_entropy_with_logits会更好,我们可以转换为一个热并使用tf.nn.softmax_cross_entropy_with_logits
  • 如果您将其与 TensorFlow 1.0 一起使用,则需要进行一些更改。 tf.concat([indices, sparse_labels], 1)outshape = tf.stack([derived_size, num_labels])
【解决方案2】:

tf.one_hot() 在 TF 中可用并且易于使用。

假设您有 4 个可能的类别(猫、狗、鸟、人类)和 2 个实例(猫、人类)。所以你的depth=4 和你的indices=[0, 3]

import tensorflow as tf
res = tf.one_hot(indices=[0, 3], depth=4)
with tf.Session() as sess:
    print sess.run(res)

请记住,如果您提供 index=-1,您将在 one-hot 向量中得到全零。

旧答案,当此功能不可用时。

查看python documentation 后,我没有发现任何类似的东西。让我更加坚信它不存在的一件事是,他们在 their own example 中手动编写了 one_hot

def dense_to_one_hot(labels_dense, num_classes=10):
  """Convert class labels from scalars to one-hot vectors."""
  num_labels = labels_dense.shape[0]
  index_offset = numpy.arange(num_labels) * num_classes
  labels_one_hot = numpy.zeros((num_labels, num_classes))
  labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1
  return labels_one_hot

您也可以在scikitlearn 中执行此操作。

【讨论】:

  • 如果我们不知道 'depth' 或 'num_classes' 怎么办?与 sklearn.preprocessing.OneHotEncoder() 相比,这不是劣势吗?
【解决方案3】:

numpy 做到了!

import numpy as np
np.eye(n_labels)[target_vector]

【讨论】:

  • target_vector 在这里做什么?
  • @Rishabh Agrahari 这是 np.ndarray 的精美索引。假设目标向量是 [2, 0] 那么np.eye(n_labels)[target_vector] 将返回单位矩阵的第三行和第一行(按此顺序)。这很漂亮。
【解决方案4】:

一种对任何整数或整数列表进行一次性编码的简单而简短的方法:

a = 5 
b = [1, 2, 3]
# one hot an integer
one_hot_a = tf.nn.embedding_lookup(np.identity(10), a)
# one hot a list of integers
one_hot_b = tf.nn.embedding_lookup(np.identity(max(b)+1), b)

【讨论】:

  • 我收到 TypeError:传递给参数“indices”的值的 DataType float32 不在允许值列表中:int32、int64。可能是因为 TF 更新..
  • 看来您必须使用 tf.castab 显式转换为 int32
【解决方案5】:

TensorFlow 的最新版本(nightlies 甚至可能是 0.7.1)有一个名为 tf.one_hot 的操作,可以满足您的需求。看看吧!

另一方面,如果您有一个密集矩阵,并且想要在其中查找和聚合值,您可能需要使用 embedding_lookup 函数。

【讨论】:

【解决方案6】:

也许这是由于自 2015 年 11 月以来对 Tensorflow 的更改,但 @dga 的回答产生了错误。我确实让它与以下修改一起工作:

sparse_labels = tf.reshape(label_batch, [-1, 1])
derived_size = tf.shape(sparse_labels)[0]
indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
concated = tf.concat(1, [indices, sparse_labels])
outshape = tf.concat(0, [tf.reshape(derived_size, [1]), tf.reshape(num_labels, [1])])
labels = tf.sparse_to_dense(concated, outshape, 1.0, 0.0)

【讨论】:

    【解决方案7】:

    看看tf.nn.embedding_lookup。它从分类 ID 映射到它们的嵌入。

    有关如何将其用于输入数据的示例,请参阅here

    【讨论】:

      【解决方案8】:

      你可以使用tf.sparse_to_dense:

      sparse_indices 参数指示应该去哪里, output_shape 应该设置为可能的输出的数量(例如标签的数量),并且 sparse_values 应该是 1 具有所需的类型(它将确定输出的类型sparse_values 的类型)。

      【讨论】:

        【解决方案9】:

        在 Scikit Flow 中有embedding_ops 以及处理分类变量等的示例。

        如果您刚开始学习 TensorFlow,我建议您先在 TensorFlow/skflow 中尝试 examples,然后在您更熟悉 TensorFlow 后,您可以很容易地插入 TensorFlow 代码来构建自定义模型你想要(也有这方面的例子)。

        希望这些图像和文本理解示例可以帮助您入门,如果您遇到任何问题,请告诉我们! (在 SO 中发布问题或标记 skflow)。

        【讨论】:

          【解决方案10】:

          当前版本的 tensorflow 实现了以下用于创建 one-hot 张量的函数:

          https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html#one_hot

          【讨论】:

            【解决方案11】:

            正如@dga 上面提到的,Tensorflow 现在有tf.one_hot

            labels = tf.constant([5,3,2,4,1])
            highest_label = tf.reduce_max(labels)
            labels_one_hot = tf.one_hot(labels, highest_label + 1)
            
            array([[ 0.,  0.,  0.,  0.,  0.,  1.],
                   [ 0.,  0.,  0.,  1.,  0.,  0.],
                   [ 0.,  0.,  1.,  0.,  0.,  0.],
                   [ 0.,  0.,  0.,  0.,  1.,  0.],
                   [ 0.,  1.,  0.,  0.,  0.,  0.]], dtype=float32)
            

            你需要指定深度,否则你会得到一个修剪过的 one-hot 张量。

            如果您喜欢手动操作:

            labels = tf.constant([5,3,2,4,1])
            size = tf.shape(labels)[0]
            highest_label = tf.reduce_max(labels)
            labels_t = tf.reshape(labels, [-1, 1])
            indices = tf.reshape(tf.range(size), [-1, 1])
            idx_with_labels = tf.concat([indices, labels_t], 1)
            labels_one_hot = tf.sparse_to_dense(idx_with_labels, [size, highest_label + 1], 1.0)
            
            array([[ 0.,  0.,  0.,  0.,  0.,  1.],
                   [ 0.,  0.,  0.,  1.,  0.,  0.],
                   [ 0.,  0.,  1.,  0.,  0.,  0.],
                   [ 0.,  0.,  0.,  0.,  1.,  0.],
                   [ 0.,  1.,  0.,  0.,  0.,  0.]], dtype=float32)
            

            注意 tf.concat() 中的参数顺序

            【讨论】:

              【解决方案12】:

              有几种方法可以做到这一点。

              ans = tf.constant([[5, 6, 0, 0], [5, 6, 7, 0]]) #batch_size*max_seq_len
              labels = tf.reduce_sum(tf.nn.embedding_lookup(np.identity(10), ans), 1)
              
              >>> [[ 0.  0.  0.  0.  0.  1.  1.  0.  0.  0.]
              >>> [ 0.  0.  0.  0.  0.  1.  1.  1.  0.  0.]]
              

              另一种方法是。

              labels2 = tf.reduce_sum(tf.one_hot(ans, depth=10, on_value=1, off_value=0, axis=1), 2)
              
               >>> [[0 0 0 0 0 1 1 0 0 0]
               >>> [0 0 0 0 0 1 1 1 0 0]]
              

              【讨论】:

                【解决方案13】:

                我的@CFB 和@dga 示例的版本,为了便于理解而缩短了一点。

                num_labels = 10
                labels_batch = [2, 3, 5, 9]
                
                sparse_labels = tf.reshape(labels_batch, [-1, 1])
                derived_size = len(labels_batch)
                indices = tf.reshape(tf.range(0, derived_size, 1), [-1, 1])
                concated = tf.concat(1, [indices, sparse_labels]) 
                labels = tf.sparse_to_dense(concated, [derived_size, num_labels], 1.0, 0.0)
                

                【讨论】:

                  【解决方案14】:
                  In [7]: one_hot = tf.nn.embedding_lookup(np.eye(5), [1,2])
                  
                  In [8]: one_hot.eval()
                  Out[8]: 
                  array([[ 0.,  1.,  0.,  0.,  0.],
                         [ 0.,  0.,  1.,  0.,  0.]])
                  

                  适用于 TF 版本 1.3.0。截至 2017 年 9 月。

                  【讨论】:

                    【解决方案15】:

                    Tensorflow 2.0 兼容答案:您可以使用 Tensorflow Transform 有效地做到这一点。

                    使用 Tensorflow Transform 执行 One-Hot 编码的代码如下所示:

                    def get_feature_columns(tf_transform_output):
                      """Returns the FeatureColumns for the model.
                    
                      Args:
                        tf_transform_output: A `TFTransformOutput` object.
                    
                      Returns:
                        A list of FeatureColumns.
                      """
                      # Wrap scalars as real valued columns.
                      real_valued_columns = [tf.feature_column.numeric_column(key, shape=())
                                             for key in NUMERIC_FEATURE_KEYS]
                    
                      # Wrap categorical columns.
                      one_hot_columns = [
                          tf.feature_column.categorical_column_with_vocabulary_file(
                              key=key,
                              vocabulary_file=tf_transform_output.vocabulary_file_by_name(
                                  vocab_filename=key))
                          for key in CATEGORICAL_FEATURE_KEYS]
                    
                      return real_valued_columns + one_hot_columns
                    

                    有关更多信息,请参阅此Tutorial on TF_Transform

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 2016-03-19
                      • 1970-01-01
                      • 2023-03-04
                      • 1970-01-01
                      • 1970-01-01
                      • 2021-12-01
                      • 2020-06-16
                      相关资源
                      最近更新 更多