您好,登錄后才能下訂單哦!
這篇文章主要講解了“python怎么實現(xiàn)預訓練詞嵌入”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“python怎么實現(xiàn)預訓練詞嵌入”吧!
讓我們直接回答一個大問題——預訓練詞嵌入到底是什么?
預訓練詞嵌入是在一個任務(wù)中學習到的詞嵌入,它可以用于解決另一個任務(wù)。
這些嵌入在大型數(shù)據(jù)集上進行訓練,保存,然后用于解決其他任務(wù)。這就是為什么預訓練詞嵌入是遷移學習的一種形式。
遷移學習,顧名思義,就是把一項任務(wù)的學習成果轉(zhuǎn)移到另一項任務(wù)上。學習既可以是權(quán)重,也可以是嵌入。在我們這里,學習的是嵌入。因此,這個概念被稱為預訓練詞嵌入。在權(quán)重的情況下,這個概念被稱為預訓練模型。
但是,為什么我們首先需要預訓練詞嵌入呢?為什么我們不能從零開始學習我們自己的嵌入呢?我將在下一節(jié)回答這些問題。
預訓練詞嵌入在大數(shù)據(jù)集上訓練時捕獲單詞的語義和句法意義。它們能夠提高自然語言處理(NLP)模型的性能。這些單詞嵌入在競賽數(shù)據(jù)中很有用,當然,在現(xiàn)實世界的問題中也很有用。
但是為什么我們不學習我們自己的嵌入呢?好吧,從零開始學習單詞嵌入是一個具有挑戰(zhàn)性的問題,主要有兩個原因:
訓練數(shù)據(jù)稀疏
大量可訓練參數(shù)
不這樣做的主要原因之一是訓練數(shù)據(jù)稀少。大多數(shù)現(xiàn)實世界的問題都包含一個包含大量稀有單詞的數(shù)據(jù)集。從這些數(shù)據(jù)集中學習到的嵌入無法得到單詞的正確表示。
為了實現(xiàn)這一點,數(shù)據(jù)集必須包含豐富的詞匯表。
其次,從零開始學習嵌入時,可訓練參數(shù)的數(shù)量增加。這會導致訓練過程變慢。從零開始學習嵌入也可能會使你對單詞的表示方式處于不清楚的狀態(tài)。
因此,解決上述問題的方法是預訓練詞嵌入。讓我們在下一節(jié)討論不同的預訓練詞嵌入。
我將把嵌入大致分為兩類:單詞級嵌入和字符級嵌入。ELMo和Flair嵌入是字符級嵌入的示例。在本文中,我們將介紹兩種流行的單詞級預訓練詞嵌入:
谷歌的Word2vec
斯坦福的GloVe
讓我們了解一下Word2Vec和GloVe的工作原理。
Word2Vec是Google開發(fā)的最流行的預訓練詞嵌入工具之一。Word2Vec是在Google新聞數(shù)據(jù)集(約1000億字)上訓練的。它有幾個用例,如推薦引擎、單詞相似度和不同的文本分類問題。
Word2Vec的架構(gòu)非常簡單。它是一個只有一個隱藏層的前饋神經(jīng)網(wǎng)絡(luò)。因此,它有時被稱為淺層神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)。
根據(jù)嵌入的學習方式,Word2Vec分為兩種方法:
連續(xù)詞袋模型(CBOW)
Skip-gram 模型
連續(xù)詞袋(CBOW)模型在給定相鄰詞的情況下學習焦點詞,而Skip-gram模型在給定詞的情況下學習相鄰詞。
連續(xù)詞袋模型模型和Skip-gram 模型是相互顛倒的。
例如,想想這句話:““I have failed at times but I never stopped trying”。假設(shè)我們想學習“failed”這個詞的嵌入。所以,這里的焦點詞是“failed”。
第一步是定義上下文窗口。上下文窗口是指出現(xiàn)在焦點詞左右的單詞數(shù)。出現(xiàn)在上下文窗口中的單詞稱為相鄰單詞(或上下文)。讓我們將上下文窗口固定為2
連續(xù)詞袋模型:Input=[I,have,at,times],Output=failed
Skip-gram 模型跳:Input = failed, Output = [I, have, at, times ]
如你所見,CBOW接受多個單詞作為輸入,并生成一個單詞作為輸出,而Skip gram接受一個單詞作為輸入,并生成多個單詞作為輸出。
因此,讓我們根據(jù)輸入和輸出定義體系結(jié)構(gòu)。但請記住,每個單詞作為一個one-hot向量輸入到模型中:
GloVe嵌入的基本思想是從全局統(tǒng)計中導出單詞之間的關(guān)系。
但是,統(tǒng)計數(shù)字怎么能代表意義呢?讓我解釋一下。
最簡單的方法之一是看共現(xiàn)矩陣。共現(xiàn)矩陣告訴我們一對特定的詞在一起出現(xiàn)的頻率。共現(xiàn)矩陣中的每個值都是一對詞同時出現(xiàn)的計數(shù)。
例如,考慮一個語料庫:“play cricket, I love cricket and I love football”。語料庫的共現(xiàn)矩陣如下所示:
現(xiàn)在,我們可以很容易地計算出一對詞的概率。為了簡單起見,讓我們把重點放在“cricket”這個詞上:
p(cricket/play)=1
p(cricket/love)=0.5
接下來,我們計算概率比:
p(cricket/play) / p(cricket/love) = 2
當比率大于1時,我們可以推斷板球最相關(guān)的詞是“play”,而不是“l(fā)ove”。同樣,如果比率接近1,那么這兩個詞都與板球有關(guān)。
我們可以用簡單的統(tǒng)計方法得出這些詞之間的關(guān)系。這就是GLoVE預訓練詞嵌入的想法。
讓我們通過一個案例來比較從頭開始學習我們自己的嵌入和預訓練詞嵌入的性能。我們還將了解使用預訓練詞嵌入是否會提高NLP模型的性能?
所以,讓我們選擇一個文本分類問題-電影評論的情感分析。
將數(shù)據(jù)集加載到Jupyter:
#導入庫 import pandas as pd import numpy as np #讀取csv文件 train = pd.read_csv('Train.csv') valid = pd.read_csv('Valid.csv') #訓練測試集分離 x_tr, y_tr = train['text'].values, train['label'].values x_val, y_val = valid['text'].values, valid['label'].values
準備數(shù)據(jù):
from keras.preprocessing.text import Tokenizer from keras.preprocessing.sequence import pad_sequences tokenizer = Tokenizer() #準備詞匯表 tokenizer.fit_on_texts(list(x_tr)) #將文本轉(zhuǎn)換為整數(shù)序列 x_tr_seq = tokenizer.texts_to_sequences(x_tr) x_val_seq = tokenizer.texts_to_sequences(x_val) #填充以準備相同長度的序列 x_tr_seq = pad_sequences(x_tr_seq, maxlen=100) x_val_seq = pad_sequences(x_val_seq, maxlen=100)
讓我們看一下訓練數(shù)據(jù)中的單詞個數(shù):
size_of_vocabulary=len(tokenizer.word_index) + 1 #+1用于填充 print(size_of_vocabulary)
Output: 112204
我們將構(gòu)建兩個相同架構(gòu)的不同NLP模型。第一個模型從零開始學習嵌入,第二個模型使用預訓練詞嵌入。
定義架構(gòu)從零開始學習嵌入:
#深度學習庫 from keras.models import * from keras.layers import * from keras.callbacks import * model=Sequential() #嵌入層 model.add(Embedding(size_of_vocabulary,300,input_length=100,trainable=True)) #lstm層 model.add(LSTM(128,return_sequences=True,dropout=0.2)) #Global Max池化 model.add(GlobalMaxPooling1D()) #Dense層 model.add(Dense(64,activation='relu')) model.add(Dense(1,activation='sigmoid')) #添加損失函數(shù)、度量、優(yōu)化器 model.compile(optimizer='adam', loss='binary_crossentropy',metrics=["acc"]) #添加回調(diào) es = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3) mc=ModelCheckpoint('best_model.h6', monitor='val_acc', mode='max', save_best_only=True,verbose=1) #輸出模型 print(model.summary())
輸出:
模型中可訓練參數(shù)總數(shù)為33889169。其中,嵌入層貢獻了33661200個參數(shù)。參數(shù)太多了!
訓練模型:
history = model.fit(np.array(x_tr_seq),np.array(y_tr),batch_size=128,epochs=10,validation_data=(np.array(x_val_seq),np.array(y_val)),verbose=1,callbacks=[es,mc])
評估模型的性能:
#加載最佳模型 from keras.models import load_model model = load_model('best_model.h6') #評估 _,val_acc = model.evaluate(x_val_seq,y_val, batch_size=128) print(val_acc)
輸出:0.865
現(xiàn)在,是時候用GLoVE預訓練的詞嵌入來構(gòu)建第二版了。讓我們把GLoVE嵌入到我們的環(huán)境中:
# 將整個嵌入加載到內(nèi)存中 embeddings_index = dict() f = open('../input/glove6b/glove.6B.300d.txt') for line in f: values = line.split() word = values[0] coefs = np.asarray(values[1:], dtype='float32') embeddings_index[word] = coefs f.close() print('Loaded %s word vectors.' % len(embeddings_index))
輸出:Loaded 400,000 word vectors.
通過為詞匯表分配預訓練的詞嵌入,創(chuàng)建嵌入矩陣:
# 為文檔中的單詞創(chuàng)建權(quán)重矩陣 embedding_matrix = np.zeros((size_of_vocabulary, 300)) for word, i in tokenizer.word_index.items(): embedding_vector = embeddings_index.get(word) if embedding_vector is not None: embedding_matrix[i] = embedding_vector
定義架構(gòu)-預訓練嵌入:
model=Sequential() #嵌入層 model.add(Embedding(size_of_vocabulary,300,weights=[embedding_matrix],input_length=100,trainable=False)) #lstm層 model.add(LSTM(128,return_sequences=True,dropout=0.2)) #Global Max池化 model.add(GlobalMaxPooling1D()) #Dense層 model.add(Dense(64,activation='relu')) model.add(Dense(1,activation='sigmoid')) #添加損失函數(shù)、度量、優(yōu)化器 model.compile(optimizer='adam', loss='binary_crossentropy',metrics=["acc"]) #添加回調(diào) es = EarlyStopping(monitor='val_loss', mode='min', verbose=1,patience=3) mc=ModelCheckpoint('best_model.h6', monitor='val_acc', mode='max', save_best_only=True,verbose=1) #輸出模型 print(model.summary())
輸出:
如你所見,可訓練參數(shù)的數(shù)量僅為227969。與嵌入層相比,這是一個巨大的下降。
訓練模型:
history = model.fit(np.array(x_tr_seq),np.array(y_tr),batch_size=128,epochs=10,validation_data=(np.array(x_val_seq),np.array(y_val)),verbose=1,callbacks=[es,mc])
評估模型的性能:
#加載最佳模型 from keras.models import load_model model = load_model('best_model.h6') #評估 _,val_acc = model.evaluate(x_val_seq,y_val, batch_size=128) print(val_acc)
輸出:88.49
與從頭學習嵌入相比,使用預訓練詞嵌入的性能有所提高。
感謝各位的閱讀,以上就是“python怎么實現(xiàn)預訓練詞嵌入”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對python怎么實現(xiàn)預訓練詞嵌入這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。