项目目标
- 数据获取。使用scrapy-redis框架构建分布式爬虫,
- 数据分析。主要分为以下三个模块:
- 新词发现。由于语料中含有许多在常规的语料当中不含有的新词,对于之后的任务的效果会有比较大的影响,因此需要进行新词发现。
- 热词发现。在这里,热词发现主要是指发现语料当中某个时间段的突发性的热词。
- 情感分析。主要是针对游戏中特定领域的情感分析。
3.数据可视化。使用数据可视化技术直观展示上述分析的结果。
数据获取
爬虫方法
在爬虫过程中,主要采用的框架是scrapy-redis。scrapy-redis是scrapy框架基于redis数据库的组件,用于scrapy项目的分布式开发和部署。有如下特征:
- 分布式爬取
可以启动多个spider工程,相互之间共享单个redis的requests队列。最适合广泛的多个域名网站的内容爬取 - 分布式数据处理
爬取到的scrapy的item数据可以推入到redis队列中,这意味着你可以根据需求启动尽可能多的处理程序来共享item的队列,进行item数据持久化处理 - Scrapy即插即用组件
Scheduler调度器 + Duplication复制 过滤器,Item Pipeline,基本spider
在本项目中,主要采用的来源于贴吧的数据集,因此在这里主要介绍贴吧的爬虫流程。
贴吧爬虫流程
- 针对贴吧的爬虫是采用深度优先的方法进行数据的抓取,从帖子的列表页到帖子的开始,依次向帖子本身,和帖子中的回复进行抓取;其中帖子中的回复是使用js动态进行加载的,因此需要分析页面在加载的过程当中的网络请求情况
- 在测试过程当中,没有发现百度贴吧会对爬虫进行非常强烈的封禁,因此无需进行复杂的诸如构建ip/账号池等的反爬虫操作
- 在实践过程当中,因为需要对最新的内容进行抓取,因此添加了一个定时启动的进程用来判定并且抓取最新的数据。
流程示意
放图
数据分析
新词发现
谈起“新词识别”“新词发现”,查看论文可以看到以下的方法:设计丰富的特征模板、建立训练语料库、引入CRF、ME、SVM、神经网络等模型并综合起来、在某某的基础上加入某种规则改进、最终在一个特定的语料库中训练处一个庞大的模型,并且在很小的规则的测试集上提高了2.33%的OOV识别率。
这种方法显然不适用与向贴吧这么大的语料,首先没有人力物力进行百万级的语料的标注,其次按照实践而言,越是复杂的方法用在实际语料当中的效果越差。
在尝试了几种常见的方法之后,发现使用左右熵和互信息的方法进行新词发现或有较好的效果。
互信息与左右熵
在这里新词的定义就是文本片段左右的搭配很丰富,并且片段内部成分搭配很固定。
互信息
一般来讲,片段的内部凝聚力可以用互信息来表示。
片段的内部信息定义为:片段的概率/(子序列概率的积)。如果将其取个对数,就得到了互信息:
左右熵
熵这个表示随机变量不确定性的量度。具体表述如下: 一般地, 设X 是取有限个值的随机变量( 或者说X 是有限个离散事件的概率场) , X 取值x 的概率为P ( x ) , 则X 的熵定义为:
外部搭配我们可以用,左右熵来表示:
实验效果
简单地对左右熵和互信息进行相加即可获得一个得分,把这个得分进行排序即可获得一个top k的排名。一般来说,语料规模越大新词发现的效果越好,当字符规模达到180k时基本上能达到100%的合理率。
语料大小(字符量) | top分词效果 |
---|---|
1800k | 御魂, 式神, sr, 萌新, 爆伤, 茨林, 鬼切, ssr, sp, 魂十, 魂土, 大岳丸, 六星, 化鲸, 酒吞, 黑蛋, 大佬们, 阎魔, 玉藻前, 破势, 针女, 崽战, up, 日和, 久次良, 辉夜, 号位, 金鱼姬, dd, 狂骨, mm, 满技能, 勾玉, 书翁… |
180k | 式神, 御魂, 萌新, sp, 鬼切, sr, 爆伤, 黑蛋, 六星, 茨林, 大岳丸, 酒吞, ssr, 书翁, 大佬们, 针女, 金鱼姬, 玉藻前, 追月, 清姬, 化鲸, 阎魔, 久次良, 破势, 小小黑, 之主, 满技能, dd, 崽战, 魂土… |
18k | 阿库娅, 车万, 夜火离歌, 式神, 真实玩家, 很多人都, 地藏大蛇, 椒图, 对啊, 琪露诺, 星输出, 御魂, 只是ch, 三千… |
构建词典
由于贴吧语料与普通的文本语料之间的语言差异是非常大的,因此在使用分词器的时候需要采用一些用户自定义词典预先加载的形式进行分词的预处理,在实际操作中,分词器一般都会实现用户预先加载自定义词典的算法来提高分词的准确率。
在本项目当中,我从以下几个方面获取了不同领域的内容并且生成了自己的用户自定义词典。
- 外部数据:主要是一些游戏相关的网站、论坛等,获取原始的游戏实体词典
- 公开词典:主要是为了获取这些公开词典当中的情感词
- 新词发现:获取识别出来的合理的新词
- 实体识别:使用其他平台的开放接口,识别出游戏中相关的实体
然后对所所有词典进行筛选和去重、构建自己的专有词典。
热词发现
热词的定义
一个词的热度可以受到以下几点影响:
- 时间:例如
- 词间:一般都是由于某个词变火而被带火的常用的搭配
- 周期:一般都是由于有固定的周期而周期性变火的单词。例如,在游戏当中一般都是周期性的活动
- 自身:因为自身因素而变火的词。也是我们最关心的词,这类词往往是重大的突发事件,在舆论分析过程当中对决策者的决策判断有重要的影响。
热词发现算法流程
数据预处理: 这里主要包括文本去重、广告识别等方法,对数据进行一些去躁的工作
-
梯度:词频增量的主要衡量指标
-
贝叶斯平均:一种利用outside information,especially a pre-existing belief,来评价the mean of a population的方法
贝叶斯平均的典型应用包括用户投票排名,产品评分排序,广告点击率的平滑等等。
以用户投票排名为例,用户投票评分的人很少,则算平均分很可能会出现不够客观的情况。这时引入外部信息,假设还有一部分人(C人)投了票,并且都给了平均分(m分)。把这些人的评分加入到已有用户的评分中,再进行求平均,可以对平均分进行修正,以在某种程度或角度上增加最终分数的客观性。容易得到,当投票人数少的时候,分数会趋向于平均分;投票人数越多,贝叶斯平均的结果就越接近真实投票的算术平均,加入的参数对最终排名的影响就越小
- 热度分数计算:利用贝叶斯平均对梯度分数进行修正
这里,公式中的平均词频是贝叶斯平均公式中的C,平均分是贝叶斯平均公式中的m。也就是说在热词提取中,我们用梯度分数的平均分作为先验m,用平均词频作为C。
热词提取中可以这么理解,词语每出现一次,相当于给词的热度进行了评分。
词频少,也就代表了评分的人数少,则评分的不确定性大,需要用平均分来进行修正、平滑。这里可以把一些词频很少的词语的高分数拉下来,例如一个词语今天出现了18次,昨天出现了6次,这里梯度分数就比较高,为0.75,但这种词语其实更可能不是一个热词。
词频大,远大于平均词频的词语,也就代表了评分的人数多。则分数会越趋向于自己的实际分数,这时平均分的影响变小。这是合理的,例如一个本来是百万量级的词语,第二天也出现了一个三倍的增量,这里热度价值就明显提高了。
实验效果
采用语料中8月14日与8月12日中的语料为例,实验效果可以参加下图:
实验结果表明具有较好效果。
情感分析
情感分析模限制于本人精力有限,无法进行更深入的细粒度的分析,只能进行比较粗粒度的三向情感分析(-1,0,1),并且先后采用了tf-idf、word2vec、bert_embedding向量化然后进行SVM、xgboost训练的方法和bert finetune的方法进行训练。
下面是几组实验的实验结果:
实验一
直接对训练数据进行三分类,与式神主题相关的约3000条回复 正样本358条 负样本298条 中性23444 条
实验二
均衡训练数据。训练数据:与式神相关5000条回复 正样本数量:负样本数量:中性样本数量≈1:1:2;测试数据:按照类别实际分布比例抽取的1000条数据;这里bert的max-seq-len为100
实验三
尝试一些trick
经过多轮试验之后,使用最佳的组合对数据进行情感分析。
数据可视化
本模块使用的是前端技术(echarts.js和ajax)技术结合flask构建HttpServer来构建的,已经上传ftp,不再赘述