IntegerLookup 层

[源代码]

IntegerLookup

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,
    name=None,
    **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 索引开头,并且输入中的掩码标记实例将被丢弃。

注意:此层在内部使用 TensorFlow。它不能用作与 TensorFlow 以外的任何后端一起使用的模型的已编译计算图的一部分。但是,它可以在急切执行时与任何后端一起使用。它也可以始终用作任何后端输入预处理管道的一部分(在模型本身之外),我们建议使用此层的方式。

注意:此层可以在tf.data管道中安全使用(无论您使用哪个后端)。

参数

  • max_tokens:此层的词汇表最大大小。仅在调整词汇表或设置pad_to_max_tokens=True时才应指定此参数。如果为 None,则词汇表大小没有上限。请注意,此大小包括 OOV 和掩码标记。默认为None
  • num_oov_indices:要使用的超出词汇表标记的数量。如果此值大于 1,则对 OOV 输入进行调制以确定其 OOV 值。如果此值为 0,则在调用层时,OOV 输入将导致错误。默认为1
  • mask_token:表示掩码输入的整数标记。当output_mode"int"时,该标记包含在词汇表中并映射到索引 0。在其他输出模式下,该标记将不会出现在词汇表中,并且输入中掩码标记的实例将被丢弃。如果设置为 None,则不会添加掩码项。默认为None
  • oov_token:仅在invertTrue时使用。要为 OOV 索引返回的标记。默认为-1
  • vocabulary:可选。整数数组或指向文本文件的字符串路径。如果传递数组,则可以传递元组、列表、1D NumPy 数组或包含整数词汇表项的 1D 张量。如果传递文件路径,则该文件应每行包含词汇表中的一项。如果设置了此参数,则无需adapt()该层。
  • vocabulary_dtype:词汇表项的数据类型,例如"int64""int32"。默认为"int64"
  • idf_weights:仅在output_mode"tf_idf"时有效。元组、列表、1D NumPy 数组或与词汇表长度相同的 1D 张量,包含浮点逆文档频率权重,这些权重将乘以每个样本的术语计数以获得最终的 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:布尔值。仅适用于"multi_hot""count""tf_idf"输出模式。仅支持 TensorFlow 后端。如果为True,则返回SparseTensor而不是密集Tensor。默认为False

示例

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

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

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([[12, 1138, 42], [42, 1000, 36]])  # Note OOV tokens
>>> layer = IntegerLookup(vocabulary=vocab)
>>> layer(data)
array([[1, 3, 4],
       [4, 0, 2]])

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

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

>>> data = np.array([[12, 1138, 42], [42, 1000, 36]])
>>> layer = IntegerLookup()
>>> layer.adapt(data)
>>> layer.get_vocabulary()
[-1, 42, 1138, 1000, 36, 12]

请注意,OOV 标记 -1 已添加到词汇表中。其余标记按频率排序(出现 2 次的 42 位于首位),然后按反向排序顺序排序。

>>> data = np.array([[12, 1138, 42], [42, 1000, 36]])
>>> layer = IntegerLookup()
>>> layer.adapt(data)
>>> layer(data)
array([[5, 2, 1],
       [1, 3, 4]])

具有多个 OOV 索引的查找

此示例演示如何使用具有多个 OOV 索引的查找层。当使用多个 OOV 索引创建层时,任何 OOV 标记都将散列到 OOV 存储桶的数量中,以确定性方式将 OOV 标记分布在整个集合中。

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([[12, 1138, 42], [37, 1000, 36]])
>>> layer = IntegerLookup(vocabulary=vocab, num_oov_indices=2)
>>> layer(data)
array([[2, 4, 5],
       [1, 0, 3]])

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

独热输出

使用output_mode='one_hot'配置层。请注意,独热编码中的前num_oov_indices维表示 OOV 值。

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([12, 36, 1138, 42, 7])  # Note OOV tokens
>>> layer = IntegerLookup(vocabulary=vocab, output_mode='one_hot')
>>> layer(data)
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'配置层。请注意,多热编码中的前num_oov_indices维表示 OOV 标记。

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([[12, 1138, 42, 42],
...                  [42,    7, 36,  7]])  # Note OOV tokens
>>> layer = IntegerLookup(vocabulary=vocab, output_mode='multi_hot')
>>> layer(data)
array([[0., 1., 0., 1., 1.],
       [1., 0., 1., 0., 1.]], dtype=float32)

标记计数输出

使用output_mode='count'配置层。与多热输出一样,输出中的前num_oov_indices维表示 OOV 标记。

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([[12, 1138, 42, 42],
...                  [42,    7, 36,  7]])  # Note OOV tokens
>>> layer = IntegerLookup(vocabulary=vocab, output_mode='count')
>>> layer(data)
array([[0., 1., 0., 1., 2.],
       [2., 0., 1., 0., 1.]], dtype=float32)

TF-IDF 输出

使用output_mode='tf_idf'配置层。与多热输出一样,输出中的前num_oov_indices维表示 OOV 标记。

每个标记仓将输出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 = np.array([[12, 1138, 42, 42],
...                  [42,    7, 36,  7]])  # Note OOV tokens
>>> layer = IntegerLookup(
...     output_mode='tf_idf', vocabulary=vocab, idf_weights=idf_weights)
>>> layer(data)
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 = np.array([[12, 1138, 42, 42],
...                  [42,    7, 36,  7]])  # Note OOV tokens
>>> layer = IntegerLookup(
...     output_mode='tf_idf', vocabulary=vocab, idf_weights=idf_weights)
>>> layer(data)
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 = np.array([[1, 3, 4], [4, 0, 2]])
>>> layer = IntegerLookup(vocabulary=vocab, invert=True)
>>> layer(data)
array([[  12, 1138,   42],
       [  42,   -1,   36]])

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

前向和反向查找对

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

>>> vocab = [12, 36, 1138, 42]
>>> data = np.array([[12, 1138, 42], [42, 1000, 36]])
>>> layer = IntegerLookup(vocabulary=vocab)
>>> i_layer = IntegerLookup(
...     vocabulary=layer.get_vocabulary(), invert=True)
>>> int_data = layer(data)
>>> i_layer(int_data)
array([[  12, 1138,   42],
       [  42,   -1,   36]])

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