Práctica de PNL: práctica de entrada de clasificación de texto basada en Pytorch

Tabla de contenido

1. Preparación preliminar

1. Preparación del entorno

2. Cargar datos

2. Código de combate

1. Construye un diccionario

2. Genera lotes de datos e iteradores

3. Definir el modelo

4. Definir la instancia

5. Definir la función de formación y la función de evaluación

6. Dividir el conjunto de datos y ejecutar el modelo

3. Evaluar el modelo utilizando el conjunto de datos de prueba

Cuatro Resumen


Esta es una implementación de clasificación de texto simple usando PyTorch. En este ejemplo, utilizaremos el conjunto de datos AG News para la clasificación de texto.

La clasificación de texto generalmente se divide en cinco pasos: corpus, claridad de texto, segmentación de palabras, vectorización de texto y modelado.

1. Preparación preliminar

1. Preparación del entorno

Para proyectos nlp, se recomienda que anaconda cree un nuevo entorno. Primero, instale las bibliotecas torchtext y portalocker.
Los números de versión que uso son:
torchtext==0.15.1
portalocker==2.7.0
Nota: también hay versiones similares disponibles, y no tienen que ser exactamente iguales

Referencia de instalación:

AG News (AG's News  Topic  Classification
Dataset) es un conjunto de datos ampliamente utilizado en tareas de clasificación de textos, especialmente en el campo de las noticias. El conjunto de datos es recopilado y organizado por el Corpus of News
Articles de AG y contiene cuatro categorías principales: mundo, deportes, negocios y tecnología.

2. Cargar datos

Al igual que el proyecto de detección de objetos anterior, llame al gpu

import torch
import torch.nn as nn
import torchvision
from torchvision import transforms, datasets
import os,PIL,pathlib,warnings

warnings.filterwarnings("ignore")             #忽略警告信息
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

print(device)

Cuda

from torchtext.datasets import AG_NEWS
train_iter = AG_NEWS(split='train')      # 加载 AG News 数据集

 Puede ver el contenido en el directorio correspondiente (el mío es C:\Users\Chen02\.cache\torch\text\datasets\AG_NEWS

2. Código de combate

1. Construye un diccionario

from torchtext.data.utils import get_tokenizer
from torchtext.vocab import build_vocab_from_iterator

tokenizer  = get_tokenizer('basic_english') # 返回分词器函数,训练营内“get_tokenizer函数详解”一文

def yield_tokens(data_iter):
    for _, text in data_iter:
        yield tokenizer(text)

vocab = build_vocab_from_iterator(yield_tokens(train_iter), specials=["<unk>"])
vocab.set_default_index(vocab["<unk>"]) # 设置默认索引,如果找不到单词,则会选择默认索引

 Explicación detallada de la función .build_vocab_from_iterator()

torchtext.vocab.build_vocab_from_iterator La función de esta función es contar la frecuencia de tokens de un objeto iterable y devolver un vocab (diccionario de vocabulario) 

Lo anterior es el formulario de definición de la interfaz API del sitio web oficial. Hay cinco parámetros, y el valor de retorno es una instancia de tipo Vocab. Los cinco parámetros son: ● iterador: un objeto iterable que se usa
para crear un vocab (diccionario de vocabulario).
● min_freq: frecuencia mínima. Solo se conservarán los tokens cuya frecuencia de ocurrencia sea mayor o igual a min_freq en el texto
specials: tokens especiales, una lista de cadenas. 用于 在 词汇 字典 中 添加 一些 特殊 的 Token/标记 , 比如 最 常用 的 '' , 用 于 代表 词 汇字典 中 未 存在 的 Token , 当然 也 也 可以 自己 喜欢 的 符号 来 代替 , 的 意义 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也 也Depende de quién lo use.
●special_first: Indica si poner especiales al principio del diccionario, el valor predeterminado es Verdadero
●max_tokens: Limita la longitud máxima del diccionario de vocabulario. Y la longitud de la lista de ofertas especiales contenida en esta longitud

print(vocab(['here', 'is', 'an', 'example']))

[475, 21, 30, 5297]

text_pipeline  = lambda x: vocab(tokenizer(x))
label_pipeline = lambda x: int(x) - 1
print(text_pipeline('here is the an example'))

[475, 21, 2, 30, 5297]

print(label_pipeline('10'))

9

2. Genera lotes de datos e iteradores

from torch.utils.data import DataLoader

def collate_batch(batch):
    label_list, text_list, offsets = [], [], [0]
    
    for (_label, _text) in batch:
        # 标签列表
        label_list.append(label_pipeline(_label))
        
        # 文本列表
        processed_text = torch.tensor(text_pipeline(_text), dtype=torch.int64)
        text_list.append(processed_text)
        
        # 偏移量,即语句的总词汇量
        offsets.append(processed_text.size(0))
        
    label_list = torch.tensor(label_list, dtype=torch.int64)
    text_list  = torch.cat(text_list)
    offsets    = torch.tensor(offsets[:-1]).cumsum(dim=0) #返回维度dim中输入元素的累计和
    
    return label_list.to(device), text_list.to(device), offsets.to(device)

# 数据加载器
dataloader = DataLoader(train_iter,
                        batch_size=8,
                        shuffle   =False,
                        collate_fn=collate_batch)

3. Definir el modelo

Aquí definimos el modelo TextClassificationModel, primero incrustando el texto y luego realizando la agregación media en los resultados después de la incrustación de oraciones.

from torch import nn

class TextClassificationModel(nn.Module):

    def __init__(self, vocab_size, embed_dim, num_class):
        super(TextClassificationModel, self).__init__()
        
        self.embedding = nn.EmbeddingBag(vocab_size,   # 词典大小
                                         embed_dim,    # 嵌入的维度
                                         sparse=False) # 
        
        self.fc = nn.Linear(embed_dim, num_class)
        self.init_weights()

    def init_weights(self):
        initrange = 0.5
        self.embedding.weight.data.uniform_(-initrange, initrange)
        self.fc.weight.data.uniform_(-initrange, initrange)
        self.fc.bias.data.zero_()

    def forward(self, text, offsets):
        embedded = self.embedding(text, offsets)
        return self.fc(embedded)

self.embedding.weight.data.uniform_(-initrange, initrange) Este código es un método para inicializar el peso de la capa de incrustación de palabras (capa de incrustación) de la red neuronal bajo el marco PyTorch. Aquí se utilizan valores aleatorios uniformemente distribuidos para inicializar los pesos, en concreto sus funciones son las siguientes:

1 self.embedding : Esta es la palabra incrustación de capa en la red neuronal. El papel de la capa de incrustación de palabras es mapear representaciones de palabras discretas (generalmente índices enteros) en vectores continuos de tamaño fijo. Estos vectores capturan la relación semántica entre palabras y sirven como entrada a la red.
2 self.embedding.weight : esta es la matriz de peso de la capa de incrustación de palabras, su forma es (vocab_size, embedding_dim), donde vocab_size es el tamaño del vocabulario y embedding_dim es la dimensión del vector de incrustación.
3 self.embedding.weight.data : esta es la parte de datos de la matriz de peso, donde podemos manipular directamente su tensor subyacente.
4. uniform_(-initrange, initrange) : Esta es una operación in situ, que se utiliza para inicializar el valor de la matriz de peso con una distribución uniforme. La distribución uniforme tiene un rango de [-initrange, initrange], donde initrange es un número positivo.

Inicializar el peso de la capa de incrustación de palabras de esta manera puede hacer que el modelo tenga cierta aleatoriedad al comienzo del entrenamiento, lo que ayuda a evitar problemas como la desaparición de gradientes o la explosión de gradientes. Durante el entrenamiento, estos pesos se actualizan continuamente mediante un algoritmo de optimización para capturar mejores representaciones de palabras.

4. Definir la instancia

num_class  = len(set([label for (label, text) in train_iter]))
vocab_size = len(vocab)
em_size     = 64
model      = TextClassificationModel(vocab_size, em_size, num_class).to(device)

5. Definir la función de formación y la función de evaluación

import time

def train(dataloader):
    model.train()  # 切换为训练模式
    total_acc, train_loss, total_count = 0, 0, 0
    log_interval = 500
    start_time   = time.time()

    for idx, (label, text, offsets) in enumerate(dataloader):
        
        predicted_label = model(text, offsets)
        
        optimizer.zero_grad()                    # grad属性归零
        loss = criterion(predicted_label, label) # 计算网络输出和真实值之间的差距,label为真实值
        loss.backward()                          # 反向传播
        optimizer.step()  # 每一步自动更新
        
        # 记录acc与loss
        total_acc   += (predicted_label.argmax(1) == label).sum().item()
        train_loss  += loss.item()
        total_count += label.size(0)
        
        if idx % log_interval == 0 and idx > 0:
            elapsed = time.time() - start_time
            print('| epoch {:1d} | {:4d}/{:4d} batches '
                  '| train_acc {:4.3f} train_loss {:4.5f}'.format(epoch, idx, len(dataloader),
                                              total_acc/total_count, train_loss/total_count))
            total_acc, train_loss, total_count = 0, 0, 0
            start_time = time.time()

def evaluate(dataloader):
    model.eval()  # 切换为测试模式
    total_acc, train_loss, total_count = 0, 0, 0

    with torch.no_grad():
        for idx, (label, text, offsets) in enumerate(dataloader):
            predicted_label = model(text, offsets)
            
            loss = criterion(predicted_label, label)  # 计算loss值
            # 记录测试数据
            total_acc   += (predicted_label.argmax(1) == label).sum().item()
            train_loss  += loss.item()
            total_count += label.size(0)
            
    return total_acc/total_count, train_loss/total_count

6. Dividir el conjunto de datos y ejecutar el modelo

from torch.utils.data.dataset import random_split
from torchtext.data.functional import to_map_style_dataset
# 超参数
EPOCHS     = 10 # epoch
LR         = 5  # 学习率
BATCH_SIZE = 64 # batch size for training

criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=LR)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1.0, gamma=0.1)
total_accu = None

train_iter, test_iter = AG_NEWS() # 加载数据
train_dataset = to_map_style_dataset(train_iter)
test_dataset  = to_map_style_dataset(test_iter)
num_train     = int(len(train_dataset) * 0.95)

split_train_, split_valid_ = random_split(train_dataset,
                                          [num_train, len(train_dataset)-num_train])

train_dataloader = DataLoader(split_train_, batch_size=BATCH_SIZE,
                              shuffle=True, collate_fn=collate_batch)
valid_dataloader = DataLoader(split_valid_, batch_size=BATCH_SIZE,
                              shuffle=True, collate_fn=collate_batch)
test_dataloader  = DataLoader(test_dataset, batch_size=BATCH_SIZE,
                              shuffle=True, collate_fn=collate_batch)

for epoch in range(1, EPOCHS + 1):
    epoch_start_time = time.time()
    train(train_dataloader)
    val_acc, val_loss = evaluate(valid_dataloader)
    
    if total_accu is not None and total_accu > val_acc:
        scheduler.step()
    else:
        total_accu = val_acc
    print('-' * 69)
    print('| epoch {:1d} | time: {:4.2f}s | '
          'valid_acc {:4.3f} valid_loss {:4.3f}'.format(epoch,
                                           time.time() - epoch_start_time,
                                           val_acc,val_loss))

    print('-' * 69)

 

La función de torchtext.data.funcional.to_map_style_dataset es convertir un conjunto de datos iterativo (conjunto de datos de estilo iterable) en un conjunto de datos de estilo de mapa (conjunto de datos de estilo de mapa). Esta conversión nos permite acceder a elementos en el conjunto de datos de manera más conveniente por índice (por ejemplo: entero).

En PyTorch, los conjuntos de datos se pueden dividir en dos tipos: estilo iterable y estilo de mapa. Los conjuntos de datos de estilo iterable implementan el método iter(), que puede acceder de forma iterativa a los elementos del conjunto de datos, pero no admite el acceso a índices. El conjunto de datos de estilo Map implementa los métodos getitem() y len(), que pueden acceder directamente a elementos específicos a través del índice y obtener el tamaño del conjunto de datos.

TorchText es una biblioteca de extensión para PyTorch que se centra en el procesamiento de datos de texto. La función to_map_style_dataset en torchtext.data.function puede ayudarnos a convertir un conjunto de datos de estilo iterable en un conjunto de datos de estilo de mapa fácil de operar. De esta forma, podemos acceder directamente a muestras específicas en el conjunto de datos a través del índice, lo que simplifica el procesamiento de datos durante el entrenamiento, la validación y las pruebas.

3. Evaluar el modelo utilizando el conjunto de datos de prueba

print('Checking the results of test dataset.')
test_acc, test_loss = evaluate(test_dataloader)
print('test accuracy {:8.3f}'.format(test_acc))

Comprobación de los resultados del conjunto de datos de prueba.
precisión de prueba 0.905

Cuatro Resumen

Este artículo presenta un caso práctico del uso de PyTorch para implementar la clasificación de texto, utilizando el conjunto de datos AG News para la clasificación de texto. El proceso de implementación se divide en cuatro partes: preparación preliminar, código de práctica, evaluación del modelo utilizando conjuntos de datos de prueba y resumen. En la preparación preliminar, prepare el entorno y cargue el conjunto de datos; en el combate de código real, cree un diccionario, genere lotes de datos e iteradores y defina el modelo; use el conjunto de datos de prueba para evaluar el modelo y pruebe el modelo entrenado ; resumir y revisar todo el proyecto. A través de este artículo, puede comprender el proceso básico de clasificación de texto y cómo usar PyTorch para implementar un modelo de clasificación de texto.

Aquí hay algunas experiencias de aprendizaje:

1. Preparación del entorno: se recomienda utilizar anaconda para crear un nuevo entorno e instalar las bibliotecas necesarias en él.

2. Carga de datos: cargue los datos llamando al método train_iter del conjunto de datos AG_NEWS y podrá ver los datos en el directorio correspondiente.

3. Cree un diccionario: use la función get_tokenizer y la función build_vocab_from_iterator para crear un diccionario, puede configurar el índice predeterminado según sea necesario y seleccionar el índice predeterminado cuando no se puede encontrar la palabra.

4. Genere lotes de datos e iteradores: use la función DataLoader para generar lotes de datos e iteradores, donde la función collate_batch se usa para convertir una sola muestra en una entrada de modelo.

5. Defina el modelo: defina el modelo TextClassificationModel, primero incruste el texto y luego realice la agregación media de los resultados después de la incrustación de oraciones.

6. Entrenamiento y evaluación del modelo: entrene y evalúe el modelo, incluidos pasos como la definición de la función de pérdida, la definición del optimizador y el entrenamiento de bucle.

Supongo que te gusta

Origin blog.csdn.net/m0_62237233/article/details/130477513
Recomendado
Clasificación