【论文解读】NLP重铸篇之Word2vec
論文標(biāo)題:Efficient Estimation of Word Representations in Vector Space
論文鏈接:https://arxiv.org/pdf/1301.3781.pdf
復(fù)現(xiàn)代碼地址:https://github.com/wellinxu/nlp_store/blob/master/papers/word2vec.py
論文標(biāo)題:word2vec Parameter Learning Explained
論文鏈接:https://arxiv.org/pdf/1411.2738.pdf
word2vec原論文講得比較簡單,幾乎沒有細(xì)節(jié),本文會根據(jù)另一篇論文【word2vec Parameter Learning Explained】,來詳細(xì)介紹兩種加速方法。本文使用python+tensorflow2.0來復(fù)現(xiàn)word2vec模型,所以模型中的反向梯度計算與參數(shù)優(yōu)化更新,都是使用的tf中的自動求導(dǎo)與優(yōu)化器實(shí)現(xiàn),也因此本文中只涉及到word2vec的兩種結(jié)構(gòu)(CBOW與Skip-gram)及兩種加速方式(Huffman樹-層次softmax和負(fù)采樣)從輸入到loss的前向計算,完整代碼已開源,具體請查看https://github.com/wellinxu/nlp_store。
重鑄系列會分享論文的解析與復(fù)現(xiàn),主要是一些經(jīng)典論文以及前沿論文,但知識還是原汁原味的好,支持大家多看原論文。分享內(nèi)容主要來自于原論文,會有些整理與刪減,以及個人理解與應(yīng)用等等,其中涉及到的算法復(fù)現(xiàn)都會開源在:https://github.com/wellinxu/nlp_store 。
引言
模型結(jié)構(gòu)
CBOW結(jié)構(gòu)
skip-gram結(jié)構(gòu)
softmax的loss計算
Huffman樹——層次softmax
Huffman樹的構(gòu)建
Huffman樹壓縮為數(shù)組
Huffman樹loss計算
負(fù)采樣
采樣權(quán)重調(diào)整
負(fù)采樣loss計算
模型訓(xùn)練
論文結(jié)果
論文之外
參考
引言
word2vec的目標(biāo)是從十億量級的文章跟百萬量級的詞匯中學(xué)習(xí)出高質(zhì)量的詞向量表示,實(shí)驗(yàn)結(jié)果表明,其向量可以達(dá)到類似“江蘇-南京+杭州≈浙江”的效果。
模型結(jié)構(gòu)
在word2vec之前,已經(jīng)有不少關(guān)于詞的連續(xù)表示模型提出來,比如LSA(Latent Semantic Analysis)跟LDA( Latent Dirichlet Allocation)。跟LAS相比,word2vec效果更好,跟LDA相比,word2vec的計算速度更快。
論文中提出了兩種新的模型結(jié)構(gòu):CBOW、Skip-gram,跟NNLM(Feedforward Neural Net Language Model)相比,word2vec為了追求更簡單的模型結(jié)構(gòu),刪除了中間的非線性隱藏層,盡管這樣可能會讓詞向量沒有NNLM的更加精確,但這可以讓模型在更大的數(shù)據(jù)集上高效訓(xùn)練。
兩種結(jié)構(gòu)都是利用中心詞跟上下文互為輸入與輸出,上下文就是中心詞前后的n個詞,實(shí)驗(yàn)表明,提高上下文的范圍(即n的大小),可以提高詞向量的質(zhì)量,但這也加大了計算復(fù)雜度。
CBOW結(jié)構(gòu)
第一種模型結(jié)構(gòu)是CBOW(Continuous Bag-of-Words Model),其思想是利用中心詞前面n個詞跟后面n個詞來預(yù)測中心詞(n可自定義),如上圖所示,用的是前面2個詞跟后面2個詞預(yù)測當(dāng)前詞,輸入層直接求和變成投影層,沒有其他任何操作,然后直接預(yù)測中心詞。整體公式可直接表示為:
其中f表示將projection映射為output的變換函數(shù),是其中的參數(shù),f的具體方式后續(xù)會講解。
Skip-gram結(jié)構(gòu)
第二種模型結(jié)構(gòu)是Skip-gram(Continuous Skip-gram Model),其思想與CBOW相反:利用中心詞預(yù)測中心詞上下文的n個詞(n可自定義),如上圖所示,利用中心詞預(yù)測上下文各2個詞,輸入層直接等價變化到投影層,然后預(yù)測上下文的詞。整體公式可以直接表示為:
本文復(fù)現(xiàn)過程中,將Skip-gram結(jié)構(gòu)視為多標(biāo)簽預(yù)測問題,word2vec的源碼中應(yīng)該是將每個輸出拆開(參考【2】得出的結(jié)論,并未真正看過源碼),組成多個單分類問題。從過程上來說,這兩種方式更新參數(shù)的順序會有差別,有些類似于批梯度下降與隨機(jī)梯度下降的區(qū)別,從工程上來說,word2vec源碼中是簡化了問題,處理更簡單。
softmax的loss計算
如果用softmax來取代上面式子中的f函數(shù),那么ouput的計算方式可具體為:
其中表示預(yù)測為第i個詞的概率,表示第i個詞的輸出權(quán)重向量,N表示詞表大小。
這是一個比較標(biāo)準(zhǔn)的分類問題,所以使用負(fù)對數(shù)似然概率或者交叉熵來計算其loss,具體的CBOW結(jié)構(gòu)的loss可表示為:
其中j表示中心詞的索引,表示預(yù)測是真實(shí)中心詞的概率。
Skip-gram結(jié)構(gòu)的loss則可表示為:
其中M是上下文的數(shù)量,表示預(yù)測是第j個上下文詞的概率。
根據(jù)上面兩種模型結(jié)構(gòu)以及l(fā)oss計算,可以完成相應(yīng)代碼,因?yàn)槟P筒魂P(guān)心輸出,只關(guān)心詞權(quán)重的更新,所以會在模型內(nèi)部直接計算loss,具體代碼如下:
從上面計算公式可以看出,當(dāng)詞表量級特別大的時候(百萬級別),的分母計算以及后續(xù)反向傳播更新所有的計算將會非常耗時,這種昂貴的計算代價使得在大語料或者大詞表情況下訓(xùn)練變得不可能。要解決這個問題,一個直覺的方法是限制每個訓(xùn)練樣本必須更新的輸出向量的數(shù)量,后續(xù)會介紹兩種方式來實(shí)現(xiàn)這一點(diǎn),分別是層次softmax與負(fù)采樣。
Huffman樹——層次softmax
層次softmax是一種高效計算softmax的方法,其使用二叉樹來表示詞表中的所有詞,每一個詞都必須是樹的葉子結(jié)點(diǎn),對于每一個結(jié)點(diǎn),都存在唯一的路徑從根結(jié)點(diǎn)到當(dāng)前葉子結(jié)點(diǎn),該路徑就被用來估計此葉子結(jié)點(diǎn)表示的詞出現(xiàn)的概率。理論上說,可以使用任何形式的樹來計算層次softmax,word2vec里面使用的是二叉Huffman樹來進(jìn)行訓(xùn)練。因?yàn)閔uffman樹中權(quán)重越高的結(jié)點(diǎn)越靠近根結(jié)點(diǎn),這樣頻率高的詞的路徑就越短,計算的次數(shù)也就越少,從而可以進(jìn)一步提高訓(xùn)練速度。
Huffman樹的構(gòu)建
給定n個結(jié)點(diǎn),每個結(jié)點(diǎn)都有一個權(quán)重,構(gòu)造一棵二叉樹,如果它的帶權(quán)路徑長度最小,則稱為最優(yōu)二叉樹,也稱為Huffman樹。給定n個值作為n個結(jié)點(diǎn)的權(quán)重,可以通過下面方法構(gòu)造huffman樹:
將看成是有n棵樹的森林(每棵樹只有一個結(jié)點(diǎn))。
在森林中選出兩個根節(jié)點(diǎn)權(quán)重最小的樹合并,分別作為新樹的左右子樹,新樹根結(jié)點(diǎn)的權(quán)重為左右子樹根結(jié)點(diǎn)權(quán)重之和。
刪除森林中選取的兩棵樹,并將新樹添加到森林。
重復(fù)上面兩步操作,直到森林里就剩一棵樹,該樹就是huffman樹。
如上圖所示,顯示了一個簡單huffman樹的構(gòu)造過程,在本文的實(shí)現(xiàn)中,將葉子結(jié)點(diǎn)優(yōu)先放在右子樹上,但這并不是必要的,也可以將權(quán)重大(或小)的結(jié)點(diǎn)放在右子樹上。
為了實(shí)現(xiàn)其構(gòu)造過程,我們需要先定義結(jié)點(diǎn)類,如下所示:
Node類中定義了權(quán)重(value)、詞(key)、編碼(code)、索引位置(index)以及左右結(jié)點(diǎn),此外還提供了combine方法,用來合并兩棵子樹。定義好結(jié)點(diǎn),就可以通過以下方式來構(gòu)建huffman樹:
class?HuffmanTree(object):#?用一個數(shù)組表示huffman樹的所有非葉子節(jié)點(diǎn)#?用word_code_map表記錄根到每個葉子節(jié)點(diǎn)的編碼def?__init__(self,?words):start?=?time.time()words.sort()??#?根據(jù)頻率排序self.words?=?words????#?[(value:頻次,?key:詞)],由小到大排序self.word_code_map?=?{}????#?詞在huffman樹中的編碼映射self.nodes_list?=?[]?????#?壓縮為數(shù)組的huffman樹self.build_huffman_tree()print("build?huffman?tree?end,time:",?time.time()-start)def?build_huffman_tree(self):#?構(gòu)建huffman樹#?每個元素都構(gòu)成單節(jié)點(diǎn)的樹,并按照權(quán)重重大到小排列#?合并權(quán)重最小的兩個子樹,并以權(quán)重和作為新樹的權(quán)重#?將新樹按照權(quán)重大小插入到序列中#?重復(fù)上述兩步,直到只剩一棵樹nodes?=?[Node(key,?value)?for?value,?key?in?self.words]while?len(nodes)?>?1:a_node?=?nodes.pop(0)b_node?=?nodes.pop(0)new_node?=?a_node.combine(b_node)left,?right?=?0,?len(nodes)l?=?right?-?1i?=?right?>>?1while?True:if?nodes?and?nodes[i].value?>=?new_node.value:if?i?==?0?or?nodes[i-1].value?<?new_node.value:nodes.insert(i,?new_node)breakelse:right?=?ii?=?(left+right)?>>?1else:if?i?==?0?or?i?==?l:nodes.insert(i,?new_node)breakleft?=?ii?=?(left+right)?>>?1其中輸入words是以(詞頻,詞)為元素的list,并以詞頻的大小由小到大排好序。
Huffman樹壓縮為數(shù)組
構(gòu)建完huffman樹,可以根據(jù)其設(shè)計二進(jìn)制前綴編碼,也稱Huffman編碼,下圖展示了一個huffman樹的編碼示例,左子樹為0右子樹為1(這個可自由設(shè)定),如“巴西”就可以編碼為“011”。在后續(xù)計算過程中,不僅需要知道詞的huffman編碼,還需要知道該詞經(jīng)過了哪些結(jié)點(diǎn),為了方便根據(jù)編碼得知結(jié)點(diǎn),我們將樹形結(jié)構(gòu)壓縮為數(shù)組型結(jié)構(gòu)(并不是必要的,也可以通過原始huffman樹,獲取該編碼經(jīng)過的結(jié)點(diǎn)),如上圖所示,huffman樹按照層次遍歷的順序跟數(shù)組的索引一一對應(yīng),數(shù)組中的值表示當(dāng)前結(jié)點(diǎn)左結(jié)點(diǎn)的索引值,如果數(shù)組的值跟索引相同,則表示該結(jié)點(diǎn)是葉子節(jié)點(diǎn)(其實(shí)也可以只將非葉子結(jié)點(diǎn)壓縮到數(shù)組里面,因?yàn)楹罄m(xù)計算中不需要葉子結(jié)點(diǎn))。
根據(jù)上述需求,我們對huffman樹進(jìn)行一次層次遍歷就可以實(shí)現(xiàn),具體代碼如下:
將huffman樹壓縮為數(shù)組后,就可以根據(jù)以下公式計算每個編碼所經(jīng)歷的結(jié)點(diǎn):
所有路徑的第一個結(jié)點(diǎn)都是根結(jié)點(diǎn)
其中表示編碼的長度,表示第i個編碼值,表示經(jīng)過的第i個結(jié)點(diǎn)的位置。比如“巴西”的編碼值是“011”,則可以計算第一個結(jié)點(diǎn)位置是0,第二個是,第三個是,所以“巴西”這個詞經(jīng)過的內(nèi)部結(jié)點(diǎn)位置依次為0-1-4(不算巴西本身這個結(jié)點(diǎn))。
根據(jù)上面公式,我們可以構(gòu)建通過huffman樹處理的訓(xùn)練數(shù)據(jù):
Huffman樹loss計算
Huffman樹中每個詞出現(xiàn)的概率,是將該詞到根結(jié)點(diǎn)路徑上的每個結(jié)點(diǎn)出現(xiàn)的概率相乘,具體公式如下:
其中是編碼長度,是第i個編碼值,為0時表示是往左結(jié)點(diǎn)走,此時用計算概率,為1時則用來計算概率;是上面兩種結(jié)構(gòu)的投影層結(jié)果,表示進(jìn)過的第i個結(jié)點(diǎn)的位置,表示第j個結(jié)點(diǎn)的參數(shù)。
跟一般softmax相比,原來需要計算與更新N(詞表大小)次參數(shù),現(xiàn)在只需要計算與更新次,的大小跟接近,從而大大提高了計算效率。
上面已經(jīng)得到單個詞似然函數(shù),如果是CBOW模型結(jié)構(gòu),那Huffman的loss則可以取其負(fù)對數(shù):
當(dāng)模型結(jié)構(gòu)是Skip-gram結(jié)構(gòu)時,會有多個輸出,此時的Huffman的loss則應(yīng)該為:
其中表示輸出的個數(shù),表示第j個輸出詞的似然概率。
根據(jù)公式,則huffman相關(guān)代碼為:
負(fù)采樣
負(fù)采樣的思想比層次softmax更加直接:為了解決softmax要計算和更新的參數(shù)太多的問題,負(fù)采樣每次只計算和更新幾個參數(shù)。也就是說,原來每個樣本進(jìn)行訓(xùn)練的時候,需要從所有詞匯中選出某個或某幾個詞,現(xiàn)在只需要從某個小的詞集里面選出某個或者某幾個詞,因?yàn)樾≡~集的數(shù)量遠(yuǎn)小于原本詞表數(shù)量,所以計算量與需要更新的參數(shù)都小很多,從而大大提高訓(xùn)練速度。
采樣權(quán)重調(diào)整
根據(jù)負(fù)采樣的思想,預(yù)測的詞肯定需要在小詞集中出現(xiàn),然后只需要從其他詞中抽取一些詞作為負(fù)樣本(負(fù)采樣的由來)。顯而易見的,可以通過詞頻計算詞的分布概率從而進(jìn)行抽樣,但為了降低詞頻過高的詞被抽的概率,以及提高詞頻過低的詞被抽的概率,word2vec中將頻率進(jìn)行了0.75次冪運(yùn)算,然后計算詞的分布概率。相關(guān)代碼,可參考:
????def?build_word_dict(self):#?構(gòu)建詞典,獲取詞頻self.words?=?[]????#?(頻率,id)self.word_map?=?{}????#?{詞:id}word_num_map?=?{}????#?頻率for?doc?in?self.docs:if?len(doc)?<?self.windows:?continuefor?word?in?doc:if?word?not?in?self.word_map.keys():self.word_map[word]?=?len(self.word_map)self.words.append(word)word_num_map[word]?=?word_num_map.get(word,?0)?+?1#?詞頻設(shè)為原本的0.75次方,根據(jù)詞頻進(jìn)行負(fù)采樣的時候,可以降低高詞頻的概率,提高低詞頻的概率(高詞頻的概率仍然大于低詞頻的概率)word_num_map?=?{k:np.power(v,?0.75)?for?k,?v?in?word_num_map.items()}num?=?sum(word_num_map.values())word_num_map?=?{k:?v/num?for?k,?v?in?word_num_map.items()}self.words?=?[(word_num_map[w],?self.word_map[w])?for?w?in?self.words]self.words.sort()????#?根據(jù)頻率排序self.voc_size?=?len(self.words)????#?詞表大小self.id_word_map?=?{v:?k?for?k,?v?in?self.word_map.items()}??#?{id:詞}有了每個詞的概率,可以將每個詞映射到0-1之間的一段范圍之內(nèi),然后生成隨機(jī)數(shù),根據(jù)其落在的空間判斷抽取的詞,遇到正例的詞則跳過,不斷重復(fù),直到抽取到一定的負(fù)樣本數(shù)量,具體代碼如下:
????????#?構(gòu)建負(fù)采樣數(shù)據(jù)if?self.is_negative:#?如果"我?愛?你?啊"出現(xiàn)的概率分別是0.4,0.2,0.3,,0.1,#?那么word_end_p就為[0.4,0.6,0.9,?1.0],即[0.4,0.4+0.2,0.4+0.2+0.3,0.4+0.2+0.3+0.1]word_end_p?=?[self.words[0][0]]????#?每個詞出現(xiàn)的概率段for?i?in?range(1,?self.voc_size):word_end_p.append(word_end_p[-1]+self.words[i][0])#?為每一條訓(xùn)練數(shù)據(jù)抽取負(fù)樣本for?y?in?self.ys:indexs?=?[]while?len(indexs)?<?self.negative_num?*?len(y):index?=?self._binary_search(random.random(),?word_end_p,?0,?self.voc_size-1)#?隨機(jī)抽取一個詞,不能再標(biāo)簽中也不能已經(jīng)被抽到if?index?not?in?indexs?and?index?not?in?y:indexs.append(index)self.negative_index.append(np.array(indexs))def?_binary_search(self,?n,?nums,?start,?end):#?二分查找,查找n在nums[start:end]數(shù)組的那個位置if?start?==?end:?return?endmid?=?(start+end)?>>?1if?nums[mid]?>=?n:return?self._binary_search(n,?nums,?start,?mid)return?self._binary_search(n,?nums,?mid+1,?end)負(fù)采樣loss計算
負(fù)采樣的基本思想是減少更新的參數(shù)數(shù)量,具體操作又是怎樣的呢?簡單的說就是,每一個樣本,對于所有抽樣出來的詞(包括正例詞跟負(fù)例詞),都做一個二分類,正例詞計算正例的概率,負(fù)例詞計算負(fù)例的概率,目標(biāo)是使得所有概率的乘積最大。更具體的解釋及相關(guān)公式可以參考【3】。
這樣就可以得到輸出概率:
其中表示輸出詞(正例詞)的索引集合,表示第i個輸出詞的負(fù)例詞索引集合。當(dāng)模型結(jié)構(gòu)是CBOW時,輸出詞只有一個,當(dāng)模型結(jié)構(gòu)是Skip-gram時,才是多個。
這時候可以計算loss:
根據(jù)公式,相關(guān)代碼如下:
????????#?負(fù)采樣loss計算if?self.is_negative:y_param?=?self.negative_params(y)????#?[label_size,?emb_dim]negative_param?=?self.negative_params(negative_index)????#?[negative_num,?emb_dim]y_dot?=?tf.einsum("ab,b->a",?y_param,?x)????#?[label_size]y_p?=?tf.math.log(tf.sigmoid(y_dot))????#?[label_size]negative_dot?=?tf.einsum("ab,b->a",?negative_param,?x)????#?[negative_num]negative_p?=?tf.math.log(tf.sigmoid(-negative_dot))????#?[negative_num]l?=?tf.reduce_sum(y_p)?+?tf.reduce_sum(negative_p)loss?-=?l以下引用為錯誤思想
根據(jù)負(fù)采樣思想,可以得到每個正例樣本輸出的概率:
其中表示索引為i的輸出詞的預(yù)測概率,表示所有正例詞跟采樣得到的負(fù)例詞索引集合,是上面兩種結(jié)構(gòu)的投影層結(jié)果。
此時,根據(jù)負(fù)對數(shù)似然或者交叉熵可以計算loss函數(shù),當(dāng)模型是CBOW結(jié)構(gòu)時:
其中表示輸出詞的概率。
當(dāng)模型是Skip-gram結(jié)構(gòu)時:
其中表示第j個輸出詞的概率,表示輸出的個數(shù)。
根據(jù)公式,相關(guān)代碼如下:
模型訓(xùn)練
上面已經(jīng)講述了整個word2vec模型的前向傳播環(huán)節(jié),本次模型復(fù)現(xiàn)使用的是tensorflow2的框架,所以反向傳播以及參數(shù)更新過程都使用的是框架的自動求導(dǎo)等功能,本文中也不會講述反向傳播相關(guān)原理及公式。模型整體訓(xùn)練代碼如下:
class?Word2vec(object):def?__init__(self,?docs=None,?emb_dim=100,?windows=5,?negative_num=10,?is_cbow=True,?is_huffman=True,?is_negative=False,?epochs=3,?save_path=None):self.docs?=?docs????#?[[我?是?一段?文本],[這是?第二段?文本]]self.windows?=?windows????#?窗口長度self.emb_dim?=?emb_dim????#?詞向量維度self.is_cbow?=?is_cbow???#?是否使用CBOW模式,False則使用SG模式self.is_huffman?=?is_huffman????#?是否使用huffman樹self.is_negative?=?is_negative????#?是否使用負(fù)采樣self.huffman_label?=?[]????#?huffman數(shù)據(jù)的標(biāo)簽,判斷每次選擇左子樹還是右子樹self.huffman_index?=?[]???#?huffman數(shù)據(jù)的編碼,用來獲取編碼上節(jié)點(diǎn)的權(quán)重self.negative_index?=?[]????#?負(fù)采樣的詞索引self.negative_num?=?negative_num????#?負(fù)采樣數(shù)量self.epochs?=?epochs????#?訓(xùn)練輪次self.save_path?=?save_path????#?模型保存路徑if?docs:??#?訓(xùn)練模型self.build_word_dict()????#?構(gòu)建詞典,獲取詞頻self.create_train_data()????#?創(chuàng)建訓(xùn)練數(shù)據(jù)self.train()????#?進(jìn)行訓(xùn)練if?self.save_path:self.save_txt(self.save_path)????#?保存詞向量elif?self.save_path:??#?直接加載詞向量self.load_txt(self.save_path)def?train(self):sample_num?=?len(self.xs)????#?樣本數(shù)量optimizer?=?tf.optimizers.SGD(0.025)????#?優(yōu)化器#?基礎(chǔ)word2vec模型self.model?=?BaseWord2vecModel(self.voc_size,?self.emb_dim,?self.is_huffman,?self.is_negative)#?模型訓(xùn)練for?epoch?in?range(self.epochs):print("start?epoch?%d"?%?epoch)i?=?0for?inputs?in?zip(self.xs,?self.huffman_label,?self.huffman_index,self.ys,?self.negative_index):with?tf.GradientTape()?as?tape:loss?=?self.model(inputs)grads?=?tape.gradient(loss,?self.model.trainable_variables)optimizer.apply_gradients(zip(grads,?self.model.trainable_variables))if?i?%?1000?==?0:print("-%s->%d/%d"?%?("-"?*?(i?*?100?//?sample_num),?i,?sample_num))i?+=?1#?獲取詞向量self.word_embeddings?=?self.model.embedding.embeddings.numpy()norm?=?np.expand_dims(np.linalg.norm(self.word_embeddings,?axis=1),?axis=1)self.word_embeddings?/=?norm????#?歸一化論文結(jié)果
如下表所示,論文中設(shè)置了5種語義問題與9種句法問題來測試向量效果,通過類似vec(big)-vec(bigger)≈vec(small)-vec(smaller)的方式來判斷。
測試結(jié)果如下圖所示,在相同數(shù)據(jù)上訓(xùn)練的640維詞向量,CBOW在句法層面上表現(xiàn)得較好,Skip-gram在語義層面上表現(xiàn)得更好,總體來說還是Skip-gram更好些。
論文也對比了訓(xùn)練語料、向量維度以及訓(xùn)練輪次對結(jié)果的影響,實(shí)驗(yàn)結(jié)果表明,訓(xùn)練語料越多效果更好,600維的結(jié)果比300維的結(jié)果更優(yōu),3輪的訓(xùn)練結(jié)果比1輪的訓(xùn)練結(jié)果更好。
論文之外
word2vec是2013年提出的模型,限于當(dāng)時的算力,在大規(guī)模的語料上進(jìn)行訓(xùn)練,確實(shí)需要更簡單的模型以及一些加速訓(xùn)練方式;之后提出的fasttext在模型結(jié)構(gòu)上可以說跟word2vec一樣,主要區(qū)別在輸入上,fasttext增加了詞的形態(tài)特征;基于算力的提升,最近的預(yù)訓(xùn)練模型參數(shù)越來越大,比如BERT、XLNET,甚至有GPT3這種龐然大物。
再反過來看word2vec,是不是用現(xiàn)在的算力訓(xùn)練,就不需要層次softmax或者負(fù)采樣的加速方式了呢?這還是要分情況討論,雖然說像BERT這樣的模型,都是直接用的softmax進(jìn)行計算,這是因?yàn)橛?xùn)練BERT的人(機(jī)構(gòu)、公司)具有遠(yuǎn)超普通情況下的算力,而且BERT這種輸出維度也只有幾萬大小,詞向量的輸出維度則會有百萬大小(可以想象下詞跟字在數(shù)量上的差別),所以自己進(jìn)行預(yù)訓(xùn)練的時候,需要根據(jù)擁有的算力和輸出維度來判斷是否要使用加速手段。
參考
【1】基于tf2的word2vec模型復(fù)現(xiàn):https://github.com/wellinxu/nlp_store/blob/master/papers/word2vec.py
【2】word2vec 中的數(shù)學(xué)原理詳解:https://www.cnblogs.com/peghoty/p/3857839.html
【3】word2vec Explained_Deriving Mikolov et al.’s Negative-Sampling Word-Embedding Method:https://arxiv.org/pdf/1402.3722v1.pdf
總結(jié)
以上是生活随笔為你收集整理的【论文解读】NLP重铸篇之Word2vec的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【心路历程】你是这样的“夜间工程师”吗?
- 下一篇: Ubuntu 20.04 LTS/RTX