字符串查找层

[源]

StringLookup

tf_keras.layers.StringLookup(
    max_tokens=None,
    num_oov_indices=1,
    mask_token=None,
    oov_token="[UNK]",
    vocabulary=None,
    idf_weights=None,
    encoding="utf-8",
    invert=False,
    output_mode="int",
    sparse=False,
    pad_to_max_tokens=False,
    **kwargs
)

一个将字符串特征映射到整数索引的预处理层。

此层通过基于表的词汇查找将一组任意字符串转换为整数输出。此层不会对输入字符串执行分割或转换。对于可以分割和分词自然语言的层,请参阅 tf.keras.layers.TextVectorization 层。

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

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

词汇表可以选择包含一个掩码标记以及一个 OOV 标记(根据 num_oov_indices 设置,可以选择在词汇表中占据多个索引)。这些标记在词汇表中的位置是固定的。当 output_mode"int" 时,词汇表将以掩码标记(如果已设置)开头,后跟 OOV 索引,再后跟词汇表的其余部分。当 output_mode"multi_hot", "count""tf_idf" 时,词汇表将以 OOV 索引开头,并且输入中的掩码标记实例将被丢弃。

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

参数

  • max_tokens: 此层的词汇表的最大大小。此参数应仅在调整词汇表或设置 pad_to_max_tokens=True 时指定。如果为 None,则词汇表大小没有上限。请注意,此大小包含 OOV 和掩码标记。默认为 None
  • num_oov_indices: 要使用的词汇外标记 (OOV token) 的数量。如果此值大于 1,OOV 输入将被哈希以确定其 OOV 值。如果此值为 0,当调用该层时,OOV 输入将导致错误。默认为 1
  • mask_token: 表示掩码输入的标记。当 output_mode"int" 时,此标记包含在词汇表中并映射到索引 0。在其他输出模式下,此标记将不会出现在词汇表中,并且输入中的掩码标记实例将被丢弃。如果设置为 None,则不会添加掩码项。默认为 None
  • oov_token: 仅当 invert 为 True 时使用。用于 OOV 索引的返回标记。默认为 "[UNK]"
  • vocabulary: 可选。可以是字符串数组或文本文件的字符串路径。如果传递数组,可以传递包含字符串词汇项的元组、列表、一维 numpy 数组或一维张量。如果传递文件路径,文件应包含词汇表中每行的项。如果设置了此参数,则无需 adapt() 层。
  • 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
  • encoding: 可选。用于解释输入字符串的文本编码。默认为 "utf-8"

示例

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

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

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant([["a", "c", "d"], ["d", "z", "b"]])
>>> layer = tf.keras.layers.StringLookup(vocabulary=vocab)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[1, 3, 4],
       [4, 0, 2]])>

使用 adapt 后的词汇表创建查找层

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

>>> data = tf.constant([["a", "c", "d"], ["d", "z", "b"]])
>>> layer = tf.keras.layers.StringLookup()
>>> layer.adapt(data)
>>> layer.get_vocabulary()
['[UNK]', 'd', 'z', 'c', 'b', 'a']

请注意,OOV 标记 "[UNK]" 已添加到词汇表中。其余标记按频率排序(出现 2 次的 "d" 排在第一位),然后按逆序排序。

>>> data = tf.constant([["a", "c", "d"], ["d", "z", "b"]])
>>> layer = tf.keras.layers.StringLookup()
>>> layer.adapt(data)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[5, 3, 1],
       [1, 2, 4]])>

使用多个 OOV 索引进行查找

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

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant([["a", "c", "d"], ["m", "z", "b"]])
>>> layer = tf.keras.layers.StringLookup(vocabulary=vocab,
...                                      num_oov_indices=2)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=int64, numpy=
array([[2, 4, 5],
       [0, 1, 3]])>

请注意,OOV 值 'm' 的输出为 0,而 OOV 值 'z' 的输出为 1。为了给额外的 OOV 值腾出空间,词汇内项的输出索引比前面的示例增加了 1(a 映射到 2,依此类推)。

One-hot 输出

将层配置为 output_mode='one_hot'。请注意,one-hot 编码中的前 num_oov_indices 个维度代表 OOV 值。

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant(["a", "b", "c", "d", "z"])
>>> layer = tf.keras.layers.StringLookup(
...     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)>

Multi-hot 输出

将层配置为 output_mode='multi_hot'。请注意,multi-hot 编码中的前 num_oov_indices 个维度代表 OOV 值。

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant([["a", "c", "d", "d"], ["d", "z", "b", "z"]])
>>> layer = tf.keras.layers.StringLookup(
...     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 = ["a", "b", "c", "d"]
>>> data = tf.constant([["a", "c", "d", "d"], ["d", "z", "b", "z"]])
>>> layer = tf.keras.layers.StringLookup(
...     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 = ["a", "b", "c", "d"]
>>> idf_weights = [0.25, 0.75, 0.6, 0.4]
>>> data = tf.constant([["a", "c", "d", "d"], ["d", "z", "b", "z"]])
>>> layer = tf.keras.layers.StringLookup(output_mode="tf_idf")
>>> layer.set_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 = ["[UNK]", "a", "b", "c", "d"]
>>> idf_weights = [0.9, 0.25, 0.75, 0.6, 0.4]
>>> data = tf.constant([["a", "c", "d", "d"], ["d", "z", "b", "z"]])
>>> layer = tf.keras.layers.StringLookup(output_mode="tf_idf")
>>> layer.set_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))

逆向查找

此示例演示如何使用此层将索引映射到字符串。(您也可以使用带有 inverse=Trueadapt(),但为了简单起见,在此示例中我们将直接传递词汇表。)

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant([[1, 3, 4], [4, 0, 2]])
>>> layer = tf.keras.layers.StringLookup(vocabulary=vocab, invert=True)
>>> layer(data)
<tf.Tensor: shape=(2, 3), dtype=string, numpy=
array([[b'a', b'c', b'd'],
       [b'd', b'[UNK]', b'b']], dtype=object)>

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

正向和逆向查找对

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

>>> vocab = ["a", "b", "c", "d"]
>>> data = tf.constant([["a", "c", "d"], ["d", "z", "b"]])
>>> layer = tf.keras.layers.StringLookup(vocabulary=vocab)
>>> i_layer = tf.keras.layers.StringLookup(vocabulary=vocab, invert=True)
>>> int_data = layer(data)
>>> i_layer(int_data)
<tf.Tensor: shape=(2, 3), dtype=string, numpy=
array([[b'a', b'c', b'd'],
       [b'd', b'[UNK]', b'b']], dtype=object)>

在此示例中,输入值 "z" 的输出为 "[UNK]",因为 1000 不在词汇表中 - 它被表示为 OOV,并且所有 OOV 值在逆向层中都返回 "[UNK]"。此外,请注意,为了使逆向查找工作,您必须在调用 get_vocabulary() 之前已经直接或通过 adapt() 设置了正向层的词汇表。