本案例将展示如何使用PyTorch和Bees算法来调整LSTM模型的文本分类问题。我们将使用IMDB电影评论数据集作为我们的示例数据集。

步骤1:准备数据

首先,我们需要准备我们的数据。我们将使用PyTorch的内置数据集IMDB,它已经被预处理为词索引的形式。我们可以使用torchtext库来轻松加载和处理这个数据集。

import torch
from torchtext import datasets
from torchtext.data import Field, LabelField, BucketIterator

# 定义字段
TEXT = Field(tokenize = 'spacy', tokenizer_language='en_core_web_sm')
LABEL = LabelField(dtype = torch.float)

# 加载数据
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)

# 构建词汇表
TEXT.build_vocab(train_data, max_size=25000, vectors="glove.6B.100d", unk_init=torch.Tensor.normal_)
LABEL.build_vocab(train_data)

# 创建数据迭代器
BATCH_SIZE = 64
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
train_iterator, test_iterator = BucketIterator.splits(
    (train_data, test_data), 
    batch_size = BATCH_SIZE, 
    device = device)

在这里,我们定义了两个字段:TEXT和LABEL。TEXT将用于存储评论文本,LABEL将用于存储评论的情感标签(正面或负面)。我们使用datasets.IMDB加载数据集,并使用Field和LabelField定义了我们的字段。我们使用build_vocab方法来构建词汇表,并使用预训练的GloVe嵌入来初始化我们的单词向量。最后,我们使用BucketIterator将数据分成相同长度的批次。

步骤2:构建模型

接下来,我们将构建我们的LSTM模型。

import torch.nn as nn

class LSTMModel(nn.Module):
    def __init__(self, vocab_size, embedding_dim, hidden_dim, output_dim, n_layers,
                 bidirectional, dropout):
        super().__init__()

        self.embedding = nn.Embedding(vocab_size, embedding_dim)

        self.lstm = nn.LSTM(embedding_dim,
                            hidden_dim,
                            num_layers=n_layers,
                            bidirectional=bidirectional,
                            dropout=dropout)

        self.fc = nn.Linear(hidden_dim * 2, output_dim)

        self.dropout = nn.Dropout(dropout)

    def forward(self, text):

        embedded = self.embedding(text)

        output, (hidden, cell) = self.lstm(embedded)

        hidden = self.dropout(torch.cat((hidden[-2,:,:], hidden[-1,:,:]), dim = 1))

        return self.fc(hidden)

在这里,我们定义了一个LSTMModel类,该类继承了nn.Module。在构造函数中,我们定义了嵌入层、LSTM层、全连接层和dropout层。在前向方法中,我们首先将文本嵌入到嵌入层中,然后将其传递到LSTM层。我们使用dropout层来减少过度拟合。最后,我们将LSTM层的最后一层隐藏状态传递到全连接层中,并返回输出。

步骤3:定义训练流程

接下来,我们将定义我们的训练流程。我们将使用交叉熵损失函数和Adam优化器。

import torch.optim as optim

model = LSTMModel(len(TEXT.vocab),
                  embedding_dim=100,
                  hidden_dim=256,
                  output_dim=1,
                  n_layers=2,
                  bidirectional=True,
                  dropout=0.5)

optimizer = optim.Adam(model.parameters())

criterion = nn.BCEWithLogitsLoss()

model = model.to(device)
criterion = criterion.to(device)

def train(model, iterator, optimizer, criterion):
    epoch_loss = 0
    epoch_acc = 0

    model.train()

    for batch in iterator:
        optimizer.zero_grad()

        predictions = model(batch.text).squeeze(1)
        loss = criterion(predictions, batch.label)
        acc = binary_accuracy(predictions, batch.label)

        loss.backward()
        optimizer.step()

        epoch_loss += loss.item()
        epoch_acc += acc.item()

    return epoch_loss / len(iterator), epoch_acc / len(iterator)

def evaluate(model, iterator, criterion):
    epoch_loss = 0
    epoch_acc = 0

    model.eval()

    with torch.no_grad():
        for batch in iterator:
            predictions = model(batch.text).squeeze(1)
            loss = criterion(predictions, batch.label)
            acc = binary_accuracy(predictions, batch.label)

            epoch_loss += loss.item()
            epoch_acc += acc.item()

    return epoch_loss / len(iterator), epoch_acc / len(iterator)

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

在这里,我们定义了train和evaluate函数。train函数将使用optimizer和criterion来更新模型的权重,并返回平均损失和准确率。evaluate函数将使用criterion计算模型在测试数据集上的损失和准确率。

步骤4:使用Bees算法进行超参数优化

接下来,我们将使用Bees算法来优化我们的超参数。我们将使用pso库来实现Bees算法。

!pip install pso

from pso import PSO

def to_params(x: list) -> dict:
    """
    将Bees算法的参数列表转换为超参数字典
    """
    return {
        'embedding_dim': int(x[0]),
        'hidden_dim': int(x[1]),
        'n_layers': int(x[2]),
        'dropout': x[3],
    }

def to_x(params: dict) -> list:
    """
    将超参数字典转换为Bees算法的参数列表
    """
    return [params['embedding_dim'], params['hidden_dim'], params['n_layers'], params['dropout']]

def bees_evaluate(x: list) -> float:
    """
    使用Bees算法评估超参数组合
    """
    params = to_params(x)

    model = LSTMModel(len(TEXT.vocab),
                      embedding_dim=params['embedding_dim'],
                      hidden_dim=params['hidden_dim'],
                      output_dim=1,
                      n_layers=params['n_layers'],
                      bidirectional=True,
                      dropout=params['dropout'])

    optimizer = optim.Adam(model.parameters())

    criterion = nn.BCEWithLogitsLoss()

    model = model.to(device)
    criterion = criterion.to(device)

    best_valid_loss = float('inf')

    for epoch in range(10):

        train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
        valid_loss, valid_acc = evaluate(model, test_iterator, criterion)

        if valid_loss < best_valid_loss:
            best_valid_loss = valid_loss

    return best_valid_loss

bounds = [(50, 300), (50, 300), (1, 3), (0.1, 0.9)]

pso = PSO(4, bees_evaluate, bounds, minimize=True, max_iter=50)
pso.run()
best_params = to_params(pso.gbest)
print(best_params)

在这里,我们首先定义了to_params和to_x函数来转换超参数组合和Bees算法的参数列表之间的格式。bees_evaluate函数将使用我们定义的超参数来构建模型,并评估其性能。我们使用PSO类来运行Bees算法,该类将使用bees_evaluate函数来评估每个超参数组合。我们使用bounds参数来限制每个超参数的搜索范围。最后,我们将打印出最佳超参数组合。

步骤5:使用最佳超参数训练模型

最后,我们将使用最佳超参数组合来训练我们的模型。

best_model = LSTMModel(len(TEXT.vocab),
                       embedding_dim=best_params['embedding_dim'],
                       hidden_dim=best_params['hidden_dim'],
                       output_dim=1,
                       n_layers=best_params['n_layers'],
                       bidirectional=True,
                       dropout=best_params['dropout'])

optimizer = optim.Adam(best_model.parameters())

criterion = nn.BCEWithLogitsLoss()

best_model = best_model.to(device)
criterion = criterion.to(device)

for epoch in range(10):

    train_loss, train_acc = train(best_model, train_iterator, optimizer, criterion)
    valid_loss, valid_acc = evaluate(best_model, test_iterator, criterion)

    print(f'Epoch: {epoch+1:02}')
    print(f'\tTrain Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
    print(f'\t Val. Loss: {valid_loss:.3f} |  Val. Acc: {valid_acc*100:.2f}%')

在这里,我们使用最佳超参数组合来构建我们的模型,并使用train和evaluate函数来训练和评估模型。我们将模型训练10个周期,并在每个周期结束时打印出训练和测试损失和准确率。

这就是使用PyTorch和Bees算法来调整LSTM模型的文本分类案例的全部内容。

使用PyTorch和Bees算法来调整LSTM模型的文本分类案例

原文地址: https://www.cveoy.top/t/topic/w0g 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录