根據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)
下面方法基於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.
input_dim: vocal_size = 50 字典的大小,由於咱們在進行one-hot編碼時,每一個詞都是由 0-49 中的某個值做爲索引值, 於是字典大小爲 49+1 = 50;
input_length: 4, 若是輸入的向量長度不足爲4,就會給向量填充0,直到向量長度爲4。
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
其實裏面還有不少方法,能夠參考該博客。