Embedding

Embedding的含義

根據tf.keras.layers.Embedding的解釋python

是將正整數轉換爲固定長度的連續向量,它和one-hot編碼的做用相似,都是對數據字符數值進行編碼。網絡

不一樣之處是,embedding是將一個單純的數值轉換成一個長度惟一的機率分佈向量,再避免one-hot編碼產生的特徵稀疏性問題的同時,也能增長特徵的描述。函數

須要注意的是,當embedding進行神經網絡構建時,embedding層必須做爲第一層對輸入數據進行embedding處理。其配置的參數以下post

  • input_dim: 配置字典的長度。embedding 是針對詞頻字典中的索引進行處理的,所以須要配置字典的長度。編碼

  • output_dim: 配置神經網絡層輸出的維度。.net

  • embeddings_initializer: 配置embedding 矩陣的初始化code

  • embeddings_regularizer: 配置embedding 矩陣的正則化方程blog

  • embedding_constraint: 配置embedding 的約束函數索引

  • mask_zero: 配置"0"是否爲Padding的值,若是配置爲True, 則將全部的"0"去掉token

  • input_length: 配置輸入語句的長度,將不足長度的用0填充。

    其中 input_dim 和 output_dim必須指定

當時,我看這個解釋仍是比較懵逼。

舉個小例子吧,下面咱們定義一個詞彙表爲200的嵌入層(例如從0到199的整數編碼的字,包括0到199),一個32維的向量空間,其中將嵌入單詞,以及輸入文檔,每一個單詞有50個單詞。

e = Embedding(input_dim=200, output_dim=32, input_length=50)

Embedding的實例

下面方法基於keras, 在tensorflow中咱們可使用 tf.keras.preprocessing.text.Tokenizer這個API庫下的相關方法

咱們將定義一個小問題,咱們有10個文本文檔,每一個文檔都有一個學生提交的工做評論。每一個文本文檔被分類爲正的「1」或負的「0」。這是一個簡單的情感分析問題。

首先,咱們將定義文檔及其類別標籤。

# define documents 定義文檔
docs = ['Well done!',
		'Good work',
		'Great effort',
		'nice work',
		'Excellent!',
		'Weak',
		'Poor effort!',
		'not good',
		'poor work',
		'Could have done better.']
# define class labels 定義分類標籤
labels = [1,1,1,1,1,0,0,0,0,0]

接下來,咱們來整數編碼每一個文件。這意味着把輸入,嵌入層將具備整數序列。咱們能夠嘗試其餘更復雜的bag of word 模型好比計數或TF-IDF。

Keras提供one_hot()函數來建立每一個單詞的散列做爲一個有效的整數編碼。咱們用估計50的詞彙表大小,這大大減小了hash函數的衝突機率。

# integer encode the documents 獨熱編碼
vocab_size = 50
encoded_docs = [one_hot(d, vocab_size) for d in docs]
print(encoded_docs)

[[6, 16], [42, 24], [2, 17], [42, 24], [18], [17], [22, 17], [27, 42], [22, 24], [49, 46, 16, 34]]

每一個詞都能有0-49的一個索引值。例如 'well done' = [6, 16], 可是因爲不一樣的序列有不一樣的長度,方便進行處理,所以咱們須要進行padding, 將全部的輸入序列的長度填充爲4.

# pad documents to a max length of 4 words 將不足長度的用0填充爲長度4
max_length = 4
padded_docs = pad_sequences(encoded_docs, maxlen=max_length, padding='post')
print(padded_docs)
[[ 6 16  0  0]
 [42 24  0  0]
 [ 2 17  0  0]
 [42 24  0  0]
 [18  0  0  0]
 [17  0  0  0]
 [22 17  0  0]
 [27 42  0  0]
 [22 24  0  0]
 [49 46 16 34]]

咱們如今準備將咱們的嵌入層定義爲咱們的神經網絡模型的一部分。

嵌入的詞彙量爲50,輸入長度爲4,咱們將選擇一個8維的嵌入空間。

該模型是一個簡單的二元分類模型。重要的是,嵌入層的輸出將是每一個8維的4個矢量,每一個單詞一個。咱們將其平鋪到一個32個元素的向量上以傳遞到密集輸出層。

# define the model 定義模型
model = Sequential()
model.add(Embedding(vocab_size, 8, input_length=max_length))
model.add(Flatten())
model.add(Dense(1, activation='sigmoid'))
# compile the model 編譯
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['acc'])
# summarize the model 打印模型信息
print(model.summary())

進行到這,咱們一直須要關注的是在進行維度的轉換,本來是10x4, 可是通過Embedding以後,其實會變成10x4x8.

  1. input_dim: vocal_size = 50 字典的大小,由於咱們在進行one-hot編碼時,每一個詞都是由 0-49 中的某個值做爲索引值, 於是字典大小爲 49+1 = 50;

  2. input_length: 4, 若是輸入的向量長度不足爲4,就會給向量填充0,直到向量長度爲4。

  3. output_dim: 8 每一個詞的向量長度,在embedding以前,每一個詞只有一個索引值,所以咱們須要將每一個詞的索 引轉變成一個長度爲8的機率分佈向量。(10x4x1 => 10x4x8)

    此處咱們能夠明白embedding到底作了什麼,舉個栗子:

    ​ 「公主」和「王妃」 使用One-hot編碼 可能會獲得: 公主 [1 0] 王妃 [0 1] 。

    ​ One-hot編碼可以獲得徹底獨立的兩個01向量,而且當若是文本集夠大,那就會致使稀疏矩陣。

    ​ 因爲二者徹底獨立,表達關聯特徵的能力幾乎就爲0, 但王妃和公主是有關係,最基本的她們都是女性。

    ​ 而embedding會將one-hot編碼(稀疏態),經過一些線性變換,讓相互獨立向量變成了有內在聯繫的關係 向量(密集態)便可能 公主 [ 1.0 0.25] 王妃 [ 0.6 0.75] 。


補充

使用tensorflow2.0中的tokenizer進行處理時。

# 定義word2vec的函數,經過統計全部訓練集中的字符出現頻率,構建字典,並使用字典中的碼值對訓練集中的語句進行替換
def tokenize(lang):
    # 使用高階API tf.keras.preprocessing.text.Tokenize實例化一個轉換器,構建字典並使用字典中的碼值對訓練集中的語句進行替換, oov_token: 配置不在字典中的字符的替換數字,通常使用「3」來替換。
    lang_tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=gConfig['enc_vocab_size'], oov_token=3)
    # 使用fit_on_texts方法對訓練數據進行處理,構建字典
    lang_tokenizer.fit_on_texts(lang)
    # 轉換器使用已經構建好的字典,將訓練集的數據所有替換爲字典的碼值
    tensor = lang_tokenizer.texts_to_sequences(lang)
    # 爲了提升計算效率,將訓練語句的長度統一補全
    tensor = tf.keras.preprocessing.sequence.pad_sequences(tensor, padding='post')

    return tensor, lang_tokenizer

其實裏面還有不少方法,能夠參考該博客

參考

相關文章
相關標籤/搜索