IntegerLookup 层

[源代码]

IntegerLookup

tf_keras.layers.IntegerLookup(
    max_tokens=None,
    num_oov_indices=1,
    mask_token=None,
    oov_token=-1,
    vocabulary=None,
    vocabulary_dtype="int64",
    idf_weights=None,
    invert=False,
    output_mode="int",
    sparse=False,
    pad_to_max_tokens=False,
    **kwargs
)

一个预处理层,用于将整数特征映射到连续范围。

此层通过基于表的词汇查找,将一组任意的整数输入令牌映射到索引整数输出。该层的输出索引将与最大词汇大小连续排列,即使输入令牌不连续或无界。该层通过 output_mode 支持多种输出编码选项,并可选支持词汇外 (OOV) 令牌和掩码。

该层的词汇表必须在构造时提供,或者通过 adapt() 学习。在 adapt() 期间,该层将分析数据集,确定各个整数令牌的频率,并从中创建词汇表。如果词汇表大小受限,将使用最频繁的令牌来创建词汇表,所有其他令牌将被视为 OOV。

该层有两种可能的输出模式。当 output_mode"int" 时,输入整数被转换为它们在词汇表中的索引(一个整数)。当 output_mode"multi_hot""count""tf_idf" 时,输入整数被编码成一个数组,其中每个维度对应词汇表中的一个元素。

词汇表可以选择性地包含一个掩码令牌以及一个 OOV 令牌(后者可以根据 num_oov_indices 的设置占用词汇表中的多个索引)。这些令牌在词汇表中的位置是固定的。当 output_mode"int" 时,词汇表将从索引 0 的掩码令牌开始,然后是 OOV 索引,最后是词汇表的其余部分。当 output_mode"multi_hot""count""tf_idf" 时,词汇表将从 OOV 索引开始,而掩码令牌的实例将被删除。

有关预处理层的概述和完整列表,请参阅预处理 指南

参数

  • max_tokens:此层的词汇表的最大大小。仅当适配词汇表或设置 pad_to_max_tokens=True 时才应指定此项。如果为 None,则词汇表大小没有上限。请注意,此大小包括 OOV 和掩码标记。默认为 None
  • num_oov_indices:要使用的词汇表外(OOV)标记的数量。如果此值大于 1,则 OOV 输入将被调制以确定其 OOV 值。如果此值为 0,则调用该层时 OOV 输入将导致错误。默认为 1
  • mask_token:代表掩码输入的整数令牌。当 output_mode"int" 时,该令牌包含在词汇表中并映射到索引 0。在其他输出模式下,该令牌不会出现在词汇表中,并且输入中的掩码令牌实例将被删除。如果设置为 None,则不会添加掩码项。默认为 None
  • oov_token:仅当 invert 为 True 时使用。为 OOV 索引返回的令牌。默认为 -1
  • vocabulary:可选。可以是整数数组或指向文本文件的字符串路径。如果传递数组,可以传递元组、列表、一维 numpy 数组或一维张量,其中包含整数词汇表项。如果传递文件路径,则文件应包含词汇表中每个项一行。如果设置了此参数,则无需 adapt() 该层。
  • vocabulary_dtype:词汇项的数据类型,例如 "int64""int32"。默认为 "int64"
  • idf_weights:仅当 output_mode"tf_idf" 时有效。一个元组、列表、一维 numpy 数组或一维张量,其长度与词汇表相同,包含浮点逆文档频率权重,这些权重将与每样本的词项计数相乘,以获得最终的 tf_idf 权重。如果设置了 vocabulary 参数,并且 output_mode"tf_idf",则必须提供此参数。
  • invert:仅当 output_mode"int" 时有效。如果为 True,该层将把索引映射到词汇项,而不是把词汇项映射到索引。默认为 False
  • output_mode:层输出的规范。值可以是 "int""one_hot""multi_hot""count""tf_idf",配置层如下:
    • "int":返回输入标记的词汇表索引。
    • "one_hot":将输入中的每个单独元素编码到一个与词汇表大小相同的数组中,该数组在元素索引处包含一个 1。如果最后一个维度的大小为 1,则在该维度上进行编码。如果最后一个维度不为 1,则会附加一个新维度用于编码输出。
    • "multi_hot":将输入中的每个样本编码成一个与词汇表大小相同的数组,其中包含一个 1 表示样本中存在的每个词汇表项。将最后一个维度视为样本维度,如果输入形状为 (..., sample_length),则输出形状为 (..., num_tokens)。
    • "count":与 "multi_hot" 相同,但整数数组包含该索引处标记在样本中出现的次数。
    • "tf_idf":与 "multi_hot" 相同,但应用 TF-IDF 算法来查找每个令牌槽中的值。对于 "int" 输出,支持任何形状的输入和输出。对于所有其他输出模式,目前仅支持高达秩 2 的输出。默认为 "int"
  • pad_to_max_tokens:仅适用于 output_mode"multi_hot""count""tf_idf" 时。如果为 True,输出的特征轴将填充到 max_tokens,即使词汇表中唯一令牌的数量少于 max_tokens,从而无论词汇表大小如何,都生成形状为 [batch_size, max_tokens] 的张量。默认为 False。
  • sparse:布尔值。仅适用于 output_mode"multi_hot""count""tf_idf" 时。如果为 True,则返回 SparseTensor 而不是密集 Tensor。默认为 False

示例

使用已知词汇表创建查找层

此示例使用预先存在的词汇表创建查找层。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[12, 1138, 42], [42, 1000, 36]])  # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(vocabulary=vocab)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[1, 3, 4],
       [4, 0, 2]])>

使用自适应词汇表创建查找层

此示例创建一个查找层,并通过分析数据集生成词汇表。

>>> data = tf.constant([[12, 1138, 42], [42, 1000, 36]])
>>> layer = tf.keras.layers.IntegerLookup()
>>> layer.adapt(data)
>>> layer.get_vocabulary()
[-1, 42, 1138, 1000, 36, 12]

请注意,OOV 令牌 -1 已添加到词汇表中。其余令牌按频率排序(出现 2 次的 42 排在前面),然后按反向排序顺序排列。

>>> data = tf.constant([[12, 1138, 42], [42, 1000, 36]])
>>> layer = tf.keras.layers.IntegerLookup()
>>> layer.adapt(data)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[5, 2, 1],
       [1, 3, 4]])>

多 OOV 索引查找

此示例演示了如何使用具有多个 OOV 索引的查找层。当一个层被创建并包含多个 OOV 索引时,任何 OOV 令牌都会被哈希到 OOV 桶的数量中,以确定性方式将 OOV 令牌分布到集合中。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[12, 1138, 42], [37, 1000, 36]])
>>> layer = tf.keras.layers.IntegerLookup(
...     vocabulary=vocab, num_oov_indices=2)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[2, 4, 5],
       [1, 0, 3]])>

请注意,OOV 令牌 37 的输出为 1,而 OOV 令牌 1000 的输出为 0。词汇表内的项的输出索引比前面示例中的(12 映射到 2 等)增加了 1,以便为额外的 OOV 令牌腾出空间。

One-hot 输出

使用 output_mode='one_hot' 配置该层。请注意,one_hot 编码中的前 num_oov_indices 个维度代表 OOV 值。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([12, 36, 1138, 42, 7]) # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(
...     vocabulary=vocab, output_mode='one_hot')
>>> layer(data)
<tf.Tensor: shape=(5, 5), dtype=float32, numpy=
  array([[0., 1., 0., 0., 0.],
         [0., 0., 1., 0., 0.],
         [0., 0., 0., 1., 0.],
         [0., 0., 0., 0., 1.],
         [1., 0., 0., 0., 0.]], dtype=float32)>

多热输出

使用 output_mode='multi_hot' 配置该层。请注意,multi_hot 编码中的前 num_oov_indices 个维度代表 OOV 令牌。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[12, 1138, 42, 42],
...                     [42, 7, 36, 7]]) # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(
...     vocabulary=vocab, output_mode='multi_hot')
>>> layer(data)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
  array([[0., 1., 0., 1., 1.],
         [1., 0., 1., 0., 1.]], dtype=float32)>

标记计数输出

使用 output_mode='count' 配置该层。与 multi_hot 输出一样,输出中的前 num_oov_indices 个维度代表 OOV 令牌。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[12, 1138, 42, 42],
...                     [42, 7, 36, 7]]) # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(
...     vocabulary=vocab, output_mode='count')
>>> layer(data)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
  array([[0., 1., 0., 1., 2.],
         [2., 0., 1., 0., 1.]], dtype=float32)>

TF-IDF 输出

使用 output_mode='tf_idf' 配置该层。与 multi_hot 输出一样,输出中的前 num_oov_indices 个维度代表 OOV 令牌。

每个令牌 bin 将输出 token_count * idf_weight,其中 idf 权重是每个令牌的逆文档频率权重。这些应与词汇表一起提供。请注意,OOV 令牌的 idf_weight 将默认为传入的所有 idf 权重的平均值。

>>> vocab = [12, 36, 1138, 42]
>>> idf_weights = [0.25, 0.75, 0.6, 0.4]
>>> data = tf.constant([[12, 1138, 42, 42],
...                     [42, 7, 36, 7]]) # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(
...     output_mode='tf_idf', vocabulary=vocab, idf_weights=idf_weights)
>>> layer(data)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
  array([[0.  , 0.25, 0.  , 0.6 , 0.8 ],
         [1.0 , 0.  , 0.75, 0.  , 0.4 ]], dtype=float32)>

要为 oov 令牌指定 idf 权重,您需要传递包括前导 oov 令牌在内的整个词汇表。

>>> vocab = [-1, 12, 36, 1138, 42]
>>> idf_weights = [0.9, 0.25, 0.75, 0.6, 0.4]
>>> data = tf.constant([[12, 1138, 42, 42],
...                     [42, 7, 36, 7]]) # Note OOV tokens
>>> layer = tf.keras.layers.IntegerLookup(
...     output_mode='tf_idf', vocabulary=vocab, idf_weights=idf_weights)
>>> layer(data)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
  array([[0.  , 0.25, 0.  , 0.6 , 0.8 ],
         [1.8 , 0.  , 0.75, 0.  , 0.4 ]], dtype=float32)>

在 tf_idf 模式下适配该层时,每个输入样本将被视为一个文档,并且每个令牌的 idf 权重将计算为 log(1 + num_documents / (1 + token_document_count))

逆向查找

此示例演示了如何使用此层将索引映射到令牌。(您也可以使用 adapt() 并设置 inverse=True,但为简单起见,在此示例中我们传递词汇表。)

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[1, 3, 4], [4, 0, 2]])
>>> layer = tf.keras.layers.IntegerLookup(vocabulary=vocab, invert=True)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[  12, 1138,   42],
       [  42,   -1,   36]])>

请注意,默认情况下,第一个索引对应于 oov 标记。

前向和逆向查找对

此示例演示如何使用标准查找层的词汇表创建逆向查找层。

>>> vocab = [12, 36, 1138, 42]
>>> data = tf.constant([[12, 1138, 42], [42, 1000, 36]])
>>> layer = tf.keras.layers.IntegerLookup(vocabulary=vocab)
>>> i_layer = tf.keras.layers.IntegerLookup(
...     vocabulary=layer.get_vocabulary(), invert=True)
>>> int_data = layer(data)
>>> i_layer(int_data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[  12, 1138,   42],
       [  42,   -1,   36]])>

在此示例中,输入令牌 1000 导致输出为 -1,因为 1000 不在词汇表中 - 它被表示为 OOV,并且所有 OOV 令牌在反向层中都返回 -1。另外,请注意,为了使反向工作,您必须在调用 get_vocabulary() 之前,通过直接设置或通过 adapt() 来设置前向层的词汇表。