Compartilhamento de tecnologia

[MindSpore Learning Check-in] Princípio de Prática de Aplicação-LLM e Implementação de Prática de Diálogo BERT Reconhecimento de Emoções Baseado em MindSpore

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

No campo atual do processamento de linguagem natural (PNL), o reconhecimento de emoções é um cenário de aplicação muito importante. Seja no atendimento inteligente ao cliente, na análise de mídia social ou no campo da computação emocional, a identificação precisa das emoções dos usuários pode melhorar muito a experiência do usuário e o nível de inteligência do sistema. BERT (Bidirecional Encoder Representations from Transformers), como um poderoso modelo de linguagem pré-treinado, demonstrou seu excelente desempenho em múltiplas tarefas de PNL. Neste blog, apresentaremos em detalhes como usar o modelo BERT para obter reconhecimento de emoções conversacionais com base na estrutura MindSpore. Ajude você a dominar essa técnica com exemplos de código passo a passo e explicações detalhadas.

Introdução do modelo

BERT (Representações de codificador bidirecional de transformadores) é um modelo de representação de codificador bidirecional baseado em transformador. Ele captura principalmente representações em nível de palavras e frases por meio de duas tarefas de pré-treinamento: Masked Language Model (MLM) e Next Sentence Prediction (NSP).

  • Modelo de Linguagem Mascarada: mascara aleatoriamente 15% das palavras no corpus, e o modelo precisa prever essas palavras mascaradas.
  • Previsão da próxima frase: O modelo precisa prever se existe uma relação sequencial entre duas sentenças.

Depois que o BERT é pré-treinado, ele pode ser usado para uma variedade de tarefas posteriores, como classificação de texto, julgamento de similaridade, compreensão de leitura, etc.

Preparação do conjunto de dados

Na parte de preparação do conjunto de dados, baixamos e descompactamos o conjunto de dados de bate-papo do robô fornecido pela equipe do Baidu Feipiao. Este conjunto de dados foi pré-processado e contém rótulos emocionais. Cada linha de dados consiste em um rótulo e um texto segmentado por palavra. O rótulo representa a categoria de emoção (0 significa negativo, 1 significa neutro, 2 significa positivo) e o texto é o conteúdo da conversa do usuário. Ao usar esses dados estruturados, podemos realizar tarefas de classificação de sentimentos de forma mais conveniente.

# 下载数据集
!wget https://baidu-nlp.bj.bcebos.com/emotion_detection-dataset-1.0.0.tar.gz -O emotion_detection.tar.gz
!tar xvf emotion_detection.tar.gz
  • 1
  • 2
  • 3

O formato do conjunto de dados é o seguinte:

label--text_a
0--谁骂人了?我从来不骂人,我骂的都不是人,你是人吗 ?
1--我有事等会儿就回来和你聊
2--我见到你很高兴谢谢你帮我
  • 1
  • 2
  • 3
  • 4

Carregamento e pré-processamento de dados

O carregamento e o pré-processamento de dados são etapas cruciais no processo de aprendizado de máquina.nós costumavamosGeneratorDataset para carregar os dados e usar operações de mapeamento para converter o texto em um formato aceitável para o modelo.Especificamente, usamosBertTokenizer Tokenize o texto em um ID de vocabulário e execute uma operação de preenchimento. O objetivo disso é garantir que o comprimento de todas as sequências de entrada seja consistente, melhorando assim a eficiência do treinamento e o desempenho do modelo.

import numpy as np
from mindspore.dataset import text, GeneratorDataset, transforms
from mindnlp.transformers import BertTokenizer

def process_dataset(source, tokenizer, max_seq_len=64, batch_size=32, shuffle=True):
    is_ascend = mindspore.get_context('device_target') == 'Ascend'
    column_names = ["label", "text_a"]
    
    dataset = GeneratorDataset(source, column_names=column_names, shuffle=shuffle)
    type_cast_op = transforms.TypeCast(mindspore.int32)
    
    def tokenize_and_pad(text):
        if is_ascend:
            tokenized = tokenizer(text, padding='max_length', truncation=True, max_length=max_seq_len)
        else:
            tokenized = tokenizer(text)
        return tokenized['input_ids'], tokenized['attention_mask']
    
    dataset = dataset.map(operations=tokenize_and_pad, input_columns="text_a", output_columns=['input_ids', 'attention_mask'])
    dataset = dataset.map(operations=[type_cast_op], input_columns="label", output_columns='labels')
    
    if is_ascend:
        dataset = dataset.batch(batch_size)
    else:
        dataset = dataset.padded_batch(batch_size, pad_info={'input_ids': (None, tokenizer.pad_token_id), 'attention_mask': (None, 0)})

    return dataset

tokenizer = BertTokenizer.from_pretrained('bert-base-chinese')
dataset_train = process_dataset(SentimentDataset("data/train.tsv"), tokenizer)
dataset_val = process_dataset(SentimentDataset("data/dev.tsv"), tokenizer)
dataset_test = process_dataset(SentimentDataset("data/test.tsv"), tokenizer, shuffle=False)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32

Insira a descrição da imagem aqui

Construção de modelo

Na parte de construção do modelo usamosBertForSequenceClassification para realizar tarefas de classificação de emoções. Este modelo pré-treinado foi treinado em corpora de grande escala e possui fortes capacidades de compreensão linguística. Ao carregar pesos pré-treinados, podemos melhorar significativamente o desempenho do modelo em tarefas de classificação de emoções. Ao mesmo tempo, utilizamos tecnologia de precisão mista automática, que não só acelera o processo de treinamento, mas também reduz o uso de memória de vídeo, alcançando assim um treinamento mais eficiente com recursos de hardware limitados.

Otimizadores e métricas de avaliação são componentes importantes no treinamento de modelos. Escolhemos o otimizador Adam devido ao seu excelente desempenho ao lidar com dados de grande escala e modelos complexos. Em termos de indicadores de avaliação, utilizamos a precisão para medir o desempenho do modelo. Com essas configurações, podemos garantir que o modelo seja continuamente otimizado durante o treinamento e alcance um bom desempenho no conjunto de validação.

As funções de retorno de chamada desempenham um papel importante no processo de treinamento do modelo. Configuramos duas funções de retorno de chamada:CheckpointCallbackeBestModelCallback . O primeiro é usado para salvar regularmente os pesos do modelo, enquanto o último carrega automaticamente os pesos do modelo com melhor desempenho. Por meio dessas funções de retorno de chamada, garantimos que parâmetros importantes do modelo não sejam perdidos durante o treinamento e que o modelo com melhor desempenho seja sempre usado para inferência e avaliação.

from mindnlp.transformers import BertForSequenceClassification
from mindspore import nn
from mindnlp._legacy.amp import auto_mixed_precision

model = BertForSequenceClassification.from_pretrained('bert-base-chinese', num_labels=3)
model = auto_mixed_precision(model, 'O1')

optimizer = nn.Adam(model.trainable_params(), learning_rate=2e-5)
metric = Accuracy()
ckpoint_cb = CheckpointCallback(save_path='checkpoint', ckpt_name='bert_emotect', epochs=1, keep_checkpoint_max=2)
best_model_cb = BestModelCallback(save_path='checkpoint', ckpt_name='bert_emotect_best', auto_load=True)

trainer = Trainer(network=model, train_dataset=dataset_train,
                  eval_dataset=dataset_val, metrics=metric,
                  epochs=5, optimizer=optimizer, callbacks=[ckpoint_cb, best_model_cb])
trainer.run(tgt_columns="labels")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

validação do modelo

Na seção de validação do modelo, usamos o conjunto de dados de validação para avaliar o desempenho do modelo. Ao calcular a precisão do modelo no conjunto de validação, podemos compreender a capacidade de generalização e o efeito real do modelo. Esta etapa é muito importante porque pode nos ajudar a descobrir possíveis problemas no processo de treinamento do modelo e fazer os ajustes e otimizações correspondentes.

evaluator = Evaluator(network=model, eval_dataset=dataset_test, metrics=metric)
evaluator.run(tgt_columns="labels")
  • 1
  • 2

Raciocínio do modelo

A seção de inferência do modelo mostra como usar o modelo treinado para realizar a classificação de sentimento em novos dados.Definimos umpredict Função que realiza a previsão de emoções inserindo texto e gerando resultados de previsão. Esta etapa demonstra os recursos práticos de aplicação do modelo e verifica o desempenho de generalização do modelo.

dataset_infer = SentimentDataset("data/infer.tsv")

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)

for label, text in dataset_infer:
    predict(text, label)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

Insira a descrição da imagem aqui

Dados de inferência personalizados

Por fim, mostramos como usar o modelo para reconhecimento de emoções em entradas personalizadas. Esta etapa não apenas demonstra as capacidades de aplicação prática do modelo, mas também verifica o desempenho do modelo sob diferentes entradas. Desta forma, podemos compreender melhor a capacidade de generalização e o efeito real do modelo.

predict("家人们咱就是说一整个无语住了 绝绝子叠buff")
  • 1

Insira a descrição da imagem aqui