欢迎访问宙启技术站
智能推送

使用pytorch和torchtext怎么对文本进行分类

发布时间:2023-05-18 16:29:35

PyTorch和TorchText两个工具库的使用可以较为方便地对文本进行分类,下面将从具体的步骤出发,介绍一下具体的实现流程。

1. 数据准备

分类任务的实现首先需要准备好数据集,通常包括训练集、验证集和测试集三个部分。从文本数据源获取原始数据后,可以使用pandas等库对数据进行预处理,并且将文本转化为数字编号的形式。使用TorchText中的数据读取器对数据进行读取:

import torchtext.datasets as datasets

train_data, valid_data, test_data = datasets.IMDB.splits(text_field=text_field, label_field=label_field)

其中,text_field和label_field是TorchText中常用的两个域类型,用于表示输入文本和标签输出。

2. 预处理

在完成数据读取后,需要对文本数据进行处理,如分词、去词干、去停用词等等。TorchText中提供了一些预处理工具,如分词器(tokenizer)、序列化工具(numericalizer)和词向量化工具(embedding)等,可以根据实际情况进行调用。示例代码如下:

from torchtext.data import Field, TabularDataset, BucketIterator

text_field = Field(tokenize=tokenizer, lower=True, sequential=True, use_vocab=True, batch_first=True, fix_length=512)
label_field = Field(sequential=False, use_vocab=False, batch_first=True)

train_data, valid_data, test_data = TabularDataset.splits(
    path="./data/",
    train="train.csv",
    validation="valid.csv",
    test="test.csv",
    format="csv",
    skip_header=True,
    fields=[("Text", text_field), ("Label", label_field)]
)

vectors = "glove.6B.100d"
text_field.build_vocab(train_data, vectors=vectors)

其中,tokenizer是一个分词器函数,在上面的代码中,使用的是spaCy提供的英文分词器。利用这个分词器将文本转化为单词的形式,并在最后一行利用glove预训练的词向量进行词汇表的构建。

3. 构建模型

TorchText中提供了一些现成的模型架构,如TextCNN、TextRNN、Transformer等,也可以自定义模型。在这里,我们使用TextCNN作为例子,代码如下:

import torch.nn as nn
import torch.nn.functional as F


class TextCNN(nn.Module):
    def __init__(self, vocab_size, embedding_dim, out_channels, kernel_sizes, dropout=0.5):
        super(TextCNN, self).__init__()

        self.embedding = nn.Embedding(vocab_size, embedding_dim)
        self.conv1 = nn.Conv2d(in_channels=1,
                               out_channels=out_channels,
                               kernel_size=(kernel_sizes[0], embedding_dim))
        self.conv2 = nn.Conv2d(in_channels=1,
                               out_channels=out_channels,
                               kernel_size=(kernel_sizes[1], embedding_dim))
        self.conv3 = nn.Conv2d(in_channels=1,
                               out_channels=out_channels,
                               kernel_size=(kernel_sizes[2], embedding_dim))
        self.dropout = nn.Dropout(dropout)
        self.fc = nn.Linear(len(kernel_sizes) * out_channels, 2)

    def forward(self, x):
        x = self.embedding(x)
        x = x.unsqueeze(1)
        x1 = F.relu(self.conv1(x)).squeeze(3)
        x2 = F.relu(self.conv2(x)).squeeze(3)
        x3 = F.relu(self.conv3(x)).squeeze(3)
        x1 = F.max_pool1d(x1, x1.size(2)).squeeze(2)
        x2 = F.max_pool1d(x2, x2.size(2)).squeeze(2)
        x3 = F.max_pool1d(x3, x3.size(2)).squeeze(2)
        x = self.dropout(torch.cat((x1, x2, x3), dim=1))
        x = self.fc(x)
        return x

TextCNN模型由多个一维卷积层和池化层以及全连接层组成,可以较好地处理文本数据。

4. 训练模型

接下来,使用构建好的模型对数据进行训练。

import torch.optim as optim

vocab_size = len(text_field.vocab)
embedding_dim = 100
out_channels = 100
dropout = 0.5
kernel_sizes = [3, 4, 5]

model = TextCNN(vocab_size, embedding_dim, out_channels, kernel_sizes, dropout=dropout)
optimizer = optim.Adam(model.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

epochs = 5
for epoch in range(1, epochs + 1):
    model.train()
    for batch in train_iter:
        x = batch.Text
        y = batch.Label
        optimizer.zero_grad()
        output = model(x).squeeze()
        loss = criterion(output, y)
        loss.backward()
        optimizer.step()

    model.eval()
    valid_loss = 0.0
    valid_acc = 0.0
    for batch in valid_iter:
        x = batch.Text
        y = batch.Label
        output = model(x).squeeze()
        loss = criterion(output, y)
        valid_loss += loss.item()
        predictions = torch.argmax(output, dim=1)
        correct = (predictions == y).float()
        valid_acc += correct.sum().item() / correct.size(0)
    valid_loss /= len(valid_iter)
    valid_acc /= len(valid_iter)

    print(f"Epoch {epoch}/{epochs}")
    print(f"Valid loss: {valid_loss:.4f}")
    print(f"Valid acc: {valid_acc:.4f}")

在训练过程中,需要使用交叉熵损失函数和Adam优化器进行参数更新,使用eval模式测试模型的表现。可以通过调节超参数如学习率、卷积核大小、dropout等等得到更好的模型效果。

5. 测试

最后,在测试集上测试模型:

test_loss = 0.0
test_acc = 0.0
for batch in test_iter:
    x = batch.Text
    y = batch.Label
    output = model(x).squeeze()
    loss = criterion(output, y)
    test_loss += loss.item()
    predictions = torch.argmax(output, dim=1)
    correct = (predictions == y).float()
    test_acc += correct.sum().item() / correct.size(0)
test_loss /= len(test_iter)
test_acc /= len(test_iter)

print(f"Test loss: {test_loss:.4f}")
print(f"Test acc: {test_acc:.4f}")

至此,就完成了对文本进行分类的全流程实现,可以得到一个较为准确的文本分类模型。