python中常用的分析文檔、計算詞語相似度的包 —— Word2Vec函數;該函數在gensim.models.Word2Vec包內。
分析文本和計算相似度有幾個步驟:
導入需要用到的庫:
# 導入第三包 import jieba import pandas as pd import gensim from collections import Counter import csv import time from tqdm import tqdm from progressbar import ProgressBar, Percentage, Bar, Timer, ETA, FileTransferSpeed import os
定義文件位置,包括數據集位置和自定義的詞庫位置:
first_dir = r'D:\Python_workspace\spyder_space\test數據集' #里面存放着一個或者多個相同結構的excel表格數據 file_list=os.listdir(first_dir) print(file_list) path_dir= r'D:\Python_workspace\spyder_space\' #存放着關鍵詞文件、停用詞文件
1. 前期分詞准備(如果已分詞並保存可以跳過):jieba分詞,也可參考:https://www.cnblogs.com/qi-yuan-008/p/11689530.html
- 導入關鍵詞庫,是為了保證某些詞不被切開,用於得到自己需要的詞:
# 讀入自定義詞 with open(path_dir+r'\自定義關鍵詞.txt', encoding='UTF-8') as words: #分詞中想保留的關鍵詞,要不然有可能會被切分開 my_words = [i.strip() for i in words.readlines()]
- 將關鍵詞加入分詞器:
# 將自定義詞加入到jieba分詞器中 for word in my_words: jieba.add_word(word)
- 導入停用詞(用於去掉無意義或者不需要的詞):
# 讀入停止詞 with open(path_dir+r'\自定義停用詞.txt', encoding='UTF-8') as words: stop_words = [i.strip() for i in words.readlines()]
- 定義分詞函數:
# 基於切詞函數,構造自定義函數 def cut_word(sentence): words = [i for i in jieba.cut(sentence) if i not in stop_words and len(i)>1] # 切完的詞用空格隔開 result = ' '.join(words) return result, words
2. 讀入數據和分詞: pd.read_excel,文件夾下多個文檔或者單個文檔
print('----------------- it is going to cut words ----------------') cut_result_list = [] cut_result_list_2 = [] out_words = '' num_rows = 0 for jj in file_list: #file_list是文件夾的文件列表,如果該文件夾下有一個或者多個相同結構的數據文檔,可以用;如果只想單獨分析一個大文檔,可以去掉for循環,直接讀入數據pd.read_excel即可 print('-------------- the file name is: '+jj) tmp_file = first_dir+'\\'+jj df = pd.read_excel(tmp_file) # 展示數據前5行 print(df.head()) sentences = df['content'] for i in tqdm(range(len(sentences))): # tqdm 是進度條函數 num_rows += 1 word = sentences[i] word_str = str(word) #為了防止出現數字 word_str = word_str.strip() #去掉空格 word_str = word_str.upper() #英文統一成大寫 # cut_words cut_result, words_list = cut_word(word_str) cut_result_list.extend(words_list) #保存所有的分詞,用於詞頻統計 cut_result_list_2.append(words_list) #保存成可迭代變量,用於word2vec函數 out_words = out_words + cut_result + '\n' #連接所有的分詞結果,用於寫入文本 with open(first_dir+r'\jieba_分詞.txt', "w",encoding='utf-8') as f: #將分詞結果保存成外部數據集,進行導入操作 f.write(out_words) print('------------ all the rows is '+str(num_rows)+'----------------')
3. 進行詞頻統計,獲取前10的熱詞:
# 詞頻統計 c = Counter() for x in cut_result_list: if len(x) > 1: if x == '\r\n' or x == '\n' or x == '': continue else: c[x] += 1 print('常用詞頻度統計結果:\n') out_words_2 = '' hotwords_list = [] for (kk, vv) in c.most_common(10): #保存前n為的熱詞 hotwords_list.append(kk) out_words_2 = out_words_2 + kk + '\t' + str(vv) + '\n' with open(first_dir+r'\熱詞詞頻.txt', "w",encoding='utf-8') as f: f.write(out_words_2)
4. 使用word2vec進行訓練,得到詞語的向量模型:min_count_num 參數是用於去掉詞頻小於該值的詞語
print('----------------- it is going to do Word2Vec ----------------') min_count_num = 10 while min_count_num > vv: min_count_num = min_count_num//2
- 如果是采用以上保存的分詞文件:jieba_分詞.txt,則需要使用:gensim.models.word2vec.Text8Corpus()
sentences_vec=gensim.models.word2vec.Text8Corpus(first_dir+r'\jieba_分詞.txt') #導入外部數據 model=gensim.models.Word2Vec(sentences, min_count=min_count_num, size=100, window=4, workers=4) #需要將分好的詞導入數據使用,sentences必須是可迭代的數據
- 當然也可以直接用以上分詞變量參數:cut_result_list_2 —— 是一個可迭代變量 list,直接使用:gensim.models.Word2Vec()
model=gensim.models.Word2Vec(cut_result_list_2, min_count=min_count_num, size=100, window=4, workers=4) #直接使用已分好的詞,不進行導入數據操作
5. 保存模型和載入模型:一般在單個*.py計算時可以不用,因為可以直接計算就行,但是你保存的模型可以下次使用;model.save和gensim.models.Word2Vec.load
model.save(first_dir+r'\test.model') #保存數據的vec模型 model = gensim.models.Word2Vec.load(first_dir+r'\test.model') #導入模型,其中包含每個詞及其對應的向量
6. 得到熱詞所對應的前5個相似度最高的詞:
print('----------------- it is going to saving data ----------------') most_similar_list = [] total = len(hotwords_list) widgets = ['Progress: ',Percentage(), ' ', Bar('=>'),' ', Timer(), ' ', ETA(), ' ', FileTransferSpeed()] pbar = ProgressBar(widgets=widgets, maxval=10*total).start() #另一種形式的進度條 for i in range(total): tt = hotwords_list[i] tmp_list = [tt] print('=== 詞庫中距離“{}”的前5個最近的詞是: ==='.format(tt)) for ii in model.most_similar(tt, topn=5): #計算余弦距離最,得到最接近每個熱詞的前5個詞 print(ii) #前面的是詞匯,后面的是相似度值,即余弦距離值 tmp_list.append(ii[0]) most_similar_list.append(tmp_list) #第1列是該熱詞,后5列是與該詞語的相似度值從高到低所對應的詞語 pbar.update(10 * i + 1) pbar.finish()
7. 前兩個詞語的結果如下(余弦距離有負值,表示余弦相似度):
8. 對於此時的模型參數,有一些方法可以使用:
# 計算與一個詞最相似的前多少個詞:
model.most_similar("哈哈哈",topn=10) #計算與該 詞最近似的詞,topn指定排名前n的詞
# 計算兩個詞的相似度:
model.similarity("word1","word2")
# 獲取某個詞對應的詞向量,前提是詞庫里面有這個詞,否則會報錯
model ['成都']
# 返回建立的model模型里面所包含的詞語:
print(model.wv.index2word)
# 找出不屬於同一類的詞:
print(model.doesnt_match("好吃 小吃 不錯 成都".split())) #結果是 '成都',當然這些詞都必須在model詞庫里面
# 追加訓練:
model.train(more_sentences_list) #追加訓練
附加:常用參數解釋:model=gensim.models.Word2Vec(cut_result_list_2, min_count=min_count_num, size=10, window=4, workers=4)
# min_count,是去除小於min_count的單詞 # size,神經網絡層數,也表示用多少維度的向量來表示一個詞語 # sg, 算法選擇 # window, 句子中當前詞與目標詞之間的最大距離 # workers,線程數
參考:
https://www.cnblogs.com/n2meetu/p/8124267.html
https://www.cnblogs.com/pinard/p/7278324.html
https://blog.csdn.net/qq_19707521/article/details/79169826
https://blog.csdn.net/leo_95/article/details/93008210