python LDA实践入门学习

来源:互联网 发布:latex windows 安装 编辑:程序博客网 时间:2024/06/04 20:07

     最近开始学习LDA,苦于没有一个浅显易懂的入门教程,索性自己来搜索了一下,还真的找到了一个不错的入门指南,在这里转载贴出来,如果需要的话也可以参考一下,欢迎交流!

转自:[python] LDA处理文档主题分布代码入门笔记

以前只知道LDA是个好东西,但自己并没有真正去使用过。同时,关于它的文章也非常之多,推荐大家阅读书籍《LDA漫游指南》,最近自己在学习文档主题分布和实体对齐中也尝试使用LDA进行简单的实验。这篇文章主要是讲述Python下LDA的基础用法,希望对大家有所帮助。如果文章中有错误或不足之处,还请海涵~



一. 下载安装

LDA推荐下载地址包括:其中前三个比较常用。
        gensim下载地址:https://radimrehurek.com/gensim/models/ldamodel.html
        pip install lda安装地址:https://github.com/ariddell/lda
        scikit-learn官网文档:LatentDirichletAllocation

其中sklearn的代码例子可参考下面这篇:

        Topic extraction with NMF and Latent Dirichlet Allocation
其部分输出如下所示,包括各个主体Topic包含的主题词:

[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Loading dataset...  
  2. Fitting LDA models with tf features, n_samples=2000 and n_features=1000...  
  3. done in 0.733s.  
  4.   
  5. Topics in LDA model:  
  6. Topic #0:  
  7. 000 war list people sure civil lot wonder say religion america accepted punishment bobby add liberty person kill concept wrong  
  8. Topic #1:  
  9. just reliable gods consider required didn war makes little seen faith default various civil motto sense currency knowledge belief god  
  10. Topic #2:  
  11. god omnipotence power mean rules omnipotent deletion policy non nature suppose definition given able goal nation add place powerful leaders  
  12. ....  

下面这三个也不错,大家有时间的可以见到看看:
        https://github.com/arongdari/python-topic-model
        https://github.com/shuyo/iir/tree/master/lda
        https://github.com/a55509432/python-LDA
其中第三个作者a55509432的我也尝试用过,模型输出文件为:
model_parameter.dat 保存模型训练时选择的参数 wordidmap.dat 保存词与id的对应关系,主要用作topN时查询 model_twords.dat 输出每个类高频词topN个 model_tassgin.dat 输出文章中每个词分派的结果,文本格式为词id:类id model_theta.dat 输出文章与类的分布概率,文本一行表示一篇文章,概率1 概率2..表示文章属于类的概率 model_phi.dat 输出词与类的分布概率,是一个K*M的矩阵,K为设置分类的个数,M为所有文章的词的总数
但是短文本信息还行,但使用大量文本内容时,输出文章与类分布概率几乎每行数据存在大量相同的,可能代码还存在BUG。

下面是介绍使用pip install lda安装过程及代码应用:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. pip install lda  

参考:[python] 安装numpy+scipy+matlotlib+scikit-learn及问题解决


二. 官方文档

这部分内容主要参考下面几个链接,强推大家去阅读与学习:
        官网文档:https://github.com/ariddell/lda
        lda: Topic modeling with latent Dirichlet Allocation
        Getting started with Latent Dirichlet Allocation in Python - sandbox
        [翻译] 在Python中使用LDA处理文本 - letiantian
        文本分析之TFIDF/LDA/Word2vec实践 - vs412237401

1.载入数据

[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import numpy as np  
  2. import lda  
  3. import lda.datasets  
  4.   
  5. # document-term matrix  
  6. X = lda.datasets.load_reuters()  
  7. print("type(X): {}".format(type(X)))  
  8. print("shape: {}\n".format(X.shape))  
  9. print(X[:5, :5])  
  10.   
  11. # the vocab  
  12. vocab = lda.datasets.load_reuters_vocab()  
  13. print("type(vocab): {}".format(type(vocab)))  
  14. print("len(vocab): {}\n".format(len(vocab)))  
  15. print(vocab[:5])  
  16.   
  17. # titles for each story  
  18. titles = lda.datasets.load_reuters_titles()  
  19. print("type(titles): {}".format(type(titles)))  
  20. print("len(titles): {}\n".format(len(titles)))  
  21. print(titles[:5])  
载入LDA包数据集后,输出如下所示:
X矩阵为395*4258,共395个文档,4258个单词,主要用于计算每行文档单词出现的次数(词频),然后输出X[5,5]矩阵;
vocab为具体的单词,共4258个,它对应X的一行数据,其中输出的前5个单词,X中第0列对应church,其值为词频;
titles为载入的文章标题,共395篇文章,同时输出0~4篇文章标题如下。
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. type(X): <type 'numpy.ndarray'>  
  2. shape: (395L4258L)  
  3. [[ 1  0  1  0  0]  
  4.  [ 7  0  2  0  0]  
  5.  [ 0  0  0  1 10]  
  6.  [ 6  0  1  0  0]  
  7.  [ 0  0  0  2 14]]  
  8.   
  9. type(vocab): <type 'tuple'>  
  10. len(vocab): 4258  
  11. ('church''pope''years''people''mother')  
  12.   
  13. type(titles): <type 'tuple'>  
  14. len(titles): 395  
  15. ('0 UK: Prince Charles spearheads British royal revolution. LONDON 1996-08-20',  
  16.  '1 GERMANY: Historic Dresden church rising from WW2 ashes. DRESDEN, Germany 1996-08-21',  
  17.  "2 INDIA: Mother Teresa's condition said still unstable. CALCUTTA 1996-08-23",  
  18.  '3 UK: Palace warns British weekly over Charles pictures. LONDON 1996-08-25',  
  19.  '4 INDIA: Mother Teresa, slightly stronger, blesses nuns. CALCUTTA 1996-08-25')  
From the above we can see that there are 395 news items (documents) and a vocabulary of size 4258. The document-term matrix, X, has a count of the number of occurences of each of the 4258 vocabulary words for each of the 395 documents.
下面是测试文档编号为0,单词编号为3117的数据,X[0,3117]:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. # X[0,3117] is the number of times that word 3117 occurs in document 0  
  2. doc_id = 0  
  3. word_id = 3117  
  4. print("doc id: {} word id: {}".format(doc_id, word_id))  
  5. print("-- count: {}".format(X[doc_id, word_id]))  
  6. print("-- word : {}".format(vocab[word_id]))  
  7. print("-- doc  : {}".format(titles[doc_id]))  
  8.   
  9.   
  10. '''''输出 
  11. doc id: 0 word id: 3117 
  12. -- count: 2 
  13. -- word : heir-to-the-throne 
  14. -- doc  : 0 UK: Prince Charles spearheads British royal revolution. LONDON 1996-08-20 
  15. '''  

2.训练模型

其中设置20个主题,500次迭代
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. model = lda.LDA(n_topics=20, n_iter=500, random_state=1)  
  2. model.fit(X)          # model.fit_transform(X) is also available   

3.主题-单词(topic-word)分布

代码如下所示,计算'church', 'pope', 'years'这三个单词在各个主题(n_topocs=20,共20个主题)中的比重,同时输出前5个主题的比重和,其值均为1。
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. topic_word = model.topic_word_  
  2. print("type(topic_word): {}".format(type(topic_word)))  
  3. print("shape: {}".format(topic_word.shape))  
  4. print(vocab[:3])  
  5. print(topic_word[:, :3])  
  6.   
  7. for n in range(5):  
  8.     sum_pr = sum(topic_word[n,:])  
  9.     print("topic: {} sum: {}".format(n, sum_pr))  
输出结果如下:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. type(topic_word): <type 'numpy.ndarray'>  
  2. shape: (20L4258L)  
  3. ('church''pope''years')  
  4.   
  5. [[  2.72436509e-06   2.72436509e-06   2.72708945e-03]  
  6.  [  2.29518860e-02   1.08771556e-06   7.83263973e-03]  
  7.  [  3.97404221e-03   4.96135108e-06   2.98177200e-03]  
  8.  [  3.27374625e-03   2.72585033e-06   2.72585033e-06]  
  9.  [  8.26262882e-03   8.56893407e-02   1.61980569e-06]  
  10.  [  1.30107788e-02   2.95632328e-06   2.95632328e-06]  
  11.  [  2.80145003e-06   2.80145003e-06   2.80145003e-06]  
  12.  [  2.42858077e-02   4.66944966e-06   4.66944966e-06]  
  13.  [  6.84655429e-03   1.90129250e-06   6.84655429e-03]  
  14.  [  3.48361655e-06   3.48361655e-06   3.48361655e-06]  
  15.  [  2.98781661e-03   3.31611166e-06   3.31611166e-06]  
  16.  [  4.27062069e-06   4.27062069e-06   4.27062069e-06]  
  17.  [  1.50994982e-02   1.64107142e-06   1.64107142e-06]  
  18.  [  7.73480150e-07   7.73480150e-07   1.70946848e-02]  
  19.  [  2.82280146e-06   2.82280146e-06   2.82280146e-06]  
  20.  [  5.15309856e-06   5.15309856e-06   4.64294180e-03]  
  21.  [  3.41695768e-06   3.41695768e-06   3.41695768e-06]  
  22.  [  3.90980357e-02   1.70316633e-03   4.42279319e-03]  
  23.  [  2.39373034e-06   2.39373034e-06   2.39373034e-06]  
  24.  [  3.32493234e-06   3.32493234e-06   3.32493234e-06]]  
  25.   
  26. topic: 0 sum: 1.0  
  27. topic: 1 sum: 1.0  
  28. topic: 2 sum: 1.0  
  29. topic: 3 sum: 1.0  
  30. topic: 4 sum: 1.0  

4.计算各主题Top-N个单词

下面这部分代码是计算每个主题中的前5个单词
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. n = 5  
  2. for i, topic_dist in enumerate(topic_word):  
  3.     topic_words = np.array(vocab)[np.argsort(topic_dist)][:-(n+1):-1]  
  4.     print('*Topic {}\n- {}'.format(i, ' '.join(topic_words)))  
输出如下所示:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. *Topic 0  
  2. - government british minister west group  
  3. *Topic 1  
  4. - church first during people political  
  5. *Topic 2  
  6. - elvis king wright fans presley  
  7. *Topic 3  
  8. - yeltsin russian russia president kremlin  
  9. *Topic 4  
  10. - pope vatican paul surgery pontiff  
  11. *Topic 5  
  12. - family police miami versace cunanan  
  13. *Topic 6  
  14. - south simpson born york white  
  15. *Topic 7  
  16. - order church mother successor since  
  17. *Topic 8  
  18. - charles prince diana royal queen  
  19. *Topic 9  
  20. - film france french against actor  
  21. *Topic 10  
  22. - germany german war nazi christian  
  23. *Topic 11  
  24. - east prize peace timor quebec  
  25. *Topic 12  
  26. - n't told life people church  
  27. *Topic 13  
  28. - years world time year last  
  29. *Topic 14  
  30. - mother teresa heart charity calcutta  
  31. *Topic 15  
  32. - city salonika exhibition buddhist byzantine  
  33. *Topic 16  
  34. - music first people tour including  
  35. *Topic 17  
  36. - church catholic bernardin cardinal bishop  
  37. *Topic 18  
  38. - harriman clinton u.s churchill paris  
  39. *Topic 19  
  40. - century art million museum city  

5.文档-主题(Document-Topic)分布

计算输入前10篇文章最可能的Topic
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. doc_topic = model.doc_topic_  
  2. print("type(doc_topic): {}".format(type(doc_topic)))  
  3. print("shape: {}".format(doc_topic.shape))  
  4. for n in range(10):  
  5.     topic_most_pr = doc_topic[n].argmax()  
  6.     print("doc: {} topic: {}".format(n, topic_most_pr))  
输出如下所示:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. type(doc_topic): <type 'numpy.ndarray'>  
  2. shape: (395L20L)  
  3. doc: 0 topic: 8  
  4. doc: 1 topic: 1  
  5. doc: 2 topic: 14  
  6. doc: 3 topic: 8  
  7. doc: 4 topic: 14  
  8. doc: 5 topic: 14  
  9. doc: 6 topic: 14  
  10. doc: 7 topic: 14  
  11. doc: 8 topic: 14  
  12. doc: 9 topic: 8  

6.两种作图分析

详见英文原文,包括计算各个主题中单词权重分布的情况:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import matplotlib.pyplot as plt  
  2. f, ax= plt.subplots(51, figsize=(86), sharex=True)  
  3. for i, k in enumerate([0591419]):  
  4.     ax[i].stem(topic_word[k,:], linefmt='b-',  
  5.                markerfmt='bo', basefmt='w-')  
  6.     ax[i].set_xlim(-50,4350)  
  7.     ax[i].set_ylim(00.08)  
  8.     ax[i].set_ylabel("Prob")  
  9.     ax[i].set_title("topic {}".format(k))  
  10.   
  11. ax[4].set_xlabel("word")  
  12.   
  13. plt.tight_layout()  
  14. plt.show()  
输出如下图所示:


第二种作图是计算文档具体分布在那个主题,代码如下所示:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import matplotlib.pyplot as plt  
  2. f, ax= plt.subplots(51, figsize=(86), sharex=True)  
  3. for i, k in enumerate([13489]):  
  4.     ax[i].stem(doc_topic[k,:], linefmt='r-',  
  5.                markerfmt='ro', basefmt='w-')  
  6.     ax[i].set_xlim(-121)  
  7.     ax[i].set_ylim(01)  
  8.     ax[i].set_ylabel("Prob")  
  9.     ax[i].set_title("Document {}".format(k))  
  10.   
  11. ax[4].set_xlabel("Topic")  
  12.   
  13. plt.tight_layout()  
  14. plt.show()  

输出结果如下图:




三. 总结

这篇文章主要是对Python下LDA用法的入门介绍,下一篇文章将结合具体的txt文本内容进行分词处理、文档主题分布计算等。其中也会涉及Python计算词频tf和tfidf的方法。
由于使用fit()总报错“TypeError: Cannot cast array data from dtype('float64') to dtype('int64') according to the rule 'safe'”,后使用sklearn中计算词频TF方法:
http://scikit-learn.org/stable/modules/feature_extraction.html#text-feature-extraction

总之,希望文章对你有所帮助吧!尤其是刚刚接触机器学习、Sklearn、LDA的同学,毕竟我自己其实也只是一个门外汉,没有系统的学习过机器学习相关的内容,所以也非常理解那种不知道如何使用一种算法的过程,毕竟自己就是嘛,而当你熟练使用后才会觉得它非常简单,所以入门也是这篇文章的宗旨吧!
最后非常感谢上面提到的文章链接作者,感谢他们的分享。如果有不足之处,还请海涵~
(By:Eastmount 2016-03-17 深夜3点半  http://blog.csdn.net/eastmount/ )


转自:[python] LDA处理文档主题分布及分词、词频、tfidf计算

  这篇文章主要是讲述如何通过LDA处理文本内容TXT,并计算其文档主题分布,主要是核心代码为主。其中LDA入门知识介绍参考这篇文章,包括安装及用法:
        [python] LDA处理文档主题分布代码入门笔记

        1.输入输出

        输入是test.txt文件,它是使用Jieba分词之后的文本内容,通常每行代表一篇文档。
        该文本内容原自博客:文本分析之TFIDF/LDA/Word2vec实践 ,推荐大家去阅读。
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. 新春 备 年货 , 新年 联欢晚会  
  2. 新春 节目单 , 春节 联欢晚会 红火  
  3. 大盘 下跌 股市 散户  
  4. 下跌 股市 赚钱  
  5. 金猴 新春 红火 新年  
  6. 新车 新年 年货 新春  
  7. 股市 反弹 下跌  
  8. 股市 散户 赚钱  
  9. 新年 , 看 春节 联欢晚会  
  10. 大盘 下跌 散户  
        输出则是这十篇文档的主题分布,Shape(10L, 2L)表示10篇文档,2个主题。
        具体结果如下所示:
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. shape: (10L, 2L)  
  2. doc: 0 topic: 0  
  3. doc: 1 topic: 0  
  4. doc: 2 topic: 1  
  5. doc: 3 topic: 1  
  6. doc: 4 topic: 0  
  7. doc: 5 topic: 0  
  8. doc: 6 topic: 1  
  9. doc: 7 topic: 1  
  10. doc: 8 topic: 0  
  11. doc: 9 topic: 1  
        同时调用 matplotlib.pyplot 输出了对应的文档主题分布图,可以看到主题Doc0、Doc1、Doc8分布于Topic0,它们主要描述主题新春;而Doc2、Doc3、Doc9分布于Topic1,主要描述股市。


        其过程中也会输出描述LDA运行的信息,如下图所示:


        2.核心代码

        其中核心代码如下图所示,包括读取文本、LDA运行、输出绘图等操作。

[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. # coding=utf-8           
  2. import os    
  3. import sys  
  4. import numpy as np  
  5. import matplotlib  
  6. import scipy  
  7. import matplotlib.pyplot as plt  
  8. from sklearn import feature_extraction    
  9. from sklearn.feature_extraction.text import TfidfTransformer    
  10. from sklearn.feature_extraction.text import CountVectorizer  
  11. from sklearn.feature_extraction.text import HashingVectorizer   
  12.   
  13. if __name__ == "__main__":  
  14.   
  15.   
  16.     #存储读取语料 一行预料为一个文档   
  17.     corpus = []  
  18.     for line in open('test.txt''r').readlines():  
  19.         #print line  
  20.         corpus.append(line.strip())  
  21.     #print corpus  
  22.       
  23.     #将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频  
  24.     vectorizer = CountVectorizer()  
  25.     print vectorizer  
  26.   
  27.     X = vectorizer.fit_transform(corpus)  
  28.     analyze = vectorizer.build_analyzer()  
  29.     weight = X.toarray()  
  30.   
  31.     print len(weight)  
  32.     print (weight[:5, :5])  
  33.   
  34.     #LDA算法  
  35.     print 'LDA:'  
  36.     import numpy as np  
  37.     import lda  
  38.     import lda.datasets  
  39.     model = lda.LDA(n_topics=2, n_iter=500, random_state=1)  
  40.     model.fit(np.asarray(weight))     # model.fit_transform(X) is also available  
  41.     topic_word = model.topic_word_    # model.components_ also works  
  42.   
  43.     #文档-主题(Document-Topic)分布  
  44.     doc_topic = model.doc_topic_  
  45.     print("type(doc_topic): {}".format(type(doc_topic)))  
  46.     print("shape: {}".format(doc_topic.shape))  
  47.   
  48.     #输出前10篇文章最可能的Topic  
  49.     label = []        
  50.     for n in range(10):  
  51.         topic_most_pr = doc_topic[n].argmax()  
  52.         label.append(topic_most_pr)  
  53.         print("doc: {} topic: {}".format(n, topic_most_pr))  
  54.           
  55.     #计算文档主题分布图  
  56.     import matplotlib.pyplot as plt    
  57.     f, ax= plt.subplots(61, figsize=(88), sharex=True)    
  58.     for i, k in enumerate([012389]):    
  59.         ax[i].stem(doc_topic[k,:], linefmt='r-',    
  60.                    markerfmt='ro', basefmt='w-')    
  61.         ax[i].set_xlim(-12)     #x坐标下标  
  62.         ax[i].set_ylim(01.2)    #y坐标下标  
  63.         ax[i].set_ylabel("Prob")    
  64.         ax[i].set_title("Document {}".format(k))    
  65.     ax[5].set_xlabel("Topic")  
  66.     plt.tight_layout()  
  67.     plt.show()    
        同时如果希望查询每个主题对应的问题词权重分布情况如下:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. import matplotlib.pyplot as plt    
  2. f, ax= plt.subplots(21, figsize=(66), sharex=True)    
  3. for i, k in enumerate([01]):         #两个主题  
  4.     ax[i].stem(topic_word[k,:], linefmt='b-',    
  5.                markerfmt='bo', basefmt='w-')    
  6.     ax[i].set_xlim(-2,20)    
  7.     ax[i].set_ylim(01)    
  8.     ax[i].set_ylabel("Prob")    
  9.     ax[i].set_title("topic {}".format(k))    
  10.     
  11. ax[1].set_xlabel("word")    
  12.     
  13. plt.tight_layout()    
  14. plt.show()  
        运行结果如下图所示:共2个主题Topics,15个核心词汇。
        绘图推荐文章:http://blog.csdn.net/pipisorry/article/details/37742423
        PS:讲到这里,整个完整的LDA算法就算结束了,你可以通过上面的代码进行LDA主题分布的计算,下面是一些问题。


        3.TFIDF计算及词频TF计算

        特征计算方法参考:Feature Extraction - scikit-learn

[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #计算TFIDF  
  2. corpus = []  
  3.   
  4. #读取预料 一行预料为一个文档   
  5. for line in open('test.txt''r').readlines():  
  6.     #print line  
  7.     corpus.append(line.strip())  
  8. #print corpus  
  9.   
  10. #将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频  
  11. vectorizer = CountVectorizer()  
  12.   
  13. #该类会统计每个词语的tf-idf权值  
  14. transformer = TfidfTransformer()  
  15.   
  16. #第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵  
  17. tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))  
  18.   
  19. #获取词袋模型中的所有词语    
  20. word = vectorizer.get_feature_names()  
  21.   
  22. #将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重  
  23. weight = tfidf.toarray()  
  24.   
  25. #打印特征向量文本内容  
  26. print 'Features length: ' + str(len(word))  
  27. for j in range(len(word)):  
  28.     print word[j]  
  29.   
  30. #打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重    
  31. for i in range(len(weight)):  
  32.     for j in range(len(word)):  
  33.         print weight[i][j],  
  34.     print '\n'  
        输出如下图所示,共统计处特征词15个,对应TF-IDF矩阵,共10行数据对应txt文件中的10个文档,每个文档15维数据,存储TF-IDF权重,这就可以通过10*15的矩阵表示整个文档权重信息。
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Features length: 15  
  2. 下跌 反弹 大盘 年货 散户 新年 新春 新车 春节 红火 联欢晚会 股市 节目单 赚钱 金猴  
  3.   
  4. 0.0 0.0 0.0 0.579725686076 0.0 0.450929562568 0.450929562568 0.0 0.0 0.0 0.507191470855 0.0 0.0 0.0 0.0   
  5. 0.0 0.0 0.0 0.0 0.0 0.0 0.356735384792 0.0 0.458627428458 0.458627428458 0.401244805261 0.0 0.539503693426 0.0 0.0   
  6. 0.450929562568 0.0 0.579725686076 0.0 0.507191470855 0.0 0.0 0.0 0.0 0.0 0.0 0.450929562568 0.0 0.0 0.0   
  7. 0.523221265036 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.523221265036 0.0 0.672665604612 0.0   
  8. 0.0 0.0 0.0 0.0 0.0 0.410305398084 0.410305398084 0.0 0.0 0.52749830162 0.0 0.0 0.0 0.0 0.620519542315  
  9. 0.0 0.0 0.0 0.52749830162 0.0 0.410305398084 0.410305398084 0.620519542315 0.0 0.0 0.0 0.0 0.0 0.0 0.0  
  10. 0.482964462575 0.730404446714 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.482964462575 0.0 0.0 0.0   
  11. 0.0 0.0 0.0 0.0 0.568243852685 0.0 0.0 0.0 0.0 0.0 0.0 0.505209504985 0.0 0.649509260872 0.0   
  12. 0.0 0.0 0.0 0.0 0.0 0.505209504985 0.0 0.0 0.649509260872 0.0 0.568243852685 0.0 0.0 0.0 0.0   
  13. 0.505209504985 0.0 0.649509260872 0.0 0.568243852685 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0   
        但是在将TF-IDF用于LDA算法model.fit(np.asarray(weight))时,总是报错如下:
        TypeError: Cannot cast array data from dtype('float64') to dtype('int64') according to the rule 'safe'
        所以后来LDA我采用的是统计词频的方法进行的,该段代码如下:
[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #存储读取语料 一行预料为一个文档   
  2. corpus = []  
  3. for line in open('test.txt''r').readlines():  
  4.     #print line  
  5.     corpus.append(line.strip())  
  6. #print corpus  
  7.   
  8. #将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频  
  9. vectorizer = CountVectorizer()  
  10.   
  11. #fit_transform是将文本转为词频矩阵  
  12. X = vectorizer.fit_transform(corpus)  
  13.   
  14. #获取词袋模型中的所有词语   
  15. word = vectorizer.get_feature_names()  
  16. analyze = vectorizer.build_analyzer()  
  17. weight = X.toarray()  
  18.   
  19. #打印特征向量文本内容  
  20. print 'Features length: ' + str(len(word))  
  21. for j in range(len(word)):  
  22.     print word[j],   
  23.   
  24. #打印每类文本词频矩阵  
  25. print 'TF Weight: '  
  26. for i in range(len(weight)):  
  27.     for j in range(len(word)):  
  28.         print weight[i][j],  
  29.     print '\n'  
  30.   
  31. print len(weight)  
  32. print (weight[:5, :5])  
        输出如下所示:
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. Features length: 15  
  2. 下跌 反弹 大盘 年货 散户 新年 新春 新车 春节 红火 联欢晚会 股市 节目单 赚钱 金猴 TF Weight:  
  3.    
  4. 0 0 0 1 0 1 1 0 0 0 1 0 0 0 0   
  5. 0 0 0 0 0 0 1 0 1 1 1 0 1 0 0   
  6. 1 0 1 0 1 0 0 0 0 0 0 1 0 0 0   
  7. 1 0 0 0 0 0 0 0 0 0 0 1 0 1 0   
  8. 0 0 0 0 0 1 1 0 0 1 0 0 0 0 1   
  9. 0 0 0 1 0 1 1 1 0 0 0 0 0 0 0   
  10. 1 1 0 0 0 0 0 0 0 0 0 1 0 0 0   
  11. 0 0 0 0 1 0 0 0 0 0 0 1 0 1 0   
  12. 0 0 0 0 0 1 0 0 1 0 1 0 0 0 0   
  13. 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0   
  14.   
  15. 10  
  16. [[0 0 0 1 0]  
  17.  [0 0 0 0 0]  
  18.  [1 0 1 0 1]  
  19.  [1 0 0 0 0]  
  20.  [0 0 0 0 0]]  
        得到weight权重后,然后调用对应的算法即可执行不用的应用,如:
        import lda
        model = lda.LDA(n_topics=20, n_iter=500, random_state=1)
        model.fit(np.asarray(weight)) 
        from sklearn.cluster import KMeans  
        clf = KMeans(n_clusters=4)   #景区 动物 人物 国家  
        s = clf.fit(weight)  


        4.百度互动主题分布例子

        输入数据主要是前面讲述过的爬取百度百科、互动百科的景区、动物、人物、国家四类信息,具体如下所示:

        输出如下所示,共12行数据,其中doc0~doc2主题分布为topic1,其主题表示景区;doc3~doc5主题分布为topic3,其主题表示动物;doc6~doc8主题分布为topic0,其主题表示人物;doc9~doc11主题分布为topic2,其主题表示国家。
[plain] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. shape: (12L, 4L)  
  2. doc: 0 topic: 1  
  3. doc: 1 topic: 1  
  4. doc: 2 topic: 1  
  5. doc: 3 topic: 3  
  6. doc: 4 topic: 3  
  7. doc: 5 topic: 3  
  8. doc: 6 topic: 0  
  9. doc: 7 topic: 0  
  10. doc: 8 topic: 0  
  11. doc: 9 topic: 2  
  12. doc: 10 topic: 2  
  13. doc: 11 topic: 2  

        5.计算主题TopN

        主要是回复读者的问题,如何计算主题的TopN关键词。核心代码如下:

[python] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #LDA算法    
  2. print 'LDA:'    
  3. import numpy as np    
  4. import lda    
  5. import lda.datasets    
  6. model = lda.LDA(n_topics=2, n_iter=500, random_state=1)    
  7. model.fit(np.asarray(weight))     # model.fit_transform(X) is also available    
  8. topic_word = model.topic_word_    # model.components_ also works  
  9.   
  10. #输出主题中的TopN关键词  
  11. word = vectorizer.get_feature_names()  
  12. for w in word:  
  13.     print w  
  14. print topic_word[:, :3]  
  15. n = 5    
  16. for i, topic_dist in enumerate(topic_word):    
  17.     topic_words = np.array(word)[np.argsort(topic_dist)][:-(n+1):-1]    
  18.     print(u'*Topic {}\n- {}'.format(i, ' '.join(topic_words)))    
  19.   
  20.   
  21. #文档-主题(Document-Topic)分布    
  22. doc_topic = model.doc_topic_    
  23. print("type(doc_topic): {}".format(type(doc_topic)))    
  24. print("shape: {}".format(doc_topic.shape))    

        通过word = vectorizer.get_feature_names()获取整个预料的词向量,其中TF-IDF对应的就是它的值。然后再获取其位置对应的关键词即可,代码中输出5个关键词,如下图所示:



        讲到此处你也应该理解了LDA的基本用法和适用场景,你可以通过它进行新闻主题分布,同时再进行引文推荐、聚类算法等操作。
        总之,希望这篇基础性的文章对你有所帮助吧!还是那句话:
        虽然我写这类文章看起来很简单,尤其对于机器学习的大牛来说,感觉没什么实质内容;但是如果你刚接触这类知识,还是非常头疼的,想找到一个可运行的算法很困难。
        这也是为什么总感觉以前学习了一些原理或理论的东西,而实际应用不是很明白,这种感觉就像学游泳,在岸上看别人感觉什么都会了,但想要学会还是得下水,一步一步来,而我写的这类基础文章就相当于带你下水吧!后面你才能做些自己喜欢的算法和研究。
        最近真的很忙,同时我认识了一位很优秀的女生,总算迈出了人生最重要的一步,就是真正的勇敢的出去接触些异性朋友,这感觉非常不错的。同时学校工作那边仍然在等消息,真心想回家当一名软件相关的教师啊~
        最后附上最近朋友圈的一条信息:

        哎!感叹下时光吧,仅以此诗纪念这三年写博客的坚持和北理最后的四个月:
        但行好事,莫问前程。
        待随满天李桃,再追学友趣事。

        (By:Eastmount 2016-03-15 深夜3点  http://blog.csdn.net/eastmount/ )

0 0
原创粉丝点击