# 通用情感信息抽取 ## **目录** ## **目录** - [1. 情感分析应用简介](#1) - [2. 特色介绍](#2) - [3. 运行环境](#3) - [4. 整体功能介绍与Taskflow快速体验](#4) - [4.1 开箱即用的情感分析能力](#4.1) - [4.1.1 语句级情感分析](#4.1.1) - [4.1.2 属性级情感分析](#4.1.2) - [4.1.3 多版本模型选择](#4.1.3) - [4.2 批量处理:从数据到情感分析可视化](#4.2) - [4.2.1 数据描述](#4.2.1) - [4.2.2 批量情感分析](#4.2.2) - [4.2.3 情感分析可视化](#4.2.3) - [4.2.3.1 一键生成情感分析结果](#4.2.3.1) - [4.2.3.2 情感分析详细展示](#4.2.3.2) - [5. 更进一步:结合业务分析经验,定制情感分析](#5) - [5.1 打通数据标注到训练样本构建](#5.1) - [5.1.1 样本构建:语句级情感分类任务](#5.1.1) - [5.1.2 样本构建:属性抽取相关任务](#5.1.2) - [5.1.3 样本构建升级1:加强属性聚合能力](#5.1.3) - [5.1.4 样本构建升级2:加强隐性观点抽取能力](#5.1.4) - [5.2 模型训练](#5.2) - [5.3 模型测试](#5.3) - [5.4 模型预测及效果展示](#5.4) - [5.4.1 使用训练后的模型进行预测](#5.4.1) - [5.4.2 属性聚合预测和分析](#5.4.2) - [5.4.3 隐性观点词抽取预测和分析](#5.4.3) - [6. 模型部署](#6) - [6.1 基于SimpleServer进行服务化部署](#6.1) - [6.2 基于Pipeline进行部署](#6.2) ## **1. 情感分析应用简介** PaddleNLP情感分析应用立足真实企业用户对情感分析方面的需求,针对情感分析领域的痛点和难点,提供基于前沿模型的情感分析解决方案,助力开发者快速分析业务相关产品或服务的用户感受。 本项目以通用信息抽取模型UIE为训练底座,提供了语句级情感分析和属性级情感分析能力、覆盖情感分类、属性抽取、观点抽取等常用情感分析能力,如下图所示。同时提供了可视化能力,支持从输入数据到情感分析结果可视化,帮助用户快速分析业务数据。更进一步地,本项目同时支持基于业务数据进行定制训练,同时支持引入业务侧积累的经验和知识,包括同义属性和隐性观点词表,加强模型进行属性聚合和隐性观点抽取的能力,进一步提高模型对于业务场景数据的分析能力。
## **2. 特色介绍** - **功能丰富🎓**:提供情感分析训练模型作为底座,支持语句级情感分析和属性级情感分析,覆盖情感分类、属性与观点抽取、同义属性聚合、隐性观点抽取、可视化分析等常见情感分析任务。 - **效果领先✊**: 以通用信息抽取模型UIE为训练底座,具有较强的零样本预测和小样本微调能力。 - **开箱即用👶**:打通Taskflow使用流程,3行代码获取分析结果,同时提供了情感分析结果可视化能力。 - **定制模型🏃**:支持针对特定业务场景进行全流程定制,包括数据标注、样本构建、模型训练和模型测试,同时通过融合业务相关的同义属性词和隐性观点词,可进一步提高模型针对业务场景的情感分析能力。 ## **3. 运行环境** **代码结构** ``` unified_sentiment_extraction/ ├── batch_predict.py # 以文件的形式输入,进行批量预测的脚本 ├── evaluate.py # 模型评估脚本 ├── finetune.py # 模型微调脚本 ├── label_studio.py # 将label-studio导出数据转换为模型输入数据的脚本 ├── label_studio.md # 将label-studio标注说明 ├── utils.py # 工具函数脚本 ├── visual_analysis.py # 情感分析结果可视化脚本 └── README.md # 使用说明 ``` **安装依赖** - python == 3.9.12 - paddlepaddle == 2.3.2 - paddlenlp == 2.4.5 - wordcloud == 1.8.2.2 **安装PaddlePaddle**: 环境中paddlepaddle-gpu或paddlepaddle版本应大于或等于2.3, 具体可以参见[飞桨快速安装](https://www.paddlepaddle.org.cn/install/quick?docurl=/documentation/docs/zh/install/pip/linux-pip.html)根据自己需求选择合适的PaddlePaddle下载命令。如下命令可以安装linux系统,CUDA版本为10.2环境下的paddlepaddle,具体版本号为支持GPU的2.3.2版本。 ```shell conda install paddlepaddle-gpu==2.3.2 cudatoolkit=10.2 --channel https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/Paddle/ ``` **安装PaddleNLP**: 安装PaddleNLP可以开启百度镜像源来加速下载,更多关于PaddleNLP安装的详细教程请查见[PaddleNLP快速安装](https://github.com/PaddlePaddle/PaddleNLP/blob/develop/docs/get_started/installation.rst)。 ```shell python3 -m pip install --upgrade paddlenlp -i https://mirror.baidu.com/pypi/simple ``` **安装wordcloud**: ```shell python3 -m pip install wordcloud==1.8.2.2 ``` ## **4. 整体功能介绍与Taskflow快速体验** 本项目以通用信息抽取模型UIE为训练底座,基于大量情感分析数据进一步训练,增强了模型对于情感知识的处理能力,支持语句级情感分类、属性抽取、观点词抽取、属性级情感分类等基础情感分析能力。下表展示了通用UIE `uie-base` 和情感知识增强的UIE `uie-senta-base` 在测试集上的效果对比。 | 模型 | Precision | Recall | F1 | | :---: | :--------: | :--------: | :--------: | | `uie-base` | 0.86759 | 0.83696 | 0.85200 | | `uie-senta-base` | 0.93403 | 0.92795 | 0.93098 | 另外,为方便用户体验和使用,本项目提供的情感分析能力已经集成到了 Taskflow,可以通过Taskflow开箱即用的能力快速体验情感分析的功能。 ### **4.1 开箱即用的情感分析能力** #### **4.1.1 语句级情感分析** 整句情感分析功能当前支持二分类:正向和负向,调用示例如下: ```python >>> from paddlenlp import Taskflow >>> schema = ['情感倾向[正向,负向]'] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema) >>> print(senta('蛋糕味道不错,店家服务也很好')) [ { '情感倾向[正向,负向]': [ { 'text': '正向', 'probability': 0.996646058824652 } ] } ] ``` #### **4.1.2 属性级情感分析** 除语句级情感分析之外,本项目同时支持属性级情感分析,包括属性抽取(Aspect Term Extraction)、观点抽取(Opinion Term Extraction)、属性级情感分析(Aspect Based Sentiment Classification)等等。可以通过设置相应的schema进行对应信息的抽取,其调用示例如下。 ```python >>> from paddlenlp import Taskflow >>> # Aspect Term Extraction >>> # schema = ["评价维度"] >>> # Aspect - Opinion Extraction >>> # schema = [{"评价维度":["观点词"]}] >>> # Aspect - Sentiment Extraction >>> # schema = [{"评价维度":["情感倾向[正向,负向,未提及]"]}] >>> # Aspect - Sentiment - Opinion Extraction >>> schema = [{"评价维度":["观点词", "情感倾向[正向,负向,未提及]"]}] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema) >>> print(senta('蛋糕味道不错,店家服务也很热情')) [ { '评价维度': [ { 'text': '服务', 'start': 9, 'end': 11, 'probability': 0.9709093024793489, 'relations': { '观点词': [ { 'text': '热情', 'start': 13, 'end': 15, 'probability': 0.9897222206316556 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '正向', 'probability': 0.9999327669598301 } ] } }, { 'text': '味道', 'start': 2, 'end': 4, 'probability': 0.9105472387838915, 'relations': { '观点词': [ { 'text': '不错', 'start': 4, 'end': 6, 'probability': 0.9946981266891619 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '正向', 'probability': 0.9998829392709467 } ] } } ] } ] ``` 更进一步地,在某些业务场景中,特别是一些垂域场景,用户可能比较关注固定的某些属性。在这种情况下,可以预先提供相应的属性集合,则本项目将只会在该属性集上进行情感分析,分析和抽取该集合中各个属性的信息。 针对固定属性的情感分析示例如下,需要将属性集合传入参数 `aspects` 中,后续将只针对这些属性进行分析。可以看到在示例中,传入了属性 `房间`,`位置` 和 `价格`,针对 `房间` 和 `价格` 均分析到了观点词和情感倾向,但是`位置`由于在样本中并未提及,因此相应观点词为空,情感倾向为 `未提及`。 ```python >>> # define schema for pre-defined aspects, schema >>> schema = ["观点词", "情感倾向[正向,负向,未提及]"] >>> aspects = ["房间", "位置", "价格"] >>> # set aspects for Taskflow >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema, aspects=aspects) >>> print(senta("这家店的房间很大,店家服务也很热情,就是价格有点贵")) [ { '评价维度': [ { 'text': '房间', 'relations': { '观点词': [ { 'text': '大', 'start': 7, 'end': 8, 'probability': 0.9998772175681552 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '正向', 'probability': 0.9999312170965595 } ] } }, { 'text': '位置', 'relations': { '情感倾向[正向,负向,未提及]': [ { 'text': '未提及', 'probability': 0.9999939203353847 } ] } }, { 'text': '价格', 'relations': { '观点词': [ { 'text': '贵', 'start': 24, 'end': 25, 'probability': 0.998841669863026 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '负向', 'probability': 0.9997340617174757 } ] } } ] } ] ``` #### **4.1.3 多版本模型选择** 为方便用户实际业务应用情况,本项目多个版本的模型,可以根据业务对于精度和速度方面的要求进行选择,下表展示了不同版本模型的结构以及在测试集上的指标。 | 模型 | 结构 | Precision | Recall | F1 | | :---: | :--------: | :--------: | :--------: | :--------: | | `uie-senta-base` (默认) | 12-layers, 768-hidden, 12-heads | 0.93403 | 0.92795 | 0.93098 | | `uie-senta-medium` | 6-layers, 768-hidden, 12-heads | 0.93146 | 0.92137 | 0.92639 | | `uie-senta-mini` | 6-layers, 384-hidden, 12-heads | 0.91799 | 0.92028 | 0.91913 | | `uie-senta-micro` | 4-layers, 384-hidden, 12-heads | 0.91542 | 0.90957 | 0.91248 | | `uie-senta-nano` | 4-layers, 312-hidden, 12-heads | 0.90817 | 0.90878 | 0.90847 | 在Taskflow中,可以直接指定相应模型名称进行使用,使用`uie-senta-mini`版本的示例如下: ```python >>> from paddlenlp import Taskflow >>> schema = [{"评价维度":["观点词", "情感倾向[正向,负向,未提及]"]}] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-mini", schema=schema) ``` ### **4.2 批量处理:从数据到情感分析可视化** 为方便使用,本项目提供了批量处理的功能,支持以文件形式输入,批量进行情感分析。同时打通了从数据到情感分析结果可视化的流程,帮助用户可以更加快速获取情感分析结果,聚焦于业务分析方面。 #### **4.2.1 数据描述** 输入数据如下方式进行组织,每行表示一个文本评论。可以点击[这里](https://paddlenlp.bj.bcebos.com/datasets/sentiment_analysis/hotel/test_hotel.tar.gz)下载酒店场景的测试数据进行分析。 ``` 非常好的酒店 不枉我们爬了近一个小时的山,另外 大厨手艺非常棒 竹筒饭 竹筒鸡推荐入住的客人必须要点, 房间隔音效果不好,楼下KTV好吵的 酒店的房间很大,干净舒适,服务热情 怎么说呢,早上办理入住的,一进房间闷热的一股怪味,很臭,不能开热风,好多了,虽然房间小,但是合理范围 总台服务很差,房间一般 ``` #### **4.2.2 批量情感分析** 通过脚本 `batch_predict.py` 批量进行情感分析,通过 `file_path` 指定要进行情感分析的文件路径,处理完后,结果将会保存在 `save_path` 指定的文件中,示例如下: ```shell python batch_predict.py \ --file_path "./data/test_hotel.txt" \ --save_path "./data/sentiment_analysis.json" \ --model "uie-senta-base" \ --schema "[{'评价维度': ['观点词', '情感倾向[正向,负向,未提及]']}]" \ --batch_size 4 \ --max_seq_len 512 ``` 参数说明: - ``file_path``: 用于进行情感分析的文件路径。 - ``save_path``: 情感分析结果的保存路径。 - ``model``: 进行情感分析的模型名称,可以在这些模型中进行选择:['uie-senta-base', 'uie-senta-medium', 'uie-senta-mini', 'uie-senta-micro', 'uie-senta-nano']。 - ``load_from_dir``: 指定需要加载的离线模型目录,比如训练后保存的模型,如果不进行指定,则默认根据 `model` 指定的模型名称自动下载相应模型。 - ``schema``: 基于UIE模型进行信息抽取的Schema描述。 - ``batch_size``: 预测过程中的批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为 16。 - ``max_seq_len``: 模型支持处理的最大序列长度,默认为512。 - ``aspects``: 预先给定的属性,如果设置,模型将只针对这些属性进行情感分析,比如分析这些属性的观点词。 #### **4.2.3 情感分析可视化** 在情感分析处理之后,可以根据情感分析的保存结果进行可视化展示,帮助用户更友好地分析业务特点。默认情况下,可视化功能支持围绕属性、观点、属性+观点、属性+情感、指定属性+观点分析功能。在各项分析中,均支持词云和直方图两类图像展示。 下面将以酒店场景数据为例进行展示。 **4.2.3.1 一键生成情感分析结果** 基于以上生成的情感分析结果,可以使用`visual_analysis.py`脚本对情感分析结果进行可视化,最终可视化结果将会被保存在 `save_dir` 指定的目录下。 使用时需要指定情感分析可视化的结果的任务类型,若是语句级的情感分类,则将task_type指定为``cls``,若是属性级的情感分析,则将task_type指定为``ext``,示例如下: ``` python visual_analysis.py \ --file_path "./outputs/test_hotel.json" \ --save_dir "./outputs/images" \ --task_type "ext" ``` 可配置参数说明: - ``file_path``: 指定情感分析结果的保存路径。 - ``save_dir``: 指定图片的保存目录。 - ``task_type``: 指定任务类型,语句级情感分类请指定为``cls``,属性级情感分析请指定为``ext``,默认为``ext``。 - ``font_path``: 指定字体文件的路径,用以在生成的wordcloud图片中辅助显示中文,如果为空,则会自动下载黑体字,用以展示中文字体。 **备注**:在`visual_analysis.py`脚本启动时,默认会删除当前已经存在的`save_dir`目录以及其中文件,然后在该目录下重新生成相应的可视化图片。 下图展示了对酒店场景数据分析后的部分图片:

**4.2.3.2 情感分析详细展示** **(1) 属性分析** 通过属性信息,可以查看客户对于产品/服务的重点关注方面. 可以通过`plot_aspect_with_frequency`函数对属性进行可视化,当前可通过参数`image_type`分别指定`wordcloud`和'histogram',通过词云和直方图的形式进行可视化。 ```python # define SentimentResult to process the result of sentiment result. sr = SentimentResult(args.file_path, sentiment_name=args.sentiment_name) # define VisualSentiment to help visualization vs = VisualSentiment(font_path=args.font_path) # visualization for aspect save_path = os.path.join(args.save_dir, "aspect_wc.png") vs.plot_aspect_with_frequency(sr.aspect_frequency, save_path, image_type="wordcloud") save_path = os.path.join(args.save_dir, "aspect_hist.png") vs.plot_aspect_with_frequency(sr.aspect_frequency, save_path, image_type="histogram") ```

**(2) 观点分析** 通过观点信息,可以查看客户对于产品/服务整体的直观印象。可以通过`plot_opinion_with_frequency`函数对观点进行可视化。 ```python # visualization for opinion save_path = os.path.join(args.save_dir, "opinion_wc.png") vs.plot_opinion_with_frequency(sr.opinion_frequency, save_path, image_type="wordcloud") ```

**(3) 属性+观点分析** 结合属性和观点两者信息,可以更加具体的展现客户对于产品/服务的详细观点,分析某个属性的优劣,从而能够帮助商家更有针对性地改善或提高自己的产品/服务质量。可以通过`plot_aspect_with_opinion`函数对属性+观点进行可视化,同时可通过设置参数`sentiment`按照情感倾向展示不同分析结果,以更好进行情感分析,若设置为`all`,则会展示正向和负向所有的属性;若为`positive`,则会仅展示正向的属性;若为`negative`,则会仅展示负向的属性。如果在绘制直方图时,通过设置参数`top_n`,可以展示频率最高的top n个属性。 ```python # visualization for aspect + opinion save_path = os.path.join(args.save_dir, "aspect_opinion_wc.png") vs.plot_aspect_with_opinion(sr.aspect_opinion, save_path, image_type="wordcloud", sentiment="all") save_path = os.path.join(args.save_dir, "aspect_opinion_hist.png") vs.plot_aspect_with_opinion(sr.aspect_opinion, save_path, image_type="histogram", sentiment="all", top_n=8) ```
**(4) 属性+情感分析** 挖掘客户对于产品/服务针对属性的情感极性,帮助商家直观地查看客户对于产品/服务的某些属性的印象。可以通过`plot_aspect_with_sentiment`函数对属性+情感进行可视化。如果在绘制直方图时,通过设置参数`top_n`,可以展示频率最高的top n个属性。 ```python # visualization for aspect + sentiment save_path = os.path.join(args.save_dir, "aspect_sentiment_wc.png") vs.plot_aspect_with_sentiment(sr.aspect_sentiment, save_path, image_type="wordcloud") save_path = os.path.join(args.save_dir, "aspect_sentiment_hist.png") vs.plot_aspect_with_sentiment(sr.aspect_sentiment, save_path, image_type="histogram", top_n=15, descend_aspects=sr.descend_aspects) ```
**(5) 对给定属性进行观点分析** 通过指定属性,更加细致查看客户对于产品/服务某个属性的观点。可以帮助商家更加细粒度地分析客户对于产品/服务的某个属性的印象。下面图片示例中,展示了客户对于属性"房间"的观点。可以通过`plot_opinion_with_aspect`函数,对给定的属性进行观点分析。默认情况下,不会自动生成该类图像,需要开发者手动调用`plot_opinion_with_aspect`进行可视化分析。 ```python aspect = "房间" save_path = os.path.join(args.save_dir, "opinions_for_aspect_wc.png") vs.plot_opinion_with_aspect(aspect, sr.aspect_opinion, save_path, image_type="wordcloud") save_path = os.path.join(args.save_dir, "opinions_for_aspect_hist.png") vs.plot_opinion_with_aspect(aspect, sr.aspect_opinion, save_path, image_type="histogram") ```
## **5. 更进一步:结合业务分析经验,定制情感分析** 考虑到用户在对业务数据进行情感分析时,往往聚焦于某个特定场景或领域,为满足用户更高的情感分析要求,本项目支持从以下方面协助用户,结合业务经验,进一步定制情感分析能力,提高模型对业务数据的理解和分析能力。 - 数据层面:打通 label-studio 平台,定制了情感信息的标注规则,支持根据标注数据自动转换为模型输入样本。 - 属性聚合:结合业务经验,支持传入同义的属性集合,可以增强模型对于数据聚合的能力。 - 隐性观点抽取:结合业务经验,支持自定义隐性观点词表,可以增强模型对于隐性观点的抽取能力。 下面以酒店场景为例,讲解定制酒店垂域的情感分析能力。具体地,将从数据标注及样本构建 - 模型训练 - 模型测试 - 模型预测及效果展示等全流程展开介绍。 ### **5.1 打通数据标注到训练样本构建** 本项目建议用户使用 label-studio 平台标注数据,同时提供了一套用于情感信息标注的规则,可以参考[情感分析任务Label Studio使用指南](./label_studio.md)获取更多信息,这里不再赘述。同时本项目打通了从 label-studio 标注平台到转换为模型输入形式数据的流程, 即支持用户在基于 label_studio 标注业务侧数据后,通过label-studio 导出标注好的json数据, 然后利用本项目提供的 `label_studio.py` 脚本,可以将导出数据一键转换为模型训练数据。 在利用 `label_studio.py` 脚本进行数据转换时,需要考虑任务类型的不同,选择相应的样本构建方式,整体可以分为 `分类` 和 `抽取` 任务。
为方便用户使用,本项目提供了300+条酒店场景的标注数据,可点击[这里](https://paddlenlp.bj.bcebos.com/datasets/sentiment_analysis/hotel/label_studio.tar.gz)进行下载,请注意该数据仅适合用于 `抽取` 类型的任务。 #### **5.1.1 样本构建:语句级情感分类任务** 对于语句级情感分类任务,默认支持2分类:``正向`` 和 ``负向``,可以通过如下命令构造相关训练数据。 ```shell python label_studio.py \ --label_studio_file ./data/label_studio.json \ --task_type cls \ --save_dir ./data \ --splits 0.8 0.1 0.1 \ --options "正向" "负向" \ --is_shuffle True \ --seed 1000 ``` 参数介绍: - ``label_studio_file``: 从label studio导出的语句级情感分类的数据标注文件。 - ``task_type``: 选择任务类型,可选有抽取和分类两种类型的任务,其中前者需要设置为``ext``,后者需要设置为``cls``。由于此处为语句级情感分类任务,因此需要设置为``cls``。 - ``save_dir``: 训练数据的保存目录,默认存储在``data``目录下。 - ``splits``: 划分数据集时训练集、验证集所占的比例。默认为[0.8, 0.1, 0.1]表示按照``8:1:1``的比例将数据划分为训练集、验证集和测试集。 - ``options``: 情感极性分类任务的选项设置。对于语句级情感分类任务,默认支持2分类:``正向`` 和 ``负向``;对于属性级情感分析任务,默认支持3分类:``正向``, ``负向``和 ``未提及``,其中``未提及``表示要分析的属性在原文本评论中未提及,因此无法分析情感极性。如果业务需要其他情感极性选项,可以通过``options``字段进行设置,需要注意的是,如果定制了``options``,参数``label_studio_file``指定的文件需要包含针对新设置的选项的标注数据。 - ``is_shuffle``: 是否对数据集进行随机打散,默认为True。 - ``seed``: 随机种子,默认为1000. **备注**:参数``options``可以不进行手动指定,如果这么做,则采用默认的设置。针对语句级情感分类任务,其默认将被设置为:``"正向" "负向"``;对于属性级情感分析任务,默认将被设置为:``"正向" "负向" "未提及"``。 #### **5.1.2 样本构建:属性抽取相关任务** 针对抽取式的任务,比如属性-观点抽取、属性-情感极性-观点词抽取、属性分类任务等,可以使用如下命令将label-studio导出数据转换为模型训练数据。 ```shell python label_studio.py \ --label_studio_file ./data/label_studio.json \ --task_type ext \ --save_dir ./data \ --splits 0.8 0.1 0.1 \ --options "正向" "负向" "未提及" \ --negative_ratio 5 \ --is_shuffle True \ --seed 1000 ``` 重点参数介绍: - ``label_studio_file``: 从label studio导出的属性抽取相关的数据标注文件。 - ``task_type``: 选择任务类型,可选有抽取和分类两种类型的任务,其中前者需要设置为``ext``,后者需要设置为``cls``。由于此处为属性抽取相关任务,因此需要设置为``ext``。 - ``negative_ratio``表示对于一个样本,为每个子任务(属性级的观点抽取,属性级的情感分类)最多生成``negative_ratio``个负样本。如果额外提供了属性同义词标或隐性观点抽取词表,将结合两者信息生成更多的负样本,以增强属性聚合和隐性观点抽取能力。 其他参数解释同上,这里不再赘述。 #### **5.1.3 样本构建升级1:加强属性聚合能力** 在用户对产品或服务进行评论时,对某一些属性可能会有不同的说法,这会在后续对属性分析时可能会带来困扰。如以下示例中的"价格","价钱"和"费用"。 ``` 蛋糕味道不错,外观很漂亮,而且价格比较便宜 蛋糕味道不错,外观很漂亮,而且价钱比较便宜 蛋糕味道不错,外观很漂亮,而且费用比较便宜 ``` 针对这种情况,针对属性相关任务,本项目同时支持用户结合业务经验,通过设置同义的属性词表,加强模型的属性聚合能力。具体来讲,本项目期望通过以下两点,支持对属性聚合能力的建设。 - 支持针对用户给定的属性进行情感分析 - 支持用户提供同义的属性词表,用以加强模型对用户领域属性同义词的理解能力 以下给出了酒店场景的示例,每行代表1类同义词,不同词之间以"空格"隔开。 ``` 房间 屋子 房子 位置 地理位置 隔音 隔声 价格 价钱 费用 ``` 可以通过以下命令,使用synonym_file指定凝聚业务经验的同义属性集合,利用同义属性生成对应的数据样本: ```shell python label_studio.py \ --label_studio_file ./data/label_studio.json \ --synonym_file ./data/synonyms.txt \ --task_type ext \ --save_dir ./data \ --splits 0.8 0.1 0.1 \ --options "正向" "负向" "未提及" \ --negative_ratio 5 \ --is_shuffle True \ --seed 1000 ``` #### **5.1.4 样本构建升级2:加强隐性观点抽取能力** 另外,本项目同时支持加强对隐性观点功能抽取的能力,这里需要说明一点,本项目中定义隐性观点是指没有对应属性的纯观点词,如以下示例中的"比较便宜"便是隐性观点。 ``` 蛋糕味道不错,外观很漂亮,而且比较便宜 ``` 本项目支持用户提供一个隐性观点映射文件,用户可以根据自己的业务场景定义隐性观点词,以下给出了酒店场景的示例。其格式为,第1个单词为隐性观点对应的属性,后续按照情感情感倾向对隐性观点词进行了归类,同一类的以"[ ]"方式放到一块。 ``` 价格, 正向[实惠 便宜 超划算 划算 物超所值 物有所值 不贵], 负向[贵 不便宜 不划算] 卫生, 正向[干净], 负向[很脏 很臭 不干净] 隔音, 负向[好吵] 位置, 负向[不太好找] ``` 可以通过参数"implicit_file"指定凝聚业务经验的隐性观点词表,生成对应的隐性观点数据样本: ```shell python label_studio.py \ --label_studio_file ./data/label_studio.json \ --implicit_file ./data/implicit_opinions.txt \ --task_type ext \ --save_dir ./data \ --splits 0.8 0.1 0.1 \ --options "正向" "负向" "未提及" \ --negative_ratio 5 \ --is_shuffle True \ --seed 1000 ``` ### **5.2 模型训练** 在生成酒店场景的训练数据后,可以通过以下命令启动模型训练: ```shell python -u -m paddle.distributed.launch --gpus "0" finetune.py \ --train_path ./data/train.json \ --dev_path ./data/dev.json \ --save_dir ./checkpoint \ --learning_rate 1e-5 \ --batch_size 16 \ --max_seq_len 512 \ --num_epochs 3 \ --model uie-senta-base \ --seed 1000 \ --logging_steps 10 \ --valid_steps 100 \ --device gpu ``` 可配置参数说明: * ``train_path``:必须,训练集文件路径。 * ``dev_path``:必须,验证集文件路径。 * ``save_dir``:模型 checkpoints 的保存目录,默认为"./checkpoint"。 * ``learning_rate``:训练最大学习率,UIE 推荐设置为 1e-5;默认值为1e-5。 * ``batch_size``:训练集训练过程批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为 16。 * ``max_seq_len``:模型支持处理的最大序列长度,默认为512。 * ``num_epochs``:模型训练的轮次,可以视任务情况进行调整,默认为10。 * ``model``:训练使用的预训练模型。可选择的有`uie-senta-base`, `uie-senta-medium`, `uie-senta-mini`, `uie-senta-micro`, `uie-senta-nano`,默认为`uie-senta-base`。 * ``logging_steps``: 训练过程中日志打印的间隔 steps 数,默认10。 * ``valid_steps``: 训练过程中模型评估的间隔 steps 数,默认100。 * ``seed``:全局随机种子,默认为 42。 * ``device``: 训练设备,可选择 'cpu'、'gpu' 其中的一种;默认为 GPU 训练。 ### **5.3 模型测试** 通过运行以下命令进行对酒店场景的测试集进行评估: ``` python evaluate.py \ --model_path ./checkpoint/model_best \ --test_path ./data/test.json \ --batch_size 16 \ --max_seq_len 512 ``` 可配置参数说明: * ``model_path``:必须,进行评估的模型文件夹路径,路径下需包含模型权重文件model_state.pdparams及配置文件model_config.json。 * ``test_path``:必须,进行评估的测试集文件。 * ``batch_size``:训练集训练过程批处理大小,请结合显存情况进行调整,若出现显存不足,请适当调低这一参数;默认为 16。 * ``max_seq_len``:文本最大切分长度,输入超过最大长度时会对输入文本进行自动切分,默认为512。 * ``debug``: 是否开启debug模式对每个正例类别分别进行评估,该模式仅用于模型调试,默认关闭。 在构造样本过程中,如果设置了最大负例比例negative_ratio,会在样本中添加一定数量的负样本,模型测试默认会对正样本和负样本共同进行评估。特别地,当开启debug模式后,会对每个正例类别分别进行评估,该模式仅用于模型调试: ``` python evaluate.py \ --model_path ./checkpoint/model_best \ --test_path ./data/test.json \ --batch_size 16 \ --max_seq_len 512 \ --debug ``` 输出打印示例: ``` [2022-12-12 05:20:06,152] [ INFO] - ----------------------------- [2022-12-12 05:20:06,152] [ INFO] - Class Name: 评价维度 [2022-12-12 05:20:06,152] [ INFO] - Evaluation Precision: 0.89655 | Recall: 0.89655 | F1: 0.89655 [2022-12-12 05:20:06,553] [ INFO] - ----------------------------- [2022-12-12 05:20:06,553] [ INFO] - Class Name: 观点词 [2022-12-12 05:20:06,553] [ INFO] - Evaluation Precision: 0.81159 | Recall: 0.86154 | F1: 0.83582 [2022-12-12 05:20:07,610] [ INFO] - ----------------------------- [2022-12-12 05:20:07,611] [ INFO] - Class Name: X的观点词 [2022-12-12 05:20:07,611] [ INFO] - Evaluation Precision: 0.92222 | Recall: 0.90217 | F1: 0.91209 [2022-12-12 05:20:08,331] [ INFO] - ----------------------------- [2022-12-12 05:20:08,331] [ INFO] - Class Name: X的情感倾向[未提及,正向,负向] [2022-12-12 05:20:08,331] [ INFO] - Evaluation Precision: 0.81481 | Recall: 0.81481 | F1: 0.81481 ``` ### **5.4 模型预测及效果展示** #### **5.4.1 使用训练后的模型进行预测** paddlenlp.Taskflow装载定制模型,通过task_path指定模型权重文件的路径,路径下需要包含训练好的模型权重文件model_state.pdparams。 ```python >>> # define schema >>> schema = [{'评价维度': ['观点词', '情感倾向[正向,负向,未提及]']}] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema, task_path="./checkpoint/model_best") >>> senta("这家点的房间很大,店家服务也很热情,就是房间隔音不好") [ { '评价维度': [ { 'text': '服务', 'start': 11, 'end': 13, 'probability': 0.9600759151746807, 'relations': { '观点词': [ { 'text': '热情', 'start': 15, 'end': 17, 'probability': 0.9995151134519027 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '正向', 'probability': 0.9998306104766073 } ] } }, { 'text': '隔音', 'start': 22, 'end': 24, 'probability': 0.9993525950520166, 'relations': { '观点词': [ { 'text': '不好', 'start': 24, 'end': 26, 'probability': 0.9992370362201655 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '负向', 'probability': 0.9842680108546062 } ] } }, { 'text': '房间', 'start': 4, 'end': 6, 'probability': 0.9991784415865368, 'relations': { '观点词': [ { 'text': '很大', 'start': 6, 'end': 8, 'probability': 0.8359714693985723 } ], '情感倾向[正向,负向,未提及]': [ { 'text': '正向', 'probability': 0.997688853839179 } ] } } ] } ] ``` #### **5.4.2 属性聚合预测和分析** 下面就 `隔音` 与 `价格` 两个属性进行分析,抽取样本中与这两个属性相关的情感信息,代码如下: ```python >>> schema = [{'评价维度': ['观点词', '情感倾向[正向,负向,未提及]']}] >>> aspects = ["隔音", "价格"] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema, task_path="./checkpoint/model_best", aspects=aspects) >>> senta("这家点的房间很大,店家服务也很热情,就是房间隔音不好") ``` 下图展示了关于模型对于属性聚合能力支持的样本,在分析之前设定固定的属性集合`["隔音", "价格"]`,可以看到尽管语料中同时出现了`隔音`、`隔声`、`价格`、`价钱`和`费用`,但是经过定制后的情感分析模型依然能够准确识别出对于属性 `隔音` 和 `价格`的情感信息,从而起到属性聚合的效果。 | 样本 | 属性 | 观点词 | 情感倾向 | | :----: |:----: |:----: |:----: | |这家店的房间很大,隔音效果不错,而且价格很便宜|隔音|不错|正向| |房间比较小,隔声也不太好,设施还是挺齐全的|隔音|不太好|负向| |房间还不错,有免费的矿泉水,而且价格很实惠|价格|实惠|正向| |房间很大,店家也挺热情,很棒,就是价钱有点贵|价格|贵|负向| |酒店不错,房间面积大,住的也舒适,而且价格很划算|价格|划算|正向| |房间好大呀,而且这边还挺安静的,不过整体还是很好的,很宽敞,而且价格很便宜|价格|便宜|正向| #### **5.4.3 隐性观点词抽取预测和分析** 下面就`价格` 和 `卫生` 两个属性进行分析隐性观点,抽取样本中与这两个属性相关的情感信息,代码如下: 对于"价格"的调用示例: ```python >>> schema = [{'评价维度': ['观点词', '情感倾向[正向,负向,未提及]']}] >>> aspects = ["价格"] >>> senta = Taskflow("sentiment_analysis", model="uie-senta-base", schema=schema, task_path="./checkpoint/model_best", aspects=aspects) >>> senta("这家店的房间很大,店家服务也很热情,而且很便宜") ``` 下图展示了关于模型对于隐性观点抽取的样本,可以看到,虽然以下这些样本中,并未出现`价格` 和 `卫生`,但模型依然正确识别除了这两个属性的情感信息。 | 样本 | 属性 | 观点词 | 情感倾向 | | :----: |:----: |:----: |:----: | |房间比较大,就是感觉贵了点,不太划算|价格|贵、不太划算|负向| |这家店的房间很大,店家服务也很热情,而且很便宜|价格|便宜|正向| |这次来荆州给我的房间小的无语了,所幸比较实惠|价格|实惠|正向| |酒店不大,有点不干净|卫生|不干净|负向| |老板人很好,房间虽然很大,但有点脏|卫生|脏|负向| |房间不大,很温暖,也很干净|卫生|干净|正向| ## **6. 模型部署** ### **6.1 基于SimpleServer进行服务化部署** 本项目支持基于PaddleNLP SimpleServing进行服务化部署,可以在`deploy`目录下执行以下命令启动服务和请求。 **启动服务** ``` paddlenlp server server:app --workers 1 --host 0.0.0.0 --port 8189 ``` **Client发送请求** 服务启动后, 通过 `client.py` 脚本发送请求: ``` python client.py ``` **多卡服务化预测** PaddleNLP SimpleServing 支持多卡负载均衡预测,主要在服务化注册的时候,注册两个Taskflow的task即可,代码示例如下: ```python senta1 = Taskflow("sentiment_analysis", schema=schema, model="uie-senta-base", device_id=0) senta2 = Taskflow("sentiment_analysis", schema=schema, model="uie-senta-base", device_id=1) app.register_taskflow('senta', [senta1, senta2]) ``` ### **6.2 基于Pipeline进行部署** 本项目支持基于Pipeline的方式进行部署,用户只需要上传测试文件,即可获取对应的情感分析可视化结果,更多信息请参考[情感分析Pipeline](https://github.com/PaddlePaddle/PaddleNLP/tree/develop/pipelines/examples/sentiment_analysis)。