至 https://nlp.stanford.edu/projects/glove 下載文件名為 glove.6B.zip 的檔案(822MB),裡面包含400,000 個單詞(或非單詞的標記)的100 維嵌入向量
讀取該文件看看內容長甚麼樣子,比較好理解接下來要做什麼。
import os glove_dir = 'C:\\Users\\Lido_Lee\\Downloads\\glove.6B' #'cp950' error 需在open中加入(encoding = 'utf-8-sig') f = open(os.path.join(glove_dir, 'glove.6B.100d.txt'), encoding = 'utf-8-sig') i=0 word=[] for line in f: values = line.split() print(values) word.append(values) i += 1 if i >= 4: break f.close()
可以看到Values[0] 都對應一個文字,分別是"the",",(逗號)",".(句號)","of"
看一下每個word含意:
>>>len(word[0])
101
這邊可以看出,每個字都是由100個tensor表示。
了解了之後,接著我們建構一個嵌入矩陣
#構建一個可以加載到Embedding 層中的嵌入矩陣 import numpy as np import os glove_dir = 'C:\\Users\\Lido_Lee\\Downloads\\glove.6B'
embeddings_index = {} #'cp950' error 需在open中加入(encoding = 'utf-8-sig') f = open(os.path.join(glove_dir, 'glove.6B.200d.txt'), encoding = 'utf-8-sig') for line in f: values = line.split() word = values[0] coefs = np.asarray(values[1:], dtype='float32') embeddings_index[word] = coefs f.close() print('Found %s word vectors.' % len(embeddings_index))Found 400000 word vectors.
#準備GloVe 詞嵌入矩陣 embedding_dim = 100 embedding_matrix = np.zeros((max_words, embedding_dim)) for word, i in word_index.items(): if i < max_words: embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector
#定義模型 from keras.models import Sequential from keras.layers import Embedding, Flatten, Dense model = Sequential() model.add(Embedding(max_words, embedding_dim, input_length=maxlen)) model.add(Flatten()) model.add(Dense(32, activation='relu')) model.add(Dense(1, activation='sigmoid')) model.summary()
#將預訓練的詞嵌入加載到Embedding 層中 model.layers[0].set_weights([embedding_matrix]) model.layers[0].trainable = False
#選擇優化器、損失函數、指標 model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc']) #丟進fit訓練模型 history = model.fit(x_train, y_train, epochs=15, batch_size=32, validation_data=(x_val, y_val))
#將訓練好的模型保存起來 model.save_weights('pre_trained_glove_model.h5')
#畫出訓練過程 import matplotlib.pyplot as plt acc = history.history['acc'] val_acc = history.history['val_acc'] loss = history.history['loss'] val_loss = history.history['val_loss'] epochs = range(1, len(acc) + 1) plt.plot(epochs, acc, 'bo', label='Training acc') plt.plot(epochs, val_acc, 'b', label='Validation acc') plt.title('Training and validation accuracy') plt.legend() plt.figure() plt.plot(epochs, loss, 'bo', label='Training loss') plt.plot(epochs, val_loss, 'b', label='Validation loss') plt.title('Training and validation loss') plt.legend() plt.show()
驗證精度大概在70%左右。
如果不使用Glove 預訓練的詞嵌入,將之mark起來。
""" #將預訓練的詞嵌入加載到Embedding 層中 model.layers[0].set_weights([embedding_matrix]) model.layers[0].trainable = False """
可以看到精度約為85%左右。
若使用Glove 預訓練的詞嵌入,且讓Glove的權重是可以跟隨著訓練過程來調整,會是怎樣的情況?
#將預訓練的詞嵌入加載到Embedding 層中 model.layers[0].set_weights([embedding_matrix]) model.layers[0].trainable = True其精度在84%左右。
這邊發生了什麼事情!? 為何預訓練的驗證精度比自己訓練的精度還要低?
這邊猜想是,預訓練的模型在處理少量資料的時候,可以藉由詞向量的特徵是可遷移的性質,在少量資料表現是比較好的,因為新的模型在少量資料時根本沒有提取到任何特徵。但是在處理大量資料(如IMDb)時,新的模型根據大量資料提取的特徵,會是處理這類問題的重要特徵,而不是預訓練模型是屬於較泛化的特徵。
沒有留言:
張貼留言