改进版的CBOW模型
復(fù)習(xí)
首先復(fù)習(xí)一下之前的CBOW筆記。
采用推理的方法認(rèn)知單詞、CBOW模型這里面主要是:
CBOW模型的核心思路:給出周圍的單詞(上下文)時,預(yù)測目標(biāo)詞處會出現(xiàn)什么單詞。
要用神經(jīng)網(wǎng)絡(luò)處理單詞,需要先將單詞轉(zhuǎn)化為固定長度的向量,這就引出了單詞的表示。
單詞的表示:將單詞轉(zhuǎn)化為固定長度的向量(one-hot 表示),神經(jīng)網(wǎng)絡(luò)的輸入層的神經(jīng)元個數(shù)就可以固定下來。
CBOW模型:它是根據(jù)上下文預(yù)測目標(biāo)詞的神經(jīng)網(wǎng)絡(luò)。模型的輸入是上下文。大致結(jié)構(gòu)如下。
上圖中的Win和Wout都是矩陣,也就是說,全連接層變換可以看作是輸入層與矩陣相乘。由此引出矩陣乘積層(MatMul)的實(shí)現(xiàn),這里面:
提到了反向傳播:
拿下圖舉例子,反過來的箭頭指向的那個心是2.2,意思就是,如果jym用心程度增加1,那么jym就能多獲得2.2×1=2.2個npy。也就是說,反向傳播目的就是看出輸入的變化對輸出有何影響(偏導(dǎo))。
乘法節(jié)點(diǎn)的反向傳播示意圖如下,可以看出乘法節(jié)點(diǎn)的反向傳播,將上游傳過來的導(dǎo)數(shù)(1.1)乘正向傳播的翻轉(zhuǎn)值,然后傳給下游。jym的心獲得的反向傳播的值是:1.1乘正向傳播的y的2=2.2。
由上面類比得到x、y、z是矩陣的情況下的反向傳播,如下圖。
接下來,需要對語料庫進(jìn)行數(shù)據(jù)的預(yù)處理。預(yù)處理究竟處理的什么,關(guān)鍵就在于下面這張圖。首先從語料庫生成上下文和目標(biāo)詞,然后把上下文和目標(biāo)詞轉(zhuǎn)化為 one-hot 表示。
然后就繼續(xù)去實(shí)現(xiàn)一下普通的CBOW模型類。
整體大致是下面這個情況(里面有的是簡寫,反向傳播還得乘前面?zhèn)鱽淼钠珜?dǎo)數(shù))。
但是這個模型有兩個問題,第一個問題就是:對于輸入層來說,one-hot表示占用內(nèi)存過多,計(jì)算one-hot表示與權(quán)重矩陣的乘積,需要花費(fèi)大量時間。解決這個問題,就需要增加一個Embedding層。也就是說,將原來CBOW模型中輸入側(cè)的MatMul層換成Embedding層。
解決這個問題的核心思路就是:計(jì)算one-hot 表示矩陣和權(quán)重矩陣的乘積,其實(shí)就是將權(quán)重矩陣的某個特定的行取出來。
Embedding 層:一個從權(quán)重矩陣中抽取單詞ID對應(yīng)行(向量)的層。
Embedding 層的正向傳播:從權(quán)重矩陣W中提取特定的行,并將特定行的神經(jīng)元原樣傳給下一層。
Embedding 層的反向傳播:上一層傳來的梯度會被應(yīng)用到權(quán)重梯度dW的特定行(idx)。
第二個問題是:中間層的神經(jīng)元和權(quán)重矩陣的乘積、Softmax層的計(jì)算需要花費(fèi)很多計(jì)算時間。
解決方法就是使用 Negative Sampling (負(fù)采樣) 替代 Softmax。也就是用二分類擬合多分類。
二分類問題:處理答案為是或否的問題,比如目標(biāo)詞是 say 嗎。讓神經(jīng)網(wǎng)絡(luò)來回答:當(dāng)上下文是 you 和 goodbye 時,目標(biāo)詞是 say 嗎?這時輸出層只需要一個神經(jīng)元,神經(jīng)元輸出的是 say 的得分。
輸出側(cè)的權(quán)重矩陣中保存了各個單詞ID對應(yīng)的單詞向量,提取目標(biāo)詞的單詞向量,再求這個向量和中間層神經(jīng)元的內(nèi)積,就是最終的得分。示意圖如下。
Embedding Dot 層合并Embedding 層和 dot 運(yùn)算(內(nèi)積運(yùn)算),優(yōu)化后的CBOW模型如下。
其中向Sigmoid with Loss 層輸入正確解標(biāo)簽1,表示現(xiàn)在正在處理的問題的答案是Yes。當(dāng)答案是No時,向 Sigmoid with Loss 層輸入0。
下圖是進(jìn)一步說明:
目前,只是對正例say進(jìn)行了二分類,如果此時模型有好的權(quán)重,則Sigmoid層的輸出概率將接近1。
真正要做的事是,對于正例say,使Sigmoid層的輸出接近1;對于負(fù)例(say 以外的單詞),使Sigmoid層的輸出接近0。
所以,接下來引出二分類負(fù)采樣方法。主要內(nèi)容如下:
負(fù)采樣方法:求正例作為目標(biāo)詞時的損失,同時采樣(選出)若干個負(fù)例,對這些負(fù)例求損失。然后,將正例和采樣出來的負(fù)例的損失加起來,作為最終的損失。
抽取負(fù)例:讓語料庫中常出現(xiàn)的單詞易被抽到,不常出現(xiàn)的單詞難被抽到。
基于頻率的采樣方法:計(jì)算語料庫中各個單詞的出現(xiàn)次數(shù),并將其表示為概率分布,然后使用這個概率分布對單詞進(jìn)行采樣。負(fù)采樣通過僅關(guān)注部分單詞的方法實(shí)現(xiàn)了計(jì)算的高速化。
至此,就通過畫圖梳理的方法,串聯(lián)起之前寫的筆記的整體脈絡(luò),把CBOW模型復(fù)習(xí)完了。
接下來需要做的是,把改進(jìn)后的CBOW模型實(shí)現(xiàn)出來,然后在PTB數(shù)據(jù)集上進(jìn)行學(xué)習(xí)。
改進(jìn)版的CBOW模型
CBOW類如下:
參數(shù):vocab_size詞匯量,hidden_size中間層的神經(jīng)元個數(shù),corpus單詞ID列表,window_size上下文的大小。
import sys sys.path.append('..') from common.np import * # import numpy as np from common.layers import Embedding from negative_sampling_layer import NegativeSamplingLossclass CBOW:def __init__(self, vocab_size, hidden_size, window_size, corpus):V, H = vocab_size, hidden_size# 初始化權(quán)重W_in = 0.01 * np.random.randn(V, H).astype('f')W_out = 0.01 * np.random.randn(V, H).astype('f')# 生成層self.in_layers = []for i in range(2 * window_size):layer = Embedding(W_in) # 使用Embedding層self.in_layers.append(layer)self.ns_loss = NegativeSamplingLoss(W_out, corpus, power=0.75, sample_size=5)# 將所有的權(quán)重和梯度整理到列表中layers = self.in_layers + [self.ns_loss]self.params, self.grads = [], []for layer in layers:self.params += layer.params#存神經(jīng)網(wǎng)絡(luò)里面的參數(shù)self.grads += layer.grads#存神經(jīng)網(wǎng)絡(luò)里面的梯度# 將單詞的分布式表示設(shè)置為成員變量self.word_vecs = W_indef forward(self, contexts, target):#contexts是上下文,target是目標(biāo)詞,這里是單詞ID形式的h = 0for i, layer in enumerate(self.in_layers):h += layer.forward(contexts[:, i])#contexts是二維數(shù)組h *= 1 / len(self.in_layers)loss = self.ns_loss.forward(h, target)#target是一維數(shù)組return lossdef backward(self, dout=1):dout = self.ns_loss.backward(dout)dout *= 1 / len(self.in_layers)for layer in self.in_layers:layer.backward(dout)return NoneCBOW模型的學(xué)習(xí):
import sys sys.path.append('..') from common import config# 開GPU config.GPU = Truefrom common.np import * import pickle from common.trainer import Trainer from common.optimizer import Adam from cbow import CBOW from skip_gram import SkipGram from common.util import create_contexts_target, to_cpu, to_gpu from dataset import ptb# 設(shè)定超參數(shù) window_size = 5 hidden_size = 100 batch_size = 100 max_epoch = 10# 讀入數(shù)據(jù) corpus, word_to_id, id_to_word = ptb.load_data('train') vocab_size = len(word_to_id)contexts, target = create_contexts_target(corpus, window_size) if config.GPU:contexts, target = to_gpu(contexts), to_gpu(target)# 生成模型等 model = CBOW(vocab_size, hidden_size, window_size, corpus) # model = SkipGram(vocab_size, hidden_size, window_size, corpus) optimizer = Adam() trainer = Trainer(model, optimizer)# 開始學(xué)習(xí) trainer.fit(contexts, target, max_epoch, batch_size) trainer.plot()# 保存必要數(shù)據(jù),以便后續(xù)使用,取出輸入側(cè)得權(quán)重和單詞與單詞ID之間轉(zhuǎn)化得字典 word_vecs = model.word_vecs if config.GPU:word_vecs = to_cpu(word_vecs) params = {} params['word_vecs'] = word_vecs.astype(np.float16) params['word_to_id'] = word_to_id params['id_to_word'] = id_to_word pkl_file = 'cbow_params.pkl' # or 'skipgram_params.pkl' with open(pkl_file, 'wb') as f:pickle.dump(params, f, -1)運(yùn)行情況如下:
CBOW模型評價(jià):
def most_similar(query, word_to_id, id_to_word, word_matrix, top=5):'''相似單詞的查找:param query: 查詢詞:param word_to_id: 從單詞到單詞ID的字典:param id_to_word: 從單詞ID到單詞的字典:param word_matrix: 匯總了單詞向量的矩陣,假定保存了與各行對應(yīng)的單詞向量:param top: 顯示到前幾位''' import sys sys.path.append('..') from common.util import most_similar, analogy import picklepkl_file = 'cbow_params.pkl' # pkl_file = 'skipgram_params.pkl'with open(pkl_file, 'rb') as f:params = pickle.load(f)word_vecs = params['word_vecs']word_to_id = params['word_to_id']id_to_word = params['id_to_word']# most similar task querys = ['you', 'year', 'car', 'toyota'] for query in querys:most_similar(query, word_to_id, id_to_word, word_vecs, top=5)# analogy task print('-'*50) analogy('king', 'man', 'queen', word_to_id, id_to_word, word_vecs) analogy('take', 'took', 'go', word_to_id, id_to_word, word_vecs) analogy('car', 'cars', 'child', word_to_id, id_to_word, word_vecs) analogy('good', 'better', 'bad', word_to_id, id_to_word, word_vecs)輸出:從結(jié)果看出,CBOW 模型獲得的單詞的分布式表示具有良好的性質(zhì)。而且,不僅可以將近似單詞聚在一起,還可以通過向量的加減法來解決類推問題,比如man : woman = king : ?
而且結(jié)果說明,單詞的分布式不僅限于捕獲單詞的含義,它也捕獲了語法中的模式。
遷移學(xué)習(xí):在某個領(lǐng)域?qū)W到的知識可以被應(yīng)用于其他領(lǐng)域。一般先在大規(guī)模語料庫上學(xué)習(xí),然后將學(xué)習(xí)好的分布式表示應(yīng)用于某個單獨(dú)的任務(wù)。
單詞的分布式表示的優(yōu)點(diǎn)是可以將單詞或文檔轉(zhuǎn)化為固定長度的向量。如果可以將自然語言轉(zhuǎn)化為向量,就可以使用常規(guī)的機(jī)器學(xué)習(xí)方法。將這個向量作為其他機(jī)器學(xué)習(xí)系統(tǒng)的輸入,利用常規(guī)的機(jī)器學(xué)習(xí)框架輸出目標(biāo)答案。比如,將向量化的郵件及其情感標(biāo)簽輸入某個情感分類系統(tǒng)(SVM 或神經(jīng)網(wǎng)絡(luò)等)進(jìn)行學(xué)習(xí)。大系統(tǒng)由:生成單詞的分布式表示的系統(tǒng)(word2vec)、對特定問題進(jìn)行分類的系統(tǒng)(比如進(jìn)行情感分類 的 SVM 等)組成。
分布式表示的評價(jià)方法:單詞的分布式表示的評價(jià)往往與實(shí)際應(yīng)用分開進(jìn)行,經(jīng)常使用的評價(jià)指標(biāo)有相似度和類推問題。
[query] youwe: 0.73095703125i: 0.70703125your: 0.6103515625they: 0.59375anybody: 0.58740234375[query] yearmonth: 0.8505859375week: 0.77392578125summer: 0.7568359375spring: 0.75390625decade: 0.69873046875[query] carluxury: 0.603515625window: 0.59375cars: 0.58349609375auto: 0.580078125truck: 0.5771484375[query] toyotamarathon: 0.65087890625nissan: 0.6455078125honda: 0.6357421875seita: 0.630859375minicomputers: 0.6005859375 --------------------------------------------------[analogy] king:man = queen:?carolinas: 5.26953125woman: 5.11328125a.m: 5.08203125downside: 4.90234375mother: 4.65234375#下面說明單詞的分布式表示編碼了時態(tài)相關(guān)的信息 [analogy] take:took = go:?went: 4.53125goes: 4.44921875were: 4.32421875was: 4.2421875came: 4.15234375[analogy] car:cars = child:?a.m: 6.54296875rape: 5.8046875children: 5.453125daffynition: 4.91796875women: 4.8984375[analogy] good:better = bad:?rather: 6.36328125less: 5.24609375more: 5.17578125greater: 4.2265625fewer: 3.80859375總結(jié)
以上是生活随笔為你收集整理的改进版的CBOW模型的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: pb11 打印 自定义纸张_pb自定义纸
- 下一篇: java中unicode显示乱码_Jav