AI Lab開源大規模高質量中文詞向量數據,800萬中文詞隨你用,質量很是高,就是一個詞向量.txt文件都有16G之多,太誇張了。。不過的確很是有特色:python
⒈ 覆蓋率(Coverage):
該詞向量數據包含不少現有公開的詞向量數據所欠缺的短語,好比「不念僧面唸佛面」、「冰火兩重天」、「煮酒論英雄」、「皇帝菜」、「喀拉喀什河」等。以「喀拉喀什河」爲例,利用騰訊AI Lab詞向量計算出的語義類似詞以下:git
墨玉河、和田河、玉龍喀什河、白玉河、喀什河、葉爾羌河、克里雅河、瑪納斯河github
⒉ 新鮮度(Freshness):
該數據包含一些最近一兩年出現的新詞,如「戀與製做人」、「三生三世十里桃花」、「打call」、「十動然拒」、「供給側改革」、「因吹斯汀」等。以「因吹斯汀」爲例,利用騰訊AI Lab詞向量計算出的語義類似詞以下:算法
一顆賽艇、因吹斯聽、城會玩、厲害了word哥、emmmmm、扎心了老鐵、神吐槽、能夠說是很是爆笑了bash
⒊ 準確性(Accuracy):
因爲採用了更大規模的訓練數據和更好的訓練算法,所生成的詞向量可以更好地表達詞之間的語義關係。服務器
騰訊AI Lab採用自研的Directional Skip-Gram (DSG)算法做爲詞向量的訓練算法。DSG算法基於普遍採用的詞向量訓練算法Skip-Gram (SG),在文本窗口中詞對共現關係的基礎上,額外考慮了詞對的相對位置,以提升詞向量語義表示的準確性。網絡
1 Tencent_AILab_ChineseEmbedding讀入與高效查詢
2 未知詞、短語向量補齊與域內類似詞搜索
網絡用語挖掘:
評論觀點
同義詞挖掘app
來看一下一個比較常見的讀入方式:lvyufeng/keras_text_sum/load_embedding.pyiphone
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變爲只讀的,這樣能夠預載類似度矩陣,對於後面得類似查詢很是有利。
這邊未知詞語、短語的補齊手法是參考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), ...
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),