特征列
特征列是将原始数据转换成机器能识别处理的一种格式。特征列在输入数据(由 input_fn 返回)与模型之间架起了桥梁。
在鸢尾花的识别实例中
# Feature columns describe how to use the input.
my_feature_columns = []
for key in train_x.keys():
my_feature_columns.append(tf.feature_column.numeric_column(key=key))
print(my_feature_columns)
打印my_feature_columns的结果:
[
_NumericColumn(key='SepalLength', shape=(1,), default_value=None, dtype=tf.float32, normalizer_fn=None),
_NumericColumn(key='SepalWidth', shape=(1,), default_value=None, dtype=tf.float32, normalizer_fn=None),
_NumericColumn(key='PetalLength', shape=(1,), default_value=None, dtype=tf.float32, normalizer_fn=None),
_NumericColumn(key='PetalWidth', shape=(1,), default_value=None, dtype=tf.float32, normalizer_fn=None)
]
Tensorflow支持的特征列
数值列 - tf.feature_column.numeric_column
定义
tf.feature_column.numeric_column(
key,
shape=(1,),
default_value=None,
dtype=tf.float32,
normalizer_fn=None
)
测试代码
import tensorflow as tf
test = {'test': [[0.], [1.], [2.], [3.], [4.], [5.]]}
column = tf.feature_column.numeric_column(key = 'test')
tensor = tf.feature_column.input_layer(test,[column])
with tf.Session() as session:
print(session.run([tensor]))
输出结果
[array([[0.],
[1.],
[2.],
[3.],
[4.],
[5.]], dtype=float32)]
分桶列 - tf.feature_column.bucketized_column
以表示房屋建造年份的原始数据为例。我们并非以标量数值列表示年份,而是将年份分成下列四个分桶:
将年份数据分成四个分桶
实际表示的意义如下表
日期范围 | 表示 |
---|---|
< 1960 年 | [1, 0, 0, 0] |
>= 1960 年但 < 1980 年 | [0, 1, 0, 0] |
>= 1980 年但 < 2000 年 | [0, 0, 1, 0] |
> 2000 年 | [0, 0, 0, 1] |
定义
tf.feature_column.bucketized_column(
source_column,
boundaries
)
实验代码
import tensorflow as tf
year={"year":[1958, 1978, 1981, 1999, 2005]}
numeric_feature_column = tf.feature_column.numeric_column("year")
bucketized_feature_column = tf.feature_column.bucketized_column(
source_column = numeric_feature_column,
boundaries = [1960, 1980, 2000])
tensor = tf.feature_column.input_layer(year,[bucketized_feature_column])
with tf.Session() as session:
print(session.run([tensor]))
输出结果
[array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]], dtype=float32)]
请注意,指定一个三元素边界矢量可创建一个四元素分桶矢量。
分类标识列 - tf.feature_column.categorical_column_with_identity
分类标识列映射是一种独热编码。正常情况下,我们要表示分类,4类可以用0,1,2,3这样的数字序列来表示。也可以用向量来表示, 将对应的位置为1,其他位置为0, 例如1表示为[0,1, 0, 0],3表示为[0,0, 0, 1]。
用向量表示的背后的优势是啥呢?是空间上的距离均等,在数据处理时获得相等的权重。如0,1,2,3表示,0和1之间的距离是1,0和3之间的距离3,而用向量表示后任意两个之间的距离为根号2。
定义
tf.feature_column.categorical_column_with_identity(
key,
num_buckets,
default_value=None
)
测试代码
import tensorflow as tf
test = {'cat': [1,3,2,0,3]}
column = tf.feature_column.categorical_column_with_identity(
key='cat',
num_buckets=4)
indicator = tf.feature_column.indicator_column(column)
tensor = tf.feature_column.input_layer(test, [indicator])
with tf.Session() as session:
print(session.run([tensor]))
输出结果
[array([[0., 1., 0., 0.],
[0., 0., 0., 1.],
[0., 0., 1., 0.],
[1., 0., 0., 0.],
[0., 0., 0., 1.]], dtype=float32)]
分类词汇列 - tf.feature_column.categorical_column_with_vocabulary_list
在分类标识列中,我们将数字直接表示为向量。我们不能直接向模型中输入字符串。相反,我们必须首先将字符串映射到数值或分类值。分类词汇列提供了一种将字符串表示为独热矢量的好方法。例如:
定义
tf.feature_column.categorical_column_with_vocabulary_list(
key,
vocabulary_list,
dtype=None,
default_value=-1,
num_oov_buckets=0
)
示例代码
import tensorflow as tf
test = {"test": ["kitchenware", "electronics", "sport", "shirt"]}
vocabulary_feature_column = tf.feature_column.categorical_column_with_vocabulary_list(
key="test",
vocabulary_list=["kitchenware", "electronics", "sports"])
indicator = tf.feature_column.indicator_column(vocabulary_feature_column)
tensor = tf.feature_column.input_layer(test, [indicator])
with tf.Session() as session:
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
print(session.run([tensor]))
输出结果
[array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 0.],
[0., 0., 0.]], dtype=float32)]
注意最后一个向量为[0, 0, 0, 0],因为shirt不在vocabulary_list里面
当词汇表很长时,需要输入的内容太多了。对于此类情况,请改为调用 tf.feature_column.categorical_column_with_vocabulary_file,以便将词汇放在单独的文件中。例如:
vocabulary_feature_column =
tf.feature_column.categorical_column_with_vocabulary_file(
key="test",
vocabulary_file="product_class.txt",
vocabulary_size=3)
哈希处列
前面介绍的方法只能处理比较少的类别。但是通常,类别的数量非常大,以至于无法为每个词汇或整数设置单独的类别,因为这会消耗太多内存。对于此类情况,我们可以反问自己:“我愿意为我的输入设置多少类别?”实际上,,tf.feature_column.categorical_column_with_hash_bucke 函数使您能够指定类别的数量。对于这种类型的特征列,模型会计算输入的哈希值,然后使用模运算符将其置于其中一个 hash_bucket_size
类别中。
定义
tf.feature_column.categorical_column_with_hash_bucket(
key,
hash_bucket_size,
dtype=tf.string
)
示例代码
import tensorflow as tf
test = {'chars': ['a','c','b','d','e','f','g','b']}
column = tf.feature_column.categorical_column_with_hash_bucket(
key='chars',
hash_bucket_size=5,
)
indicator = tf.feature_column.indicator_column(column)
tensor = tf.feature_column.input_layer(test, [indicator])
with tf.Session() as session:
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
print(session.run([tensor]))
输出结果
[array([[0., 0., 0., 0., 1.],
[0., 0., 1., 0., 0.],
[0., 0., 1., 0., 0.],
[1., 0., 0., 0., 0.],
[0., 1., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 1., 0., 0.]], dtype=float32)]
组合列 - tf.feature_column.crossed_column
通过将多个特征组合为一个特征称为特征组合,模型可学习每个特征组合的单独权重。将一个城市的纬度和经度表示为单独的特征用处不大;但是,将纬度和经度组合为一个特征则可精确定位位置。假设我们将亚特兰大表示为一个 100x100 的矩形网格区块,按纬度和经度的特征组合标识全部 10000 个区块。借助这种特征组合,模型可以针对与各个区块相关的房价条件进行训练,这比单独的经纬度信号强得多。
定义
tf.feature_column.crossed_column(
keys,
hash_bucket_size,
hash_key=None
)
示例代码
import tensorflow as tf
featrues = {
'longtitude': [19,61,30,9,45],
'latitude': [45,40,72,81,24]
}
longtitude = tf.feature_column.numeric_column('longtitude')
latitude = tf.feature_column.numeric_column('latitude')
longtitude_b_c = tf.feature_column.bucketized_column(longtitude, [33,66])
latitude_b_c = tf.feature_column.bucketized_column(latitude,[33,66])
column = tf.feature_column.crossed_column([longtitude_b_c, latitude_b_c], 12)
indicator = tf.feature_column.indicator_column(column)
tensor = tf.feature_column.input_layer(featrues, [indicator])
with tf.Session() as session:
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
print(session.run([tensor]))
输出结果
[array([[0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.]], dtype=float32)]
嵌入列 - tf.feature_column.embedding_column
指标列将每个类别视为独热矢量中的一个元素,其中匹配类别的值为 1,其余类别为 0。当数据数量特别大是,这个向量非常大,变得不容易处理。
嵌入列并非将数据表示为很多维度的独热矢量,而是将数据表示为低维度普通矢量,其中每个单元格可以包含任意数字,而不仅仅是 0 或 1。通过使每个单元格能够包含更丰富的数字,嵌入列包含的单元格数量远远少于指标列。
假设我们的输入样本包含多个不同的字词(取自仅有 81 个字词的有限词汇表)。我们进一步假设数据集在 4 个不同的样本中提供了下列输入字词:
为什么示例中的嵌入矢量大小为 3?下面的“公式”提供了关于嵌入维度数量的一般经验法则(类别数量开4次方):
embedding_dimensions = number_of_categories**0.25
定义:
tf.feature_column.embedding_column(
categorical_column,
dimension,
combiner='mean',
initializer=None,
ckpt_to_load_from=None,
tensor_name_in_ckpt=None,
max_norm=None,
trainable=True
)
示例代码
import tensorflow as tf
features = {'pets': ['dog','cat','rabbit','pig','mouse']}
pets_f_c = tf.feature_column.categorical_column_with_vocabulary_list(
'pets',
['cat','dog','rabbit','pig'],
dtype=tf.string,
default_value=-1)
column = tf.feature_column.embedding_column(pets_f_c, 3)
tensor = tf.feature_column.input_layer(features, [column])
with tf.Session() as session:
session.run(tf.global_variables_initializer())
session.run(tf.tables_initializer())
print(session.run([tensor]))
输出结果:
[array([[ 0.73085886, -0.47090757, 0.2534118 ],
[-0.1105554 , -0.4139628 , 0.13513751],
[ 1.0573914 , 0.00786706, 0.00665331],
[-0.36653328, 0.4501444 , 0.98030204],
[ 0. , 0. , 0. ]], dtype=float32)]
总结
参考
https://tensorflow.google.cn/get_started/feature_columns
https://www.jianshu.com/p/fceb64c790f3
网友评论