(本文所使用的Python庫和版本號: Python 3.6, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2, NLTK 3.3)
文字的主題建模時用NLP來識別文字文件中隱藏的某種模式的過程,可以發現該文件的隱藏主題,以便對文件進行分析。主題建模的實現過程是,識別出某文字文件中最有意義,最能表徵主題的詞來實現主題分類,即尋找文字文件中的關鍵詞,通過關鍵詞就可以識別出某文件的隱藏主題。
1. 準備資料集
本次所用的資料集存放在一個txt文件中,故而需要從txt文件中載入該文字內容,然後再對這些文字進行預處理。由於預處理的步驟比較多,故而此處建立一個class來完成資料的載入和預處理過程,也使得程式碼看起來更簡潔,更通用。
# 準備資料集,建一個class來載入資料集,對資料進行預處理
from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
from nltk.stem.snowball import SnowballStemmer
from gensim import models, corpora
class DataSet:
def __init__(self,txt_file_path):
self.__txt_file=txt_file_path
def __load_txt(self): # 從txt文件中載入文字內容,逐行讀入
with open(self.__txt_file,'r') as file:
content=file.readlines() # 一次性將所有的行都讀入
return [line[:-1] for line in content] # 去掉每一行末尾的\n
def __tokenize(self,lines_list): # 預處理之一:對每一行文字進行分詞
tokenizer=RegexpTokenizer('\w+')
# 此處用正規表示式分詞器而不用word_tokenize的原因是:排除帶有標點的單詞
return [tokenizer.tokenize(line.lower()) for line in lines_list]
def __remove_stops(self,lines_list): # 預處理之二:對每一行取出停用詞
# 我們要刪除一些停用詞,避免這些詞的噪聲干擾,故而需要一個停用詞表
stop_words_list=stopwords.words('english') # 獲取英文停用詞表
return [[token for token in line if token not in stop_words_list]
for line in lines_list]
# 這兒有點難以理解,lines_list含有的元素也是list,這一個list就是一行文字,
# 而一行文字內部有N個分片語成,故而lines_list可以看出二維陣列,需要用兩層generator
def __word_stemm(self,lines_list): # 預處理之三:對每個分詞進行詞幹提取
stemmer=SnowballStemmer('english')
return [[stemmer.stem(word) for word in line] for line in lines_list]
def prepare(self):
'''供外部呼叫的函式,用於準備資料集'''
# 先從txt檔案中載入文字內容,再進行分詞,再去除停用詞,再進行詞幹提取
stemmed_words=self.__word_stemm(self.__remove_stops(self.__tokenize(self.__load_txt())))
# 後面的建模需要用到基於dict的詞矩陣,故而先用corpora構建dict在建立詞矩陣
dict_words=corpora.Dictionary(stemmed_words)
matrix_words=[dict_words.doc2bow(text) for text in stemmed_words]
return dict_words, matrix_words
# 以下函式主要用於測試上面的幾個函式是否執行正常
def get_content(self):
return self.__load_txt()
def get_tokenize(self):
return self.__tokenize(self.__load_txt())
def get_remove_stops(self):
return self.__remove_stops(self.__tokenize(self.__load_txt()))
def get_word_stemm(self):
return self.__word_stemm(self.__remove_stops(self.__tokenize(self.__load_txt())))
複製程式碼
這個類是否執行正常,是否能夠得到我們預期的結果了?可以用下面的程式碼來測試
# 檢驗上述DataSet類是否執行正常
dataset=DataSet("E:\PyProjects\DataSet\FireAI\data_topic_modeling.txt")
# 以下測試load_txt()函式是否正常
content=dataset.get_content()
print(len(content))
print(content[:3])
# 以下測試__tokenize()函式是否正常
tokenized=dataset.get_tokenize()
print(tokenized)
# 一下測試__remove_stops()函式是否正常
removed=dataset.get_remove_stops()
print(removed)
# 以下測試__word_stemm()函式是否正常
stemmed=dataset.get_word_stemm()
print(stemmed)
# 以下測試prepare函式是否正常
_,prepared=dataset.prepare()
print(prepared)
複製程式碼
輸出的執行結果比較長,可以看我的github原始碼。
2. 構建模型,訓練資料集
我們用LDA模型(Latent Dirichlet Allocation, LDA)做主題建模,如下:
# 獲取資料集
dataset=DataSet("E:\PyProjects\DataSet\FireAI\data_topic_modeling.txt")
dict_words, matrix_words =dataset.prepare()
# 使用LDAModel建模
lda_model=models.ldamodel.LdaModel(matrix_words,num_topics=2,
id2word=dict_words,passes=25)
# 此處假設原始文件有兩個主題
複製程式碼
上面的程式碼會建立LDAModel並對模型進行訓練,需要注意,LDAModel位於gensim模組中,這個模組需要自己用pip install gensim來安裝,安裝之後才能使用。
LDAModel會計算每個單詞的重要性,然後建立重要性計算方程,依靠此方程來給出預測主題。
如下程式碼可以列印出該重要性方程:
# 檢視模型中最重要的N個單詞
print('Most important words to topics: ')
for item in lda_model.print_topics(num_topics=2,num_words=5):
# 此處只列印最重要的5個單詞
print('Topic: {}, words: {}'.format(item[0],item[1]))
複製程式碼
-------------------------------------輸---------出--------------------------------
Most important words to topics: Topic: 0, words: 0.075*"need" + 0.053*"order" + 0.032*"system" + 0.032*"encrypt" + 0.032*"work" Topic: 1, words: 0.037*"younger" + 0.037*"develop" + 0.037*"promot" + 0.037*"talent" + 0.037*"train"
--------------------------------------------完-------------------------------------
########################小**********結###############################
1,一般機器學習專案需要我們自己處理的內容都是資料集方面,可以將資料集處理過程寫成一個專門的class,比如上面我把文字預處理過程寫在class裡面,每一個函式代表一種預處理方式,這樣條理清楚,具有一定通用性。
2,此處我們使用gensim模組中的LDAModel來做主題建模,gensim模組是一個非常有用的NLP處理工具,在文字內容分析中應用較多。
#################################################################
注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。
參考資料:
1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯