学习笔记-estimator
基于tensorflow 1.15
import tensorflow as tf
# 创建一个分类特征列,使用词汇表列表
categorical_column = tf.feature_column.categorical_column_with_vocabulary_list(
key="your_feature_name", # 这应该是你的数据中特征的键名
vocabulary_list=["value1", "value2", "value3"], # 你的词汇表列表
dtype=tf.string, # 数据类型,默认为字符串
num_oov_buckets=1 # 你可以指定多少个 out-of-vocabulary buckets
)
# 通常情况下,你需要将分类列转换为指标列(indicator column)或嵌入列(embedding column)
# 这里我们将其转换为指标列
indicator_column = tf.feature_column.indicator_column(categorical_column)
# 创建一个输入层,用于接收特征数据
feature_columns = [indicator_column]
features = tf.placeholder(tf.string, shape=[None], name='your_feature_name')
# 创建一个特征列的字典,用于输入到模型中
features_dict = { "your_feature_name": features }
# 使用特征列构建输入层
dense_tensor = tf.feature_column.input_layer(features_dict, feature_columns)
# 初始化所有变量
init = tf.global_variables_initializer()
# 开始一个会话
with tf.Session() as sess:
sess.run(init)
sess.run(tf.tables_initializer())
# 假设你有一些数据
input_data = ["value1", "value2", "value3", "unknown_value"]
# 运行会话,将数据传入
result = sess.run(dense_tensor, feed_dict={features: input_data})
print(result)
为什么可以多个不同的embedding dim
import tensorflow as tf
# 定义类别特征列
categorical_column_a = tf.feature_column.categorical_column_with_vocabulary_list(
key='cat_feature_a',
vocabulary_list=['A', 'B', 'C', 'D']
)
categorical_column_b = tf.feature_column.categorical_column_with_vocabulary_list(
key='cat_feature_b',
vocabulary_list=['X', 'Y', 'Z']
)
# 为每个类别特征定义不同的嵌入维度
embedding_column_a = tf.feature_column.embedding_column(
categorical_column=categorical_column_a,
dimension=8 # 特征a的嵌入维度为8
)
embedding_column_b = tf.feature_column.embedding_column(
categorical_column=categorical_column_b,
dimension=5 # 特征b的嵌入维度为4
)
# 创建一个列表,包含所有特征列
feature_columns = [
embedding_column_a,
embedding_column_b
]
# 创建输入数据
features = {
'cat_feature_a': tf.constant(['A', 'B', 'C', 'D']), # 假设是4个样本
'cat_feature_b': tf.constant(['X', 'Y', 'Z', 'X'])
}
# 使用input_layer函数
input_layer = tf.feature_column.input_layer(features, feature_columns)
# 创建一个会话来运行这个图
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.tables_initializer())
input_layer_output = sess.run(input_layer)
print("Input Layer Output:")
print(input_layer_output)
输出形状:输出的形状为 [batch_size, total_embedding_dimension]。在这个例子中
序列长度为0的时候的shape
import tensorflow as tf
from tensorflow.contrib import feature_column as feature_column_old
seq_feature = feature_column_old.sequence_categorical_column_with_hash_bucket('sequence_feature', 3)
emb_col = tf.feature_column.embedding_column(seq_feature, dimension=8)
# 创建一个输入数据字典
features = {
'sequence_feature': tf.constant([[]], dtype=tf.string)
}
# 使用sequence_input_layer函数
input_layer = feature_column_old.sequence_input_layer(features, [emb_col])
# 创建一个会话来运行这个图
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.tables_initializer())
input_layer_output = sess.run(input_layer)
print("Input Layer Output:")
print(input_layer_output)
输出Input Layer Output:
(array([], shape=(1, 0, 8), dtype=float32), array([0]))
SparseTensor如何理解
https://www.ritchie.top/2020/01/22/tensorflow2-feature-column/
↑中反复用到,比如
"feature": tf.SparseTensor(
indices=[
[0, 0, 2],
[0, 0, 3],
[0, 2, 1],
[1, 0, 1],
[1, 1, 3]
],
values=["value1", "value2", "value3", "value4", "value1"],
dense_shape=[2, 3, 5]
)
其实看源码注释就好理解,
SparseTensor(indices=[[0, 0], [1, 2]], values=[1, 2], dense_shape=[3, 4])
第一个参数维度[N, ndims],是位置
第二个参数是对应位置上的值
第三个参数是维度,3*4
represents the dense tensor
```python
[[1, 0, 0, 0]
[0, 0, 2, 0]
[0, 0, 0, 0]]
crossed_column用法
注释中
python shape = [2, 2] { [0, 0]: "a" [1, 0]: "b" [1, 1]: "c" }
-
SparseTensor referred by second key:
shape = [2, 1] { [0, 0]: "d" [1, 0]: "e" }
then crossed feature will look like:
shape = [2, 2]
{
[0, 0]: Hash64("d", Hash64("a")) % hash_bucket_size
[1, 0]: Hash64("e", Hash64("b")) % hash_bucket_size
[1, 1]: Hash64("e", Hash64("c")) % hash_bucket_size
}
为什么[1, 1]是ec交叉,(其他都是[0, 0] 位置和 [1, 0] 位置,好理解)
回答: 由于第二个SparseTensor是一个列向量,即形状为[2, 1],这意味着它只有一个列,所以无论是在位置(1, 0)还是(1, 1),它的值都是"e"。因此,在创建交叉特征时,对于位置(1, 1),我们需要从第一个SparseTensor中获取值"c",并且从第二个SparseTensor中获取值"e"。
## sparsetensor如何和下面定义的feature column配合
def tag_embedding(self, key_name, hash_bucket, embedding_dim):
id_fea ture = tf.feature_column.categorical_column_with_hash_bucket(key_name, hash_bucket, dtype=tf.string)
emb_col = tf.feature_column.embedding_column(id_feature, dimension=embedding_dim, combiner='mean')
return emb_col, id_feature
```python
import tensorflow as tf
class FeatureColumnExample:
def __init__(self, hash_bucket, embedding_dim):
self.hash_bucket = hash_bucket
self.embedding_dim = embedding_dim
def tag_embedding(self, key_name):
id_feature = tf.feature_column.categorical_column_with_hash_bucket(key_name, self.hash_bucket, dtype=tf.string)
emb_col = tf.feature_column.embedding_column(id_feature, dimension=self.embedding_dim, combiner='mean')
return emb_col, id_feature
# 创建FeatureColumnExample实例
example = FeatureColumnExample(hash_bucket=10000, embedding_dim=8)
# 定义嵌入特征列
emb_col, _ = example.tag_embedding('tags')
# 创建SparseTensor
sparse_tensor = tf.SparseTensor(
indices=[[0, 0], [0, 1], [1, 0]],
values=['tag1', 'tag2', 'tag3'],
dense_shape=[2, 2]
)
# 创建特征字典
features = {'tags': sparse_tensor}
# 获取输入层
input_layer = tf.feature_column.input_layer(features, [emb_col])
# 创建一个会话来运行这个图
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.tables_initializer())
input_layer_output = sess.run(input_layer)
print("Input Layer Output:")
print(input_layer_output)
输出示例
假设我们运行了上面的代码,input_layer_output
的输出可能类似于以下形式:
Input Layer Output:
[[ 0.1234 0.5678 0.9012 0.3456 0.7890 0.2345 0.6789 0.0123]
[ 0.4567 0.8901 0.2345 0.6789 0.0123 0.4567 0.8901 0.2345]]
解释输出
- 我们创建了一个
SparseTensor
,其形状为[2, 2]
,表示两个样本,每个样本有两个位置。 - 我们定义了一个嵌入特征列
emb_col
,它使用categorical_column_with_hash_bucket
来处理类别特征,并使用embedding_column
来创建嵌入向量。 - 通过
input_layer
函数,我们将SparseTensor
转换为一个稠密的张量,其中每个类别值被映射到一个固定长度的向量上。
总结
- 通过上述步骤,你可以将
SparseTensor
与定义好的feature_column
配合使用。 - 你需要确保
SparseTensor
的键与特征列中的键相匹配。 - 使用
input_layer
函数可以将SparseTensor
转换为模型可以直接使用的稠密张量。
这样的方式可以让你有效地处理稀疏数据,并利用嵌入层来捕捉特征之间的关系。
categorical_column_with_hash_bucket是对sparsetensor的第一维哈希吗
categorical_column_with_hash_bucket并不是对SparseTensor的第一维进行哈希,而是对SparseTensor中的值进行哈希,并将它们映射到一个整数索引。
通过这种方式,你可以将稀疏的类别特征转换为稠密的表示,这可以用于构建嵌入层或进行其他机器学习任务。
在使用SparseTensor时,你需要确保特征列中的键与特征字典中的键匹配。
embedding_column是怎么将哈希之后的整数变成小数
embedding_column内部实际上做了以下几件事情:
初始化嵌入矩阵:当模型开始训练时,embedding_column会随机初始化一个嵌入矩阵,这个矩阵的大小是hash_bucket_size乘以dimension。每个整数索引对应矩阵中的一行。
查找嵌入向量:当embedding_column接收一个整数索引时,它会在嵌入矩阵中查找对应行的向量。这个向量通常是一个浮点数数组,这就是为什么输出变成了小数的原因。
前向传播:在模型的前向传播过程中,这些嵌入向量会被用来代替原始的整数索引,从而形成一个低维稠密表示。
sparsetensor中有多个整数,那么对应整数索引中多行,如何处理
当SparseTensor中的每个样本包含多个整数索引时,embedding_column会根据配置的combiner参数来处理这些索引对应的嵌入向量。combiner参数决定了如何将这些嵌入向量组合成一个单一的向量。以下是几种常见的combiner选项以及它们如何工作:
- mean (默认值)
描述:计算所有嵌入向量的平均值。
效果:将每个样本中所有嵌入向量的值相加,然后除以嵌入向量的数量。 - sum
描述:将所有嵌入向量的值相加。
效果:将每个样本中所有嵌入向量的值相加,不进行除法运算。 - sqrtn
描述:计算所有嵌入向量的平均值,但分母是嵌入向量数量的平方根。
效果:将每个样本中所有嵌入向量的值相加,然后除以嵌入向量数量的平方根。 - none
描述:不执行任何聚合操作。
效果:返回所有嵌入向量的列表,每个嵌入向量对应于SparseTensor中的一个值
种一棵树最好的时间是十年前,其次是现在。