Tensorflow特征列

2018-08-02  本文已影响0人  YANWeichuan

特征列

特征列是将原始数据转换成机器能识别处理的一种格式。特征列在输入数据(由 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

上一篇下一篇

猜你喜欢

热点阅读