当前位置:   article > 正文

《昇思25天学习打卡营第21天|基于 MindSpore 实现 BERT 对话情绪识别》

《昇思25天学习打卡营第21天|基于 MindSpore 实现 BERT 对话情绪识别》

#学习打卡第21天#

1. BERT 模型

        BERT全称是来自变换器的双向编码器表征量(Bidirectional Encoder Representations from Transformers),它是Google于2018年末开发并发布的一种新型语言模型,是基于Transformer中的Encoder并加上双向的结构。

        BERT模型的主要创新点都在pre-train方法上,即用了Masked Language Model和Next Sentence Prediction两种方法分别捕捉词语和句子级别的representation。

        1. 在用Masked Language Model方法训练BERT的时候,随机把语料库中15%的单词做Mask操作。对于这15%的单词做Mask操作分为三种情况:80%的单词直接用[Mask]替换、10%的单词直接替换成另一个新的单词、10%的单词保持不变。

        2. 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,比如:文本分类、相似度判断、阅读理解等。

2. 情绪识别

        情绪识别(Emotion Detection,简称EmoTect),专注于识别智能对话场景中用户的情绪,针对智能对话场景中的用户文本,自动判断该文本的情绪类别并给出相应的置信度,情绪类型分为积极、消极、中性。 对话情绪识别适用于聊天、客服等多个场景,能够帮助企业更好地把握对话质量、改善产品的用户交互体验,也能分析客服服务质量、降低人工质检成本。

3. 案例搭建

3.1 数据集

        采用来自于百度飞桨团队,一份已标注的、经过分词预处理的机器人聊天数据集。数据由两列组成,以制表符('\t')分隔,第一列是情绪分类的类别(0表示消极;1表示中性;2表示积极),第二列是以空格分词的中文文本,如下示例,文件为 utf8 编码。

  1. # download dataset
  2. !wget https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz -O emotion_detection.tar.gz
  3. !tar xvf emotion_detection.tar.gz

数据预处理

  1. import os
  2. import numpy as np
  3. import mindspore
  4. from mindspore.dataset import text, GeneratorDataset, transforms
  5. from mindspore import nn, context
  6. from mindnlp._legacy.engine import Trainer, Evaluator
  7. from mindnlp._legacy.engine.callbacks import CheckpointCallback, BestModelCallback
  8. from mindnlp._legacy.metrics import Accuracy
  9. from mindnlp.transformers import BertTokenizer
  10. # prepare dataset
  11. class SentimentDataset:
  12. """Sentiment Dataset"""
  13. def __init__(self, path):
  14. self.path = path
  15. self._labels, self._text_a = [], []
  16. self._load()
  17. def _load(self):
  18. with open(self.path, "r", encoding="utf-8") as f:
  19. dataset = f.read()
  20. lines = dataset.split("\n")
  21. for line in lines[1:-1]:
  22. label, text_a = line.split("\t")
  23. self._labels.append(int(label))
  24. self._text_a.append(text_a)
  25. def __getitem__(self, index):
  26. return self._labels[index], self._text_a[index]
  27. def __len__(self):
  28. return len(self._labels)
  29. def process_dataset(source, tokenizer, max_seq_len=64, batch_size=32, shuffle=True):
  30. is_ascend = mindspore.get_context('device_target') == 'Ascend'
  31. column_names = ["label", "text_a"]
  32. dataset = GeneratorDataset(source, column_names=column_names, shuffle=shuffle)
  33. # transforms
  34. type_cast_op = transforms.TypeCast(mindspore.int32)
  35. def tokenize_and_pad(text):
  36. if is_ascend:
  37. tokenized = tokenizer(text, padding='max_length', truncation=True, max_length=max_seq_len)
  38. else:
  39. tokenized = tokenizer(text)
  40. return tokenized['input_ids'], tokenized['attention_mask']
  41. # map dataset
  42. dataset = dataset.map(operations=tokenize_and_pad, input_columns="text_a", output_columns=['input_ids', 'attention_mask'])
  43. dataset = dataset.map(operations=[type_cast_op], input_columns="label", output_columns='labels')
  44. # batch dataset
  45. if is_ascend:
  46. dataset = dataset.batch(batch_size)
  47. else:
  48. dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id),
  49. 'attention_mask': (None, 0)})
  50. return dataset
  51. tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
  52. dataset_train = process_dataset(SentimentDataset("data/train.tsv"), tokenizer)
  53. dataset_val = process_dataset(SentimentDataset("data/dev.tsv"), tokenizer)
  54. dataset_test = process_dataset(SentimentDataset("data/test.tsv"), tokenizer, shuffle=False)

3.2 模型构建

        通过 BertForSequenceClassification 构建用于情感分类的 BERT 模型,加载预训练权重,设置情感三分类的超参数自动构建模型。

  1. from mindnlp.transformers import BertForSequenceClassification, BertModel
  2. from mindnlp._legacy.amp import auto_mixed_precision
  3. # set bert config and define parameters for training
  4. model = BertForSequenceClassification.from_pretrained('bert-base-chinese', num_labels=3)
  5. model = auto_mixed_precision(model, 'O1')
  6. optimizer = nn.Adam(model.trainable_params(), learning_rate=2e-5)
  7. metric = Accuracy()
  8. # define callbacks to save checkpoints
  9. ckpoint_cb = CheckpointCallback(save_path='checkpoint', ckpt_name='bert_emotect', epochs=1, keep_checkpoint_max=2)
  10. best_model_cb = BestModelCallback(save_path='checkpoint', ckpt_name='bert_emotect_best', auto_load=True)
  11. trainer = Trainer(network=model, train_dataset=dataset_train,
  12. eval_dataset=dataset_val, metrics=metric,
  13. epochs=5, optimizer=optimizer, callbacks=[ckpoint_cb, best_model_cb])
  14. # start training
  15. trainer.run(tgt_columns="labels")

3.3 模型推理

  1. from mindspore import Tensor
  2. def predict(text, label=None):
  3. label_map = {0: "消极", 1: "中性", 2: "积极"}
  4. text_tokenized = Tensor([tokenizer(text).input_ids])
  5. logits = model(text_tokenized)
  6. predict_label = logits[0].asnumpy().argmax()
  7. info = f"inputs: '{text}', predict: '{label_map[predict_label]}'"
  8. if label is not None:
  9. info += f" , label: '{label_map[label]}'"
  10. print(info)
  11. dataset_infer = SentimentDataset("data/infer.tsv")
  12. for label, text in dataset_infer:
  13. predict(text, label)

4. 心得总结

        BERT模型基于Transformer架构,通过双向自注意力机制捕捉文本中的上下文信息。这种架构使得模型能够更好地理解词语在不同上下文中的含义,从而提高情绪识别的准确性。

        收益于在大规模语料库上进行预训练,学习语言的通用表示,使得BERT能够充分利用预训练阶段学到的知识,提高微调阶段的性能。相比于传统的基于规则或特征工程的方法,BERT模型在情绪识别任务上通常表现出更高的准确性和鲁棒性。这主要得益于其强大的上下文理解能力和大规模预训练的优势。

        现有的一些深度学习框架,如MindSpore,对Transformer以及BERT等模型架构都已经做好了封装、预训练。非常方便进行集成和调用,用于各领域下游任务。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/835325
推荐阅读
相关标签
  

闽ICP备14008679号