天天看點

Keras 模型中使用預訓練的詞向量(用word2vec替換keras自帶的Embedding層)

由于Keras中自帶的Embedding層的表現效果不佳,想用word2vec做為預訓練模型替換Keras中自帶的Embedding層,在此記錄下來。

本文假設大家已經有了訓練好的Word2vec模型,并且簡單了解的keras的embeddings層。可以檢視中文官方文檔了解一下。

1.首先要導入預訓練的詞向量。

## 1 導入 預訓練的詞向量
myPath = './CarComment_vord2vec_100' # 本地詞向量的位址
model = gensim.models.Word2Vec.load(myPath) # 讀取詞向量
           

2.構造“詞語-詞向量”字典

(1) word2idx 儲存詞語和 token 的對應關系,語料庫 tokenize 時候需要。(這個東西我也沒弄明白有什麼作用,我把它删掉之後也是可以正常運作的,大神求告知。)

(2) vocab_list 儲存[(詞語1,詞向量1),(詞語2,詞向量3),········]的清單

(3) embeddings_matrix 存儲所有 word2vec 中所有向量的矩陣,用于初始化模型 Embedding 層

word2idx = {"_PAD": 0} # 初始化 `[word : token]` 字典,後期 tokenize 語料庫就是用該詞典。

vocab_list = [(k, model.wv[k]) for k, v in model.wv.vocab.items()]

# 存儲所有 word2vec 中所有向量的數組,留意其中多一位,詞向量全為 0, 用于 padding
embeddings_matrix = np.zeros((len(model.wv.vocab.items()) + 1, model.vector_size))
           

3.填充字典和矩陣

for i in range(len(vocab_list)):
    word = vocab_list[i][0]
    word2idx[word] = i + 1
    embeddings_matrix[i + 1] = vocab_list[i][1]
           

4.在keras的Embedding層中使用 預訓練詞向量

#使用方法
from keras.layers import Embedding

EMBEDDING_DIM = 100 #詞向量次元

embedding_layer = Embedding(len(embeddings_matrix),          #詞向量矩陣的高(高是詞向量矩陣的特征數,長是詞向量的次元)
                            EMBEDDING_DIM,                   #詞向量的次元
                            weights = [embeddings_matrix],   #Word2vec的預訓練的參數
                            trainable = False                #是否在訓練的過程中更新詞向量
                            )
           

5.構模組化型的完整代碼

from gensim.models import Word2Vec
import numpy as np
from keras.models import Sequential,Input
from keras.layers.core import Dense, Dropout, Activation,Flatten
from keras.layers.embeddings import Embedding
import numpy as np
from gensim.models import word2vec, Word2Vec
from keras import Model
from keras.layers import Conv1D, MaxPooling1D, concatenate

def word2vec2keras_cnn(maxlen = 150,max_features = 2000,embed_size = 32):
    #Input
    comment_seq = Input(shape=[maxlen],name='x_seq')

    model_path = ("./Keras_study/300features_40minwords_10context")#我自己本地的訓練好的word2vec模型
    model = Word2Vec.load(model_path)#加載訓練好的wordvec模型

    word2idx = {"_PAD":0}#初始化'[word : token]'字典,後期tokenize語料庫就是用該字典。
    vocab_list = [(k,model.wv[k]) for k,v in model.wv.vocab.items()]

    #儲存所有 word2vec 中所有向量的數組,留意其中多一位,詞向量全為0,用于padding
    embeddings_matrix = np.zeros((len(model.wv.vocab.items()) + 1,model.vector_size))#建立一個空的矩陣(儲存多個數組)
    for i in range(len(vocab_list)):
        word = vocab_list[i][0]
        word2idx[word] = i + 1
        embeddings_matrix[i+1] = vocab_list[i][1]

    #使用方法
    from keras.layers import Embedding

    EMBEDDING_DIM = 300 #詞向量次元

    embed_comment = Embedding(len(embeddings_matrix),  #詞向量矩陣的高(高是詞向量矩陣的特征數,長是詞向量的次元)
                                EMBEDDING_DIM,          #詞向量的次元
                                weights = [embeddings_matrix],
                                trainable = False
                                )(comment_seq)

    convs = []
    filter_sizes = [2, 3, 4, 5]
    for fsz in filter_sizes:
        l_conv = Conv1D(filters=100, kernel_size=fsz, activation='tanh')(embed_comment)
        l_pool = MaxPooling1D(maxlen - fsz + 1)(l_conv)
        l_pool = Flatten()(l_pool)
        convs.append(l_pool)
    merge = concatenate(convs, axis=1)

    out = Dropout(0.5)(merge)
    output = Dense(32, activation='relu')(out)

    output = Dense(units=1, activation='sigmoid')(output)

    model = Model([comment_seq], output)
    model.compile(loss="binary_crossentropy", optimizer="adam", metrics=['accuracy'])
    return model

model = word2vec2keras_cnn()
print(model.summary())
           

6.模型結構(圖太大,隻顯示出來一部分)

Keras 模型中使用預訓練的詞向量(用word2vec替換keras自帶的Embedding層)

7.實驗結果

用Keras中自帶的Embedding層的精确度為:0.86

Keras 模型中使用預訓練的詞向量(用word2vec替換keras自帶的Embedding層)

用Word2vec替換Keras中自帶的Embedding層精确度為:0.87

Keras 模型中使用預訓練的詞向量(用word2vec替換keras自帶的Embedding層)

精确度有少量的提升,證明了word2vec的有效性。提升幅度小很有可能是因為我訓練word2vec模型的語料庫與我的測試集的語料庫有一定差距,如果用相似的語料庫訓練word2vec模型作為預訓練的初始參數,效果應該會更好。

繼續閱讀