1. BERT 模型概述
BERT(Bidirectional Encoder Representations from Transformers)是一个预训练的语言表示模型,可以应用于多种自然语言处理任务,包括对话情绪识别。BERT 通过双向 Transformer 编码器,能同时考虑句子中每个词的前后文信息,从而生成更为丰富的语义表示。
BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型。与BERT模型相似的预训练语言模型例如问答、命名实体识别、自然语言推理、文本分类等在许多自然语言处理任务中发挥着重要作用。模型是基于Transformer中的Encoder并加上双向的结构,因此一定要熟练掌握Transformer的Encoder的结构。
BERT模型的主要创新点都在pre-train方法上,即用了Masked Language Model和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。
在用Masked Language Model方法训练BERT的时候,随机把语料库中15%的单词做Mask操作。对于这15%的单词做Mask操作分为三种情况:80%的单词直接用[Mask]替换、10%的单词直接替换成另一个新的单词、10%的单词保持不变。
因为涉及到Question Answering (QA) 和 Natural Language Inference (NLI)之类的任务,增加了Next Sentence Prediction预训练任务,目的是让模型理解两个句子之间的联系。与Masked Language Model任务相比,Next Sentence Prediction更简单些,训练的输入是句子A和B,B有一半的几率是A的下一句,输入这两个句子,BERT模型预测B是不是A的下一句。
BERT预训练之后,会保存它的Embedding table和12层Transformer权重(BERT-BASE)或24层Transformer权重(BERT-LARGE)。使用预训练好的BERT模型可以对下游任务进行Fine-tuning,比如:文本分类、相似度判断、阅读理解等。
对话情绪识别(Emotion Detection,简称EmoTect),专注于识别智能对话场景中用户的情绪,针对智能对话场景中的用户文本,自动判断该文本的情绪类别并给出相应的置信度,情绪类型分为积极、消极、中性。 对话情绪识别适用于聊天、客服等多个场景,能够帮助企业更好地把握对话质量、改善产品的用户交互体验,也能分析客服服务质量、降低人工质检成本。
2. 数据预处理
在进行对话情绪识别之前,需要对数据进行预处理,包括:
- 数据清洗:去除特殊字符、空白符等无关内容。
- 分词:将句子拆分为词或子词,可以使用 BERT 的分词器。
- 标注情感标签:为每个对话句子标注情感类别。
3. BERT 模型架构
BERT 的架构包括多个 Transformer 层,每层包括一个多头自注意力机制和一个前馈神经网络。具体步骤如下:
- 输入嵌入层:将输入的词转换为词向量,并加上位置编码。
- Transformer 编码器:经过多个自注意力机制和前馈网络,生成上下文敏感的词表示。
- 输出层:取 [CLS] 标记的输出向量作为整个句子的表示,并通过一个全连接层和 softmax 层进行分类。
4. 模型训练
模型训练过程包括以下步骤:
- 定义损失函数:使用交叉熵损失函数来衡量预测结果和实际情感标签之间的差异。
- 优化算法:使用优化算法(如 Adam)调整模型参数以最小化损失函数。
- 训练过程:迭代地将数据输入模型,计算损失并反向传播误差,更新模型参数。
5. 模型评估
使用验证集或测试集评估模型的性能,常用的评估指标包括准确率、精确率、召回率和 F1 分数。
6. MindSpore 实现
在 MindSpore 中实现 BERT 对话情绪识别的主要步骤包括:
import mindspore as ms
import mindspore.nn as nn
from mindspore import context, Tensor
from mindspore.train import Model
from mindspore.train.callback import LossMonitor
from mindspore.dataset import GeneratorDataset
from transformers import BertTokenizer, BertForSequenceClassification
# 设置执行环境
context.set_context(mode=context.GRAPH_MODE, device_target="CPU")
# 加载预训练的 BERT 模型和分词器
tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertForSequenceClassification.from_pretrained('bert-base-uncased', num_labels=2)
# 数据预处理函数
def preprocess_data(texts, labels, tokenizer):
inputs = tokenizer(texts, return_tensors="ms", padding=True, truncation=True, max_length=128)
inputs['labels'] = Tensor(labels, dtype=ms.int32)
return inputs
# 自定义数据集
class MyDataset:
def __init__(self, texts, labels, tokenizer):
self.data = preprocess_data(texts, labels, tokenizer)
def __getitem__(self, index):
return {k: v[index] for k, v in self.data.items()}
def __len__(self):
return len(self.data['input_ids'])
# 创建数据集
texts = ["I love this!", "I hate this!"]
labels = [1, 0]
dataset = GeneratorDataset(MyDataset(texts, labels, tokenizer), column_names=['input_ids', 'attention_mask', 'labels'])
# 定义损失函数和优化器
loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')
optimizer = nn.Adam(model.trainable_params(), learning_rate=1e-5)
# 创建训练模型
train_model = Model(model, loss_fn=loss_fn, optimizer=optimizer, metrics={'accuracy'})
# 训练模型
train_model.train(1, dataset, callbacks=[LossMonitor()])
# 模型评估
eval_result = train_model.eval(dataset)
print("Evaluation result:", eval_result)
7. 模型预测
训练完成后,可以使用模型进行对话情绪预测:
def predict(text, label=None):
label_map = {0: "消极", 1: "中性", 2: "积极"}
text_tokenized = Tensor([tokenizer(text).input_ids])
logits = model(text_tokenized)
predict_label = logits[0].asnumpy().argmax()
info = f"inputs: '{text}', predict: '{label_map[predict_label]}'"
if label is not None:
info += f" , label: '{label_map[label]}'"
print(info)
from mindspore import Tensor
for label, text in dataset_infer:
predict(text, label)