Basado en chino-roberta-wwm-ext entrenamiento de ajuste fino 6 modelo de análisis de sentimiento de clasificación

1. Introducción al modelo y al conjunto de datos

1.1 Modelo de pre-entrenamiento

chinese-roberta-wwm-extSe RoBERTadesarrolla en base al marco, donde wwmrepresenta Whole Word Masking, es decir, enmascara la palabra completa. De esta manera, el modelo puede comprender mejor el contexto y la asociación semántica, y mejorar la precisión y el efecto del procesamiento de texto chino.

BERTEn comparación con el modelo original , chinese-roberta-wwm-extse han realizado algunos ajustes en el tamaño de los datos de entrenamiento y la cantidad de pasos de entrenamiento para mejorar aún más el rendimiento y la solidez del modelo. Y ha sido entrenado previamente en un corpus no supervisado a gran escala, de modo que tenga una sólida comprensión del idioma y capacidades de generación. Puede ser ampliamente utilizado en varias tareas de procesamiento de lenguaje natural, como clasificación de texto, reconocimiento de entidades nombradas, análisis de sentimientos, etc. Podemos usar este modelo como base para afinar y transferir el aprendizaje en diferentes tareas para lograr un procesamiento de texto chino más preciso y eficiente.

Dirección de Huggingface: https://huggingface.co/hfl/chinese-roberta-wwm-ext

Entra para huggingfacedescargar el modelo pre-entrenado:

inserte la descripción de la imagen aquí

1.2 Conjunto de datos

Se adopta el conjunto de datos SMP2020微博情绪分类评测, ingrese el enlace a continuación para descargar el conjunto de datos:

https://smp2020ewect.github.io/

inserte la descripción de la imagen aquí

Después de la descarga, los datos se dividen en tres tipos 训练集、测试集、验证集:

inserte la descripción de la imagen aquí

El formato de los datos es JSONformat, y la estructura es la siguiente:

inserte la descripción de la imagen aquí

Entre ellas, se encuentra la clasificación labelactual content, que se divide en 6categorías, de la siguiente manera:

etiqueta ilustrar
miedo miedo
neutral sin emociones
triste triste
sorpresa sorpresa
enojado enojo
feliz positivo

2. Entrenamiento de ajuste fino del modelo

2.1, procesamiento de conjuntos de datos para construir DataLoader

from transformers import BertTokenizer
from torch.utils.data import DataLoader, RandomSampler, TensorDataset
import numpy as np
import torch
import json
import os


class GenDateSet():
    def __init__(self, tokenizer, train_file, val_file, label_dict, max_length=128, batch_size=10):
        self.train_file = train_file
        self.val_file = val_file
        self.max_length = max_length
        self.batch_size = batch_size
        self.label_dict = label_dict
        self.tokenizer = tokenizer

    def gen_data(self, file):
        if not os.path.exists(file):
            raise Exception("数据集不存在")
        input_ids = []
        input_types = []
        input_masks = []
        labels = []
        with open(file, encoding='utf8') as f:
            data = json.load(f)
        if not data:
            raise Exception("数据集不存在")

        # 处理数据
        for index, item in enumerate(data):
            text = item['content']
            label = item['label']
            tokens = self.tokenizer(text, padding="max_length", truncation=True, max_length=self.max_length)
            input_id, types, masks = tokens['input_ids'], tokens['token_type_ids'], tokens['attention_mask']
            input_ids.append(input_id)
            input_types.append(types)
            input_masks.append(masks)
            y_ = self.label_dict[label]
            labels.append([y_])

            if index % 1000 == 0:
                print('处理', index, '条数据')

        # 构建 TensorDataset
        data_gen = TensorDataset(torch.LongTensor(np.array(input_ids)),
                                 torch.LongTensor(np.array(input_types)),
                                 torch.LongTensor(np.array(input_masks)),
                                 torch.LongTensor(np.array(labels)))
        # 打乱
        sampler = RandomSampler(data_gen)
        # 构建 DataLoader
        return DataLoader(data_gen, sampler=sampler, batch_size=self.batch_size)

    def gen_train_data(self):
        # 生成训练集
        return self.gen_data(self.train_file)

    def gen_val_data(self):
        # 生成验证集
        return self.gen_data(self.val_file)

2.2 Construir un modelo de entrenamiento iterativo

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification
import torch.nn as nn
from tqdm import tqdm
from gen_datasets import GenDateSet

# 标签结构
label_dict = {
    
    
    'fear': 0,
    'neutral': 1,
    'sad': 2,
    'surprise': 3,
    'angry': 4,
    'happy': 5
}

# 预训练模型位置
model_dir = 'D:\\AIGC\\model\\chinese-roberta-wwm-ext'
# 这里暂时使用测试集训练,数据较少
train_file = 'data/usual_train.txt'
# train_file = 'data/usual_test_labeled.txt'
# 验证集
val_file = 'data/virus_eval_labeled.txt'
# 训练模型存储位置
save_model_path = './model/'
# 最大长度
max_length = 128
# 分类数
num_classes = 6
batch_size = 10
epoch = 10

def val(model, device, data):
    model.eval()
    test_loss = 0.0
    acc = 0
    for (input_id, types, masks, y) in tqdm(data):
        input_id, types, masks, y = input_id.to(device), types.to(device), masks.to(device), y.to(device)
        with torch.no_grad():
            y_ = model(input_id, token_type_ids=types, attention_mask=masks)
            logits = y_['logits']
        test_loss += nn.functional.cross_entropy(logits, y.squeeze())
        pred = logits.max(-1, keepdim=True)[1]
        acc += pred.eq(y.view_as(pred)).sum().item()
    test_loss /= len(data)
    return acc / len(data.dataset)


def main():
    # 加载 tokenizer 和  model
    tokenizer = AutoTokenizer.from_pretrained(model_dir)
    model = AutoModelForSequenceClassification.from_pretrained(model_dir, num_labels=num_classes)
    # 加载数据集
    dateset = GenDateSet(tokenizer, train_file, val_file, label_dict, max_length, batch_size)
    # 训练集
    train_data = dateset.gen_train_data()
    # 验证集
    val_data = dateset.gen_val_data()

    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model.train()
    model = model.to(device)
    # 优化器
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-5)

    best_acc = 0.0
    for epoch_index in range(epoch):
        batch_epoch = 0
        for (input_id, types, masks, y) in tqdm(train_data):
            input_id, types, masks, y = input_id.to(device), types.to(device), masks.to(device), y.to(device)
            # 前向传播
            outputs = model(input_id, token_type_ids=types, attention_mask=masks, labels=y)
            # 梯度清零
            optimizer.zero_grad()
            # 计算 loss
            loss = outputs.loss
            # 反向传播
            loss.backward()
            optimizer.step()
            batch_epoch += 1
            if batch_epoch % 10 == 0:
                print('Train Epoch:', epoch_index, ' , batch_epoch: ', batch_epoch, ' , loss = ', loss.item())

        # 评估准确度
        acc = val(model, device, val_data)
        print('Train Epoch:', epoch_index, ' val acc = ', acc)
        # 存储 best model
        if best_acc < acc:
            # torch.save(model.state_dict(), save_model_path)
            model.save_pretrained("./model")
            tokenizer.save_pretrained("./model")
            best_acc = acc

if __name__ == '__main__':
    main()

Después de correr, puedes ver el progreso del entrenamiento:

inserte la descripción de la imagen aquí

Durante la capacitación, puede ver la precisión del conjunto de verificación. Una vez finalizada la capacitación, puede ver el modelo y los archivos guardados modelen tokenizer:

inserte la descripción de la imagen aquí

3. Pruebas de modelos

import torch
from transformers import AutoTokenizer, AutoModelForSequenceClassification

label_dict = {
    
    
    0: '恐惧',
    1: '无情绪',
    2: '悲伤',
    3: '惊奇',
    4: '愤怒',
    5: '积极'
}
model_dir = "./model"
num_classes = 6
max_length = 128


def main():
    # 加载预训练模型和分词器
    tokenizer = AutoTokenizer.from_pretrained(model_dir)
    model = AutoModelForSequenceClassification.from_pretrained(model_dir, num_labels=num_classes)

    while True:
        text = input("请输入内容: \n ")
        if not text or text == "":
            continue
        if text == "q":
            break

        encoded_input = tokenizer(text, padding="max_length", truncation=True, max_length=max_length)

        input_ids = torch.tensor([encoded_input['input_ids']])
        token_type_ids = torch.tensor([encoded_input['token_type_ids']])
        attention_mask = torch.tensor([encoded_input['attention_mask']])
        # 前向传播
        y_ = model(input_ids, token_type_ids=token_type_ids, attention_mask=attention_mask)
        output = y_['logits'][0]
        pred = output.max(-1, keepdim=True)[1][0].item()
        print('预测结果:', label_dict[pred])

if __name__ == '__main__':
    main()

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/qq_43692950/article/details/131792392
Recomendado
Clasificación