当前位置:   article > 正文

gensim实现LDA主题模型-------实战案例(分析希拉里邮件的主题)_gensim.models.ldamodel

gensim.models.ldamodel

数据集下载:https://download.csdn.net/download/qq_41185868/10963668

第一步: 加载一些必要的库, 我们用的是gensim中的LDA模型,所以必须安装gensim库

  1. import pandas as pd
  2. import re
  3. from gensim.models import doc2vec, ldamodel
  4. from gensim import corpora

第二步:咱们看一下数据集, 这里的数据集有20个特征,我们只取两个。 id 和 邮件内容。

  1. if __name__ == '__main__':
  2. # 加载数据
  3. df = pd.read_csv('./data/HillaryEmails.csv')
  4. df = df[['Id', 'ExtractedBodyText']].dropna() # 这两列主要有空缺值,这条数据就不要了。
  5. print(df.head())
  6. print(df.shape) # (6742, 2)

    分析上面代码: 先用pandas加载数据集,然后取出那两列,如果哪一套数据有空值,我们直接扔掉。  接下来打印前五行以及数据的规格

第三步:数据清洗

       很明显看出数据里面的特殊字符比较多,如邮箱号,时间等,对咱们的主题生成没有什么帮助,所以,咱们必须将其清除掉。 

  1. def clean_email_text(text):
  2. # 数据清洗
  3. text = text.replace('\n', " ") # 新行,我们是不需要的
  4. text = re.sub(r"-", " ", text) # 把 "-" 的两个单词,分开。(比如:july-edu ==> july edu)
  5. text = re.sub(r"\d+/\d+/\d+", "", text) # 日期,对主体模型没什么意义
  6. text = re.sub(r"[0-2]?[0-9]:[0-6][0-9]", "", text) # 时间,没意义
  7. text = re.sub(r"[\w]+@[\.\w]+", "", text) # 邮件地址,没意义
  8. text = re.sub(r"/[a-zA-Z]*[:\//\]*[A-Za-z0-9\-_]+\.+[A-Za-z0-9\.\/%&=\?\-_]+/i", "", text) # 网址,没意义
  9. pure_text = ''
  10. # 以防还有其他特殊字符(数字)等等,我们直接把他们loop一遍,过滤掉
  11. for letter in text:
  12. # 只留下字母和空格
  13. if letter.isalpha() or letter == ' ':
  14. pure_text += letter
  15. # 再把那些去除特殊字符后落单的单词,直接排除。
  16. # 我们就只剩下有意义的单词了。
  17. text = ' '.join(word for word in pure_text.split() if len(word) > 1) # 而且单词长度必须是2以上
  18. return text

       主要就是清除里面的特殊字符,最后再将长度小于1的词也扔掉,对主题生成没有什么帮助。记住:LDA是一个词袋模型。没有上下文的信息。

      在我们的main里面调用上述方法进行数据清洗, 也就是添加五行代码。  最后docs.values是直接从表格中把数据拿出来,见一下输出:

  1. if __name__ == '__main__':
  2. # 加载数据
  3. df = pd.read_csv('./data/HillaryEmails.csv')
  4. df = df[['Id', 'ExtractedBodyText']].dropna() # 这两列主要有空缺值,这条数据就不要了。
  5. print(df.head())
  6. print(df.shape) # (6742, 2)
  7. # 新添加的代码
  8. docs = df['ExtractedBodyText'] # 获取邮件
  9. docs = docs.apply(lambda s: clean_email_text(s)) # 对邮件清洗
  10. print(docs.head(1).values)
  11. doclist = docs.values # 直接将内容拿出来
  12. print(docs)

   注意:一行代表的是一个邮件 

第四步:进一步清洗:去除停用词

     首先,我们本地有一个停用词表,我们加载进行,然后对文本进行停用词的去除

  1. def remove_stopword():
  2. stopword = []
  3. with open('./data/stop_words.utf8', 'r', encoding='utf8') as f:
  4. lines = f.readlines()
  5. for line in lines:
  6. line = line.replace('\n', '')
  7. stopword.append(line)
  8. return stopword

    在我们的main中调用, 再main中进行代码的添加:

  1. stop_word = remove_stopword()
  2. texts = [[word for word in doc.lower().split() if word not in stop_word] for doc in doclist]
  3. print(texts[0]) # 第一个文本现在的样子

   我们这一步不管进行了停用词的处理,还将句子进行了分词,因为gensim中用LDA需要进行分词。 所以我们这一步的输出是:(这里我们只打印了第一个文本)

第五步:开始准备模型进行训练  

    直接在main中添加以下代码:

  1. dictionary = corpora.Dictionary(texts)
  2. corpus = [dictionary.doc2bow(text) for text in texts]
  3. print(corpus[0]) # [(36, 1), (505, 1), (506, 1), (507, 1), (508, 1)]
  4. lda = ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20)
  5. print(lda.print_topic(10, topn=5)) # 第10个主题最关键的五个词
  6. print(lda.print_topics(num_topics=20, num_words=5)) # 把所有的主题打印出来看看

   解释一下以上代码: 第一行是词空间的生成,也就是将所有文章中取出来去重,剩下的词组成的列表。并进行编号  

                                    第二行是针对每个文本,将词汇转为id    如上述第三行后面的注释,(36, 1)的意思就是你这篇文章有36号单词,这个单词在你这篇文章中出现了1次。

                                    下面就是LDA模型的建立训练,注意里面传的参数,  前两个不用讲,最后一个参数说一下,就是我们想让其生成几个主题,跟kmeans中需要指定簇的个数是一个意思。  接着打印最能体现第十个主题的前五个单词。 然后打印这20个主题相关的词。

 

  第二行是一个列表,直截取了一部分。

第六步:保存模型,方面以后的使用

  1. # 保存模型
  2. lda.save('zhutimoxing.model')

第七步:加载模型,并给定一个新邮件,让其判断属于哪个主题

     新邮件内容:'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'

  1. # 加载模型
  2. lda = ldamodel.LdaModel.load('zhutimoxing.model')
  3. # 新鲜数据,判读主题
  4. text = 'I was greeted by this heartwarming display on the corner of my street today. ' \
  5. 'Thank you to all of you who did this. Happy Thanksgiving. -H'
  6. text = clean_email_text(text)
  7. texts = [word for word in text.lower().split() if word not in stop_word]
  8. bow = dictionary.doc2bow(texts)
  9. print(lda.get_document_topics(bow)) # 最后得出属于这三个主题的概率为[(4, 0.6081926), (11, 0.1473181), (12, 0.13814318)]

最后的输出:

 可以看出,属于第17个主题的概率最大 。值为0.5645

完整代码:

  1. """
  2. @file : 010-希拉里邮件进行主题建立之主题模型.py
  3. @author : xiaolu
  4. @time1 : 2019-05-11
  5. """
  6. import numpy as np
  7. import pandas as pd
  8. import re
  9. from gensim.models import doc2vec, ldamodel
  10. from gensim import corpora
  11. def clean_email_text(text):
  12. # 数据清洗
  13. text = text.replace('\n', " ") # 新行,我们是不需要的
  14. text = re.sub(r"-", " ", text) # 把 "-" 的两个单词,分开。(比如:july-edu ==> july edu)
  15. text = re.sub(r"\d+/\d+/\d+", "", text) # 日期,对主体模型没什么意义
  16. text = re.sub(r"[0-2]?[0-9]:[0-6][0-9]", "", text) # 时间,没意义
  17. text = re.sub(r"[\w]+@[\.\w]+", "", text) # 邮件地址,没意义
  18. text = re.sub(r"/[a-zA-Z]*[:\//\]*[A-Za-z0-9\-_]+\.+[A-Za-z0-9\.\/%&=\?\-_]+/i", "", text) # 网址,没意义
  19. pure_text = ''
  20. # 以防还有其他特殊字符(数字)等等,我们直接把他们loop一遍,过滤掉
  21. for letter in text:
  22. # 只留下字母和空格
  23. if letter.isalpha() or letter == ' ':
  24. pure_text += letter
  25. # 再把那些去除特殊字符后落单的单词,直接排除。
  26. # 我们就只剩下有意义的单词了。
  27. text = ' '.join(word for word in pure_text.split() if len(word) > 1) # 而且单词长度必须是2以上
  28. return text
  29. def remove_stopword():
  30. stopword = []
  31. with open('./data/stop_words.utf8', 'r', encoding='utf8') as f:
  32. lines = f.readlines()
  33. for line in lines:
  34. line = line.replace('\n', '')
  35. stopword.append(line)
  36. return stopword
  37. if __name__ == '__main__':
  38. # 加载数据
  39. df = pd.read_csv('./data/HillaryEmails.csv')
  40. df = df[['Id', 'ExtractedBodyText']].dropna() # 这两列主要有空缺值,这条数据就不要了。
  41. print(df.head())
  42. print(df.shape) # (6742, 2)
  43. docs = df['ExtractedBodyText'] # 获取邮件
  44. docs = docs.apply(lambda s: clean_email_text(s)) # 对邮件清洗
  45. print(docs.head(1).values)
  46. doclist = docs.values # 直接将内容拿出来
  47. print(docs)
  48. stop_word = remove_stopword()
  49. texts = [[word for word in doc.lower().split() if word not in stop_word] for doc in doclist]
  50. print(texts[0]) # 第一个文本现在的样子
  51. dictionary = corpora.Dictionary(texts)
  52. corpus = [dictionary.doc2bow(text) for text in texts]
  53. print(corpus[0]) # [(36, 1), (505, 1), (506, 1), (507, 1), (508, 1)]
  54. lda = ldamodel.LdaModel(corpus=corpus, id2word=dictionary, num_topics=20)
  55. print(lda.print_topic(10, topn=5)) # 第10个主题最关键的五个词
  56. print(lda.print_topics(num_topics=20, num_words=5)) # 把所有的主题打印出来看看
  57. # 保存模型
  58. lda.save('zhutimoxing.model')
  59. # 加载模型
  60. lda = ldamodel.LdaModel.load('zhutimoxing.model')
  61. # 新鲜数据,判读主题
  62. text = 'I was greeted by this heartwarming display on the corner of my street today. ' \
  63. 'Thank you to all of you who did this. Happy Thanksgiving. -H'
  64. text = clean_email_text(text)
  65. texts = [word for word in text.lower().split() if word not in stop_word]
  66. bow = dictionary.doc2bow(texts)
  67. print(lda.get_document_topics(bow)) # 最后得出属于这三个主题的概率为[(4, 0.6081926), (11, 0.1473181), (12, 0.13814318)]

    

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/148605
推荐阅读
相关标签
  

闽ICP备14008679号