实战微博互动预测之二 _ 中文分析

#算法实战 #自然语言处理

1. 说明

  前篇《实战微博互动预测之一 _ 问题分析》中,已经对微博的整体反馈情况,以及单个用户的反馈做了初步的分析。本篇将从微博的信息内容中提取更多特征。

  文本分析是数据分析中的常用技术,使用范围很广,比如:信息搜索,内容推荐,文章分类,内容提取等等。其核心是分析连续的文本,抽取关键数据,再进行下一步分析。

2. 文本分析

1) TF-IDF 算法

 TF-IDF 是一种统计方法,TF 指词频,IDF 是逆向文件频率。TF 好理解,就是词在文章中出现的频率,出现频率高的词更可能是文章的关键词。但有些词如:“是”,“的”,“了”(即停用词)在任何文章出现频率都高,于是使用 IDF。IDF 通过总文件数目除以包含该词语之文件的数目,再将商取对数得到,它弱化了常用词的权重。TF-IDF 倾向于过滤掉常见的词语,保留重要的词语。

2) 中文分词

  中文分析一般以词为单位,与英文不同的是中文的词与词之间没有空格划分,所以处理时,首先要分词。简单的方法是把所有词放在一个词典中,通过正向匹配,逆向匹配,双向匹配等方式分词,这种方式经常会产生歧义;也可以利用统计的方法如 HMM,SVM 通过训练学习分词。实际操作中最常使用的方法是直接调库。常用库有 jieba 分词,SnowNLP 等,后面详述。

3) 文本分析功能

  常见的文本分析一般有:分词,计算 TF、IDF,词性标注,提取关键词,提取摘要,情感分析,文本相似度等等。

4) 文本分析工具

  有很多在线工具提供 API 实际自然语言的处理,效果比离线的好一些,但在处理大量数据时,速度太慢了。下面来看看常用的离线工具。

  1. NLTK

Natural Language Toolkit,自然语言处理工具包,它是 NLP 领域中,最常使用的一个 Python 库。功能非常全,但对中文处理相对弱一些。

  1. SnowNLP

SnowNLP 是一个中文工具,它实现了大部分文本分析的常用功能,并且可以自己训练数据。但是试了一下它自带的分析器,如:情感分析,关键词提取功能,代入微博文本,效果都不太好,后面只使用了它的分词功能。使用方法如下:

1
2
3
4
5
6
7
8
9
10
from snownlp import SnowNLP

s = SnowNLP("跟框架学代码设计,跟应用学功能设计")
print(s.words) # 分词
print(s.sentiments) # 消极or积极,结果在0-1之间
print(s.tags) # 词性标注
print(s.keywords(3)) # 关键词
print(s.summary(3)) # 摘要
print(s.tf) # tf
print(s.idf) # idf

  我的机器速度一般,计算 1000 条微博 20s,处理所有数据约 5 小时左右。

  1. 结巴分词

结巴分词的效果也不错,支持自定义词典,词性标注等等,具体使用方法如下:

1
2
3
#encoding=utf-8
import jieba
print(jieba.cut("跟框架学代码设计,跟应用学功能设计", cut_all=True))
  1. 其它

  这里只使用了分词功能,所以用哪个工具都差不多。除上述工具,还有 PyLTP,THULAC,Pynlpir,CoreNLP 等中文文本处理工具,详见:

http://blog.csdn.net/sinat_26917383/article/details/77067515

3. 文本的简单分析

  微博的训练数据有 100 多万条,分析一遍花很多时间,所以第一步,先对文本做简单的字符串处理,包括:判断是否含有@,是否含有链接,提取标题,提取表情。这里主要用到的技术是:对 DataFrame 数据列的函数处理 apply,以及正则表达式。

1) 正则表达式

  具体使用 re 库,假设标题是用”##”,”【】”,”《》”括起来的字符串。提取标题的方法如下:

1
2
3
4
import re
patt=re.compile(r'[#【《](.*?)[#】》]',re.S)
topics=patt.findall(content) # 提取标题
plain=re.sub(patt,'', content) # 从正文中去掉标题

2) Apply 处理列数据

  假设 content 列存储的是文本信息,提取标题到 topic 列中:

1
2
3
def getTopic(content):

data['topic']=data.content.apply(getTopic)

  注意尽量不要用 for 循环处理 DataFrame,那样做速度非常慢。

4. 文本提供的信息量

1) 统计分析

  没人关注的用户发的文约占 9%(发的所有微博都得不到反馈),这部分数据单独处理。

  其它数据统计如下:带标题占 39%,带链接占 55%,带表情占 12%,带@占 20%。

2) 计算相关系数

 dataframe.corr()

  计算得出的结论和人的经验类似:带表情的更容易得到反馈,自己写的更容易得到反馈(不带标题,不带链接),带链接的容易被转发,带@得到的反馈较少,正文长度与转发相关……

3) 分析

  从上面的分析看来,用户个人的相关数据比信息内容重要得多,但回想前篇我们对单一用户的数据分析,他发的 700 多条微信中,167 条转发 0 次,而其中有一篇被转发了 8000 多次。对于用户个体来说,还是需要根据信息内容来进一步判断。这个原理就如同决策树,在第一层“用户信息”的信息增益更大,但在第一层之后,其它信息就变得重要了。

5. 文本的复杂分析

  分词和文章分类,都是庞大的体系,有很多方法构造和优化。但在微博预测问题中,只是想借此得到更多的数据特征。所以这里不去构造分类器,而是寻找现成最简单有效的方法,这里使用了 SnowNLP 和《同义词词林》。

  首先使用 SnowNLP 对标题和正文分词和词性标注,然后筛选出句子中的名词,代入同义词词林,找到相应的分类。

  同义词词林是一本词典,最初目标是提供较多的同义词语,对创作和翻译工作有所帮助。它把中文词组分为大类,中类,小类。这里对信息中的名词归类,最终将信息归类。分词后共抽取名词性关键字 2605965 个,去重后 18515 个,用词林分成 95 个类别。

  使用时还需要解决一词多义,以及句中含有不同类别名词的问题,具体的方法是优先选择:社会,经济,文教等抽象分类。

6. 一些想法

  一开始做的时候,数据很多,可提取的特征也多,有点无从下手。解决的方法是:先切出一部分,使用现有的工具测试。

  当数据多的时候,每个操作,尤其是面向所有数据的操作,都会花很多时间,最好是先处理少量记录,并且记下各个步骤的运行时间。

  我觉得无论是写算法还是文本分析,能确定的都用确定的,不能确定的再用统计方法处理。比如某个用户数据中均值确定,方差很少,那就直接用均值。