用深度学习进行情感分析
如何训练你自己的高性能情感分析模型
照片:Pietro JengonUnsplash
目标
情感分析是自然语言处理中的一种技术,用于识别与文本相关的情感。情感分析的常见用例包括监测客户在社交媒体上的反馈、品牌和活动监测。
在本文中,我们将研究如何利用预先训练好的 HuggingFace 模型,在自定义数据集上训练自己的情感分析模型。我们还将研究如何在 CPU 和 GPU 环境中对微调后的模型有效地进行单一和批量预测。如果你正在寻找一个开箱即用的情感分析模型,请查看我之前的文章:如何在python中仅用3行代码进行情感分析。
安装
pip install transformers
导入软件包
import numpy as np
启用GPU加速器(如果有的话)。
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
数据准备
我们将使用一个电子商务数据集,其中包含女性服装的文本评论和评级。
df = pd.read_csv('/kaggle/input/womens-ecommerce-clothing-reviews/Womens Clothing E-Commerce Reviews.csv')
我们只对评论文本和评价列感兴趣。评论文本列作为模型的输入变量,评级列是我们的目标变量,它的值范围是1(最不喜欢)到5(最喜欢)。
为了清楚起见,让我们在每个整数等级后面加上 "星 "或 "星"。
df_reviews = df.loc[:, ['Review Text', 'Rating']].dropna()
这就是数据现在的样子,其中1,2,3,4,5星是我们的类标签。
让我们用Sklearn的LabelEncoder对评分进行编码。
le = LabelEncoder()
请注意,Rating列已经从文本转化为整数列了。
评级列中的数字范围从0到4。这些是类标签的类ID,将用于训练模型。每一个类的ID都对应着一个评级。
print (le.classes_)
>> ['1 Star' '2 Stars' '3 Stars' **'4 Stars'** '5 Stars']
列表中的位置索引是班级ID(0到4),位置上的值是原始评级。例如,在3号位置,类的ID是 "3",它对应的类标签是 "4星"。
让我们把数据按80%、10%和10%的比例分成训练、验证和测试。
(train_texts, train_labels,
将评论文本从pandas系列转换为句子列表。
train_texts = train_texts['Review Text'].to_list()
创建一个DataLoader类,用于在训练和推理阶段处理和加载数据。
class DataLoader(torch.utils.data.Dataset):
def __len__(self):
让我们来看看DataLoader的运行情况。
train_dataset = DataLoader(train_texts, train_labels)
DataLoader初始化了一个预训练的标记器并对输入的句子进行编码。我们可以通过使用__getitem__函数从DataLoader获得一条记录。下面是一个输入句子被标记化后的结果。
print (train_dataset.__getitem__(0))
输出的数据是一个由3个键值对组成的字典
- input_ids:它包含一个整数张量,每个整数代表原句中的单词。标记化步骤已经将单个单词转化为由整数代表的标记。第一个标记101是句子的开始标记,102标记是句子的结束标记。请注意,有许多尾部的零,这是由于在标记化步骤中对句子进行了填充。
- Attention_mask:这是一个二进制值的数组。Attention_mask的每个位置都对应于input_ids中相同位置的一个标记。1表示给定位置的标记应该被关注,0表示给定位置的标记是一个填充值。
- labels:这是目标标签
定义评价指标
我们希望在训练阶段每隔一段时间就对模型的性能进行评估。为此,我们需要一个指标计算函数,接受一个(预测,标签)的元组作为参数,并返回一个指标字典。{'metric1':value1,metric2:value2}。
f1 = datasets.load_metric('f1')
def compute_metrics(eval_pred):
return metrics_dict
训练
接下来,我们从预训练的检查点配置实例化的distilbert-base-uncased模型。
id2label = {idx:label for idx, label in enumerate(le.classes_)}
config = AutoConfig.from_pretrained('distilbert-base-uncased',
model = AutoModelForSequenceClassification.from_config(config)
- num_labels: 类的数量
- id2label:将类的id映射到类的标签的字典{0: '1星', 1: '2星', 2: '3星', 3: '4星', 4: '5星'}。
- label2id:映射字典,将班级标签映射到班级ID {'1星':0, '2星':1, '3星': 2, '4星':3, '5星':4}
我们来看看模型的配置。id2label和label2id字典已经被纳入配置中。我们可以在推理过程中从模型的配置中检索这些字典,以找出预测的类ID对应的类标签。
print (config)
>> DistilBertConfig {
我们还可以通过以下方式检查模型的架构
print (model)
设置训练参数。
training_args = TrainingArguments(
- report_to可以将训练工件和结果记录到mlflow、tensorboard、azure_ml等平台。
- per_device_train_batch_size是训练期间每个TPU/GPU/CPU的批次大小。如果你的设备上面临内存不足的问题,可以降低这个数值。
- per_device_eval_batch_size是评估时每个TPU/GPU/CPU的批量大小。如果你的设备面临内存不足的问题,请降低这个数值。
- logging_step决定了在训练期间进行指标评估的频率。
实例化训练器。在引擎盖下,训练器根据给定的训练参数、模型、数据集和度量标准运行训练和评估循环。
trainer = Trainer(
让我们开始训练吧
trainer.train()
评估是每50步进行一次。我们可以通过改变TrainingArguments中的logging_steps参数来改变评估的间隔时间。除了默认的训练和验证损失指标外,我们还得到了额外的指标,这些指标是我们在前面的compute_metric函数中定义的。
评估
让我们在测试集上评估我们的训练。
eval_results = trainer.predict(test_dataset)
训练器的预测函数返回3个项目。
- 一个原始预测分数的数组
print (test_results.predictions)
2.地面真实标签ID
print (test_results.label_ids)
3.衡量标准
print (test_results.metrics)
模型预测功能输出非标准化的概率分数。为了找到类的概率,我们在未归一化的分数中取一个softmax。具有最高类别概率的类别被认为是预测的类别。我们可以通过获取类别概率的argmax来找到这个概率。我们先前存储在模型配置中的id2label属性可以用来将类的id(0-4)映射到类的标签(1星,2星...)。
label2id_mapper = model.config.id2label
我们使用Sklearn的classification_report来获得精度、召回率、f1和准确率的分数。
class_report = classification_report(actual, pred, output_dict = True)
保存模型
trainer.save_model('/kaggle/working/sentiment_model')
推理
在这一节中,我们看一下如何加载和执行对训练好的模型的预测。让我们在一个单独的笔记本中测试一下推理。
设置
import pandas as pd
推理可以在GPU或CPU环境下工作。如果你的环境中有GPU,请启用它。
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")
这与我们在训练阶段使用的DataLoader相同。
class DataLoader(torch.utils.data.Dataset):
def __len__(self):
创建一个模型类
SentimentModel类有助于初始化模型,并包含predict_proba和batch_predict_proba方法,分别用于单一和批量预测。batch_predict_proba使用HuggingFace的Trainer来执行批量评分。
class SentimentModel():
return proba
return proba
数据准备
让我们加载一些样本数据
df = pd.read_csv('/kaggle/input/womens-ecommerce-clothing-reviews/Womens Clothing E-Commerce Reviews.csv')
我们将创建两组数据。一个用于批量评分,另一个用于单次评分。
batch_sentences = df_reviews.sample(n = 10000, random_state = 1)['Review Text'].to_list()
预测
实例化模型
sentiment_model = SentimentModel('../input/fine-tune-huggingface-sentiment-analysis/sentiment_model')
使用predict_proba方法对一个单句进行预测。
single_sentence_probas = sentiment_model.predict_proba(single_sentence)
print (predicted_class_label)
使用batch_predict_proba方法对一批句子进行预测。
batch_sentence_probas = sentiment_model.batch_predict_proba(batch_sentences)
推理的速度
让我们比较一下predict_proba和batch_predict_proba方法的推理速度
在CPU和GPU环境下的10k个样本数据的推理速度。我们将对predict_proba的10k个样本进行迭代,每次只做一个预测,而使用batch_predict_proa的方法则不需要迭代就能得到所有10k个样本的分数。
%%time
%%time
GPU环境
迭代predict_proba需要约2分钟,而batch_predict_proba对10k样本数据需要约30秒。批量预测比在GPU环境下使用单一预测快了近4倍。
CPU环境
在CPU环境下,predict_proba花了14分钟,而batch_predict_proba花了40分钟,这几乎是3倍长。
因此,对于大型数据集,如果你有GPU,请使用batch_predict_proba。如果你没有GPU,你最好使用predict_proba对数据集进行迭代。
总结
在这篇文章中,我们研究了。
- 如何利用预训练的HuggingFace模型来训练自己的深度学习情感分析模型
- 如何创建用于评分的单次和批量预测方法
- 在CPU和GPU环境下,单次和批量评分的推理速度
这篇文章的笔记本可以在这里找到。
How To Train A Deep Learning Sentiment Analysis Model最初发表于Towards Data Scienceon Medium,人们通过强调和回应这个故事继续对话。