TM05. Word Embedding
Introduction
Features from documents to words
詞嵌入(Word embedding)是詞彙的特徵,顧名思義是該詞被鑲嵌在什麼樣的脈絡下,或者在什麼樣的脈絡下被用。因此,操作型定義就是某個詞周遭有哪些詞,但要怎麼被記錄下來做運算呢?在了解詞嵌入前,先想想「何謂文本的特徵」,也就是文本要怎麼被表達。
文本特徵的表達法中,最直覺的方法就是用詞袋(Bag-of-words)來表示,也就是這個文本裡面有哪些字,且每個字出現過幾次。但我今天如果有100篇文本,我想把他記錄在一起,最有可能的方法就是用矩陣來記錄。每一列為一篇文章,每一欄為某個字,記錄了每個字的出現次數,這個矩陣就是Document-Term-Matrix。

那詞彙的特徵可不可以也用一個詞周遭有哪些詞來表達?當然可以,我們就會得到一個Term-to-Term matrix,橫欄紀錄著每一列的詞和哪些詞「一起出現」。但「一起出現」顯然是個可以操作並設計的定義,總不好把所謂的「詞和詞一起出現」定義為出現在同一篇文章中叫做一起出現。在一篇文章中,第一個詞與最後一個詞的關係可能天差地遠,這樣的定義不切實際。而有個辦法是把他定義為「出現在同一個句子中的詞」或者是「出現在我周遭10個字之內的詞」。而詞嵌入所採取的作法是後者。所以,我們會獲得一個Term-to-Term Matrix。這個Term-to-Term Matrix就可說是詞向量了。
但這樣的Term-to-Term Matrix有個缺點,該矩陣紀錄了任兩個詞周遭分別會有哪些詞,但搞不好完全沒重疊,也就是這個矩陣大部分都是零,那這樣來算詞和詞的相似性顯然說服力不高。如果是Document-Term-Matrix這種問題可能比較小,至少如果我的文本是有目的性地抽出,至少我還有一些中頻關鍵字甚至停用詞,比較文本間的詞彙有什麼差異並不是太詭異。
所以最好的狀況是,我能夠用比較低的維度(例如300維)來表達每個字,又不失去每個字的脈絡。要怎麼做?直接SVD做降維看看?有喔!有人這麼做。不然就是用Word2Vec,用類神經網絡來求得這300維的詞特徵向量。
Resource
Slide
Using tidy approach to implement word embedding
Preparation
Download Chinese word embeddings from CKIP https://ckip.iis.sinica.edu.tw/resource/
Unzip it and pull into suitable directory
Training model
Read csv by pandas
import pandas as pd
df = pd.read_csv('data/sentiment.csv')
df.head(5)

print(len(df))
print(df['tag'].value_counts())
6388
N 3347
P 3041
Name: tag, dtype: int64
Tokenization by jieba
import jieba
df['token_text'] = df['text'].apply(lambda x:list(jieba.cut(x)))
df.head(5)
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/61/5bvzqdmn7455dm96br7vs9jw0000gn/T/jieba.cache Loading model cost 0.661 seconds.
Prefix dict has been built successfully.

Building model
# Training
from gensim.models import Word2Vec
model = Word2Vec(df['token_text'], min_count=1, size=300, window=5, sg=0, workers=4)
# Saving
model.wv.save_word2vec_format('model.bin', binary=True)
Using model
print(model.most_similar(positive=['不會', '他'], negative=['她'], topn=20))
print("-"*40)
print(model.most_similar(positive=['不會', '她'], negative=['他'], topn=20))
print("-"*40)
Loading pre-built model
English
import fasttext.util
fasttext.util.download_model('en', if_exists='ignore') # English
ft = fasttext.load_model('cc.en.300.bin')
Chinese: Using CKIP
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format("/Users/jirlong/Downloads/wordVec/w2v_CNA_ASBC_300d.vec",
binary = False,
unicode_errors='ignore')
print(len(model['好吃']))
print(model.most_similar('好吃'))
300
[('美味', 0.7559595704078674), ('品嚐', 0.719903290271759), ('吃起來', 0.7154861092567444), ('吃到', 0.710068941116333), ('爽口', 0.7017905712127686), ('可口', 0.6996539831161499), ('吃', 0.6877780556678772), ('香甜', 0.6855288743972778), ('鮮美', 0.6764703989028931), ('口感', 0.6668637990951538)]
Last updated