一篇看懂詞向量


為什么需要詞向量?

眾所周知,不管是機器學習還是深度學習本質上都是對數字的數字,Word Embedding(詞嵌入)做的事情就是將單詞映射到向量空間里,並用向量來表示

一個簡單的對比

  • One-hot Vector

對應的詞所在的位置設為1,其他為0;

例如:King, Queen, Man and Woman這句里面Queen對應的向量就是\([0,1,0,0]\)

不足:難以發現詞之間的關系,以及難以捕捉句法(結構)和語義(意思)之間的關系

  • Word2Vec

基本思想是把每個詞表征為\(K\)維的實數向量(每個實數都對應着一個特征,可以是和其他單詞之間的聯系),將相似的單詞分組映射到向量空間的不同部分。也就是Word2Vec能在沒有人為干涉下學習到單詞之間的關系。

舉個最經典的例子:

king- man + woman = queen

實際上的處理是:從king提取了maleness的含義,加上了woman具有的femaleness的意思,最后答案就是queen.

借助表格來理解就是:

animal pet
dog -0.4 0.02
lion 0.2 0.35

比如,animal那一列表示的就是左邊的詞與animal這個概念的相關性


兩個重要模型

  • 原理:擁有差不多上下文的兩個單詞的意思往往是相近的

  • Continuous Bag-of-Words(CBOW)

    • 功能:通過上下文預測當前詞出現的概率

    • BOW的思想:\(v(“a b c”)=1/3( v(“a”) + v(“b”) + v(“c”) )\)

    • 原理分析

      假設文本如下:“the florid prose of the nineteenth century.

      想象有個滑動窗口,中間的詞是關鍵詞,兩邊為相等長度(m,是超參數)的文本來幫助分析。文本的長度為7,就得到了7個one-hot向量,作為神經網絡的輸入向量,訓練目標是:最大化在給定前后文本7情況下輸出正確關鍵詞的概率,比如給定("prose","of","nineteenth","century")的情況下,要最大化輸出"the"的概率,用公式表示就是\(P("the"|("prose","of","nineteenth","century"))\)

    • 特性

      • hidden layer只是將權重求和,傳遞到下一層,是線性的
  • Skip-gram

  • 功能:根據當前詞預測上下文

  • 原理分析

    • 和CBOW相反,則我們要求的概率就變為\(P(Context(w)|w)\)
    • 以上面的句子為例,數據集的構成\(,(input,output)\)就是\((the, prose), (the, of), (the,nineteenth), (the, century)\)
  • 損失函數

    • 如果假設當前詞為\(w\),那么可以寫成\(P(w_{t+j}|w_t)(-m<=j<=m,j\ne0)\),每個詞都會有一個概率,訓練的目標就是最大化這些概率的乘積
    • 也就是:\(L(\theta )=\prod_{(-m\leq j\leq m,j\neq0)}P(w_{t+j}|w_t;\theta)\),表示准確度,要最大化
    • 在概率中也經常有:\(J(\theta)=-\frac{1}{T}logL(\theta)=-\frac{1}{T}\sum^T_{t=1} \sum log(P(w_{t+j}|w_t;\theta))\),加個負號就改成最小
    • 概率示意\(P(o|c)=\frac{exp(u_o^Tv_c)}{\sum^v_{w=1}exp(u_w^Tv_c)}\)
      • \(v_c\):當\(c\)為中心詞時用\(v\)
      • \(u_c\):當\(c\)\(Context\)里時用\(u\)
  • 優點

    • 在數據集比較大的時候結果更准確
  • 不足

    • 詞的順序不重要,並沒有考慮到中文的語法
    • 一詞多義:比如tie的意思有很多個,要如何聚類,可以分出tie-1,tie-2等

代碼

from nltk.tokenize import sent_tokenize, word_tokenize
import warnings
import requests

warnings.filterwarnings(action='ignore')

import gensim
from gensim.models import Word2Vec

#爬取alice.txt文檔
sample = requests.get("http://www.gutenberg.org/files/11/11-0.txt")
s = sample.text

#將換行符變為空格
f = s.replace("\n", " ")

data = []   #存儲的是單詞表

#迭代文本中的每一句話
for i in sent_tokenize(f):
    temp = []

    #將句子進行分詞
    for j in word_tokenize(i):
        temp.append(j.lower())  #存儲的的時候全變為小寫

    data.append(temp)

#創建CBOW模型
model1 = gensim.models.Word2Vec(data, min_count=1,size=200, window=7)   #忽略出現次數小於1的詞,size是每個單詞的詞向量的維度

#輸出結果
print("Cosine similarity between 'alice' " + "and 'wonderland' - CBOW : ", model1.similarity('alice', 'wonderland'))    #計算兩個單詞之間的余弦距離,返回相似度

print("Cosine similarity between 'alice' " + "and 'machines' - CBOW : ", model1.similarity('alice', 'machines'))

#創建Skip-Gram模型
model2 = gensim.models.Word2Vec(data, min_count=1, size=200, window=7, sg=1)    #sg=1說明使用的是Skip-gram模型

#輸入結果
print("Cosine similarity between 'alice' " + "and 'wonderland' - Skip Gram : ", model2.similarity('alice', 'wonderland'))

print("Cosine similarity between 'alice' " + "and 'machines' - Skip Gram : ", model2.similarity('alice', 'machines'))


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM