特征处理之tf.feature_column

1. 整体介绍

特征数据主要分为categorical和dense两类,可以使用tf.feature_column做相关的处理,它通过对特征处理将数据输入网络中。

特征数据:为dict格式

在这里插入图片描述

2 功能介绍:

用户API返回值
离散数值列numeric_column数值
指标列indicator_columnone/multi hot
emb嵌入列embedding_columnembedding(N)
分桶列bucketized_columnone-hot
直接类别列categorical_column_with_identityone-hot
文件类别列categorical_column_with_vocabulary_fileone-hot
数组类别列categorical_column_with_vocabulary_listone-hot
Hash类别类categorical_column_with_hash_bucketone-hot
特征交叉列crossed_columnone-hot

Tips: 这里 Categorical Column 需要通过 indicator_column 或者 embedding_column 转换为 Dense Column 才能应用于深度模型输入。上述标红的 feature_column 是最外层返回的特征列,只有用他们包装其他特征列才可以得到模型正确的输入。

3 使用流程

  1. 构建特征列: feature_column = tf.feature_column...
  2. 构建features{ },其中key要与feature_columnkey对齐,features = {key:value}
  3. 构建特征层 layer = tf.keras.layers.DenseFeatures(feature_column|| List(feature_column))
  4. 将features 喂给特征层DenseFeaturesinput = layer(features)

将带输入的样本数据封装成字典类型的对象。

4. 具体应用

4.1 数值型

4.1.1 直接返回对应数值

直接使用 numeric_column,输入对应的数值特征:直接返回对应数值

number = tf.feature_column.numeric_column("number", normalizer_fn=lambda x: (x - 1.0) / 2.0)
feature_layer = tf.keras.layers.DenseFeatures(number)

feature_dict = {"number": [1.1, 1.2, 1.3]} # 特征列字典
output = feature_layer(feature_dict)
print(output)

Tips: normalizer_fn 数值类型还支持归一化函数,可以传入函数或者 lambda 表达式表征归一化方法

4.1.2 数值离散分桶

使用: numeric_column + bucketized_column

  • numeric_column: 获取离散数值
  • buketized_column: 离散数值分桶,需给定 boundaries
cos_index = tf.feature_column.bucketized_column(
    tf.feature_column.numeric_column(key='cos', shape=(1,),
                                     default_value=0,
                                     dtype=tf.dtypes.float32),
    boundaries=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
# 假设 boundaries 有9个元素,则原始数值会被分到10个桶中,并得到 10 维的 one-hot 向量

product_dict = {"cos": np.random.random(size=(10, 1))}
feature_layer = tf.keras.layers.DenseFeatures(cos_index)
output = feature_layer(product_dict)
print(output)

4.2 类别特征

4.2.1 列表分桶

使用categorical_column_with_vocabulary_list (通过列表标识所有种类)+ indicator_column

age = tf.feature_column.indicator_column(
    tf.feature_column.categorical_column_with_vocabulary_list(key='age', vocabulary_list=(
        '50s', '60s', '70s', '80s', '90s'), num_oov_buckets=0, default_value=0))
# list的长度代表输出 one-hot 的维度,通过字符串列表与传入的字符串进行匹配

feature_layer = tf.keras.layers.DenseFeatures(age)
feature_dict = {"age": ["90s", "70s"]}
output = feature_layer(feature_dict)
print(output)

4.2.2 文件分桶

使用categorical_column_with_vocabulary_file(通过文件标识所有种类) + indicator_column

Tips: 与上面唯一区别就是分类依据从 List 放到了 File 中,主要针对类别特别多的情况。加入 File 中放入如下类别,则 feature_column 会顺序编号代表他们的 index

在这里插入图片描述

file = tf.feature_column.indicator_column(
    tf.feature_column.categorical_column_with_vocabulary_file(key='app',
    vocabulary_file='../FileList/app_list', vocabulary_size=10, num_oov_buckets=0,
    default_value=0))
feature_dict = {"app": ["a", "b", "c", "d"]}
feature_layer = tf.keras.layers.DenseFeatures(file)
output = feature_layer(feature_dict)
print(output)
    

4.2.3 Hash分桶

categorical_column_with_hash_bucket + indicator_column
将原始特征 Hash 分桶得到 one-hot

Tips:

Hash 规则需要指定好传入数据的类型,例如 string 还是 int 还是其他等等

hash_word = tf.feature_column.indicator_column(
    tf.feature_column.categorical_column_with_hash_bucket(key='id',
    hash_bucket_size=100, dtype=tf.dtypes.string))
feature_dict = {"id": ["123", "234", "345", "456"]}
feature_layer = tf.keras.layers.DenseFeatures(hash_word)
output = feature_layer(feature_dict)
print(output)
   

4.2.4 multi_hot 返回值

categorical_column_with_identity + indicator_column
上面的类别需要通过文件,列表,Hash获取映射关系,将特征值映射到数字索引,identity 属于直接类型,即你告诉我你是哪个类别,无需映射,直接输入类别。

Tips: features 中多维类别数组需要保持相同维度,如果不够可以使用默认值填充

# 返回 multi_hot 向量,向量维度由 identity 定义的分类类别数量决定
multi_category = tf.feature_column.indicator_column(
    tf.feature_column.categorical_column_with_identity("multi", 50))
feature_dict = {"multi": [[4, 5, 7, 10], [1, 2, 9, 30], [0, 1, 2, 3]]}  # 必须是大于等于0的数,不能是负数
feature_layer = tf.keras.layers.DenseFeatures(multi_category)
output = feature_layer(feature_dict)
print(output)

4.2.5 向量化

categorical_column_with_hash_bucket ( hash生成类别特征向量)+ embedding_column(映射到多维向量)

embedding = tf.feature_column.embedding_column(tf.feature_column.categorical_column_with_hash_bucket(
   'embedding', hash_bucket_size=3, dtype=tf.string), dimension=10)
feature_dict = {"embedding": [["a"], ["b"], ["c"]]}
feature_layer = tf.keras.layers.DenseFeatures(embedding)
output = feature_layer(feature_dict)
print(output)
  

这里先使用 categorical_column_with_hash_bucket 生成特征 one-hot 向量,随后通过embedding_column 映射到多维向量,这里 dimension 表征映射后的向量,这里有点像为原始特征接入一个 hash_bucket_size x dimensiondense 层,将 one-hot 转化到对应 embedding,这里默认的 TrainableTrue

4.3 交叉特征

crossed_column : 将多个特征结合在一起并重新hash得到新的特征,相当于做了一次特征交叉

sex = tf.feature_column.categorical_column_with_identity("sex", num_buckets=2)
age = tf.feature_column.categorical_column_with_identity("age", num_buckets=10)
feature_cross = tf.feature_column.crossed_column([sex, age], hash_bucket_size=20)
feature_cross = tf.feature_column.indicator_column(feature_cross)
feature_dict = {"sex": [[0], [0], [1]], "age": [[1], [3], [5]]}
feature_layer = tf.keras.layers.DenseFeatures(feature_cross)
output = feature_layer(feature_dict)
print(output)

这里使用年龄与性别特征交叉,采用 identity 特征列,所以需要直接给出类别,sex 共分两类,age共分两类,所以 num_buckets 为 2 和 10,crossed_columnhash_bucket_size 并不一定需要等于 2 * 10 = 20,也可以大于,小于,只要大于0即可,这涉及到信息压缩和维度选择的问题,可以根据实际场景自定义。最后返回的 Embedding 维度以 hash_bucket_size 为准。

4.4 多特征列

上面介绍的方法都是针对单个或多个特征得到最终的一个特征Tensor,实际应用场景中特征工程都是根据一条样本生成多个特征的特征列,所以常用的是将多个特征列同时应用。

feature_1 = tf.feature_column.numeric_column("feat1")
feature_2 = tf.feature_column.categorical_column_with_hash_bucket(
    "feat2", hash_bucket_size=3)
feature_3 = tf.feature_column.embedding_column(
    feature_2, dimension=3)
feature_4 = tf.feature_column.indicator_column(feature_2)
feature_dict = {
    "feat1": [[1.1], [2.2]],
    "feat2": [["hello"], ["world"]]
}
# feature1 常数 feature2 Emb feature3 one-hot
feature_layer = tf.keras.layers.DenseFeatures([feature_1, feature_3, feature_4])
output = feature_layer(feature_dict)
print(output)

传参:

多个 feature_column 通过 List 传入,特征工程返回的顺序与列表顺序一致,这里 features 的顺序不用按照 feature_column List 的顺序传入,因为 feature_columnfeatures 通过 key 关联,只有找不到 key 或者 key 对应的 value 不合规时才会出问题。

返回值:

  1. feat1 为 numeric_column,直接返回数值
  2. feat2 为 categorical_column_with_hash_bucket,dimention 为3,为
    feat3,feat4提供支持
  3. feat3 为 embedding_column 返回维度为3的 Emb Tensor
  4. feat4 为 indicator_column 返回维度为3的 One Hot Tensor

共7维,分别为 number-1 + emb-3 + one-hot-3,复杂的特殊工程大家也只需要根据数据类型,扩展 feature_column 的list和样本即可。

5. 总结

经过上面的实例展示了开篇图中所有9种 feature_column 的使用方法,现在我们可以处理:

5.1离散特征:

  • 直接得到数值,也可归一化
  • 通过 List,File,idnetity 得到 one-hot
  • hash得到one-hot
  • 映射得到 multi_hot
  • 得到 embedding 向量

5.2 连续特征:

  • 直接得到数值,也可归一化
  • 通过 hash_bucket 做特征分桶并得到 one-hot
  • 得到 embedding 向量

5.3 组合特征:

将多类型特征组合并重新hash得到新的特征

通过 List 将上述特征列传入 Layer,配合样本就可以得到一套特征工程,我们只需要保证没有脏数据,做好异常处理即可得到模型需要的 Input,后续可以通过 Esitimator,Keras 配合模型获得结果。

Feature Column 的优点通过上面的例子也可以看出来,只需要定义好特征的类型和处理方式,剩下的按 key 扔到 features 里即可,非常的省事,但是也存在缺点和不足,由于 python 的运算效率较低,在一些大规模的工业场景下 feature_column 的吞吐和处理效率可能会偏低,不过这不影响它在常规机器学习中应用的位置。

5.4 补充

1. weighted_categorical_column
有时候我们需要给一个类别特征赋予一定的权重,比如给用户行为序列按照行为发生的时间到某个特定时间的差来计算不同的权重,这是可以用到weighted_categorical_column

color_data = {'color': [['R'], ['G'], ['B'], ['A']],
              'weight': [[1.0], [2.0], [4.0], [8.0]]}  # 4行样本

color_column = feature_column.categorical_column_with_vocabulary_list(
    'color', ['R', 'G', 'B'], dtype=tf.string, default_value=-1
)

color_weight_categorical_column = feature_column.weighted_categorical_column(color_column, 'weight')

2. shared_embeddings
用途:同一个类型的变量,共享同一个空间

watched_video_id = categorical_column_with_vocabulary_file(
    'watched_video_id', video_vocabulary_file, video_vocabulary_size)
impression_video_id = categorical_column_with_vocabulary_file(
    'impression_video_id', video_vocabulary_file, video_vocabulary_size)
 # 传入参数 category_column_list
columns = shared_embedding_columns(
    [watched_video_id, impression_video_id], dimension=10)


6. 应用

  1. 如何在TensorFlow中处理可变长度特征

  2. tf2.x中如何处理多值离散特征

使用feature_columns接口

# 定义所有商品的集合
good_sets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
# 假设现在有两个用户,用户a和b a点击了a,b,c b点击了a,e,f

click_data = {'click': [['a', 'b', 'c'], ['a', 'e', 'f']]}

color_column = feature_column.categorical_column_with_vocabulary_list(
    'click', good_sets, dtype=tf.string, default_value=-1
)

embedding_column = feature_column.embedding_column(color_column, 3, combiner='mean')

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值