PyTorch Ejemplo - Proyecto de Análisis de Sentimiento de Texto

El análisis de sentimiento de texto es una tarea fundamental en el procesamiento del lenguaje natural (NLP) que tiene como objetivo determinar la tendencia emocional (positiva/negativa) expresada en un texto. Este proyecto utilizará PyTorch para construir un modelo de aprendizaje profundo que realice la clasificación de sentimientos de reseñas de películas.

Escenarios de aplicación del análisis de sentimiento

  • Análisis de reseñas de productos
  • Monitoreo de opinión pública en redes sociales
  • Clasificación de comentarios de servicio al cliente
  • Predicción de tendencias de mercado

Preparación del entorno

Herramientas y bibliotecas necesarias

Ejemplo

import torch
import torch.nn as nn
import torch.optim as optim
from torchtext.data import Field, TabularDataset, BucketIterator
import spacy
import numpy as np

Instalar dependencias

pip install torch torchtext spacy
python -m spacy download en_core_web_sm

Preparación de datos

Introducción al conjunto de datos

Se utiliza el conjunto de datos de reseñas de películas IMDB, que contiene 50,000 reseñas con etiquetas de sentimiento (positivo/negativo).

Preprocesamiento de datos

Ejemplo

# Definir el procesamiento de campos
TEXT = Field(tokenize='spacy',
            tokenizer_language='en_core_web_sm',
            include_lengths=True)
LABEL = Field(sequential=False, use_vocab=False)

# Cargar el conjunto de datos
train_data, test_data = TabularDataset.splits(
    path='./data',
    train='train.csv',
    test='test.csv',
    format='csv',
    fields=[('text', TEXT), ('label', LABEL)]
)

# Construir el vocabulario
TEXT.build_vocab(train_data,
                max_size=25000,
                vectors="glove.6B.100d")

Construcción del modelo

Arquitectura del modelo LSTM

4.2 Código de implementación del modelo

Ejemplo

class SentimentLSTM(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.lstm = nn.LSTM(embedding_dim,
                           hidden_dim,
                           num_layers=n_layers,
                           bidirectional=True)
        self.fc = nn.Linear(hidden_dim * 2, output_dim)
        self.dropout = nn.Dropout(0.5)
       
    def forward(self, text, text_lengths):
        embedded = self.dropout(self.embedding(text))
        packed_embedded = nn.utils.rnn.pack_padded_sequence(
            embedded, text_lengths.to('cpu'))
        packed_output, (hidden, cell) = self.lstm(packed_embedded)
        hidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim=1))
        return self.fc(hidden)

Entrenamiento del modelo

Configuración de parámetros de entrenamiento

Ejemplo

# Parámetros del modelo
INPUT_DIM = len(TEXT.vocab)
EMBEDDING_DIM = 100
HIDDEN_DIM = 256
OUTPUT_DIM = 1
N_LAYERS = 2

# Inicializar el modelo
model = SentimentLSTM(INPUT_DIM, EMBEDDING_DIM, HIDDEN_DIM, OUTPUT_DIM, N_LAYERS)

# Optimizador y función de pérdida
optimizer = optim.Adam(model.parameters())
criterion = nn.BCEWithLogitsLoss()

Bucle de entrenamiento

Ejemplo

def train(model, iterator, optimizer, criterion):
    epoch_loss = 0
    epoch_acc = 0
   
    model.train()
   
    for batch in iterator:
        text, text_lengths = batch.text
        predictions = model(text, text_lengths).squeeze(1)
        loss = criterion(predictions, batch.label)
       
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
       
        epoch_loss += loss.item()
        epoch_acc += accuracy(predictions, batch.label)
       
    return epoch_loss / len(iterator), epoch_acc / len(iterator)

Evaluación del modelo

Función de evaluación

Ejemplo

def evaluate(model, iterator, criterion):
    epoch_loss = 0
    epoch_acc = 0
   
    model.eval()
   
    with torch.no_grad():
        for batch in iterator:
            text, text_lengths = batch.text
            predictions = model(text, text_lengths).squeeze(1)
            loss = criterion(predictions, batch.label)
            epoch_loss += loss.item()
            epoch_acc += accuracy(predictions, batch.label)
           
    return epoch_loss / len(iterator), epoch_acc / len(iterator)

Cálculo de precisión

Ejemplo

def accuracy(preds, y):
    rounded_preds = torch.round(torch.sigmoid(preds))
    correct = (rounded_preds == y).float()
    acc = correct.sum() / len(correct)
    return acc

Aplicación del modelo

Predecir texto nuevo

Ejemplo

def predict_sentiment(model, sentence):
    tokenized = [tok.text for tok in nlp.tokenizer(sentence)]
    indexed = [TEXT.vocab.stoi[t] for t in tokenized]
    length = [len(indexed)]
    tensor = torch.LongTensor(indexed).to(device)
    tensor = tensor.unsqueeze(1)
    length_tensor = torch.LongTensor(length)
    prediction = torch.sigmoid(model(tensor, length_tensor))
    return prediction.item()

Predicción de ejemplo

Ejemplo

positive_review = "This movie was fantastic! I really enjoyed it."
negative_review = "The film was terrible and boring."

print(f"Positive review score: {predict_sentiment(model, positive_review):.4f}")
print(f"Negative review score: {predict_sentiment(model, negative_review):.4f}")
Otras extensiones