使用pytorch和torchtext进行文本分类的实例

1. 引言

自然语言处理(NLP)在过去几年中迅速发展。其中,文本分类也是很重要的一环。今天,我们将介绍如何使用 PyTorch 和 TorchText 进行文本分类。

2. 数据集

在这个文本分类的实例中,我们将使用 IMDb 数据集。这个数据集包含了 50,000 条电影评论,其中 25,000 条是在训练集中,另外 25,000 条在测试集中。

在 PyTorch 中,我们可以使用 `torchtext` 轻松地对数据集进行处理。

2.1 安装 torchtext

我们可以使用以下命令来安装 `torchtext` 模块:

pip install torchtext

2.2 下载 IMDb 数据集

我们可以使用以下命令来下载 IMDb 数据集:

wget https://ai.stanford.edu/~amaas/data/sentiment/aclImdb_v1.tar.gz

3. 数据预处理

在 `torchtext` 中,我们可以使用 `Field` 对象进行数据预处理。

我们需要考虑的主要是文本的预处理。在这个例子中,我们需要对原始 IMDb 数据集进行以下处理:

- 移除 HTML 标签;

- 将所有字符转换为小写字母;

- 根据空格划分单词;

3.1 定义预处理规则

在这里,我们将定义 `Field` 类型的对象,以规定文本预处理的方式。我们将使用 `TEXT` 和 `LABEL` 两个类型的对象。`TEXT` 表示数据集中的文本数据,`LABEL` 表示数据集中的标签数据。

from torchtext.legacy.data import Field, TabularDataset

# 定义字段

TEXT = Field(sequential=True, lower=True, tokenize='spacy')

LABEL = Field(sequential=False, use_vocab=False)

# 构建数据集

train, test = TabularDataset.splits(

path = '.',

train = 'train.csv',

test = 'test.csv',

format = 'csv',

fields=[('label', LABEL), ('text', TEXT)],

skip_header = True)

3.2 创建数据迭代器

我们需要使用一个数据迭代器来遍历数据集中的样本。在这里,我们将使用 `BucketIterator` 迭代器。这个迭代器将返回数据集中的一个迭代器,其中每一批数据的长度都是相等的。

from torchtext.legacy.data import BucketIterator

# 创建数据迭代器

train_iter, test_iter = BucketIterator.splits((train, test), batch_size=32, sort_key=lambda x: len(x.text), repeat=False)

4. 构建模型

在这个实例中,我们将使用一个简单的卷积神经网络(CNN)。CNN 已经被广泛应用于文本分类任务。

在 PyTorch 中,我们可以通过继承 `nn.Module` 类来构建自己的模型。

4.1 定义模型

这里是我们模型的定义。CNN 由一个卷积层、一个最大池层和两个全连接层组成。

import torch.nn as nn

import torch.nn.functional as F

class CNN(nn.Module):

def __init__(self, vocab_size, embed_dim, num_filters, filter_sizes, output_dim, dropout):

super().__init__()

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

self.convs = nn.ModuleList([

nn.Conv2d(in_channels=1,

out_channels=num_filters,

kernel_size=(fs, embed_dim))

for fs in filter_sizes

])

self.fc = nn.Linear(len(filter_sizes)*num_filters, output_dim)

self.dropout = nn.Dropout(dropout)

def forward(self, text):

embedded = self.embedding(text)

embedded = embedded.unsqueeze(1)

conved = [F.relu(conv(embedded)).squeeze(3) for conv in self.convs]

pooled = [F.max_pool1d(conv, conv.shape[2]).squeeze(2) for conv in conved]

cat = self.dropout(torch.cat(pooled, dim=1))

return self.fc(cat)

4.2 设置模型参数

接下来,我们设置模型的参数。在这里,我们需要指定词汇表的大小、嵌入层的维度、卷积层的数量及其大小、全连接层的输出维度和 droupout 的概率。

VOCAB_SIZE = len(TEXT.vocab)

EMBED_DIM = 100

NUM_FILTERS = 100

FILTER_SIZES = [3,4,5]

OUTPUT_DIM = 1

DROPOUT = 0.5

model = CNN(VOCAB_SIZE, EMBED_DIM, NUM_FILTERS, FILTER_SIZES, OUTPUT_DIM, DROPOUT)

4.3 查看模型结构

我们可以使用以下命令来查看模型的结构:

print(model)

5. 训练

在这个实例中,我们将使用二元交叉熵损失函数和随机梯度下降(SGD)来训练我们的模型。

5.1 定义损失函数和优化器

我们将使用二元交叉熵损失函数和随机梯度下降(SGD)作为我们的损失函数和优化器。

import torch.optim as optim

criterion = nn.BCEWithLogitsLoss()

optimizer = optim.SGD(model.parameters(), lr=0.01)

5.2 训练模型

我们定义了一个 `train` 函数,来训练我们的模型。在每一轮训练之后,我们会计算一次准确率,并将模型保存。

在每次训练迭代中,我们需要将模型的梯度清零,我们可以使用以下命令来实现:

optimizer.zero_grad()

在得到了模型的预测结果之后,我们需要计算预测结果与真实结果之间的误差。误差可以使用下面的命令来计算:

loss = criterion(predictions, batch.label.float())

在计算出误差后,我们可以通过以下命令来计算梯度并更新参数:

loss.backward()

optimizer.step()

from torch.utils.tensorboard import SummaryWriter

def train(model, iterator, optimizer, criterion):

writer = SummaryWriter('runs/imdb')

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.float())

acc = binary_accuracy(predictions, batch.label.float())

loss.backward()

optimizer.step()

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

5.3 进行测试和评估

在训练完成后,我们需要测试我们的模型。我们将使用 `eval` 函数来使模型在测试模式下运行。

在每一轮中,我们将计算在测试数据集上的准确率和损失。

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.float())

acc = binary_accuracy(predictions, batch.label.float())

epoch_loss += loss.item()

epoch_acc += acc.item()

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

6. 训练模型

我们使用上面定义的 `train` 函数来训练我们的模型。

我们将对模型进行 5 轮训练,并使用 `temperature=0.6` 来控制我们的预测。预测结果会传递给 `sigmoid` 函数,来获取处于 0 到 1 之间的概率值。

N_EPOCHS = 5

best_valid_loss = float('inf')

for epoch in range(N_EPOCHS):

train_loss, train_acc = train(model, train_iter, optimizer, criterion)

valid_loss, valid_acc = evaluate(model, test_iter, criterion)

if valid_loss < best_valid_loss:

best_valid_loss = valid_loss

torch.save(model.state_dict(), 'tut4-model.pt')

print(f'Epoch: {epoch+1:02}')

print(f'Train Loss: {train_loss:.3f} | Train Acc: {train_acc*100:.2f}%')

print(f'Val. Loss: {valid_loss:.3f} | Val. Acc: {valid_acc*100:.2f}%')

7. 结论

在这个实例中,我们介绍了如何使用 PyTorch 和 TorchText 来进行文本分类。我们使用了一个简单的卷积神经网络(CNN)模型,对 IMDb 数据集进行了训练,并在测试集上进行了评估。

我们还介绍了如何使用 `torchtext` 来对数据集进行处理,并使用 `BucketIterator` 迭代器来遍历数据集。

最后,我们通过在测试集上计算准确率和损失,来对我们的模型进行了评估。

以上是 PyTorch 和 TorchText 中的文本分类实例,希望能帮助大家更好地理解文本分类的技术原理。

后端开发标签