使用 tf.data 的 One-hot 编码混合了列
Posted
技术标签:
【中文标题】使用 tf.data 的 One-hot 编码混合了列【英文标题】:One-hot encoding using tf.data mixes up columns 【发布时间】:2020-02-04 19:29:53 【问题描述】:最少的工作示例
考虑以下 CSV 文件 (example.csv
)
animal,size,weight,category
lion,large,200,mammal
ostrich,large,150,bird
sparrow,small,0.1,bird
whale,large,3000,mammal
bat,small,0.2,mammal
snake,small,1,reptile
condor,medium,12,bird
目标是将所有分类值转换为 one-hot 编码。在 Tensorflow 2.0 中执行此操作的 standard 方法是使用 tf.data
。按照那个例子,上面处理数据集的代码是
import collections
import tensorflow as tf
# Load the dataset.
dataset = tf.data.experimental.make_csv_dataset(
'example.csv',
batch_size=5,
num_epochs=1,
shuffle=False)
# Specify the vocabulary for each category.
categories = collections.OrderedDict()
categories['animal'] = ['lion', 'ostrich', 'sparrow', 'whale', 'bat', 'snake', 'condor']
categories['size'] = ['large', 'medium', 'small']
categories['category'] = ['mammal', 'reptile', 'bird']
# Define the categorical feature columns.
categorical_columns = []
for feature, vocab in categories.items():
cat_col = tf.feature_column.categorical_column_with_vocabulary_list(
key=feature, vocabulary_list=vocab)
categorical_columns.append(tf.feature_column.indicator_column(cat_col))
# Retrieve the first batch and apply the one-hot encoding to it.
iterator = iter(dataset)
first_batch = next(iterator)
categorical_layer = tf.keras.layers.DenseFeatures(categorical_columns)
print(categorical_layer(first_batch).numpy())
问题
运行上面的代码,得到
[[1. 0. 0. 0. 0. 0. 0. 1. 0. 0. 1. 0. 0.]
[0. 1. 0. 0. 0. 0. 0. 0. 0. 1. 1. 0. 0.]
[0. 0. 1. 0. 0. 0. 0. 0. 0. 1. 0. 0. 1.]
[0. 0. 0. 1. 0. 0. 0. 1. 0. 0. 1. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 1. 0. 0. 0. 0. 1.]]
看起来最后两列 size
和 category
已被翻转,尽管事实上 categories
是一个 有序 字典并且在实际的数据集。就好像tf.feature_column.categorical_column_with_vocabulary_list()
对列进行了一些毫无根据的字母排序。
上面的原因是什么。这真的是本着tf.data
的精神进行one-hot编码的最佳方式吗?
【问题讨论】:
【参考方案1】:排序在哪里?
tf.feature_column.categorical_column_with_vocabulary_list()
没有进行排序。如果你打印categorical_columns
,你会看到这些列仍然按照你添加到feature_column的顺序:
[
IndicatorColumn(categorical_column=VocabularyListCategoricalColumn(key='animal', vocabulary_list=('lion', 'ostrich', 'sparrow', 'whale', 'bat', 'snake', 'condor'), dtype=tf.string, default_value=-1, num_oov_buckets=0)),
IndicatorColumn(categorical_column=VocabularyListCategoricalColumn(key='size', vocabulary_list=('large', 'medium', 'small'), dtype=tf.string, default_value=-1, num_oov_buckets=0)),
IndicatorColumn(categorical_column=VocabularyListCategoricalColumn(key='category', vocabulary_list=('mammal', 'reptile', 'bird'), dtype=tf.string, default_value=-1, num_oov_buckets=0))
]
排序发生在tf.keras.layers.DenseFeatures 对象中。
在代码中,您可以看到排序发生在here 的位置(我通过跟踪从tf.keras.layers.DenseFeatures 类到tensorflow.python.feature_column.dense_features.DenseFeatures 类到tensorflow.python.feature_column.feature_column_v2._BaseFeaturesLayer 类到_normalize_feature_columns 函数的类继承找到了这一点)。
为什么要排序?
那么为什么要排序呢? Elsewhere 在包含_normalize_feature_columns
函数(即数据排序的函数)的同一个文件中,有一个类似的排序函数与此注释:
# Sort the columns so the default collection name is deterministic even if the
# user passes columns from an unsorted collection, such as dict.values().
我认为这个解释也适用于为什么在使用 tf.keras.layers.DenseFeatures
类时对列进行排序。你的列和数据是一致的,但是 tensorflow 不假设输入是一致的,所以它会对其进行排序以确保顺序一致。
【讨论】:
感谢您的彻底调查。我认为 TensorFlow 在底层进行排序的基本原理会让许多人感到困惑,尽管......以上是关于使用 tf.data 的 One-hot 编码混合了列的主要内容,如果未能解决你的问题,请参考以下文章
独热编码(one-hot)是什么?什么数据类型需要进行独热编码?pandas如何进行独热编码(one-hot)?
机器学习入门-数据预处理-数字映射和one-hot编码 1.LabelEncoder(进行数据自编码) 2.map(进行字典的数字编码映射) 3.OnehotEncoder(进行one-hot编码)