步驟 3:準備資料

資料必須先轉換為格式,才能提供給模型 讓模型能理解

首先,我們所收集的資料樣本可能按照特定順序排列。我們自己 不希望任何與樣本順序相關的資訊 說明文字和標籤之間的關係例如,如果資料集已排序 並分為訓練/驗證集 代表資料的整體分佈情形

如要確保模型不受資料順序影響,最簡單的最佳做法就是 在執行其他作業前 一律必須重組資料如果您的資料已經 分為訓練集和驗證集,請務必轉換驗證 方法與轉換訓練資料的方式相同如果還沒有 您可以將樣本分割為兩個獨立的訓練集 隨機播放;通常使用 80% 的樣本進行訓練,20% 用於訓練 驗證。

第二,機器學習演算法將數字做為輸入內容。這表示我們 必須將文字轉換成數值向量您需要完成兩個步驟 這項程序:

  1. 符記化:將文字分成文字或較小的副文字, 幫助文字和標籤之間建立良好的一般化關係。 這會決定資料集的「字彙」( 資料)。

  2. 向量:定義良好的數值度量,使其具有特徵 文字。

接下來說明如何針對 n 元語法向量和序列執行這兩個步驟 以及如何使用特徵碼將向量表示法最佳化 選擇與正規化技術

N 公克向量 [Option A]

在後續段落中,我們會說明如何權杖化與 n-gram 模型的向量化功能此外,我們也會探討如何最佳化 n- 透過特徵選擇和正規化技術呈現的文法表示法。

在 n 元語法向量中,文字會以一組不重複的 n 元語法表示。 一組相鄰符記 (通常是字詞) 的群組。假設文字為 The mouse ran up the clock。這裡:

  • 一字不差 (n = 1) 為 ['the', 'mouse', 'ran', 'up', 'clock']
  • 「大字」字樣 (n = 2) 是['the mouse', 'mouse ran', 'ran up', 'up the', 'the clock']
  • 而其他人員也會有資料管理的需求。

代碼化

我們發現,若將文字權杖化為一元語法 + 大字機,就能帶來正面影響 同時減少運算時間的精確度

向量化

將文字樣本分割為 n-grams 後,就需要將這些文字樣本 轉換為機器學習模型可以處理的數值向量範例 下方顯示指派給一元語法和二元數的索引 文字。

Texts: 'The mouse ran up the clock' and 'The mouse ran down'
Index assigned for every token: {'the': 7, 'mouse': 2, 'ran': 4, 'up': 10,
  'clock': 0, 'the mouse': 9, 'mouse ran': 3, 'ran up': 6, 'up the': 11, 'the
clock': 8, 'down': 1, 'ran down': 5}

將索引指派給 n 元語法後,我們通常會使用 下列選項。

One-hot 編碼:每個範例文字都會以表示 是否存在文字中的符記

'The mouse ran up the clock' = [1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]

計數編碼:每個範例文字都會以向量表示 文字中的符記數量。請注意,與 一元畫的「the」現在已表示 2,因為 "the" 出現了兩次

'The mouse ran up the clock' = [1, 0, 1, 1, 1, 0, 1, 2, 1, 1, 1, 1]

Tf-idf 編碼:問題 主要是用在類似的方式中 所有文件中的頻率 (例如,不重複的字詞 資料集內的文字樣本) 則不受影響。例如「a」 出現頻率非常高因此,「the」的符記數量比 都不是很有意義的字詞

'The mouse ran up the clock' = [0.33, 0, 0.23, 0.23, 0.23, 0, 0.33, 0.47, 0.33, 0.23, 0.33, 0.33]

(請參閱 Scikit-learn TfidfTransformer)。

還有許多其他向量表示法

我們發現 tf-idf 編碼比 準確度 (平均提高 0.25-15%),建議使用這個方法 用於向量化 n 元語法但請注意,這類記憶體會佔用較多記憶體 (例如 使用浮點表示法) 且需要較多時間運算 以大型資料集來說 (在某些情況下可能需要兩倍時間)。

選取特徵

當我們將資料集中的所有文字轉換為一字 + 方格符記時, 可能會產生數萬個符記部分權杖/功能並非 對標籤預測結果的貢獻我們可以捨棄特定符記 資料集內極少發生的情況你也可以測量 特徵重要性 (每個符記對標籤預測結果的影響程度) 僅包含資訊最豐富的符記

許多統計函式採用特徵, 並輸出特徵重要性分數有兩種常用的函式 f_classifchi2。我們的 實驗顯示,這兩種函式的成效都一樣好。

更重要的是,許多特徵的準確率達到約 20,000 個 資料集 (請參閱圖 6)。達到這個門檻後新增更多地圖項目,有助於 有時甚至會導致 過度配適 且會降低效能

「前 K 個」與「準確率」的比較

圖 6:主要 K 功能與準確率。如為多個資料集,準確度約為 2 萬個特徵。

正規化

正規化會將所有特徵/範例值轉換為小型和類似的值。 這可簡化學習演算法中的梯度下降法收斂。根據內容 如先前所述,資料預先處理期間的正規化似乎不會增加 無法解決文字分類問題建議您略過這個步驟

以下程式碼集結了以上所有步驟:

  • 將文字樣本代碼化為單字 + Bigrams,
  • 使用 tf-idf 編碼進行向量化
  • 捨棄符記向量中前 20,000 個地圖項目 符記顯示次數不到 2 次,且使用 f_classif 計算特徵 重要性。
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import f_classif

# Vectorization parameters
# Range (inclusive) of n-gram sizes for tokenizing text.
NGRAM_RANGE = (1, 2)

# Limit on the number of features. We use the top 20K features.
TOP_K = 20000

# Whether text should be split into word or character n-grams.
# One of 'word', 'char'.
TOKEN_MODE = 'word'

# Minimum document/corpus frequency below which a token will be discarded.
MIN_DOCUMENT_FREQUENCY = 2

def ngram_vectorize(train_texts, train_labels, val_texts):
    """Vectorizes texts as n-gram vectors.

    1 text = 1 tf-idf vector the length of vocabulary of unigrams + bigrams.

    # Arguments
        train_texts: list, training text strings.
        train_labels: np.ndarray, training labels.
        val_texts: list, validation text strings.

    # Returns
        x_train, x_val: vectorized training and validation texts
    """
    # Create keyword arguments to pass to the 'tf-idf' vectorizer.
    kwargs = {
            'ngram_range': NGRAM_RANGE,  # Use 1-grams + 2-grams.
            'dtype': 'int32',
            'strip_accents': 'unicode',
            'decode_error': 'replace',
            'analyzer': TOKEN_MODE,  # Split text into word tokens.
            'min_df': MIN_DOCUMENT_FREQUENCY,
    }
    vectorizer = TfidfVectorizer(**kwargs)

    # Learn vocabulary from training texts and vectorize training texts.
    x_train = vectorizer.fit_transform(train_texts)

    # Vectorize validation texts.
    x_val = vectorizer.transform(val_texts)

    # Select top 'k' of the vectorized features.
    selector = SelectKBest(f_classif, k=min(TOP_K, x_train.shape[1]))
    selector.fit(x_train, train_labels)
    x_train = selector.transform(x_train).astype('float32')
    x_val = selector.transform(x_val).astype('float32')
    return x_train, x_val

我們採用 n 元語法向量表示法,因此捨棄了許多字詞相關資訊 排序及文法 (最好能我們保留部分排序資訊 當 n >1)。也就是所謂的簡明扼要。這種表示法 搭配較不考量排序的模型,例如 邏輯迴歸、多層感知、梯度增強機器 支援向量機。

序列向量 [選項 B]

在後續段落中,我們會說明如何權杖化與 以及序列模型的向量化功能我們也會介紹如何最佳化 透過特徵選擇和正規化技術進行序列表示法。

在某些文字樣本中,字詞順序對文字的含意至關重要。適用對象 像是「我以前討厭通勤時,我的新腳踏車改變了 必須用到順序閱讀。CNN/RNN 等型號 能夠根據樣本的字詞順序推論出含意。對於這類模型 會以保留順序的符記序列來表示文字。

代碼化

文字能以一串字元或一系列的字元表示 還能分析語法及擷取語言資訊 例如字詞之間的關係我們發現,使用字詞層級表示法可帶來更好的效果 整體效能比字元符記這是 產業只在文字包含大量文字的情況下,才適合使用字元符記 但其實並非這個情況

向量化

將文字樣本轉換為字詞序列後, 將這些序列轉換為數值向量以下範例顯示索引 一組生成至兩段文字產生的一元公克 將第一個文字轉換成的索引。

Texts: 'The mouse ran up the clock' and 'The mouse ran down'

每個符記指派的索引:

{'clock': 5, 'ran': 3, 'up': 4, 'down': 6, 'the': 1, 'mouse': 2}

注意:「the」一詞所以索引值 1 是 。有些程式庫會為未知符記保留索引 0, 或這裡顯示案例

權杖索引的順序:

'The mouse ran up the clock' = [1, 2, 3, 4, 1, 5]

有兩種選項可用於向量符記序列:

One-hot 編碼:序列會以 n- 這個詞向量表示 n = 詞彙量大小。這種呈現方式的效果很好 而符記化為字元又太小了 當我們將詞彙符記化時,詞彙通常 導致一次性向量非常稀疏且效率低落 範例:

'The mouse ran up the clock' = [
  [0, 1, 0, 0, 0, 0, 0],
  [0, 0, 1, 0, 0, 0, 0],
  [0, 0, 0, 1, 0, 0, 0],
  [0, 0, 0, 0, 1, 0, 0],
  [0, 1, 0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0, 1, 0]
]

嵌入字詞:字詞含意與字詞相關聯。因此 可以表示文字符記在稠密向量空間 (約幾百個實數) 中 其中字詞之間的位置和距離代表字詞的相似程度 語意上下文 (請參閱圖 7)。這種表示法稱為 字詞嵌入

文字嵌入

圖 7:字詞嵌入

序列模型的第一層通常會有這樣的嵌入層。這個 模型會學習如何將字詞索引序列 轉換成字詞嵌入向量 確保每個字詞索引都會對應至 表示該字詞在語意空間中的實際值 (請見圖 8)。

嵌入層

圖 8:嵌入層

選取特徵

並非所有資料都會用於標籤預測。我們可以最佳化 從詞彙中捨棄罕見或不相關的字詞,提升學習體驗。於 事實上,我們發現最常使用 20,000 個功能, 而負責任的 AI 技術做法 有助於達成這項目標這也適用於 n 元語法模型 (請見圖 6)。

讓我們將上述所有步驟以序列向量化。 以下程式碼會執行這些工作:

  • 將文字權杖化
  • 使用前 20,000 個符記建立詞彙
  • 將符記轉換為序列向量
  • 將序列固定至固定序列長度
from tensorflow.python.keras.preprocessing import sequence
from tensorflow.python.keras.preprocessing import text

# Vectorization parameters
# Limit on the number of features. We use the top 20K features.
TOP_K = 20000

# Limit on the length of text sequences. Sequences longer than this
# will be truncated.
MAX_SEQUENCE_LENGTH = 500

def sequence_vectorize(train_texts, val_texts):
    """Vectorizes texts as sequence vectors.

    1 text = 1 sequence vector with fixed length.

    # Arguments
        train_texts: list, training text strings.
        val_texts: list, validation text strings.

    # Returns
        x_train, x_val, word_index: vectorized training and validation
            texts and word index dictionary.
    """
    # Create vocabulary with training texts.
    tokenizer = text.Tokenizer(num_words=TOP_K)
    tokenizer.fit_on_texts(train_texts)

    # Vectorize training and validation texts.
    x_train = tokenizer.texts_to_sequences(train_texts)
    x_val = tokenizer.texts_to_sequences(val_texts)

    # Get max sequence length.
    max_length = len(max(x_train, key=len))
    if max_length > MAX_SEQUENCE_LENGTH:
        max_length = MAX_SEQUENCE_LENGTH

    # Fix sequence length to max value. Sequences shorter than the length are
    # padded in the beginning and sequences longer are truncated
    # at the beginning.
    x_train = sequence.pad_sequences(x_train, maxlen=max_length)
    x_val = sequence.pad_sequences(x_val, maxlen=max_length)
    return x_train, x_val, tokenizer.word_index

標籤向量

我們已經瞭解如何將範例文字資料轉換成數值向量。類似的程序 都必須套用至標籤只要把標籤轉換成 [0, num_classes - 1]。例如,有 3 個類別 值 0、1 和 2 來表示。內部網路則會使用一次性圖片 用來代表這些值的向量 (以避免推斷出錯誤關係) 標籤)。此表示法取決於損失函式和 我們用於類神經網路的資料層啟用函式稍後我們將深入探討 相關內容