基于Python的自然语言处理系列(8):使用TorchText进行新闻分类

        在本篇文章中,我们将探讨如何使用TorchText库来进行新闻分类任务。我们将使用AG_NEWS数据集,它包含四个分类标签:“World”,“Sports”,“Business”,“Sci/Tech”。我们将详细讲解数据的加载与预处理、模型设计、训练与评估,以及如何在PyTorch中结合RNN进行分类。

1. TorchText简介

        TorchText 是 PyTorch 的一个辅助库,专门用于处理文本数据。虽然 PyTorch 本身已经非常强大,能够处理多种类型的数据集,但TorchText 提供了许多专为自然语言处理(NLP)任务优化的功能,例如文本的加载、处理、词汇构建、批处理等。在这篇文章中,我们将展示如何使用 TorchText 处理新闻分类任务。

import torch, torchdata, torchtext
from torch import nn
import time

# 设置设备
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(device)

# 保持随机性一致
SEED = 1234
torch.manual_seed(SEED)
torch.backends.cudnn.deterministic = True

2. 数据加载与预处理

        我们将使用 AG_NEWS 数据集,该数据集已经包含在 TorchText 库中。我们将通过 DataPipe 加载数据,并进行一些简单的探索性数据分析(EDA)。

2.1 数据加载

from torchtext.datasets import AG_NEWS

# 加载数据
train, test = AG_NEWS()
train_size = len(list(iter(train)))
print(f"训练集大小: {train_size}")

2.2 数据预处理

        为了使模型高效训练,我们将对数据进行随机拆分,并将数据集缩小到较小的子集,以便快速进行模型训练。

too_much, train, valid = train.random_split(total_length=train_size, weights={"too_much": 0.7, "train": 0.2, "valid": 0.1}, seed=999)

train_size = len(list(iter(train)))
val_size = len(list(iter(valid)))
print(f"训练集大小: {train_size}, 验证集大小: {val_size}")

        接下来,我们需要将文本转换为整数表示,即使用 tokenizer 将句子拆分为词,并通过 build_vocab_from_iterator 创建词汇表。

from torchtext.data.utils import get_tokenizer
tokenizer = get_tokenizer('spacy', language='en_core_web_sm')

from torchtext.vocab import build_vocab_from_iterator
def yield_tokens(data_iter):
    for _, text in data_iter:
        yield tokenizer(text)

vocab = build_vocab_from_iterator(yield_tokens(train), specials=['<unk>', '<pad>'])
vocab.set_default_index(vocab["<unk>"])

3. 模型设计

        接下来,我们将设计一个简单的基于RNN的模型来进行文本分类任务。模型包括三个主要部分:embedding层RNN层全连接层

class simpleRNN(nn.Module):
    def __init__(self, input_dim, emb_dim, hid_dim, output_dim):
        super().__init__()
        self.embedding = nn.Embedding(input_dim, emb_dim)
        self.rnn = nn.RNN(emb_dim, hid_dim, batch_first=True)
        self.fc  = nn.Linear(hid_dim, output_dim)
        
    def forward(self, text):
        embedded = self.embedding(text)
        output, hidden = self.rnn(embedded)
        return self.fc(hidden.squeeze(0))

模型初始化与参数设置

        我们为模型的每一层初始化参数,以确保更好的学习效果。

def initialize_weights(m):
    if isinstance(m, nn.Linear):
        nn.init.xavier_normal_(m.weight)
        nn.init.zeros_(m.bias)
    elif isinstance(m, nn.RNN):
        for name, param in m.named_parameters():
            if 'bias' in name:
                nn.init.zeros_(param)
            elif 'weight' in name:
                nn.init.xavier_normal_(param)

input_dim  = len(vocab)
hid_dim    = 256
emb_dim    = 200
output_dim = 4

model = simpleRNN(input_dim, emb_dim, hid_dim, output_dim).to(device)
model.apply(initialize_weights)

4. 模型训练与评估

        我们定义了训练和评估的函数。每个epoch结束后,我们会计算训练和验证的损失与准确率,并保存最佳的验证集模型。

import torch.optim as optim

optimizer = optim.SGD(model.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

def train(model, loader, optimizer, criterion, loader_length):
    model.train()
    epoch_loss, epoch_acc = 0, 0
    for label, text in loader:
        label, text = label.to(device), text.to(device)
        predictions = model(text).squeeze(1)
        loss = criterion(predictions, label)
        acc = (predictions.argmax(1) == label).sum() / len(label)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        epoch_loss += loss.item()
        epoch_acc += acc.item()
    return epoch_loss / loader_length, epoch_acc / loader_length

        同样,我们也定义了模型的评估函数:

def evaluate(model, loader, criterion, loader_length):
    model.eval()
    epoch_loss, epoch_acc = 0, 0
    with torch.no_grad():
        for label, text in loader:
            label, text = label.to(device), text.to(device)
            predictions = model(text).squeeze(1)
            loss = criterion(predictions, label)
            acc = (predictions.argmax(1) == label).sum() / len(label)
            epoch_loss += loss.item()
            epoch_acc += acc.item()
    return epoch_loss / loader_length, epoch_acc / loader_length

5. 模型测试

在训练完成后,我们可以测试模型在随机新闻样本上的表现。你可以输入任意新闻文本,模型将预测它属于哪个类别。

def predict(text):
    model.eval()
    tokens = tokenizer(text)
    indices = vocab(tokens)
    text_tensor = torch.tensor(indices).unsqueeze(0).to(device)
    with torch.no_grad():
        prediction = model(text_tensor)
        return prediction.argmax(1).item()

test_str = "Google is facing major challenges in its recent business strategies."
pred = predict(test_str)
print(f'预测类别: {pred}')

结语

        在这篇文章中,我们探索了如何使用TorchText库进行新闻分类任务。从数据的加载与预处理,到模型的设计与训练,我们详细讲解了每个步骤,尤其是如何利用RNN来处理序列数据。通过这种方式,读者不仅可以掌握如何构建自然语言处理(NLP)pipeline,还能了解如何在实际项目中应用这些技术。

        虽然我们使用了一个简单的RNN模型,但这仅仅是NLP世界的一小部分。在后续的文章中,我们将继续优化模型,尝试更多的高级架构(如LSTM、GRU和Transformer),并探讨如何提升分类的性能和准确性。希望这篇文章能为你在NLP的学习旅程中提供有益的帮助,敬请期待更多深入的技术内容!

如果你觉得这篇博文对你有帮助,请点赞、收藏、关注我,并且可以打赏支持我!

欢迎关注我的后续博文,我将分享更多关于人工智能、自然语言处理和计算机视觉的精彩内容。

谢谢大家的支持!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会飞的Anthony

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值