实验室抓取了数百万条外网评论,主要以脸书和推特为主,其中有一个环节需要分析评论情感,并且尽可能做到情感细分,而不是积极、消极、中性的简单分类。
考虑到快速开箱即用的需求,模型尽量不要太复杂,预训练模型直接跑,看下结果如何再考虑下游fine tune当然是不二之选。但是还需要注重准确性,早期的模型或者传统机器学习工具包不够高大上,那还说啥,上bert。
实验室其他同学已经将十多种语言的评论翻成了英语,并且翻译质量较高,直接选取英文预训练的分析模型,roberta太大,选取蒸馏过的distilroberta较为合适。
大致流程:数据清洗 ——> 调包 ——> 生成结果 ——> 分析效果
这是大致的数据格式,最后一列是翻译后的结果,我们主要以这一列作为分析目标,最后结果还需要添加原有的三度情感分析进行比较。
数据主要是北京冬奥会相关推文评论与转发内容。
import pandas as pd
import numpy as np
import re
import emoji
import collections
from transformers import pipeline
classifier = pipeline("text-classification", model="j-hartmann/emotion-english-distilroberta-base")
初次运行会自动连网下载,有同学可能因为网络问题下载失败,我个人有两个方式:
1:huggingface其实没有被墙,一般而言不用挂梯子,dns污染的可能性比较大,可以尝试修改host为指定ip
2:手动下载并指定路径,可以搜一下指定路径的方式,这里不多赘述
data = pd.read_csv('Untitled.csv')
pd.set_option('display.max_colwidth',200) # 设置notebook中展示宽度
给我的数据是20000整,做个demo看看效果,但在这里有一个大坑,translation_sentence数据有时是空的,这20000条中有9条为NAN,在数据清洗时总是报奇怪的错误,花费了不少时间debug。
# translation_sentence存在空数据
# 剔除nan数据,否则报错
nan_list = [index for index,i in enumerate(data['translation_sentence']) if type(i)!=type(' ') ]
data = data.drop(nan_list, axis=0)
# 展示处理后的前二十条数据
data['translation_sentence'][:20]
可以看到评论中存在网址、@用户、表情等脏数据,后续其实还有特殊符号、部分中文、韩文、日文等其他语言,数据清洗时需要剔除。
# 数据清洗
def sentence_remove(tweet):
# 为了直观展示,这里分步处理,实际使用过程中建议合并
r = "[_.!+-=——,$%^,。?、~@#¥%……&*《》<>「」“”‘’(){}【】□‡()//\\\[\]\"]"
tweet = emoji.replace_emoji(tweet, replace=' ') # 删除emoji
tweet = re.sub(r'[http|https]*://[a-zA-Z0-9.?/&=:]*', ' ', tweet) # 删除网址
tweet = re.sub(r'@\S+', ' ', tweet) # 删除 @用户
tweet = re.sub(r, ' ', tweet) # 删除特殊符号
tweet = re.sub(r'\s+', ' ', tweet) # 删除多余空格换行符
# 删除 中日韩 三语
tweet = re.sub('[\u4e00-\u9fa5\uac00-\ud7ff\u3040-\u309f\u30a0-\u30ff]', '', tweet)
return tweet
translation_sentence= data['translation_sentence'].apply(sentence_remove).tolist()
清洗完毕后转换为python的list格式,方便传入分类器进行分类
translation_sentence[:20]
看一眼清洗后的数据,其实还可以设置部分停用词,但是这里时间原因暂未考虑,有余力的小伙伴可以试试效果如何。
# 数据清洗后的句子传入分类器
results=classifier(translation_sentence)
# 提取结果中的情感标签
bert_sentiment=[i['label'] for i in results]
其中results长这样,我们还可以再classifier中设置返回全部评分结果,获取多个可能的情感值
我们评估的结果文档需要包含以下四部分内容:
# 未进行清洗的评论
raw_sentence= data['translation_sentence'].tolist()
# translation_sentence 清洗后的评论
# 其他方式得到的三度情感判别
ori_sentiment= data['sentiment'].tolist()
# bert_sentiment 采用该模型得到的情感标签
设置生成文档的格式及内容
# 表头名称
head = ['raw_sentence', 'processed_en_sentence','ori_sentiment','bert_sentiment']
# 详细数据
Data = [raw_sentence,translation_sentence,ori_sentiment,bert_sentiment]
整合并保存
Data = np.transpose(Data) #数据行列互换
test = pd.DataFrame(columns=head, data=Data)
test.to_csv('distilroberta_sentiment_20000.csv') #将列表中的数据输出
大概观察了一下,除了fear标签,其余标签的分类结果比原结果要好很多,某些评论会被标记为fear的原因个人认为有两个:
1、XX与XX即将进行比赛、竞争类型的评论,会被划定为fear,可能是取的担忧的意思,而不是“恐惧害怕”。
2、因为数据集的倾向性明显,主题围绕冬奥会赛事,但是模型是根据日常语料进行训练的,泛化性再强也会出现偏差。例如“比赛”、“竞争”之类的话语归结为担忧的情况,可以通过下游训练改善。
四、代码及数据集
老规矩,全部打包放在这里啦,对大家有帮助还请多多点赞收藏关注,日后还会更新更多的小demo及其他分享哦
链接:https://pan.baidu.com/s/1PTOKAU3bW9qAan6N58i3nw
提取码:8cef