学习笔记-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选项以及它们如何工作:

  1. mean (默认值)
    描述:计算所有嵌入向量的平均值。
    效果:将每个样本中所有嵌入向量的值相加,然后除以嵌入向量的数量。
  2. sum
    描述:将所有嵌入向量的值相加。
    效果:将每个样本中所有嵌入向量的值相加,不进行除法运算。
  3. sqrtn
    描述:计算所有嵌入向量的平均值,但分母是嵌入向量数量的平方根。
    效果:将每个样本中所有嵌入向量的值相加,然后除以嵌入向量数量的平方根。
  4. none
    描述:不执行任何聚合操作。
    效果:返回所有嵌入向量的列表,每个嵌入向量对应于SparseTensor中的一个值
posted @ 2024-07-15 11:00  种树人  阅读(3)  评论(0编辑  收藏  举报