使用 PyTorch 和 Bees 算法优化 LSTM 模型的文本分类示例
本文将介绍如何使用 PyTorch 和 Bees 算法来调整 LSTM 模型的文本分类案例。我们将训练一个 LSTM 模型来对 IMDb 影评进行二元分类(正面或负面评价),并使用 Bees 算法来调整模型的超参数,以提高模型的准确率。
首先,我们需要准备数据集。我们将使用 IMDb 数据集,它包含 50,000 条 IMDb 影评,其中 25,000 条用于训练,另外 25,000 条用于测试。每个影评都被标记为正面或负面评价。
我们将使用 PyTorch 的 torchtext 库来加载和预处理数据集。首先,我们需要定义数据集的字段:
from torchtext import data
TEXT = data.Field(sequential=True, lower=True, tokenize='spacy')
LABEL = data.LabelField(dtype=torch.float)
这里,我们定义了两个字段:TEXT 和 LABEL。TEXT 表示文本内容,是一个序列,我们将用 spacy 库来对文本进行分词,并将所有单词转换为小写。LABEL 表示影评的标签,是一个标量,它的值为 1 表示正面评价,为 0 表示负面评价。
接下来,我们将加载数据集,并将其拆分为训练集和测试集:
from torchtext import datasets
train_data, test_data = datasets.IMDB.splits(TEXT, LABEL)
现在,我们可以使用训练集来构建词汇表,并将其应用于测试集:
TEXT.build_vocab(train_data, max_size=10000, vectors="glove.6B.100d")
LABEL.build_vocab(train_data)
print('Vocabulary size:', len(TEXT.vocab))
print('Label size:', len(LABEL.vocab))
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
train_iterator, test_iterator = data.BucketIterator.splits(
(train_data, test_data), batch_size=64, device=device)
这里,我们使用了 GloVe 词向量来初始化词汇表。我们还使用了 BucketIterator 来生成训练集和测试集的批次。
接下来,我们将定义 LSTM 模型:
import torch.nn as nn
class LSTM(nn.Module):
def __init__(self, input_dim, embedding_dim, hidden_dim, output_dim):
super().__init__()
self.embedding = nn.Embedding(input_dim, embedding_dim)
self.lstm = nn.LSTM(embedding_dim, hidden_dim)
self.fc = nn.Linear(hidden_dim, output_dim)
self.dropout = nn.Dropout(0.5)
def forward(self, text):
embedded = self.dropout(self.embedding(text))
output, (hidden, cell) = self.lstm(embedded)
hidden = self.dropout(hidden[-1])
return self.fc(hidden)
这里,我们定义了一个 LSTM 模型,它包含一个嵌入层(用于将单词转换为词向量)、一个 LSTM 层和一个全连接层(用于将 LSTM 的输出转换为标签)。我们还添加了一个 dropout 层,以防止过拟合。
接下来,我们将定义训练和测试函数:
import torch.optim as optim
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() 函数,用于训练和测试模型。我们还定义了一个 binary_accuracy() 函数,用于计算准确率。
现在,我们可以训练模型,并评估其性能:
model = LSTM(len(TEXT.vocab), 100, 256, 1)
model.to(device)
optimizer = optim.Adam(model.parameters())
criterion = nn.BCEWithLogitsLoss()
N_EPOCHS = 5
for epoch in range(N_EPOCHS):
train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
test_loss, test_acc = evaluate(model, test_iterator, criterion)
print(f'Epoch: {epoch+1:02}')
print(f' Train Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')
print(f' Test Loss: {test_loss:.3f} | Test Acc: {test_acc*100:.2f}%')
这里,我们使用 Adam 优化器和 BCEWithLogitsLoss 损失函数来训练模型。我们将模型迭代 5 次,并在每次迭代后评估其性能。我们希望通过调整超参数来提高模型的准确率。
现在,我们将使用 Bees 算法来调整 LSTM 模型的超参数。我们将使用 hyperopt 库来实现 Bees 算法。首先,我们需要定义超参数空间:
from hyperopt import hp
space = {
'embedding_dim': hp.choice('embedding_dim', [50, 100, 200]),
'hidden_dim': hp.choice('hidden_dim', [128, 256, 512]),
'dropout': hp.uniform('dropout', 0, 0.5),
'lr': hp.loguniform('lr', -6, -3),
'batch_size': hp.choice('batch_size', [32, 64, 128])
}
这里,我们定义了五个超参数:embedding_dim(嵌入层维度)、hidden_dim(LSTM 层维度)、dropout(dropout 概率)、lr(学习率)和 batch_size(批次大小)。
接下来,我们将定义目标函数,即我们要优化的指标:
import time
def objective(params):
model = LSTM(len(TEXT.vocab), params['embedding_dim'], params['hidden_dim'], 1)
model.to(device)
optimizer = optim.Adam(model.parameters(), lr=params['lr'])
criterion = nn.BCEWithLogitsLoss()
train_iterator, test_iterator = data.BucketIterator.splits(
(train_data, test_data), batch_size=params['batch_size'], device=device)
for epoch in range(N_EPOCHS):
train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
test_loss, test_acc = evaluate(model, test_iterator, criterion)
return {'loss': -test_acc, 'status': 'ok'}
这里,我们定义了一个 objective() 函数,它将超参数作为输入,并返回一个字典,其中包含我们要优化的指标(即负的测试准确率)。
现在,我们可以使用 hyperopt 库来运行 Bees 算法,并搜索最佳超参数:
from hyperopt import tpe, fmin, Trials
trials = Trials()
best = fmin(fn=objective,
space=space,
algo=tpe.suggest,
max_evals=50,
trials=trials)
print(best)
这里,我们使用 tpe.suggest 算法来指导搜索过程。我们将最多进行 50 次评估,并将 Trials 对象传递给 fmin() 函数,以记录每次评估的结果。
最后,我们可以使用最佳超参数来训练模型,并评估其性能:
best_params = trials.best_trial['result']['params']
model = LSTM(len(TEXT.vocab), best_params['embedding_dim'], best_params['hidden_dim'], 1)
model.to(device)
optimizer = optim.Adam(model.parameters(), lr=best_params['lr'])
criterion = nn.BCEWithLogitsLoss()
train_iterator, test_iterator = data.BucketIterator.splits(
(train_data, test_data), batch_size=best_params['batch_size'], device=device)
for epoch in range(N_EPOCHS):
train_loss, train_acc = train(model, train_iterator, optimizer, criterion)
test_loss, test_acc = evaluate(model, test_iterator, criterion)
print(f'Best params: {best_params}')
print(f'Best test acc: {test_acc*100:.2f}%')
这里,我们使用最佳超参数来训练模型,并在测试集上评估其性能。我们可以看到,使用 Bees 算法调整超参数后,模型的准确率有所提高。
在本文中,我们介绍了如何使用 PyTorch 和 Bees 算法来调整 LSTM 模型的文本分类案例。我们使用 IMDb 数据集训练了一个 LSTM 模型,并使用 Bees 算法来搜索最佳超参数。最后,我们使用最佳超参数来训练模型,并在测试集上评估其性能。
原文地址: https://www.cveoy.top/t/topic/lLeI 著作权归作者所有。请勿转载和采集!