整体过程就是:
一、首先拿到文档集合,使用分词工具进行分词,得到词组序列;
二、为每个词语分配ID,既corpora.Dictionary;
三、分配好ID后,整理出各个词语的词频,使用“词ID:词频”的形式形成稀疏向量,
四、使用LDA模型进行训练。
五、inference进行主题推断
代码实现:
第二步和第三步
dictionary = corpora.Dictionary(texts)
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus[0]) # [(36, 1), (505, 1), (506, 1), (507, 1), (508, 1)]
第四步
lda = ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #lda参数,语料库,字典(id,word),主题数
print(lda.print_topic(10, topn=5)) # 第10个主题最关键的五个词
使用希拉里邮件数据得到的完整代码如下:
import pandas as pd
import re
from gensim.models import doc2vec,ldamodel
from gensim import corpora
from nltk.corpus import stopwords
def clean_email_text(text):
# 数据清洗
text = text.replace('\n', " ") # 新行,我们是不需要的
text = re.sub(r"-", " ", text) # 把 "-" 的两个单词,分开。(比如:july-edu ==> july edu)
text = re.sub(r"\d+/\d+/\d+", "", text) # 日期,对主体模型没什么意义
text = re.sub(r"[0-2]?[0-9]:[0-6][0-9]", "", text) # 时间,没意义
text = re.sub(r"[\w]+@[\.\w]+", "", text) # 邮件地址,没意义
text = re.sub(r"/[a-zA-Z]*[:\//\]*[A-Za-z0-9\-_]+\.+[A-Za-z0-9\.\/%&=\?\-_]+/i", "", text) # 网址,没意义
pure_text = ''
# 以防还有其他特殊字符(数字)等等,我们直接把他们loop一遍,过滤掉
for letter in text:
# 只留下字母和空格
if letter.isalpha() or letter == ' ':
pure_text += letter
# 再把那些去除特殊字符后落单的单词,直接排除。
# 我们就只剩下有意义的单词了。
text = ' '.join(word for word in pure_text.split() if len(word) > 1) # 而且单词长度必须是2以上
return text
if __name__ == '__main__':
# 加载数据
df = pd.read_csv('./data/HillaryEmails.csv')
df = df[['Id', 'ExtractedBodyText']].dropna() # 这两列只要有空缺值,这条数据就不要了。
print(df.head())
print(df.shape) # (6742, 2)
print('-------------------------------------上边的是加载数据---------------------------------------------')
##清洗数据
docs = df['ExtractedBodyText'] # 获取邮件
docs = docs.apply(lambda s: clean_email_text(s)) # 对邮件清洗
print(docs.head(1).values)
doclist = docs.values # 直接将内容拿出来
print(docs)
print('-------------------------------------上边的是清洗数据---------------------------------------------')
##去除停用词
stop_word = stopwords.words('english')
texts = [[word for word in doc.lower().split() if word not in stop_word] for doc in doclist]
print(texts[0]) # 第一个文本现在的样子
print('-------------------------------------上边的是去除停用词---------------------------------------------')
##对每句话进行编号
dictionary = corpora.Dictionary(texts) ##生成字典,对所有的文本中的词进行编号
corpus = [dictionary.doc2bow(text) for text in texts]
print(corpus[0]) # [(36, 1), (505, 1), (506, 1), (507, 1), (508, 1)]
lda = ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20) #lda参数,语料库,字典(id,word),主题数
print(lda.print_topic(10, topn=5)) # 第10个主题最关键的五个词
print(lda.print_topics(num_topics=20, num_words=5)) # 把所有的主题打印出来看看
# 保存模型
lda.save('zhutimoxing.model')
# 加载模型
lda = ldamodel.LdaModel.load('zhutimoxing.model')
# 新鲜数据,判读主题
text = 'I was greeted by this heartwarming display on the corner of my street today. ' \
'Thank you to all of you who did this. Happy Thanksgiving. -H'
text = clean_email_text(text)
texts = [word for word in text.lower().split() if word not in stop_word]
bow = dictionary.doc2bow(texts)
print(lda.get_document_topics(bow)) # 最后得出属于这三个主题的概率为[(4, 0.6081926), (11, 0.1473181), (12, 0.13814318)]