AI Lab開源大規模高品質中文詞向量資料,800萬中文詞随你用,品質非常高,就是一個詞向量.txt檔案都有16G之多,太誇張了。。不過的确非常有特點:
- ⒈ 覆寫率(Coverage):
該詞向量資料包含很多現有公開的詞向量資料所欠缺的短語,比如“不念僧面念佛面”、“冰火兩重天”、“煮酒論英雄”、“皇帝菜”、“喀拉喀什河”等。以“喀拉喀什河”為例,利用騰訊AI Lab詞向量計算出的語義相似詞如下:
墨玉河、和田河、玉龍喀什河、白玉河、喀什河、葉爾羌河、克裡雅河、瑪納斯河
- ⒉ 新鮮度(Freshness):
該資料包含一些最近一兩年出現的新詞,如“戀與制作人”、“三生三世十裡桃花”、“打call”、“十動然拒”、“供給側改革”、“因吹斯汀”等。以“因吹斯汀”為例,利用騰訊AI Lab詞向量計算出的語義相似詞如下:
一顆賽艇、因吹斯聽、城會玩、厲害了word哥、emmmmm、紮心了老鐵、神吐槽、可以說是非常爆笑了
- ⒊ 準确性(Accuracy):
由于采用了更大規模的訓練資料和更好的訓練算法,所生成的詞向量能夠更好地表達詞之間的語義關系。
騰訊AI Lab采用自研的Directional Skip-Gram (DSG)算法作為詞向量的訓練算法。DSG算法基于廣泛采用的詞向量訓練算法Skip-Gram (SG),在文本視窗中詞對共現關系的基礎上,額外考慮了詞對的相對位置,以提高詞向量語義表示的準确性。
文章目錄
- 1 Tencent_AILab_ChineseEmbedding讀入與高效查詢
- 2 未知詞、短語向量補齊與域内相似詞搜尋
- 網絡用語挖掘:
- 評論觀點
- 同義詞挖掘
1 Tencent_AILab_ChineseEmbedding讀入與高效查詢
來看一下一個比較常見的讀入方式:lvyufeng/keras_text_sum/load_embedding.py
import numpy as np
def load_embedding(path):
embedding_index = {}
f = open(path,encoding='utf8')
for index,line in enumerate(f):
if index == 0:
continue
values = line.split(' ')
word = values[0]
coefs = np.asarray(values[1:],dtype='float32')
embedding_index[word] = coefs
f.close()
return embedding_index
load_embedding('/home/lv/data_set/Tencent_AILab_ChineseEmbedding/Tencent_AILab_ChineseEmbedding.txt')
複制
這樣純粹就是以字典的方式讀入,當然用于模組化沒有任何問題,但是筆者想在之中進行一些相似性操作,最好的就是重新載入gensim.word2vec系統之中,但是筆者發現載入半天都會報錯:
ValueError: invalid vector on line 418987 (is this really the text format?)
複制
仔細一檢視,發現原來一些詞向量的詞就是數字,譬如
-0.2121
或
57851
,是以一直導入不進去。隻能自己用txt讀入後,删除掉這一部分,儲存的格式參考下面。
5 4
是 -0.119938 0.042054504 -0.02282253 -0.10101332
中國人 0.080497965 0.103521846 -0.13045108 -0.01050107
你 -0.0788643 -0.082788676 -0.14035964 0.09101376
我 -0.14597991 0.035916027 -0.120259814 -0.06904249
複制
第一行是一共5個詞,每個詞次元為4.
然後清洗完畢之後,就可以讀入了:
wv_from_text = gensim.models.KeyedVectors.load_word2vec_format('Tencent_AILab_ChineseEmbedding_refine.txt',binary=False)
複制
但是又是一個問題,占用記憶體太大,導緻不能查詢相似詞,是以這裡可以用一下這個神奇的函數,可以高效運作,這樣就可以順利使用
most_similar
這類函數了:
wv_from_text.init_sims(replace=True) # 神奇,很省記憶體,可以運算most_similar
複制
該操作是指model已經不再繼續訓練了,那麼就鎖定起來,讓Model變為隻讀的,這樣可以預載相似度矩陣,對于後面得相似查詢非常有利。
2 未知詞、短語向量補齊與域内相似詞搜尋
這邊未知詞語、短語的補齊手法是參考FastText的用法:極簡使用︱Gemsim-FastText 詞向量訓練以及OOV(out-of-word)問題有效解決
這邊筆者借鑒了fasttext之中的方式,當出現未登入詞或短語的時候,會:
- 先将輸入詞進行n-grams
- 然後去詞表之中查找
- 查找到的詞向量進行平均
主要函數可見:
import numpy as np
def compute_ngrams(word, min_n, max_n):
#BOW, EOW = ('<', '>') # Used by FastText to attach to all words as prefix and suffix
extended_word = word
ngrams = []
for ngram_length in range(min_n, min(len(extended_word), max_n) + 1):
for i in range(0, len(extended_word) - ngram_length + 1):
ngrams.append(extended_word[i:i + ngram_length])
return list(set(ngrams))
def wordVec(word,wv_from_text,min_n = 1, max_n = 3):
'''
ngrams_single/ngrams_more,主要是為了當出現oov的情況下,最好先不考慮單字詞向量
'''
# 确認詞向量次元
word_size = wv_from_text.wv.syn0[0].shape[0]
# 計算word的ngrams詞組
ngrams = compute_ngrams(word,min_n = min_n, max_n = max_n)
# 如果在詞典之中,直接傳回詞向量
if word in wv_from_text.wv.vocab.keys():
return wv_from_text[word]
else:
# 不在詞典的情況下
word_vec = np.zeros(word_size, dtype=np.float32)
ngrams_found = 0
ngrams_single = [ng for ng in ngrams if len(ng) == 1]
ngrams_more = [ng for ng in ngrams if len(ng) > 1]
# 先隻接受2個單詞長度以上的詞向量
for ngram in ngrams_more:
if ngram in wv_from_text.wv.vocab.keys():
word_vec += wv_from_text[ngram]
ngrams_found += 1
#print(ngram)
# 如果,沒有比對到,那麼最後是考慮單個詞向量
if ngrams_found == 0:
for ngram in ngrams_single:
word_vec += wv_from_text[ngram]
ngrams_found += 1
if word_vec.any():
return word_vec / max(1, ngrams_found)
else:
raise KeyError('all ngrams for word %s absent from model' % word)
vec = wordVec('千奇百怪的詞向量',wv_from_text,min_n = 1, max_n = 3) # 詞向量擷取
wv_from_text.most_similar(positive=[vec], topn=10) # 相似詞查找
複制
compute_ngrams
函數是将詞條N-grams找出來,譬如:
compute_ngrams('萌萌的哒的',min_n = 1,max_n = 3)
>>> ['哒', '的哒的', '萌的', '的哒', '哒的', '萌萌的', '萌的哒', '的', '萌萌', '萌']
複制
這邊沒有沿用fasttext之中的
<>
來區分詞頭、詞尾。
wordVec
函數是計算未登入詞的,其中筆者小小加了一些内容,就是:當出現oov的情況下,最好先不考慮單字詞向量,如果能比對到兩個字以上的内容就優先進行平均。
在得到未登入詞或短語的向量之後,就可以快速進行查找,gensim裡面是支援給入向量進行相似詞查找:
wv_from_text.most_similar(positive=[vec], topn=10)
複制
其實,有了這麼一個小函數 + 稍微大記憶體的伺服器,就可以開始挖金礦了,筆者在此給出一部分可供參考與使用的小案例,案例中找出來的相似肯定還是不那麼幹淨,需要自行清洗一下:
網絡用語挖掘:
vec = wordVec('天了噜',wv_from_text,min_n = 1, max_n = 3)
wv_from_text.most_similar(positive=[vec], topn=20)
[('天了噜', 1.0),
('天啦噜', 0.910751223564148),
('天惹', 0.8336831331253052),
('我的天呐', 0.8315592408180237),
('天哪噜', 0.8200887441635132),
('也是醉了', 0.8048921823501587),
('哦買噶', 0.7951157093048096),
('我也是醉了', 0.7925893664360046),
('我的天哪', 0.7903991937637329),
('天呐', 0.7862901091575623)
......
]
複制
評論觀點
vec = wordVec('真難吃',wv_from_text,min_n = 1, max_n = 3)
wv_from_text.most_similar(positive=[vec], negative=['好吃'], topn=20)
[('真難', 0.8344259858131409),
('難吃', 0.8344259262084961),
('不好吃', 0.7413374185562134),
('難啊', 0.7120314836502075),
('難喝', 0.6996017694473267),
('難以下咽', 0.6920732259750366),
('好難', 0.6856701374053955),
('挺好吃', 0.6801191568374634),
('真不容易', 0.6788320541381836),
('真的很難', 0.671592116355896),
('真的很好吃', 0.6692471504211426),
...
複制
例子2:
vec = wordVec('環境幹淨',wv_from_text,min_n = 1, max_n = 3)
wv_from_text.most_similar(positive=[vec], topn=20)
[('環境幹淨', 0.9999998807907104),
('環境幹淨整潔', 0.8523852825164795),
('環境舒适', 0.8281853199005127),
('環境幹淨衛生', 0.8241869211196899),
('衛生幹淨', 0.8118663430213928),
('幹淨衛生', 0.7971832156181335),
('幹淨舒适', 0.796349287033081),
('環境清新', 0.7937666773796082),
('衛生好', 0.7925254702568054),
('環境整潔', 0.7919654846191406),
('環境好', 0.7814522981643677),
('房間幹淨', 0.7802159786224365),
('環境優雅', 0.7685255408287048),
複制
同義詞挖掘
vec = wordVec('蘋果',wv_from_text,min_n = 1, max_n = 3)
wv_from_text.most_similar(positive=[vec],negative=['水果'], topn=20)
[('蘋果公司', 0.5877306461334229),
('蘋果開發', 0.5226757526397705),
('高通', 0.5215991735458374),
('谷歌', 0.5213730335235596),
('蘋果的iphone', 0.5150437355041504),
('微軟', 0.5127487778663635),
('蘋果新', 0.5012987852096558),
('pixel手機', 0.49072039127349854),
('蘋果高管', 0.4897959530353546),
('蘋果iphone', 0.4875335991382599),
('蘋果手機iphone', 0.4791686534881592),
('蘋果晶片', 0.47766292095184326),
('iphone', 0.4754045307636261),
複制