舆情情感分析

  主要介绍下舆情情感分析内容,百度的paddlehub和预训练模型ernie。  

  舆情情感分析背景:举几个例子大家可能就清楚了,例如美团点评的用户评价内容,有些是正面的评价,有些是负面的评价,以及对电影的评价有正面、负面之分,收集这些有助于后台以及推荐等功能,那么如何让机器根据内容来判断这个内容的情感呢?这边会通过预训练模型来告诉大家。总结:给定一段文本,预测文本的情感是正面的还是负面的。这就是情感分析。

       真实例子:在我讲的demo里面,主要是对财经新闻、舆情进行利空、利好以及中性的预测。及时准确的判断舆情情感,对于行情的预测以及公司舆情的管理都是非常有作用的。

       预训练模型: 举个例子,假设我们有大量的维基百科数据,那么我们可以用这部分巨大的数据来训练一个泛化能力很强的模型,当我们需要在特定场景使用时,例如做文本相似度计算,那么,只需要简单的修改一些输出层,再用我们自己的数据进行一个增量训练,对权重进行一个轻微的调整。预训练的好处在于在特定场景使用时不需要用大量的语料来进行训练,节约时间效率高效,bert就是这样的一个泛化能力较强的预训练模型。

  舆情情感分析步骤:

  第一,数据集的准备:因为预训练模型所使用的语料是通用语料,对于专业领域,例如财经、金融等领域专业性比较强,需要特定的这方面相关的语料。这方面可以通过爬虫或者数据库下载的方式得到语料。得到了语料之后,还需要对数据进行初步的处理,之后进行人工标注。标注之后的内容如下所示:一行里面tab分割,前面是新闻内容,后面是该内容的人工标注内容。在这里,我们标注的是利好、利空和中性标签。

  第二,准备好数据集,就开始模型训练了。在这里,我选的是百度的paddlehub工具。对它的简介:PaddleHub是飞桨生态的预训练模型应用工具,开发者可以便捷地使用高质量的预训练模型结合Fine-tune API快速完成模型迁移到部署的全流程工作。

  第三,准备下载模型以及工具包。根据自己的情况,安装paddlepaddle模块。https://www.paddlepaddle.org.cn/install/quick/zh/1.8.5-windows-pip

 正式到模型内容:

深度学习的流程:数据处理 ---> 网络构建 ---> 模型训练 ---> 模型评估 ---> 模型部署

 第一步,载入模块

 1 #载入模块
 2 from __future__ import absolute_import
 3 from __future__ import division
 4 from __future__ import print_function
 5  
 6 import numpy as np
 7 import os
 8  
 9 import paddle
10 import paddle.fluid as fluid
11 import paddlehub as hub
12 from paddlehub.finetune.evaluate import chunk_eval, calculate_f1
13 from paddlehub.dataset.base_nlp_dataset import BaseNLPDataset
14 import pandas as pd
15 import datetime

第二部,加载数据集

 1 #自定义数据集输入
 2 class DemoDataset(BaseNLPDataset):
 3     """DemoDataset"""
 4     def __init__(self):
 5         # 数据集存放位置
 6         self.dataset_dir = ".../dataset"
 7         super(DemoDataset, self).__init__(
 8             base_path=self.dataset_dir,
 9             train_file="train.tsv",
10             dev_file="dev.tsv",
11             test_file="test.tsv",
12             
13             train_file_with_header=True,
14             dev_file_with_header=True,
15             test_file_with_header=True,
16            
17             # 数据集类别集合
18             label_list=['中性','利空','利好'])
19 dataset = DemoDataset()

第三步,导入预训练模型

1 import paddlehub as hub
2 module = hub.Module(name="ernie")

如果想尝试其他语义模型(如ernie_tiny, RoBERTa等),只需要更换Module中的name参数即可.

模型名PaddleHub Module
ERNIE, Chinese hub.Module(name='ernie')
ERNIE 2.0 Tiny, Chinese hub.Module(name='ernie_tiny')
ERNIE 2.0 Base, English hub.Module(name='ernie_v2_eng_base')
ERNIE 2.0 Large, English hub.Module(name='ernie_v2_eng_large')
RoBERTa-Large, Chinese hub.Module(name='roberta_wwm_ext_chinese_L-24_H-1024_A-16')
RoBERTa-Base, Chinese hub.Module(name='roberta_wwm_ext_chinese_L-12_H-768_A-12')
BERT-Base, Uncased hub.Module(name='bert_uncased_L-12_H-768_A-12')
BERT-Large, Uncased hub.Module(name='bert_uncased_L-24_H-1024_A-16')
BERT-Base, Cased hub.Module(name='bert_cased_L-12_H-768_A-12')
BERT-Large, Cased hub.Module(name='bert_cased_L-24_H-1024_A-16')
BERT-Base, Multilingual Cased hub.Module(nane='bert_multi_cased_L-12_H-768_A-12')
BERT-Base, Chinese hub.Module(name='bert_chinese_L-12_H-768_A-12')

第四步,构建Reader

接着生成一个文本分类的reader,reader负责将dataset的数据进行预处理,首先对文本进行切词,接着以特定格式组织并输入给模型进行训练。

ClassifyReader的参数有以下三个:

  • dataset: 传入PaddleHub Dataset;
  • vocab_path: 传入ERNIE/BERT模型对应的词表文件路径;
  • max_seq_len: ERNIE模型的最大序列长度,若序列长度不足,会通过padding方式补到max_seq_len, 若序列长度大于该值,则会以截断方式让序列长度为max_seq_len;
  • sp_model_path: 传入 ERNIE tiny的subword切分模型路径;
  • word_dict_path: 传入 ERNIE tiny的词语切分模型路径;
1 #接着生成一个文本分类的reader,reader负责将dataset的数据进行预处理,首先对文本进行切词,接着以特定格式组织并输入给模型进行训练。
2 reader = hub.reader.ClassifyReader(
3     dataset=dataset,
4     vocab_path=module.get_vocab_path(),
5     sp_model_path=module.get_spm_path(),
6     word_dict_path=module.get_word_dict_path(),
7     max_seq_len=128)

第五步,选择Fine-Tune优化策略

适用于ERNIE/BERT这类Transformer模型的迁移优化策略为AdamWeightDecayStrategy

AdamWeightDecayStrategy的参数:

  • learning_rate: 最大学习率
  • lr_scheduler: 有linear_decaynoam_decay两种衰减策略可选
  • warmup_proprotion: 训练预热的比例,若设置为0.1, 则会在前10%的训练step中学习率逐步提升到learning_rate
  • weight_decay: 权重衰减,类似模型正则项策略,避免模型overfitting
  • optimizer_name: 优化器名称
1 #选择Fine-Tune优化策略
2 strategy = hub.AdamWeightDecayStrategy(
3     weight_decay=0.01,
4     warmup_proportion=0.1,
5     learning_rate=5e-5,
6     lr_scheduler="linear_decay",
7     optimizer_name="adam")

第六步,选择运行配置

在进行Finetune前,我们可以设置一些运行时的配置,例如如下代码中的配置,表示:

  • use_cuda:设置为False表示使用CPU进行训练。如果您本机支持GPU,且安装的是GPU版本的PaddlePaddle,我们建议您将这个选项设置为True;

  • num_epoch:Finetune时遍历训练集的次数,;

  • batch_size:每次训练的时候,给模型输入的每批数据大小为16,模型训练时能够并行处理批数据,因此batch_size越大,训练的效率越高,但是同时带来了内存的负荷,过大的batch_size可能导致内存不足而无法训练,因此选择一个合适的batch_size是很重要的一步;

  • log_interval:每隔10 step打印一次训练日志;

  • eval_interval:每隔50 step在验证集上进行一次性能评估;

  • checkpoint_dir:训练的参数和数据的保存目录;

  • strategy:Fine-tune策略;

  • use_data_parallel: 设置为False表示单卡训练;设置为True表示多卡训练

  • use_pyreader: 设置为False表示不使用py_reader读取数据;设置为True表示使用py_reader读取数据

1 #选择运行配置
2 config = hub.RunConfig(
3     use_cuda=False,#使用CPU训练
4     num_epoch=6,
5     checkpoint_dir="ernie_txt_cls",
6     batch_size=32,
7     eval_interval=50,
8     strategy=strategy)

第7步,组建Finetune Task

有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个Task。

  1. 获取module的上下文环境,包括输入和输出的变量,以及Paddle Program;
  2. 从输出变量中找到用于情感分类的文本特征pooled_output;
  3. 在pooled_output后面接入一个全连接层,生成Task;

TextClassifierTask的参数有:

  • data_reader:读取数据的reader;

  • config: 运行配置;

  • feature:从预训练提取的特征;

  • feed_list:program需要输入的变量;

  • num_classes:数据集的类别数量;

  • metric_choic:任务评估指标,默认为"acc"。metrics_choices支持训练过程中同时评估多个指标,作为最佳模型的判断依据,例如["matthews", "acc"],"matthews"将作为主指标,为最佳模型的判断依据;

 1 #组建Finetune Task
 2 
 3 inputs, outputs, program = module.context(
 4     trainable=True, max_seq_len=128)
 5 
 6 # Use "pooled_output" for classification tasks on an entire sentence.
 7 pooled_output = outputs["pooled_output"]
 8 
 9 feed_list = [
10     inputs["input_ids"].name,
11     inputs["position_ids"].name,
12     inputs["segment_ids"].name,
13     inputs["input_mask"].name,
14 ]
15 
16 cls_task = hub.TextClassifierTask(
17         data_reader=reader,
18         feature=pooled_output,
19         feed_list=feed_list,
20         num_classes=dataset.num_labels,
21         config=config,
22         metrics_choices=["acc"])

NOTE: Reader参数max_seq_len、moduel的context接口参数max_seq_len三者应该保持一致,最大序列长度max_seq_len是可以调整的参数,建议值128,根据任务文本长度不同可以调整该值,但最大不超过512。

第8步,开始Finetune

我们选择finetune_and_eval接口来进行模型训练,这个接口在finetune的过程中,会周期性的进行模型效果的评估,以便我们了解整个训练过程的性能变化。

1 #开始Finetune
2 run_states = cls_task.finetune_and_eval()

 可以看到模型的效果不错,test 数据集上 acc可以达到0.9。

第9步,使用模型进行预测

当Finetune完成后,我们使用模型来进行预测,整个预测流程大致可以分为以下几步:

  1. 构建网络
  2. 生成预测数据的Reader
  3. 切换到预测的Program
  4. 加载预训练好的参数
  5. 运行Program进行预测
 1 #预测
 2 inv_label_map = {val: key for key, val in reader.label_map.items()}
 3 
 4 # Data to be prdicted
 5 data = [[d.text_a, d.text_b] for d in dataset.get_test_examples()[:10]]
 6 
 7 
 8 index = 0
 9 run_states = cls_task.predict(data=data)
10 
11 results = [run_state.run_results for run_state in run_states]
12 for batch_result in results:
13     # get predict index
14     batch_result = np.argmax(batch_result, axis=2)[0]
15     for result in batch_result:
16         print("%s	%s" % (data[index][0], inv_label_map[result]))
17         print("
")
18         index += 1

  打印出例子看下,结果也是符合的。

  总结:利用预训练模型ernie对财经、金融的文本进行舆情情感分析(利空、利好、中性),其准确率可以达到0.9左右,效果还是非常不错的。

参考资料:

1、https://mp.weixin.qq.com/s/voHq_ErxRIt5gSDXh8wxFA

2、https://www.cnblogs.com/enhaofrank/p/13554130.html

3、https://www.cnblogs.com/enhaofrank/p/13255718.html

4、https://github.com/PaddlePaddle/PaddleHub

5、https://paddlehub.readthedocs.io/zh_CN/develop/index.html

---------------------------本博客所有内容以学习、研究和分享为主,如需转载,请联系本人,标明作者和出处,并且是非商业用途,谢谢!---------------------

作者:enhaofrank

出处:https://www.cnblogs.com/enhaofrank/

中科院硕士毕业

现为深漂打工人

原文地址:https://www.cnblogs.com/enhaofrank/p/14001021.html