[关闭]
@Perfect-Demo 2018-12-18T06:36:32.000000Z 字数 5483 阅读 1437

搜狗实验室新闻数据分析

机器学习深度学习


包括下面几项内容:

1. 原始语料库提取内容

由于从搜狗实验室下载的语料,属于原始数据,还包含各种HTML标签,所以需要进行处理,用下面的shell语句就可以解决:
(另外文件名字是news_tensite_xml.dat)

  1. cat news_tensite_xml.dat | iconv -f gbk -t utf-8 -c | grep "<content>" > corpus.txt

保存为corpus.txt
(但是这里面内容仍然包含了一个标签,之后可以通过re库来去除)

2. 中文分词

需要引入jieba库
并且需要re库来去除"标签"

下面这一段代码将文本进行分词并且保存

  1. import jieba
  2. import re
  3. def reTest(content):
  4. reContent = re.sub('<content>|</content>', '', content)
  5. return reContent
  6. space = " "
  7. i = 0
  8. content_S = []
  9. finput = open("corpus.txt")
  10. foutput = open("corpus_seg.txt", 'w')
  11. for line in finput:
  12. line_seg = jieba.lcut(reTest(line))
  13. foutput.write(space.join(line_seg))
  14. content_S.append(line_seg)
  15. i = i + 1
  16. if (i % 10000 == 0):
  17. print("Saved " + str(i) + " articles_seg")
  18. finput.close()
  19. foutput.close()
  20. print("Finished Saved " + str(i) + " articles")

3. 使用停词表

我们发下分词之后还有很多的标点符号出现了很多次,这样会影响我们之后用TF-IDF进行关键词提取.所以我们需要将这些(停用词)进行去除

对于停词表,可以直接在百度里搜索,然后建立一个txt文件储存即可

我的停词表名字叫 "stopwords.txt"
下面可以先读入它然后显示出来看看

  1. #停词表
  2. stopwords = pd.read_csv("stopwords.txt", index_col=False, sep = "\n", quoting=3,names=['stopword'], encoding='utf-8')
  3. stopwords.head(50)

下面的代码是去除停用词

  1. #去掉停用词
  2. def drop_stopwords(contents, stopwords):
  3. contents_clean = []
  4. all_words = []
  5. for line in contents:
  6. line_clean = []
  7. for word in line:
  8. if word in stopwords:
  9. continue
  10. line_clean.append(word)
  11. all_words.append(str(word))
  12. contents_clean.append(line_clean)
  13. return contents_clean, all_words
  14. contents = df_content.content_s.values.tolist()
  15. stopwords = stopwords.stopword.values.tolist()
  16. contents_clean, all_words = drop_stopwords(contents, stopwords)
  17. df_content = pd.DataFrame({'contents_clean':contents_clean})
  18. df_content.head()

4. 制作词云

通过上面的代码,我们已经去除了停用词,然后我们现在可以将所有词的出现频率做一个排序,然后通过词云显示出来(我们需要用到wordcloud库)

首先我们将字符出现的频率进行排序,然后保存在一个DataFrame里

  1. import numpy as np
  2. #统计字符出现的次数
  3. words_count=df_all_words.groupby(by=['all_words'])['all_words'].agg({"count":np.size})
  4. #进行排序,将出现次数多的排在前面
  5. words_count=words_count.reset_index().sort_values(by=["count"],ascending=False)
  6. words_count.head()

注意:这里中文字符的显示需要我们另外设置字体,我们可以直接用电脑中的字体

  1. # 制作词云
  2. from wordcloud import WordCloud
  3. import matplotlib.pyplot as plt
  4. import matplotlib
  5. matplotlib.rcParams['figure.figsize'] = (10.0, 5.0)
  6. # wordcloud=WordCloud(font_path="/usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc",background_color="white",max_font_size=80)
  7. wordcloud = WordCloud(
  8. # 设置背景颜色
  9. background_color="white",
  10. # 设置最大显示的词云数
  11. max_words=100,
  12. # 这种字体都在电脑字体中,一般路径
  13. font_path="/usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc",
  14. # height= 600,
  15. # width= 800,
  16. # 设置字体最大值
  17. max_font_size=80,
  18. # 设置有多少种随机生成状态,即有多少种配色方案
  19. random_state=50,
  20. )
  21. word_frequence = {x[0]:x[1] for x in words_count.head(100).values}
  22. wordcloud=wordcloud.fit_words(word_frequence)
  23. plt.imshow(wordcloud)
  24. wordcloud.to_file('py_book.png') # 把词云保存下

5. TF-IDF关键词提取

我们这里要用到一个公式如下:


得到的result越大越关键

然后对于我们可以分别由如下公式得到:


对于实现我们可以用jieba.analyse进行统计输出,代码如下:

  1. import jieba.analyse
  2. index= 112
  3. news = []
  4. finput = open("corpus.txt")
  5. for line in finput:
  6. news.append(reTest(line))
  7. finput.close()
  8. df_news = pd.DataFrame({'content':news})
  9. print(df_news['content'][index])
  10. content_S_str = "".join(content_S[index])
  11. #提取前五个作为关键词
  12. print(" ".join(jieba.analyse.extract_tags(content_S_str, topK=5, withWeight=False)))

然后我们可以得到五个词,可以看出来,这五个词差不多可以作为新闻摘要了

6. 用word2vec进行词向量嵌入

用了word2vec库然后将之前获得的分词文件放入得到结果后保存该模型即可.代码如下:

  1. import word2vec as wv
  2. wv.word2vec("corpus_seg.txt", "word2vec_segm.bin", size = 300, verbose=True)

然后我得到了如下结果:

Starting training using file corpus_seg.txt
Vocab size: 190705
Words in train file: 67084609
Alpha: 0.000012 Progress: 99.96% Words/thread/sec: 140.97k


每次使用时可以将模型导入然后使用

  1. model = wv.load("word2vec_segm.bin")

然后我们就可以通过model变量来调用这个模型了

比如我们可以输出一下整个model的词向量(我这个算是比较巨大)

  1. print(model.vectors)

我们也可以输出指定词的词向量

  1. print(model["美食"])

这样会输出一个300的词向量(因为我们之前做word2vec的时候用的维度是300)

我们可以将指定位置的词输出

  1. index= 100000
  2. print(model.vocab[index])

之后我们还可以看看指定词的有联系的词,用下面的语句:

  1. indexs = model.cosine("美食")
  2. for index in indexs[0]:
  3. print(model.vocab[index])

7. PCA在二维空间显示词向量

首先我们用sklearn库中的PCA模型进行降维
然后用matplotlib进行绘图显示

先导入库

  1. import matplotlib
  2. import matplotlib.pyplot as plt
  3. from sklearn.decomposition import PCA

然后用一个变量先提取model中的词向量,再进行PCA降维

  1. raw_word2vec = model.vectors
  2. X_reduced = PCA(n_components=2).fit_transform(raw_word2vec)

这样X_reduced就变成了一个降维的词向量集合了,对于每个词,只有两个坐标(x和y)


然后我们提取几个词的联系紧密的词记录他们的index,然后显示在坐标轴上
(注意,这里因为要显示中文字,所以需要加入字体文件,加入字体和之前的词云那是一样的)

下面是降维后进行可视化的过程

  1. #下面来展示几个降维后的例子
  2. #首先是添加下面这几个(中心)词的联系紧密的词
  3. index1, metrics1 = model.cosine("中国")
  4. index2, metrics2 = model.cosine("北京")
  5. index3, metrics3 = model.cosine("国家")
  6. index4, metrics4 = model.cosine("美食")
  7. #然后添加上面这几个(中心)词
  8. index01 = np.where(model.vocab == "中国")
  9. index02 = np.where(model.vocab == "北京")
  10. index03 = np.where(model.vocab == "国家")
  11. index04 = np.where(model.vocab == "美食")
  12. index1 = np.append(index1, index01)
  13. index2 = np.append(index2, index02)
  14. index3 = np.append(index3, index03)
  15. index4 = np.append(index4, index04)
  16. #下面开始绘图
  17. fig = plt.figure()
  18. ax = fig.add_subplot(1, 1, 1)
  19. #注意中文显示需要做特殊处理,就像词云图里一样要选择字体
  20. Cfont = matplotlib.font_manager.FontProperties(fname="/usr/share/fonts/opentype/noto/NotoSansCJK-Medium.ttc")
  21. for i in index1:
  22. ax.text(X_reduced[i][0], X_reduced[i][1], model.vocab[i], fontproperties = Cfont, color = 'r')
  23. # print(model.vocab[i])
  24. for i in index2:
  25. ax.text(X_reduced[i][0], X_reduced[i][1], model.vocab[i], fontproperties = Cfont, color = 'b')
  26. # print(model.vocab[i])
  27. for i in index3:
  28. ax.text(X_reduced[i][0], X_reduced[i][1], model.vocab[i], fontproperties = Cfont, color = 'g')
  29. # print(model.vocab[i])
  30. for i in index4:
  31. ax.text(X_reduced[i][0], X_reduced[i][1], model.vocab[i], fontproperties = Cfont, color = 'y')
  32. ax.axis([0, 0.8, -0.5, 0.5])
  33. plt.show()

效果如下:
此处输入图片的描述

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注