結論:用史丹佛做好的 GloVe 字典去考 19,544 題,答對 63.11%。首都、國名→國籍很準(將近九成),貨幣、反義字首、形容詞→副詞很差(14%~24%)。t-SNE 圖上,有些男女配對黏在一起(boy/girl、man/woman),也有分很開的(brother/sister)。
for analogy in tqdm(data["Question"]): # 一題一題做(tqdm 只是顯示進度條)
word_a, word_b, word_c, word_d = analogy.lower().split() # ① 先轉小寫,再切成四個字
golds.append(word_d) # 正確答案先記下來,等一下對答案
if all(w in model.key_to_index for w in (word_a, word_b, word_c)): # 邊界情況 2:三個字都查得到嗎?
preds.append(model.most_similar(positive=[word_b, word_c], # ② b − a + c,③ 找最近的字
negative=[word_a], topn=1)[0][0])
else:
preds.append(None) # 查不到 → 這題算答錯
| # | 在做什麼 | 為什麼 |
|---|---|---|
| ① | 先轉小寫 | GloVe 字典裡的字全部是小寫。考卷有 Athens、Greece 這種大寫字,不轉的話這些字查不到,整題會被算成答錯。正確答案也要轉小寫,不然 iraq 和 Iraq 會被判成不一樣。 |
| ② | 算 b − a + c | 就是第 1 節的手算第 1 小步。positive=[b, c] 是「加」,negative=[a] 是「減」。 |
| ③ | 找相似度最高的字 | 就是第 1 節的手算第 2、3 小步。topn=1 只拿第 1 名當答案。most_similar 回傳一串「(字, 相似度)」,例如 [('woman', 0.71)](數字是舉例);第一個 [0] 拿第一組,第二個 [0] 拿這一組裡的字 'woman'。 |
字典裡沒有的字叫 OOV(查不到的字)。a、b、c 有一個查不到,就沒辦法算 b − a + c,所以程式先檢查(model.key_to_index 是字典收的所有字,w in model.key_to_index 就是問「這個字查得到嗎?」);查不到就記 None,這題算答錯。
如果沒有這個檢查,most_similar 遇到查不到的字會直接報錯、整個程式停下來。GloVe 字典收了 40 萬字(外部知識),這次 0 題查不到(In [12] 印的)。
most_similar 會自動排除題目裡的 a、b、c 三個字。原因見第 1 節「邊界情況 1」:算出來的點有可能離題目自己的字很近(外部知識:gensim 的設計)。
電腦答的第 1 名跟正確答案 d 一樣,這題就算對。19,544 題全部做完,答對題數 ÷ 19,544 就是正確率。一題真題從頭到尾的完整例子在第 7 節(用 Wiki 20% 字典,因為筆記本只對它印了錯題)。
| 小類 | 正確率 | 例題 |
|---|---|---|
| 整體 | 63.11% | (語意類 65.34%、語法類 61.26%) |
| 常見國家首都 | 93.87% | Athens : Greece = Baghdad : ? |
| 全世界首都 | 88.95% | |
| 國名→國籍 | 87.87% | Albania : Albanian |
| 家人/性別 | 81.62% | boy : girl |
| 比較級 | 79.13% | bad : worse |
| 名詞複數 | 72.00% | banana : bananas |
| -ing | 69.51% | code : coding |
| 動詞第三人稱 | 58.39% | decrease : decreases |
| 過去式 | 55.45% | dancing : danced |
| 最高級 | 54.28% | bad : worst |
| 美國城市在哪州 | 30.81% | Chicago : Illinois |
| 形容詞→副詞 | 24.40% | amazing : amazingly |
| 反義字首 | 20.07% | aware : unaware |
| 貨幣 | 14.20% | Algeria : dinar |
| 情況 | 原因(白話) |
|---|---|
| 首都、國名→國籍很準 | 新聞和維基百科裡天天寫「某國首都某某」「某國人」,而且這些字都很常見,詞向量學得很穩。 |
| 貨幣很差 | kwanza(安哥拉的錢)、dram(亞美尼亞的錢)這些字一年也出現不了幾次,詞向量學不準。而且 won(韓圜)、real(巴西的錢)這種字平常是別的意思(贏了、真的),詞向量被平常的意思拉走。 |
| 反義字首、形容詞→副詞很差 | aware 和 unaware 的前後文常常一樣(「I was __ of it」),所以詞向量很近,但「加上 un-」這個方向不夠一致。詞向量只看前後文,看不到字的拼法。 |
| 美國城市在哪州普通 | 很多美國城市名同時出現在好幾個州(例如好多州都有 Springfield,外部知識),不好學。 |
上面的原因是根據詞向量的原理推論的;要真的確認,要看錯題分析(第 12 節)。
把家人/性別小類(筆記本上叫 family)的 46 個字,從 100 維壓成 2 維畫出來。下圖是用跟筆記本 In [14] 完全一樣的設定重畫的(點的位置相同),只多加了圈和顏色,方便你找:
⟦IMG:glove_tsne_marked⟧
怎麼看這張圖:
perplexity 大約是「照顧幾個近鄰」,這裡設 15)。所以它只保證「近的還是近」,不保證「遠的有多遠」。perplexity 預設 30,但只有 46 個字,所以調成 15;它必須比點的數量小,不然會報錯。
most_similar。考試最常問的是 positive/negative 各放什麼。
結論:自己用 20% 維基百科訓練的字典(本文叫 Wiki 20% 字典),正確率 ⟦R:w20_overall⟧,比 GloVe 字典低約 15 個百分點。語法類掉得比語意類多。但有一個小類反而贏 GloVe:美國城市在哪州。
跟 TODO2 一模一樣,只是把 model(GloVe 字典)換成 my_wv(程式裡的變數名,就是本文的 Wiki 20% 字典)。另外模板在 TODO6 後面沒有放評分的格子,所以我在同一格(In [23])最後補了印成績的程式(照抄 Part II 評分格的寫法)。不然看不到成績。
在看 19,544 題的正確率之前,先跟著一題走完。這題來自筆記本 In [38] 的錯題分析(家人/性別小類):
boy girl father mother
| 小類 | GloVe 字典 | Wiki 20% 字典 | 差幾個百分點 |
|---|
| 原因 | 說明 |
|---|---|
| 教材少很多 | 我們的教材 6.66 億字。GloVe 讀的是維基百科全部+大量新聞(Gigaword),共約 60 億字,大約 9 倍(外部知識:GloVe 官方公布)。 |
| 方法不同 | GloVe 用整份教材的共現統計(Global),Word2Vec 用局部視窗(Local)。老師說「一般來講我們會覺得 GloVe 比 word2vec 好」(W3 01:32:25)。 |
| 教材種類不同 | GloVe 混了新聞,我們只有維基。 |
語法類為什麼掉比較多?(推論)比較級、最高級、-ing 這些字形,在百科全書裡比較少用(百科很少寫「最好的」「正在跑」);GloVe 混了新聞,可能因此比較多。第 10 節的論壇實驗顯示「文體會影響語法類」,但論壇是網友口語,不是新聞,所以不能直接證明新聞的效果。而且 GloVe 跟我們同時差了方法、教材字數、教材種類,無法分開。
美國城市在哪州為什麼反而贏?維基百科每一個美國城市都有一篇文章,開頭常常是「X 是 Y 州的一個城市」,這種句型很多(推論,沒有數過)。我們讀的 100% 是維基百科,GloVe 混了新聞,所以這一類我們的比例比較高。(這是推論,沒有直接驗證。)
一樣是用跟筆記本 In [24] 完全相同的設定重畫、只加了圈和顏色:
⟦IMG:w20_tsne_marked⟧
| 這一次畫出來的圖 | GloVe 字典 | Wiki 20% 字典 |
|---|---|---|
| 男女配對黏在一起 | 有 | 有(boy/girl、bride/groom、dad/mom) |
| 皇室一群 | 有 | 有(king、queen、prince、princess 在右下自成一群) |
| 代名詞一群、複數一群 | 有 | 有 |
| 「繼」字輩自成一群 | 有 | 這次沒有看到,綠色字散在 father、mother、sister 中間 |
可能的解釋:stepfather 這類字在維基百科出現得不多,我們的教材又只有 GloVe 的九分之一,還學不出「繼父」跟「父親」的差別。(推論;t-SNE 每次跑可能不同,這只是一次的圖。)