最近斯坦福的CS224N開(kāi)課了难礼,看了下課程介紹,去年google發(fā)表的Transformer以及最近特別火的Contextual Word Embeddings都會(huì)在今年的課程中進(jìn)行介紹如绸。NLP領(lǐng)域確實(shí)是一個(gè)知識(shí)迭代特別快速的領(lǐng)域啰脚,每年都有新的知識(shí)冒出來(lái)。所以身處NLP領(lǐng)域的同學(xué)們要時(shí)刻保持住學(xué)習(xí)的狀態(tài)啊氏涩。筆者又重新在B站上看了這門課程的第一二節(jié)課菲盾。這里是課程鏈接竿屹。前兩節(jié)課的主要內(nèi)容基本上圍繞著詞向量進(jìn)行。所以這篇文章筆者想簡(jiǎn)單的介紹一下詞向量妇穴,以及如何利用python的gensim訓(xùn)練一個(gè)自己的詞向量爬虱。
詞向量簡(jiǎn)介
詞向量指的是一個(gè)詞的向量表示。如果你希望計(jì)算機(jī)能夠進(jìn)行一些復(fù)雜點(diǎn)的文本語(yǔ)義學(xué)習(xí)腾它,你必須得將文本數(shù)據(jù)編碼成計(jì)算機(jī)能夠處理的數(shù)值向量吧跑筝,所以詞向量是一個(gè)自然語(yǔ)言處理任務(wù)中非常重要的一環(huán)。
one-hot representations
很久很久之前瞒滴,一個(gè)詞用onehot進(jìn)行編碼曲梗,如下圖所示,這種方式簡(jiǎn)單粗暴,將一個(gè)詞用一個(gè)只有一個(gè)位置為1稀并,其他地方為0的向量表示仅颇。1的位置就代表了是什么詞。
這種表示有如下缺點(diǎn):
- 占用空間大
- 詞與詞之間的向量是正交關(guān)系碘举,沒(méi)有任何語(yǔ)義關(guān)聯(lián)
Distributional representations
為了克服onehot表示的兩個(gè)缺點(diǎn)忘瓦,Distributional representations的詞向量應(yīng)運(yùn)而生。Distributional representations的詞向量指的是將單詞從原先所屬的空間(一般是one-hot編碼)映射到新的低維空間中去引颈,同時(shí)耕皮,低維空間的詞向量還能表達(dá)出一些語(yǔ)義,比如蝙场,詞的相似性(similarity)或者一對(duì)詞與一對(duì)之間的類比關(guān)系(analogy)凌停。
詞的相似性(similarity): 老婆 和 妻子
類比關(guān)系(analogy): 國(guó)王 - 男人 = 王后 -女人
詞向量模型
Word2vec簡(jiǎn)介
那我們?nèi)绾蔚玫缴鲜鼍哂姓Z(yǔ)義Distributional representations的詞向量呢,2013年提出的word2vec的方法就是一種非常方便得到高質(zhì)量詞向量的方式售滤。其主要思想是:一個(gè)詞的上下文可以很好的表達(dá)出詞的語(yǔ)義罚拟,它是一種通過(guò)無(wú)監(jiān)督的學(xué)習(xí)文本來(lái)用產(chǎn)生詞向量的方式。word2vec中有兩個(gè)非常經(jīng)典的模型:skip-gram和cbow完箩。
模型任務(wù):
- skip-gram:已知中心詞預(yù)測(cè)周圍詞赐俗。
- cbow:已知周圍詞預(yù)測(cè)中心詞。
比如 "the quick brown fox jumps over the lazy dog" 如果定義window-size為2的話弊知,
就會(huì)產(chǎn)生如下圖所示的數(shù)據(jù)集阻逮,window-size決定了目標(biāo)詞會(huì)與多遠(yuǎn)距離的上下文產(chǎn)生關(guān)系:
Skip-Gram:(the,quick) ,其中the 是模型的輸入,quick是模型的輸出秩彤。
Cbow: ((quick,brown),the) ,其中 (quick叔扼,brown)是模型的輸入,the是模型的輸出漫雷。
模型架構(gòu):
skip-gram瓜富,cbow的模型架構(gòu)都是一層單層的神經(jīng)網(wǎng)絡(luò),如下圖所示珊拼,需要注意的部分是:神經(jīng)網(wǎng)絡(luò)的參數(shù)就是我們最后得到的詞向量食呻,神經(jīng)網(wǎng)絡(luò)訓(xùn)練過(guò)程就是學(xué)習(xí)詞向量(網(wǎng)絡(luò)參數(shù))的過(guò)程。
Fasttext簡(jiǎn)介
gensim 中Fasttext 模型架構(gòu)和Word2Vec的模型架構(gòu)差幾乎一樣澎现,只不過(guò)在模型詞的輸入部分使用了詞的n-gram的特征仅胞。這里需要講解一下n-gram特征的含義。舉個(gè)例子剑辫,如果原詞是一個(gè)很長(zhǎng)的詞:你吃了嗎干旧。jieba分詞結(jié)果為["你","吃了","嗎"]妹蔽。
unigram(1-gram)的特征:["你","吃了"椎眯,"嗎"]
bigram(2-gram) 的特征: ["你吃了"挠将,"吃了嗎"]
所以大家發(fā)現(xiàn)沒(méi),n-gram的意思將詞中連續(xù)的n個(gè)詞連起來(lái)組成一個(gè)單獨(dú)的詞编整。
如果使用unigram和bigram的特征舔稀,詞的特征就會(huì)變成:["你","吃了","嗎"掌测,"你吃了"内贮,"吃了嗎"]這么一長(zhǎng)串。使用n-gram的詞向量使得Fast-text模型可以很好的解決未登錄詞(OOV——out-of-vocabulary)的問(wèn)題汞斧。
gensim實(shí)戰(zhàn)部分
首先導(dǎo)入必要的python包夜郁,jieba,gensim等必要的包粘勒。
from gensim.models import fasttext
from gensim.models import word2vec
import pandas as pd
import logging
import jieba
數(shù)據(jù)載入與預(yù)處理
這里筆者用的是某個(gè)比賽的一些評(píng)論文本數(shù)據(jù)竞端,讀入評(píng)論文本數(shù)據(jù)之后對(duì)每一條評(píng)論進(jìn)行分詞。代碼如下:
data = pd.read_csv("data_train.csv",sep="\t",encoding='gbk',header=None)
sentance = list(data[2])
## 對(duì)句子進(jìn)行分詞分詞
def segment_sen(sen):
sen_list = []
try:
sen_list = jieba.lcut(sen)
except:
pass
return sen_list
# 將數(shù)據(jù)變成gensim中 word2wec函數(shù)的數(shù)據(jù)格式
sens_list = [segment_sen(i) for i in sentance]
最終將文本數(shù)據(jù)處理如下格式:一個(gè)list ——包含每一條分詞后的文本list庙睡。
[['烤鴨', '還是', '不錯(cuò)', '的', '事富,', '別的', '菜', '沒(méi)什么', '特殊', '的'],
['使用', '說(shuō)明', '看不懂', '!', '不會(huì)', '用', '埃撵,', '很多', '操作', '沒(méi)', '詳細(xì)', '標(biāo)明', '赵颅!'],
['越來(lái)越', '不好', '了', '虽另,', '菜品', '也', '少', '了', '暂刘,', '服務(wù)', '也', '不', '及時(shí)', '。'],
['是', '在', '是', '不', '知道', '該', '吃', '什么', '好', '捂刺、', '就', '來(lái)', '了'],
......]
Word2vec模型訓(xùn)練
這里筆者簡(jiǎn)單介紹一下word2vec.Word2Vec這個(gè)API的一些重要參數(shù)谣拣。
- size: 表示詞向量的維度,默認(rèn)值是100族展。
- window:決定了目標(biāo)詞會(huì)與多遠(yuǎn)距離的上下文產(chǎn)生關(guān)系森缠,默認(rèn)值是5。
- sg: 如果是0仪缸, 則是CBOW模型贵涵,是1則是Skip-Gram模型,默認(rèn)是0即CBOW模型恰画。
這里筆者都是采用默認(rèn)參數(shù)宾茂。即采用CBOW模型——通過(guò)周圍詞預(yù)測(cè)中心詞的方式訓(xùn)練詞向量。
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model = word2vec.Word2Vec(sens_list,min_count=1,iter=20)
model.save("word2vec.model")
模型訓(xùn)練過(guò)程如下圖所示拴还,筆者的數(shù)據(jù)一個(gè)有61678不同的詞跨晴,所以會(huì)得到一個(gè)61678個(gè)詞向量模型。
Fasttext模型訓(xùn)練
fasttext.FastText API一些重要參數(shù):
- size: 表示詞向量的維度片林,默認(rèn)值是100端盆。
- window:決定了目標(biāo)詞會(huì)與多遠(yuǎn)距離的上下文產(chǎn)生關(guān)系怀骤,默認(rèn)值是5。
- sg: 如果是0焕妙, 則是CBOW模型蒋伦,是1則是Skip-Gram模型,默認(rèn)是0即CBOW模型焚鹊。
上方參數(shù)和word2vec.Word2Vec API的參數(shù)一模一樣凉敲。
- word_ngrams :({1,0}, optional) 1表示使用n-gram的信息,0代表不使用n-gram的信息寺旺,如果設(shè)置為0就等于CBOW或者Skip-gram爷抓。
下方是模型訓(xùn)練代碼:
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
model1 = fasttext.FastText(sens_list,min_count=1,iter=20)
model1.save("fast_text.model")
模型訓(xùn)練過(guò)程如下圖所示,由于數(shù)據(jù)沒(méi)變:同樣有61678不同的詞阻塑,依然會(huì)得到一個(gè)61678個(gè)詞向量模型蓝撇。
兩種模型詞向量?jī)?yōu)劣勢(shì)的對(duì)比
接下來(lái)筆者隨機(jī)找了幾個(gè)詞測(cè)試了下兩種方式訓(xùn)練的詞向量效果如何,model 是 cbow的詞向量模型陈莽,model1是fasttext的詞向量模型渤昌。從下方兩張圖片可以看出,cbow的詞向量的語(yǔ)義相似度的判斷能力要好于fasttext的詞向量走搁。
可是倘若碰到未登錄詞(OOV)独柑,cbow的詞向量模型就無(wú)法處理這些沒(méi)有見(jiàn)過(guò)的詞。
而fasttext可以計(jì)算未登錄詞n-gram詞(subword)的詞向量的平均值私植,從而得到未登錄詞的詞向量忌栅,最終求得和未登錄詞比較相似的詞。
結(jié)語(yǔ)
這里筆者只是簡(jiǎn)單的介紹了一下詞向量的含義曲稼,兩種訓(xùn)練詞向量的方法索绪,同時(shí)對(duì)比了一下這兩種方法的優(yōu)劣勢(shì)。對(duì)于詞向量的訓(xùn)練技術(shù)依然有很多沒(méi)有介紹到贫悄,比如負(fù)采樣瑞驱,分層softmax等加速模型訓(xùn)練技術(shù),還有對(duì)于高頻詞的下采樣技術(shù)窄坦。這里筆者在參考文獻(xiàn)放了一些博客供你學(xué)習(xí)唤反,當(dāng)然這些技術(shù)gensim都封裝好了,你只需調(diào)用就可以啦鸭津。
參考文獻(xiàn):
https://blog.csdn.net/sinat_26917383/article/details/83041424
http://mccormickml.com/tutorials/