StringLookup 層

[原始碼]

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:要使用的詞彙外標記的數量。如果此值大於 1,則 OOV 輸入會被雜湊以確定其 OOV 值。如果此值為 0,則在呼叫此層時,OOV 輸入會導致錯誤。預設值為 1
  • mask_token:代表遮罩輸入的標記。當 output_mode"int" 時,該標記會包含在詞彙中並對應到索引 0。在其他輸出模式中,該標記不會出現在詞彙中,並且會捨棄輸入中遮罩標記的實例。如果設定為 None,則不會新增任何遮罩項。預設值為 None
  • oov_token:僅當 invert 為 True 時使用。要為 OOV 索引傳回的標記。預設值為 "[UNK]"
  • vocabulary:選用。可以是字串陣列或文字檔案的字串路徑。如果傳遞陣列,可以傳遞包含字串詞彙項目的元組、清單、1D numpy 陣列或 1D 張量。如果傳遞檔案路徑,則檔案應在每行包含一個詞彙項目。如果設定了此參數,則不需要 adapt() 此層。
  • 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" 相同,但 int 陣列包含該索引處的標記在樣本中出現的次數計數。
    • "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]])>

使用調整過的詞彙建立查找層

此範例建立一個查找層,並透過分析資料集來產生詞彙。

>>> 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。詞彙內項目的輸出索引從之前的範例增加 1(a 對應到 2,依此類推),以便為額外的 OOV 值騰出空間。

單熱輸出

使用 output_mode='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)>

多熱輸出

使用 output_mode='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' 設定此層。與多熱輸出一樣,輸出中的前 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" 設定此層。與多熱輸出一樣,輸出中的前 num_oov_indices 維度表示 OOV 值。

每個標記儲存桶將輸出 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=True 搭配 adapt(),但為了簡單起見,我們將在此範例中傳入詞彙。)

>>> 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]" 形式傳回。此外,請注意,為了使反向工作,您必須先直接或透過 adapt() 設定正向層詞彙,然後才能呼叫 get_vocabulary()