文本挖掘简介



王成军

wangchengjun@nju.edu.cn

计算传播网 http://computational-communication.com

What can be learned from 5 million books

http://v.youku.com/v_show/id_XMzA3OTA5MjUy.html

This talk by Jean-Baptiste Michel and Erez Lieberman Aiden is phenomenal.

Michel, J.-B., et al. (2011). Quantitative Analysis of Culture Using Millions of Digitized Books. Science, 331, 176–182.

试一下谷歌图书的数据: https://books.google.com/ngrams/

数据下载: http://www.culturomics.org/home

Bag-of-words model (BOW)

Represent text as numerical feature vectors

  • We create a vocabulary of unique tokens—for example, words—from the entire set of documents.
  • We construct a feature vector from each document that contains the counts of how often each word occurs in the particular document.

Since the unique words in each document represent only a small subset of all the words in the bag-of-words vocabulary, the feature vectors will consist of mostly zeros, which is why we call them sparse

Bag of words,也叫做“词袋”,在信息检索中,Bag of words model假定对于一个文本,忽略其词序和语法,句法,将其仅仅看做是一个词集合,或者说是词的一个组合,文本中每个词的出现都是独立的,不依赖于其他词是否出现,或者说当这篇文章的作者在任意一个位置选择一个词汇都不受前面句子的影响而独立选择的。这种假设虽然对自然语言进行了简化,便于模型化。

假定在有些情况下是不合理的,例如在新闻个性化推荐中,采用Bag of words的模型就会出现问题。例如用户甲对“南京醉酒驾车事故”这个短语很感兴趣,采用bag of words忽略了顺序和句法,则认为用户甲对“南京”、“醉酒”、“驾车”和“事故”感兴趣,因此可能推荐出和“南京”,“公交车”,“事故”相关的新闻,这显然是不合理的。

解决的方法可以采用SCPCD的方法抽取出整个短语,或者采用高阶(2阶以上)统计语言模型,例如bigram,trigram来将词序保留下来,相当于bag of bigram和bag of trigram,这样能在一定程度上解决这种问题。简言之,bag of words模型是否适用需要根据实际情况来确定。对于那些不可以忽视词序,语法和句法的场合均不能采用bag of words的方法。

Transforming words into feature vectors

A document-term matrix or term-document matrix is a mathematical matrix that describes the frequency of terms that occur in a collection of documents.

In a document-term matrix, rows correspond to documents in the collection and columns correspond to terms.

There are various schemes for determining the value that each entry in the matrix should take. One such scheme is tf-idf. They are useful in the field of natural language processing.

D1 = "I like databases"

D2 = "I hate databases"

I like hate databases
D1 1 1 0 1
D2 1 0 1 1
In [1]:
import numpy as np
from sklearn.feature_extraction.text import CountVectorizer
count = CountVectorizer()
docs = np.array([
        'The sun is shining',
        'The weather is sweet',
        'The sun is shining and the weather is sweet'])
bag = count.fit_transform(docs)
In [2]:
' '.join(dir(count))  
Out[2]:
'__class__ __delattr__ __dict__ __dir__ __doc__ __eq__ __format__ __ge__ __getattribute__ __gt__ __hash__ __init__ __le__ __lt__ __module__ __ne__ __new__ __reduce__ __reduce_ex__ __repr__ __setattr__ __sizeof__ __str__ __subclasshook__ __weakref__ _char_ngrams _char_wb_ngrams _check_vocabulary _count_vocab _get_param_names _limit_features _sort_features _validate_vocabulary _white_spaces _word_ngrams analyzer binary build_analyzer build_preprocessor build_tokenizer decode decode_error dtype encoding fit fit_transform fixed_vocabulary fixed_vocabulary_ get_feature_names get_params get_stop_words input inverse_transform lowercase max_df max_features min_df ngram_range preprocessor set_params stop_words stop_words_ strip_accents token_pattern tokenizer transform vocabulary vocabulary_'
In [2]:
count.get_feature_names()
Out[2]:
['and', 'is', 'shining', 'sun', 'sweet', 'the', 'weather']
In [3]:
print(count.vocabulary_)
{'weather': 6, 'the': 5, 'and': 0, 'is': 1, 'shining': 2, 'sun': 3, 'sweet': 4}
In [4]:
type(bag)
Out[4]:
scipy.sparse.csr.csr_matrix
In [5]:
print(bag.toarray())
[[0 1 1 1 0 1 0]
 [0 1 0 0 1 1 1]
 [1 2 1 1 1 2 1]]
In [70]:
import pandas as pd
pd.DataFrame(bag.toarray(), columns = count.get_feature_names())
Out[70]:
and is shining sun sweet the weather
0 0 1 1 1 0 1 0
1 0 1 0 0 1 1 1
2 1 2 1 1 1 2 1

1-gram

The sequence of items in the bag-of-words model that we just created is also called the 1-gram or unigram model

  • each item or token in the vocabulary represents a single word.

n-gram

The choice of the number n in the n-gram model depends on the particular application

  • 1-gram: "the", "sun", "is", "shining"
  • 2-gram: "the sun", "sun is", "is shining"

The CountVectorizer class in scikit-learn allows us to use different n-gram models via its ngram_range parameter.

While a 1-gram representation is used by default

we could switch to a 2-gram representation by initializing a new CountVectorizer instance with ngram_range=(2,2).

Assessing word relevancy via term frequency-inverse document frequency

$tf-idf(t, d) = tf(t, d) \times idf(t)$

$tf(t, d)$ is the term frequency of term t in document d.

inverse document frequency $idf(t)$ can be calculated as:

$idf(t) = log \frac{n_d}{1 + df(d, t)}$

SKlearn use_idf=True, smooth_idf=True

$idf(t) = log \frac{n_d}{df(d, t) + 1} + 1$

where $n_d$ is the total number of documents, and $df(d, t)$ is the number of documents $d$ that contain the term $t$.

提问: Why do we add the constant 1 to the denominator ?

课堂作业:请根据公式计算'is'这个词在文本2中的tfidf数值?

TfidfTransformer

Scikit-learn implements yet another transformer, the TfidfTransformer, that takes the raw term frequencies from CountVectorizer as input and transforms them into tf-idfs:

In [7]:
from sklearn.feature_extraction.text import TfidfTransformer
np.set_printoptions(precision=2)

tfidf = TfidfTransformer(use_idf=True, norm='l2', smooth_idf=True)
print(tfidf.fit_transform(count.fit_transform(docs)).toarray())
[[ 0.    0.43  0.56  0.56  0.    0.43  0.  ]
 [ 0.    0.43  0.    0.    0.56  0.43  0.56]
 [ 0.4   0.48  0.31  0.31  0.31  0.48  0.31]]
In [16]:
from sklearn.feature_extraction.text import TfidfTransformer
np.set_printoptions(precision=2)

tfidf = TfidfTransformer(use_idf=True, norm=None, smooth_idf=True)
print(tfidf.fit_transform(count.fit_transform(docs)).toarray())
[[ 0.    1.    1.29  1.29  0.    1.    0.  ]
 [ 0.    1.    0.    0.    1.29  1.    1.29]
 [ 1.69  2.    1.29  1.29  1.29  2.    1.29]]
In [17]:
import pandas as pd
bag = tfidf.fit_transform(count.fit_transform(docs))
pd.DataFrame(bag.toarray(), columns = count.get_feature_names())
Out[17]:
and is shining sun sweet the weather
0 0.000000 1.0 1.287682 1.287682 0.000000 1.0 0.000000
1 0.000000 1.0 0.000000 0.000000 1.287682 1.0 1.287682
2 1.693147 2.0 1.287682 1.287682 1.287682 2.0 1.287682
In [19]:
# 一个词的tfidf值
import numpy as np
tf_is = 2.0
n_docs = 3.0
#idf_is = np.log(n_docs / (3))
idf_is = np.log(n_docs / (3)) + 1

tfidf_is = tf_is * idf_is
print('tf-idf of term "is" = %.2f' % tfidf_is)
tf-idf of term "is" = 2.00
In [20]:
# 最后一个文本里的词的tfidf原始数值(未标准化)
tfidf = TfidfTransformer(use_idf=True, norm=None, smooth_idf=False)
raw_tfidf = tfidf.fit_transform(count.fit_transform(docs)).toarray()[-1]
raw_tfidf, count.get_feature_names()
Out[20]:
(array([ 2.1 ,  2.  ,  1.41,  1.41,  1.41,  2.  ,  1.41]),
 ['and', 'is', 'shining', 'sun', 'sweet', 'the', 'weather'])

The tf-idf equation that was implemented in scikit-learn is as follows:

$tf-idf(t, d) = tf(t, d) \times (idf(t, d) + 1)$

L2-normalization

$l2_{x} = \frac{x} {np.sqrt(np.sum(x^2))}$

In [21]:
# l2标准化后的tfidf数值
l2_tfidf = raw_tfidf / np.sqrt(np.sum(raw_tfidf**2))
l2_tfidf 
Out[21]:
array([ 0.47,  0.44,  0.31,  0.31,  0.31,  0.44,  0.31])

政府工作报告文本挖掘

0. 读取数据

In [22]:
with open('../data/gov_reports1954-2017.txt', 'r') as f:
    reports = f.readlines()
In [23]:
len(reports)
Out[23]:
48
In [24]:
print(reports[33][:1000])
2003	2003年政府工作报告		——2003年3月5日在第十届全国人民代表大会第一次会议上		                               国务院总理 朱镕基   各位代表:  本届政府1998年3月就职,任期即将结束。现在,我代表国务院,向第十届全国人民代表大会第一次会议报告过去五年的工作,对今年的工作提出建议,请予审议,并请全国政协各位委员提出意见。  一、过去五年政府工作的回顾  第九届全国人民代表大会第一次会议以来的五年,是很不平凡的五年。本届政府初期,亚洲金融危机冲击,世界经济增长放慢;国内产业结构矛盾十分突出,国有企业职工大量下岗;1998、1999年连续遭受特大洪涝灾害。全国各族人民在中国共产党领导下,团结奋进,顽强拼搏,战胜种种困难,改革开放和经济社会发展取得举世公认的伟大成就。我们胜利实现了现代化建设第二步战略目标,开始向第三步战略目标迈进。  五年来,国民经济保持良好发展势头,经济结构战略性调整迈出重要步伐。  ——经济持续较快增长。国内生产总值从1997年的7.4万亿元增加到2002年的10.2万亿元,按可比价格计算,平均每年增长7.7%。产业结构调整成效明显。粮食等主要农产品供给实现了由长期短缺到总量平衡、丰年有余的历史性转变。以信息产业为代表的高新技术产业迅速崛起。传统工业改造步伐加快。现代服务业快速发展。经济增长质量和效益不断提高。国家税收连年大幅度增长。全国财政收入从1997年的8651亿元增加到2002年的18914亿元,平均每年增加2053亿元;国家外汇储备从1399亿美元增加到2864亿美元。五年全社会固定资产投资累计完成17.2万亿元,特别是发行6600亿元长期建设国债,带动银行贷款和其他社会资金形成3.28万亿元的投资规模,办成不少多年想办而没有力量办的大事。社会生产力跃上新台阶,国家的经济实力、抗风险能力和国际竞争力明显增强。  ——基础设施建设成就显著。我们集中力量建成了一批关系全局的重大基础设施项目。进行了新中国成立以来规模最大的水利建设。五年全国水利建设投资3562亿元,扣除价格变动因素,相当于1950年到1997年全国水利建设投资的总和。一批重大水利设施项目相继开工和竣工。江河堤防加固工程开工3.5万公里,完成了长达3500多公里的长江干堤和近千公里的黄河堤防加固工程,防洪能力大大增强。举世瞩目的

pip install jieba

https://github.com/fxsjy/jieba

pip install wordcloud

https://github.com/amueller/word_cloud

pip install gensim

在terminal里成功安装第三方的包,结果发现在notebook里无法import

这个问题多出现于mac用户,因为mac有一个系统自带的python,成功安装的第三方包都被安装到了系统自带的python里。因此需要确保我们使用的是conda自己的pip,即需要指定pip的路径名,比如我的pip路径名在:/Users/chengjun/anaconda/bin/pip,那么在terminal里输入:

/Users/chengjun/anaconda/bin/pip install package_name

In [25]:
%matplotlib inline
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import sys 
import numpy as np
from collections import defaultdict
import statsmodels.api as sm
from wordcloud import WordCloud
import jieba
import matplotlib
import gensim
from gensim import corpora, models, similarities
from gensim.utils import simple_preprocess
from gensim.parsing.preprocessing import STOPWORDS
#matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei'] #指定默认字体 
matplotlib.rc("savefig", dpi=400)
In [23]:
# 为了确保中文可以在matplotlib里正确显示
#matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei'] #指定默认字体 
# 需要确定系统安装了Microsoft YaHei
In [23]:
# import matplotlib
# my_font = matplotlib.font_manager.FontProperties(
#     fname='/Users/chengjun/github/cjc/data/msyh.ttf')

1. 分词

In [26]:
import jieba

seg_list = jieba.cut("我来到北京清华大学", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式

seg_list = jieba.cut("我来到北京清华大学", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精确模式

seg_list = jieba.cut("他来到了网易杭研大厦")  # 默认是精确模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明硕士毕业于中国科学院计算所,后在日本京都大学深造")  # 搜索引擎模式
print(", ".join(seg_list))
Building prefix dict from the default dictionary ...
Dumping model to file cache /var/folders/8b/hhnbt0nd4zsg2qhxc28q23w80000gn/T/jieba.cache
Loading model cost 1.435 seconds.
Prefix dict has been built succesfully.
Full Mode: 我/ 来到/ 北京/ 清华/ 清华大学/ 华大/ 大学
Default Mode: 我/ 来到/ 北京/ 清华大学
他, 来到, 了, 网易, 杭研, 大厦
小明, 硕士, 毕业, 于, 中国, 科学, 学院, 科学院, 中国科学院, 计算, 计算所, ,, 后, 在, 日本, 京都, 大学, 日本京都大学, 深造

2. 停用词

In [27]:
filename = '../data/stopwords.txt'
stopwords = {}
f = open(filename, 'r')
line = f.readline().rstrip()
while line:
    stopwords.setdefault(line, 0)
    stopwords[line] = 1
    line = f.readline().rstrip()
f.close()
In [28]:
adding_stopwords = [u'我们', u'要', u'地', u'有', u'这', u'人',
                    u'发展',u'建设',u'加强',u'继续',u'对',u'等',
                    u'推进',u'工作',u'增加']
for s in adding_stopwords: stopwords[s]=10

3. 关键词抽取

基于TF-IDF 算法的关键词抽取

In [29]:
import jieba.analyse
txt = reports[-1]
tf = jieba.analyse.extract_tags(txt, topK=200, withWeight=True)
In [30]:
u"、".join([i[0] for i in tf[:50]])
Out[30]:
'发展、改革、推进、建设、加强、加快、推动、深化、完善、创新、就业、全面、促进、经济、政府、深入、实施、提高、企业、支持、群众、服务、坚持、人民、坚决、制度、治理、政策、农村、试点、扩大、机制、社会、落实、工作、保障、增长、国家、生态、安全、今年、稳定、继续、地区、保护、中国、合作、产能、维护、重点'
In [31]:
plt.hist([i[1] for i in tf])
plt.show()

基于 TextRank 算法的关键词抽取

In [32]:
tr = jieba.analyse.textrank(txt,topK=200, withWeight=True)
u"、".join([i[0] for i in tr[:50]])
Out[32]:
'发展、改革、推进、建设、经济、加强、推动、加快、政府、完善、创新、企业、全面、实施、促进、提高、支持、服务、政策、深入、中国、就业、国家、制度、群众、社会、人民、地区、坚持、扩大、农村、地方、保护、继续、增长、机制、工作、保障、治理、试点、合作、综合、重点、市场、投资、领域、加大、消费、制定、维护'
In [97]:
plt.hist([i[1] for i in tr])
plt.show()
In [33]:
import pandas as pd

def keywords(index):
    txt = reports[-index]
    tf = jieba.analyse.extract_tags(txt, topK=200, withWeight=True)
    tr = jieba.analyse.textrank(txt,topK=200, withWeight=True)
    tfdata = pd.DataFrame(tf, columns=['word', 'tfidf'])
    trdata = pd.DataFrame(tr, columns=['word', 'textrank'])
    worddata = pd.merge(tfdata, trdata, on='word')
    fig = plt.figure(figsize=(16, 6),facecolor='white')
    plt.plot(worddata.tfidf, worddata.textrank, linestyle='',marker='.')
    for i in range(len(worddata.word)):
        plt.text(worddata.tfidf[i], worddata.textrank[i], worddata.word[i], 
                 fontsize = worddata.textrank[i]*30, 
                 color = 'red', rotation = 0
                )
    plt.title(txt[:4])
    plt.xlabel('Tf-Idf')
    plt.ylabel('TextRank')
    plt.show()
In [34]:
keywords(1)
In [52]:
keywords(2)
In [53]:
keywords(3)

算法论文:

TextRank: Bringing Order into Texts

基本思想:

  • 将待抽取关键词的文本进行分词
  • 以固定窗口大小(默认为5,通过span属性调整),词之间的共现关系,构建图
  • 计算图中节点的PageRank,注意是无向带权图

4. 词云

In [35]:
def wordcloudplot(txt, year):
    wordcloud = WordCloud(font_path='../data/msyh.ttf').generate(txt)
    # Open a plot of the generated image.
    fig = plt.figure(figsize=(16, 6),facecolor='white')
    plt.imshow(wordcloud)
    plt.title(year)
    plt.axis("off")
    #plt.show()

基于tfidf过滤的词云

In [57]:
txt = reports[-1]
tfidf200= jieba.analyse.extract_tags(txt, topK=200, withWeight=False)
seg_list = jieba.cut(txt, cut_all=False)
seg_list = [i for i in seg_list if i in tfidf200]
txt200 = r' '.join(seg_list)
wordcloudplot(txt200, txt[:4]) 
In [60]:
txt = reports[-2]
tfidf200= jieba.analyse.extract_tags(txt, topK=200, withWeight=False)
seg_list = jieba.cut(txt, cut_all=False)
seg_list = [i for i in seg_list if i in tfidf200]
txt200 = r' '.join(seg_list)
wordcloudplot(txt200, txt[:4]) 
In [326]:
txt = reports[-2]
tfidf200= jieba.analyse.extract_tags(txt, topK=200, withWeight=False)
seg_list = jieba.cut(txt, cut_all=False)
seg_list = [i for i in seg_list if i in tfidf200]
txt200 = r' '.join(seg_list)
wordcloudplot(txt200, txt[:4]) 
In [59]:
wordfreq = defaultdict(int)
for i in seg_list:
    wordfreq[i] +=1
wordfreq = [[i, wordfreq[i]] for i in wordfreq]

wordfreq.sort(key= lambda x:x[1], reverse = True )
u"、 ".join([ i[0] + u'(' + str(i[1]) +u')' for i in wordfreq ])
Out[59]:
'发展(125)、 改革(68)、 推进(65)、 建设(54)、 经济(52)、 加强(45)、 推动(42)、 加快(40)、 政府(36)、 创新(36)、 完善(35)、 企业(35)、 全面(35)、 促进(34)、 提高(32)、 就业(31)、 实施(31)、 中国(31)、 支持(29)、 深化(29)、 政策(28)、 服务(27)、 国家(26)、 人民(26)、 工作(26)、 制度(25)、 我们(25)、 深入(25)、 社会(25)、 增长(25)、 群众(24)、 坚持(24)、 今年(23)、 继续(23)、 地区(22)、 扩大(22)、 农村(20)、 坚决(20)、 机制(19)、 治理(19)、 稳定(19)、 地方(19)、 保障(18)、 安全(18)、 保护(18)、 持续(17)、 合作(17)、 市场(17)、 重点(17)、 实现(17)、 消费(16)、 投资(16)、 综合(16)、 落实(16)、 试点(16)、 结构(15)、 有效(15)、 维护(15)、 加大(15)、 产能(15)、 积极(15)、 领域(15)、 教育(15)、 改善(14)、 国际(14)、 国内(14)、 城市(14)、 我国(14)、 生态(14)、 以上(14)、 基本(14)、 问题(14)、 强化(13)、 增加(13)、 农业(13)、 提升(13)、 制定(13)、 力度(13)、 质量(13)、 引导(13)、 降低(13)、 依法(12)、 战略(12)、 升级(12)、 重要(12)、 标准(12)、 作用(12)、 健康(12)、 保持(12)、 增强(12)、 生产(12)、 文化(12)、 更加(12)、 必须(12)、 创业(12)、 目标(12)、 民生(12)、 下降(12)、 确保(11)、 取得(11)、 供给(11)、 生活(11)、 核心(11)、 规范(11)、 环境(11)、 收费(11)、 进一步(11)、 管理(11)、 做好(10)、 完成(10)、 资金(10)、 能力(10)、 不断(10)、 开展(10)、 产业(10)、 健全(10)、 水平(10)、 科技(10)、 体系(10)、 风险(10)、 世界(10)、 鼓励(10)、 重大(10)、 一年(10)、 监管(10)、 一批(10)、 困难(10)、 突出(9)、 代表(9)、 责任(9)、 金融(9)、 全国(9)、 大力(9)、 行政(9)、 区域(9)、 体制改革(9)、 减少(9)、 贯彻(9)、 组织(9)、 经济社会(9)、 国务院(8)、 各位(8)、 协调(8)、 制造(8)、 发挥(8)、 合理(8)、 优化(8)、 扶贫(8)、 调控(8)、 习近平(8)、 党中央(8)、 专项(8)、 动能(8)、 现代化(8)、 资源(8)、 城镇(8)、 行动(8)、 文明(7)、 全年(7)、 取消(7)、 住房(7)、 新型(7)、 万人(7)、 特色(7)、 生产总值(7)、 出台(7)、 引领(7)、 城乡(7)、 实体(7)、 更好(7)、 基础设施(7)、 和谐(7)、 高校(7)、 脱贫(7)、 改造(7)、 抓好(6)、 严肃查处(6)、 转型(6)、 新兴产业(6)、 打造(6)、 互联网(6)、 对外开放(6)、 补助(6)、 结构性(6)、 扎实(6)、 减税(6)、 涉企(6)、 培育(6)、 补短(6)、 办好(5)、 双创(5)、 精准(5)、 督查(5)、 试验区(5)、 医保(5)、 政策措施(5)、 实干(5)、 2000(4)、 降费(4)、 问责(4)'

基于停用词过滤的词云

In [70]:
#jieba.add_word('股灾', freq=100, tag=None) 

txt = reports[-1]
seg_list = jieba.cut(txt, cut_all=False)
seg_list = [i for i in seg_list if i not in stopwords]
txt = r' '.join(seg_list)
wordcloudplot(txt, txt[:4]) 
#file_path = '/Users/chengjun/GitHub/cjc2016/figures/wordcloud-' + txt[:4] + '.png'
#plt.savefig(file_path,dpi = 300, bbox_inches="tight",transparent = True)

绘制1954-2016政府工作报告词云

In [113]:
#jieba.add_word('股灾', freq=100, tag=None) 

for txt in reports:
    seg_list = jieba.cut(txt, cut_all=False)
    seg_list = [i for i in seg_list if i not in stopwords]
    txt = r' '.join(seg_list)
    wordcloudplot(txt, txt[:4]) 
    file_path = '../figure/wordcloud-' + txt[:4] + '.png'
    plt.savefig(file_path,dpi = 400, bbox_inches="tight",\
                transparent = True)

5. 词向量的时间序列

In [36]:
import jieba.analyse

wordset = []
for txt in reports:
    top20= jieba.analyse.textrank(txt, topK=200, withWeight=False)
    for w in top20:
        if w not in wordset:
            wordset.append(w)
In [37]:
len(wordset)
Out[37]:
1302
In [63]:
' '.join(wordset)
Out[63]:
'国家 人民 工业 发展 建设 工作 生产 美国 企业 经济 计划 社会主义 中国 进行 全国 技术 亚洲 集团 需要 问题 农业 方面 完成 建立 台湾 生活 事业 没有 改造 应当 资本主义 增加 关系 组织 保证 会议 侵略 不能 注意 加强 战争 提高 社会 文化 继续 政府 现代化 能够 日内瓦 世界 东南亚 运动 起来 参加 苏联 少数民族 协议 管理 浪费 实行 群众 机关 采取 解决 得到 制度 现象 条约 改善 领导 资金 革命 集体 职工 任务 政策 地方 增长 斗争 商业 工作人员 合作 情况 农民 规定 恢复 日本 卖国 法律 比重 解放 物质 实现 劳动 原则 改进 力量 城市 工程 时期 破坏 企图 朝鲜 研究 印度支那 总产值 帮助 地区 扩大 重工业 保障 合理 教育 产品 财政 作用 依靠 才能 民主 成为 巩固 华侨 中央 任意 培养 收购 制造厂 要求 分子 供应 权利 代表 粮食 包括 棉花 基础 推广 使用 表现 节约 国际 水平 损失 公私合营 行政 全部 宪法 防务 忽视 防洪 人才 不够 产量 思想 容许 国民经济 还有 等于 准备 加以 时候 希望 干涉 大家 商品 民族 经验 大陆 适应 胜利 不顾 领土 五年计划 克服 中华人民共和国 设备 工业化 决定 达到 活动 国营商业 势力 缺点 加紧 有关 联系 支持 已有 满足 指导 开展 发挥 市场 独立 铁路 昌都地区 保卫 部门 正义 知识分子 应该 可能 投资 增产 单位 设计 工人 条件 制造 形式 建成 原料 手工业 工厂 开始 办法 资本家 规模 新建 农村 例如 过渡时期 认为 工业生产 干部 大量 职员 施工 减少 学习 土地 帝国主义 利用 援助 数量 限额 人员 指标 厂矿 加工 汽车 种类 速度 工人阶级 原有 学校 质量 科学技术 方针 政治 轻工业 错误 措施 定货 合作化 改变 经营 统治 接受 周转量 试制 改建 材料 个体 道路 工业品 面积 积极性 薯类 产值 重点 实际 建筑 促进 水利 所有制 消费品 总任务 历史 掌握 非生产性 标准 比例 预算 支出 收入 部分 执行 国营 立井 公路 项目 税收 总数 片面 数字 价格 钢材 扣除 国营企业 预计 收支 状况 兰州 拨付 货物 水库 工业部 降低 可比 过程 储备 包头 决算 铺轨 军备 超过 新疆 去年同期 统计 获得 用于 农户 经费 水利工程 修建 开支 数额 物资 公方 电厂 调整 结果 投入 鹤岗 信贷资金 工资 月份 利润 建筑安装 设法 自筹 贯通 发生 乡村 费用 影响 预备 收到 通车 中央预算 年收入 零售总额 变化 住宅 是否 西藏 全面 机器设备 银行 淮河 附加 煤炭 灌溉面积 奖励制度 联合 水泥 分配 科学 基本 资产阶级 提出 存在 右派分子 取得 日益 学生 工农 条例 集中 科学家 机构 科学研究 建议 性质 批判 委员会 意见 成绩 官僚主义 队伍 人口 偏差 草案 宗派主义 个别 科学事业 立场 规划 民主党派 制订 改革 工农业 阶级 选举 否定 说明 提倡 留学生 毕业生 殖民主义 剥削 造成 态度 只能 变为 成果 业务 基本上 学徒 派遣 实践 争取 控制 批评 表示 运输 鼓掌 跃进 服务 相结合 战线 统一 全世界 阵营 结合 制造业 劳动力 共产主义 方法 威胁 出现 叛乱 人们 总路线 定期 公社 非洲 发动 维护 愿意 军事 自治区 利益 岸信 武装 祖国 失败 西藏地方 帝国主义者 安排 自治 讨论 时间 挑拨 证明 复活 知道 作为 受到 纲要 食堂 提前 消灭 机械化 危害 防治 举办 社办 效益 做到 坚持 养猪 农具 改良 公布 病虫害 社员 扑灭 办好 大会 棉田 群众性 过渡 八字宪法 麻雀 种子 全体 纲领 大办 保持 耕地 灌溉 科学试验 动员 充分发挥 分配制度 精耕细作 农作物 程度 负担 事情 家庭 臭虫 修改 血吸虫病 同志 施肥 修好 养鹅 水稻 养鸭 灭病 养鸡 号召 节约用粮 牲畜 工具 广东省 佛山市 指出 加快 渔业生产 掀起 合一 内容 托儿所 化肥厂 穷队 普及 地块 水土 总产量 土壤 创造 普查 制定 小学 识字 耕作 种得 树冠 兴办 鼠疫 分析 水灾 山区 作风 善于 范围 治疗 反动派 修正主义 认识 马克思列宁主义 毛主席 精神 反帝 支援 复辟 核武器 印度 意义 拉丁美洲 处理 革命化 品种 外国 成就 符合 称号 燃料 具有 阴谋 深入 相信 西藏自治区 走狗 亚非 大寨 增强 主任委员 观点 为首 进攻 民族团结 反动 食糖 筹委会 总结 有所 爱国 防止 总理 锡兰 推行 自然界 举行 有着 民族主义 刚果 报告 提供 不会 路线 马克思主义 被压迫 边界 批林批孔 专政 武装冲突 争议地区 领域 争夺 武力 接触 理论 老干部 正确处理 中苏 脱离 争论 双方 有利于 包含 选拔 粉碎 两国 设想 倾向 妇女干部 军队 文艺 广积粮 反霸 颠覆 认真执行 广大干部 方向 谅解 拒绝 签订 继续执行 断言 有力 国际形势 回答 埋葬 推动 试验 爱国人士 称霸 战备 奴隶 柬埔寨 美苏 背弃 直至 越南 挑起 角落 打击 玩弄 打仗 教条主义 领导岗位 优秀分子 担负 人类 光荣任务 保卫祖国 外交 光荣传统 谈判 为主 备战 民主集中制 欧洲 工农兵 打倒 主力军 洋奴哲学 空洞 动荡 内债 歼灭 敢于 强国 教导 搞好 基地 大力 敌人 指示 社队 抓好 加速 妄图 战胜 重视 两国人民 中心 高速度 保护 树立 居住 召开 发扬 做好 苏美 污蔑 霸权主义 无政府主义 事业单位 秩序 负责 引进 法制 纪律 当局 生产力 管理体制 安定团结 就业 原材料 资源 农副产品 试行 动力 纠正 允许 义务 现有企业 机械 试点 开发 结构 能源 效果 自主权 竞争 勘探 调查 流通 协作 海域 节能 观念 打破 缝纫机 节约能源 奖金 季节 入学 自销 积累 作出 自行车 进展 购买力 货运量 行业 总量 交通 经济作物 前进 来源 增长速度 能耗 广播 共生矿 毕业 校舍 港口 电视 生产能力 石油 调动 总额 提高质量 棉纱 沼气 煤矿 综合 化工 劳动者 优先 工业锅炉 经济效益 责任制 物价 国民收入 能力 放在 财政收入 方式 出口 下降 手段 信贷 关心 不得 经济体制 违反 建设项目 煤田 不合理 全局 女婴 严格控制 依法 确定 体制 应用 城乡 出版 形势 抓紧 鼓励 科技 政法 作品 艺术 国防 前提 消除 体育 上交 职业 个人 财力 对立 成本 承包 主张 香港 五项原则 公司 赞成 审批 科研 包干 裁军 社会制度 招标 承担 交流 建筑业 供销社 利改税 经济特区 监督 工期 遵循 地位 相应 厂长 磋商 投标 地步 贸易中心 购销 消费 工资制度 基金 补贴 消费基金 搞活 货币 工资总额 基数 考虑 出发 追求 增多 核定 决不能 消费者 部署 盲目 产业结构 价格体系 协调 城镇 宏观经济 献计 建材 持续增长 幅度 增加收入 商品经济 调节 进入 专业银行 前景 劳动生产率 因素 购买 乱提 金融 决策 联产承包 放开 长远利益 完善 运用 进口 贸易 外汇 投资规模 转变 系统 体系 引导 出口创汇 转向 战略 里程 行为 活力 局面 劳务 共培养 自由化 开放 思潮 推进 特色 增产节约 增收节支 探索 不变 横向 纳入 差额 轨道 相适应 经营机制 产品质量 目标 实施 形成 看到 外贸 理顺 职能 基层 环境 经营责任制 素质 压缩 需求 治理 制止 储蓄 对话 协商 责任 总需求 教育经费 消耗 审计 供给 宏观调控 优化 贷款 动乱 暴乱 市场调节 销售 住房 案件 产业政策 目的 传统 在于 计划经济 新增 回升 农产品 全民 电子 调整结构 家用 回落 进出口 专业 大体 运行 充分利用 投产 强化 高技术 油田 积压 城乡居民 丰收 人权 开拓 机制 欢迎 步伐 澳门 吸收 集中力量 高新技术 转换 民主监督 贯彻 实力 面向 根本利益 海外侨胞 法规 民族区域 继续加强 社会保障 基础设施 精简 社会化 国有企业 接近 市场经济 进程 设置 特点 达成 国民 国有资产 相当于 避免 政策性 突出 优势 改革方案 减轻 低价 乡镇企业 国债 外资 合法权益 原因 开发区 禁止 财税 增进 保险 市场需求 乱收费 偷税 办学 主体 格局 经济社会 规范 振兴 总体 注重 差距 民主法制 效率 力度 区域 期待 腐败分子 扶贫 公民 调控 分裂 产业 兼并 破产 债务 改组 成立 资本金 查处 征管 负责制 加大 签署 行使主权 分流 树正气 国有经济 压力 资产 宣传 股份合作制 金融危机 防范 长江 停止 金融风险 财政赤字 下岗职工 澳门特别行政区 犯罪 债券 确保 居民 人民币 严禁 关键 产业化 创新 污染 财政政策 金融机构 采伐 趋势 收储 失业 脱困 违法 势头 城镇居民 违纪 手软 发放 旅游 战略性 袭击 台湾同胞 服务业 升级 着力 信息 积极探索 培育 农民收入 自主 节水 宗教 战略目标 监管 竞争力 参与 重组 违规 信息化 足额 农村税费 转移 规则 带动 生态 把握 环境保护 设施 科研机构 公共卫生 疫情 农民工 非公有制 执法 拖欠 医疗卫生 股份制 应对 医疗 补助 统筹 程序 工作者 预防 履行 农业税 预期 专项 经济运行 阶段 进城 务工 支付 事件 遏制 资本 创新能力 救助 知识产权 扶持 服务体系 生产总值 相关 用地 政策措施 减排 过剩 产能 高于 装备 保护环境 实践经验 集约 增幅 同胞 优化结构 民生 免费 排放 依法行政 养老保险 公共服务 覆盖 来自 出台 两岸关系 增速 灾区 拓展 转型 参保 挑战 创业 信心 气候变化 启动 风险 融资 公益性 药物 有序 提升 保障性 结构性 城镇化 低收入 分开 监测 构建 融合 营业税 方案 大病 增值税 安居工程 互联网 货币政策 公平 累计 补偿 框架 权益 退休 权力 居民消费 领导人 贫困地区 区间 地震 法治 淘汰 协同 支撑 利率 事项 设立 核心 民间 深度 海洋 定向 示范区 下放 取消 核准 修订 化解 打造 突破 管理制度 大国 下行 动能 市场化 绿色 脱贫 小康社会 行动 空间 高校 网络 收费 全球 引领 整治 实体 优质 涉企 减税 政务'
In [38]:
from collections import defaultdict

data = defaultdict(dict)
years = [int(i[:4]) for i in reports]
for i in wordset:
    for year in years:
        data[i][year] = 0 
In [39]:
for txt in reports:
    year = int(txt[:4])
    top1000= jieba.analyse.textrank(txt, topK=1000, withWeight=True)
    for ww in top1000:
        word, weight = ww
        if word in wordset:
            data[word][year]+= weight
In [45]:
word_weight = []
for i in data:
    word_weight.append([i, np.sum(list(data[i].values()))])
In [46]:
word_weight[:2]
Out[46]:
[['上交', 0.24873017673930453], ['推进', 10.481536397526137]]
In [47]:
word_weight.sort(key= lambda x:x[1], reverse = True )
top50 = [i[0] for i in word_weight[:50]]
In [48]:
' '.join(top50) 
Out[48]:
'发展 建设 经济 加强 企业 工作 改革 国家 人民 继续 社会主义 提高 社会 生产 农业 政府 制度 增加 推进 问题 促进 增长 加快 农村 方面 管理 进行 重点 坚持 全国 教育 市场 投资 完善 地区 工业 支持 政策 中国 实行 计划 文化 生活 扩大 实现 基本 改善 建立 群众 技术'
In [52]:
def plotEvolution(word, color, linestyle, marker):
    cx = data[word]
    plt.plot(list(cx.keys()), list(cx.values()), color = color, 
             linestyle=linestyle, marker=marker, label= word)
    plt.legend(loc=2,fontsize=8)
    plt.ylabel(u'词语重要性')
In [53]:
plotEvolution(u'民主', 'g', '-', '>')
plotEvolution(u'法制', 'b', '-', 's')
In [363]:
plotEvolution(u'动能', 'b', '-', 's')
plotEvolution(u'互联网', 'g', '-', '>')
In [364]:
plotEvolution(u'工业', 'y', '-', '<')
plotEvolution(u'农业', 'r', '-', 'o')
plotEvolution(u'制造业', 'b', '-', 's')
plotEvolution(u'服务业', 'g', '-', '>')
In [362]:
plotEvolution(u'教育', 'r', '-', 'o')
plotEvolution(u'社会保障', 'b', '-', 's')
plotEvolution(u'医疗', 'g', '-', '>')
In [356]:
plotEvolution(u'环境', 'b', '-', 's')
plotEvolution(u'住房', 'purple', '-', 'o')
In [357]:
plotEvolution(u'发展', 'y', '-', '<')
plotEvolution(u'经济', 'r', '-', 'o')
plotEvolution(u'改革', 'b', '-', 's')
plotEvolution(u'创新', 'g', '-', '>')
In [359]:
plotEvolution(u'社会主义', 'r', '-', 'o')
plotEvolution(u'马克思主义', 'b', '-', 's')
In [208]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in enumerate(top50[:5]):
    years = data[word].keys()[-40:]
    tfidfs = data[word].values()[-40:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [207]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in enumerate(top50[5:10]):
    years = data[word].keys()[-40:]
    tfidfs = data[word].values()[-40:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [206]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in  enumerate(top50[10:15]):
    years = data[word].keys()[-40:]
    tfidfs = data[word].values()[-40:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [205]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in  enumerate(top50[15:20]):
    years = data[word].keys()[-40:]
    tfidfs = data[word].values()[-40:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [204]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in  enumerate(top50[20:25]):
    years = data[word].keys()[-40:]
    tfidfs = data[word].values()[-40:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [202]:
fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',5)

for k, word in  enumerate(top50[25:30]):
    years = data[word].keys()[-30:]
    tfidfs = data[word].values()[-30:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()

kmeans 聚类

In [209]:
from sklearn import metrics
from sklearn.metrics import pairwise_distances
dataX = []
wordX = []
for word in top50:
    dataX.append(data[word].values()[-40:])
    wordX.append(word)
dataX = np.array(dataX)
In [210]:
dataX
Out[210]:
array([[ 0.39284121,  0.90665311,  0.77657535, ...,  1.06351347,
         1.06421625,  1.06899944],
       [ 0.34494242,  0.69077968,  0.55668702, ...,  0.68252707,
         0.70822817,  0.60889902],
       [ 0.17303628,  0.41761107,  0.55415715, ...,  0.53748179,
         0.56932235,  0.55195392],
       ..., 
       [ 0.14998888,  0.3440277 ,  0.23697201, ...,  0.10974867,
         0.10210809,  0.12931368],
       [ 0.04497681,  0.12520492,  0.25926694, ...,  0.05835174,
         0.03954806,  0.04108153],
       [ 0.11544036,  0.20476903,  0.10921159, ...,  0.07690967,
         0.05190462,  0.03248575]])
In [211]:
import numpy as np
from sklearn.cluster import KMeans
silhouette_score = []
for cluster_num in range(2, 10):
    kmeans_model = KMeans(n_clusters=cluster_num, random_state=1).fit(dataX)
    labels = kmeans_model.labels_
    sscore = metrics.silhouette_score(dataX, labels, metric='euclidean')
    silhouette_score.append(sscore)

fig = plt.figure(figsize=(4, 2),facecolor='white')    
plt.plot(range(2, 10), silhouette_score)
plt.xlabel('# Clusters')
plt.ylabel('Silhouette Score')
plt.show()
/Users/chengjun/anaconda/lib/python2.7/site-packages/numpy/core/_methods.py:59: RuntimeWarning: Mean of empty slice.
  warnings.warn("Mean of empty slice.", RuntimeWarning)

The score is bounded between -1 for incorrect clustering and +1 for highly dense clustering. Scores around zero indicate overlapping clusters. The score is higher when clusters are dense and well separated, which relates to a standard concept of a cluster.

In [212]:
kmeans_model = KMeans(n_clusters=2, random_state=1).fit(dataX)
labels = kmeans_model.labels_
labels
Out[212]:
array([1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
       0, 0, 0, 0], dtype=int32)
In [213]:
print ' '.join(wordX)
发展 建设 经济 加强 企业 工作 改革 国家 人民 社会主义 继续 提高 社会 生产 农业 政府 增加 制度 推进 问题 增长 促进 农村 方面 加快 管理 进行 坚持 重点 全国 教育 投资 工业 完善 市场 地区 支持 实行 计划 政策 生活 文化 扩大 实现 中国 基本 建立 群众 技术 关系
In [214]:
print '\t'.join([wordX[index] \
                 for index in np.where(labels==0)[0]])
国家	人民	社会主义	继续	提高	社会	生产	农业	政府	增加	制度	推进	问题	增长	促进	农村	方面	加快	管理	进行	坚持	重点	全国	教育	投资	工业	完善	市场	地区	支持	实行	计划	政策	生活	文化	扩大	实现	中国	基本	建立	群众	技术	关系
In [215]:
word_cluster1 = [wordX[index] for index in np.where(labels==0)[0]]

fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',10)

for k, word in  enumerate(word_cluster1[:10]):
    years = data[word].keys()[-30:]
    tfidfs = data[word].values()[-30:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()
In [216]:
print '\t'.join([wordX[index] for index in np.where(labels==1)[0]])
发展	建设	经济	加强	企业	工作	改革
In [217]:
word_cluster2 = [wordX[index] for index in np.where(labels==1)[0]]

fig = plt.figure(figsize=(12, 4),facecolor='white')
cmap = cm.get_cmap('rainbow_r',10)

for k, word in  enumerate(word_cluster2[:10]):
    years = data[word].keys()[-30:]
    tfidfs = data[word].values()[-30:]
    plt.plot(years, tfidfs, color=cmap(k), linestyle='-',marker='.',label= word)
plt.legend(loc=1,fontsize=8)
plt.show()

词性标注

In [137]:
import jieba.posseg as pseg
words = pseg.cut("我爱北京天安门")
words = [str(w).split('/') for w in words]
for i in words:
    print i[0], i[1]
我 r
爱 v
北京 ns
天安门 ns

ICTCLAS 汉语词性标注集

汉语文本词性标注标记集

Ag 形语素 形容词性语素。形容词代码为a,语素代码g前面置以A。

a 形容词 取英语形容词adjective的第1个字母。

ad 副形词 直接作状语的形容词。形容词代码a和副词代码d并在一起。

an 名形词 具有名词功能的形容词。形容词代码a和名词代码n并在一起。

b 区别词 取汉字“别”的声母。

c 连词 取英语连词conjunction的第1个字母。

Dg 副语素 副词性语素。副词代码为d,语素代码g前面置以D。

d 副词 取adverb的第2个字母,因其第1个字母已用于形容词。

e 叹词 取英语叹词exclamation的第1个字母。

f 方位词 取汉字“方”

g 语素 绝大多数语素都能作为合成词的“词根”,取汉字“根”的声母。

h 前接成分 取英语head的第1个字母。

i 成语 取英语成语idiom的第1个字母。

j 简称略语 取汉字“简”的声母。

k 后接成分

l 习用语 习用语尚未成为成语,有点“临时性”,取“临”的声母。

m 数词 取英语numeral的第3个字母,n,u已有他用。

Ng 名语素 名词性语素。名词代码为n,语素代码g前面置以N。

n 名词 取英语名词noun的第1个字母。

nr 人名 名词代码n和“人(ren)”的声母并在一起。

ns 地名 名词代码n和处所词代码s并在一起。

nt 机构团体 “团”的声母为t,名词代码n和t并在一起。

nz 其他专名 “专”的声母的第1个字母为z,名词代码n和z并在一起。

o 拟声词 取英语拟声词onomatopoeia的第1个字母。

p 介词 取英语介词prepositional的第1个字母。

q 量词 取英语quantit的第1个字母。

r 代词 取英语代词pronoun的第2个字母,因p已用于介词。

s 处所词 取英语space的第1个字母。

Tg 时语素 时间词性语素。时间词代码为t,在语素的代码g前面置以T。

t 时间词 取英语time的第1个字母。

u 助词 取英语助词auxiliary

Vg 动语素 动词性语素。动词代码为v。在语素的代码g前面置以V。

v 动词 取英语动词verb的第一个字母。

vd 副动词 直接作状语的动词。动词和副词的代码并在一起。

vn 名动词 指具有名词功能的动词。动词和名词的代码并在一起。

w 标点符号

x 非语素字 非语素字只是一个符号,字母x通常用于代表未知数、符号。

y 语气词 取汉字“语”的声母。

z 状态词 取汉字“状”的声母的前一个字母。


a: 形容词 b: 区别词 c: 连词 d: 副词 e: 叹词 g: 语素字 h: 前接成分 i: 习用语 j: 简称 k: 后接成分 m: 数词 n: 普通名词 nd: 方位名词 nh: 人名 ni: 机构名 nl: 处所名词 ns: 地名 nt: 时间词 nz: 其他专名 o: 拟声词 p: 介词 q: 量词 r: 代词 u: 助词 v: 动词 wp: 标点符号 ws: 字符串 x: 非语素字

主题模型

In [230]:
def getCorpus(data):
    processed_docs = [tokenize(doc) for doc in data]
    word_count_dict = gensim.corpora.Dictionary(processed_docs)
    print "In the corpus there are", len(word_count_dict), "unique tokens"
    word_count_dict.filter_extremes(no_below=5, no_above=0.2) # word must appear >5 times, and no more than 10% documents
    print "After filtering, in the corpus there are only", len(word_count_dict), "unique tokens"
    bag_of_words_corpus = [word_count_dict.doc2bow(pdoc) for pdoc in processed_docs]
    return bag_of_words_corpus, word_count_dict

def cleancntxt(txt, stopwords):
    tfidf1000= jieba.analyse.extract_tags(txt, topK=1000, withWeight=False)
    seg_generator = jieba.cut(txt, cut_all=False)
    seg_list = [i for i in seg_generator if i not in stopwords]
    seg_list = [i for i in seg_list if i != u' ']
    seg_list = [i for i in seg_list if i in tfidf1000]
    return(seg_list)

def getCnCorpus(data):
    processed_docs = [cleancntxt(doc) for doc in data]
    word_count_dict = gensim.corpora.Dictionary(processed_docs)
    print "In the corpus there are", len(word_count_dict), "unique tokens"
    #word_count_dict.filter_extremes(no_below=5, no_above=0.2) 
    # word must appear >5 times, and no more than 10% documents
    print "After filtering, in the corpus there are only", len(word_count_dict), "unique tokens"
    bag_of_words_corpus = [word_count_dict.doc2bow(pdoc) for pdoc in processed_docs]
    return bag_of_words_corpus, word_count_dict

def inferTopicNumber(bag_of_words_corpus, num, word_count_dict):
    lda_model = gensim.models.LdaModel(bag_of_words_corpus, num_topics=num, id2word=word_count_dict, passes=10)
    _ = lda_model.print_topics(-1) #use _ for throwaway variables.
    logperplexity = lda_model.log_perplexity(bag_of_words_corpus)
    return logperplexity

def ppnumplot(topicnum,logperplexity): #做主题数与困惑度的折线图
    plt.plot(topicnum,logperplexity,color="red",linewidth=2)
    plt.xlabel("Number of Topic")
    plt.ylabel("Perplexity")
    plt.show()  
    
# 定义一些常用的函数
def flushPrint(variable):
    if variable %10^2 == 0:
        sys.stdout.write('\r')
        sys.stdout.write('%s' % variable)
        sys.stdout.flush()
    
    
def top(data):
    for i in data:
        print i
        
def freq(data):
    dtable = defaultdict(int)
    for i in data:
        dtable[i] += 1
    return dtable

def sortdict(data):
    '''data is a dict, sorted by value'''
    return sorted(data.items(), lambda x, y: cmp(x[1], y[1]), reverse=True) 

对2016年政府工作报告建立主题模型

In [118]:
import urllib2
from bs4 import BeautifulSoup
import sys

url2016 = 'http://news.xinhuanet.com/fortune/2016-03/05/c_128775704.htm'
content = urllib2.urlopen(url2016).read()
soup = BeautifulSoup(content) 
In [231]:
gov_report_2016 = [s.text for s in soup('p')]
for i in gov_report_2016[:10]:print i
政府工作报告
——2016年3月5日在第十二届全国人民代表大会第四次会议上
国务院总理 李克强
各位代表:
  现在,我代表国务院,向大会报告政府工作,请予审议,并请全国政协各位委员提出意见。
  一、2015年工作回顾
  过去一年,我国发展面临多重困难和严峻挑战。在以习近平同志为总书记的党中央坚强领导下,全国各族人民以坚定的信心和非凡的勇气,攻坚克难,开拓进取,经济社会发展稳中有进、稳中有好,完成了全年主要目标任务,改革开放和社会主义现代化建设取得新的重大成就。
  ——经济运行保持在合理区间。国内生产总值达到67.7万亿元,增长6.9%,在世界主要经济体中位居前列。粮食产量实现"十二连增",居民消费价格涨幅保持较低水平。特别是就业形势总体稳定,城镇新增就业1312万人,超过全年预期目标,成为经济运行的一大亮点。
  ——结构调整取得积极进展。服务业在国内生产总值中的比重上升到50.5%,首次占据"半壁江山"。消费对经济增长的贡献率达到66.4%。高技术产业和装备制造业增速快于一般工业。单位国内生产总值能耗下降5.6%。
  ——发展新动能加快成长。创新驱动发展战略持续推进,互联网与各行业加速融合,新兴产业快速增长。大众创业、万众创新蓬勃发展,全年新登记注册企业增长21.6%,平均每天新增1.2万户。新动能对稳就业、促升级发挥了突出作用,正在推动经济社会发生深刻变革。
In [232]:
def clean_txt(txt):
    for i in [u'、', u',', u'—', u'!', u'。', u'《', u'》', u'(', u')']:
        txt = txt.replace(i, ' ')
    return txt
In [233]:
gov_report_2016 = [clean_txt(i) for i in gov_report_2016]
    
In [234]:
for i in gov_report_2016[:10]:print i
政府工作报告
  2016年3月5日在第十二届全国人民代表大会第四次会议上
国务院总理 李克强
各位代表:
  现在 我代表国务院 向大会报告政府工作 请予审议 并请全国政协各位委员提出意见 
  一 2015年工作回顾
  过去一年 我国发展面临多重困难和严峻挑战 在以习近平同志为总书记的党中央坚强领导下 全国各族人民以坚定的信心和非凡的勇气 攻坚克难 开拓进取 经济社会发展稳中有进 稳中有好 完成了全年主要目标任务 改革开放和社会主义现代化建设取得新的重大成就 
    经济运行保持在合理区间 国内生产总值达到67.7万亿元 增长6.9% 在世界主要经济体中位居前列 粮食产量实现"十二连增" 居民消费价格涨幅保持较低水平 特别是就业形势总体稳定 城镇新增就业1312万人 超过全年预期目标 成为经济运行的一大亮点 
    结构调整取得积极进展 服务业在国内生产总值中的比重上升到50.5% 首次占据"半壁江山" 消费对经济增长的贡献率达到66.4% 高技术产业和装备制造业增速快于一般工业 单位国内生产总值能耗下降5.6% 
    发展新动能加快成长 创新驱动发展战略持续推进 互联网与各行业加速融合 新兴产业快速增长 大众创业 万众创新蓬勃发展 全年新登记注册企业增长21.6% 平均每天新增1.2万户 新动能对稳就业 促升级发挥了突出作用 正在推动经济社会发生深刻变革 
In [227]:
len(gov_report_2016[5:-1])
Out[227]:
103
In [243]:
jieba.add_word(u'屠呦呦', freq=None, tag=None)
#del_word(word) 

' '.join(cleancntxt(u'屠呦呦获得了诺贝尔医学奖。', stopwords))
屠呦呦 获得 诺贝尔 医学奖
In [244]:
processed_docs = [cleancntxt(doc, stopwords) for doc in gov_report_2016[5:-1]]
word_count_dict = gensim.corpora.Dictionary(processed_docs)
print "In the corpus there are", len(word_count_dict), "unique tokens"
# word_count_dict.filter_extremes(no_below=5, no_above=0.2) # word must appear >5 times, and no more than 10% documents
# print "After filtering, in the corpus there are only", len(word_count_dict), "unique tokens"
bag_of_words_corpus = [word_count_dict.doc2bow(pdoc) for pdoc in processed_docs]
In the corpus there are 2622 unique tokens
In [245]:
tfidf = models.TfidfModel(bag_of_words_corpus )
corpus_tfidf = tfidf[bag_of_words_corpus ]
lda_model = gensim.models.LdaModel(corpus_tfidf, num_topics=20, id2word=word_count_dict, passes=10)
#lda_model = gensim.models.LdaMulticore(corpus_tfidf, num_topics=10, id2word=word_count_dict, passes=10)
In [246]:
perplexity_list = [inferTopicNumber(bag_of_words_corpus, num, word_count_dict) for num in [5, 15, 20, 25, 30, 35, 40 ]]
In [247]:
plt.plot([5, 15, 20, 25, 30, 35, 40], perplexity_list)
Out[247]:
[<matplotlib.lines.Line2D at 0x10cdcf2d0>]
In [252]:
topictermlist = lda_model.print_topics(-1)
top_words = [[j.split('*')[1] for j in i.split(' + ')] for i in topictermlist] 
for i in top_words: print " ".join(i) + '\n'
2016 重点 供给 增收 结构性 农民 医保 深化 协定 自贸区

就业 燃煤 创业 排放 计划 完成 坚定 重大成就 稳中有进 攻坚克难

基本 就业 宗教 贯彻 发挥 救助 左右 保持 增长 社会

领导人 调控 论坛 峰会 宏观调控 货币政策 区间 联合国 会议 系列

军队 残疾人 大国 利益 社会 国防 妇女 儿童 外交 补贴

回顾 2015 经济 投资 服务 开展 促进 城市 规模 深化

出口 调控 贸易 存量 进口 外贸 安全 遏制 风险 注重

以下 一年 主要 贡献 赢得 富强 奋斗 奋发进取 复兴 民主

审批 万元 动能 结构性 优化 事项 供给 2020 腐败分子 惩处

金融 存在 一些 汇率 规范 适当 支付 债务 科技领域 诺贝尔

需求 大气 生态环境 无穷 自信心 优越性 凝聚力 奋力 展现 巨大

各位 代表 节能 环保 诚挚 表示 感谢 结果 随机 过程

规划 考虑 五年 海洋 国民经济 第十三个 强国 纲要 草案 6.5

港澳 生态 香港 投资 挑战 积累 融资 长期 重大项目 严格

经济 创新 改革 企业 政府 地方 政策 加快 实施 合作

非公有制 财政支出 万公里 教育 里程 范围 水平 所有 学校 品质

民生 脱贫 农业 国有企业 扶贫 世界反法西斯战争 保障 国有资产 市场化 人民

贸易 党风廉政 自贸 经济运行 体制 亿美元 深化改革 对外贸易 出口 形势

八个 两岸 重点 做好 方面 居民 下决心 事关 环境治理 双赢

消费 支付 外商投资 成绩 存款 百分点 旅游 这些 减少 项目

In [249]:
top_words_shares = [[j.split('*')[0] for j in i.split(' + ')] for i in topictermlist] 
top_words_shares = [map(float, i) for i in top_words_shares]
def weightvalue(x):
    return (x - np.min(top_words_shares))*40/(np.max(top_words_shares) -np.min(top_words_shares)) + 10
 
top_words_shares = [map(weightvalue, i) for i in top_words_shares]  

def plotTopics(mintopics, maxtopics):
    num_top_words = 10
    plt.rcParams['figure.figsize'] = (10.0, 4.0)  
    n = 0
    for t in range(mintopics , maxtopics):
        plt.subplot(2, 15, n + 1)  # plot numbering starts with 1
        plt.ylim(0, num_top_words)  # stretch the y-axis to accommodate the words
        plt.xticks([])  # remove x-axis markings ('ticks')
        plt.yticks([]) # remove y-axis markings ('ticks')
        plt.title(u'主题 #{}'.format(t+1), size = 5)
        words = top_words[t][0:num_top_words ]
        words_shares = top_words_shares[t][0:num_top_words ]
        for i, (word, share) in enumerate(zip(words, words_shares)):
            plt.text(0.05, num_top_words-i-0.9, word, fontsize= np.log(share*10))
        n += 1
In [250]:
plotTopics(0, 10)
In [251]:
plotTopics(10, 20)