使用 PyTorch 进行自然语言处理
介绍
自然语言处理是数据科学和人工智能的一个大领域。它包括多种应用,例如情绪分析、机器翻译、语音识别、聊天机器人创建、市场情报和文本分类。PyTorch是一个流行且功能强大的深度学习库,具有执行自然语言处理任务的丰富功能。在本指南中,您将探索和学习使用PyTorch进行文本分类的自然语言处理技术。
数据和所需库
首先,加载所需的库。您要导入的第一个包是torch库,它用于定义张量并执行数学运算。要导入的第二个库是torchtext库,它是 PyTorch 中的 NLP 库,其中包含数据处理实用程序。
import torch
import torchtext
下一步是加载数据集。torchtext库包含模块torchtext.data ,该模块有多个数据集可用于执行自然语言处理任务。在本指南中,您将使用内置的SogouNews数据集进行文本分类。这是一个监督学习新闻数据集,有五个标签:0代表体育,1代表金融,2代表娱乐,3代表汽车,4代表科技。
下面的代码行加载数据集。设置NGRAMS = 2将确保数据集中的文本将是单个单词加二元词串的列表。
from torchtext.datasets import text_classification
NGRAMS = 2
import os
if not os.path.isdir('./.data'):
os.mkdir('./.data')
train_dataset, test_dataset = text_classification.DATASETS['SogouNews'](
root='./.data', ngrams=NGRAMS, vocab=None)
BATCH_SIZE = 16
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
输出:
sogou_news_csv.tar.gz: 384MB [00:04, 94.7MB/s]
450000lines [08:18, 902.49lines/s]
450000lines [17:33, 427.10lines/s]
60000lines [02:19, 428.77lines/s]
您已经加载了数据,下一步是设置模型架构。
模型架构
该模型架构由一个嵌入层和一个线性层组成。nn.EmbeddingBag函数计算一袋嵌入的平均值(无填充),因为文本长度保存在偏移量中。
下面的前两行代码导入了所需的模块。下一步是在nn.Module中实现TextSentiment()模型类,这是通过第三行代码完成的。
然后,使用__init__()方法设置架构。__ init__()方法下的self参数表示对象本身的实例。参数vocab_size表示词汇表的大小,默认值为 20,000。参数embed_dim表示词嵌入的维度。num_class参数表示目标变量中的类数。
您已经定义了层,但您还需要定义它们如何相互作用。这是通过def forward()函数完成的。简而言之,这意味着您以正向方式从输入到输出。
import torch.nn as nn
import torch.nn.functional as F
class TextSentiment(nn.Module):
def __init__(self, vocab_size, embed_dim, num_class):
super().__init__()
self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True)
self.fc = nn.Linear(embed_dim, num_class)
self.init_weights()
def init_weights(self):
initrange = 0.5
self.embedding.weight.data.uniform_(-initrange, initrange)
self.fc.weight.data.uniform_(-initrange, initrange)
self.fc.bias.data.zero_()
def forward(self, text, offsets):
embedded = self.embedding(text, offsets)
return self.fc(embedded)
模型架构已设置好,下一步是定义上面讨论的将在模型构建中使用的重要参数。这可以通过以下代码完成。
VOCAB_SIZE = len(train_dataset.get_vocab())
EMBED_DIM = 32
NUN_CLASS = len(train_dataset.get_labels())
model = TextSentiment(VOCAB_SIZE, EMBED_DIM, NUN_CLASS).to(device)
批次生成
数据集中的文本长度各不相同,因此需要编写一个生成数据批次的函数。此任务由以下代码中的generate_batch()函数执行。
def generate_batch(batch):
label = torch.tensor([entry[0] for entry in batch])
text = [entry[1] for entry in batch]
offsets = [0] + [len(entry) for entry in text]
offsets = torch.tensor(offsets[:-1]).cumsum(dim=0)
text = torch.cat(text)
return text, offsets, label
定义训练函数
下一步是定义训练函数。在下面的代码中使用辅助函数def train_func(sub_train_)来执行此操作。
从torch.utils.data实用程序导入DataLoader模块,以便于并行加载数据。主要参数包括:
batch_size:每个批次要加载的样本数量。默认值为 1。
collate_fn:合并张量列表以形成张量的小批量。之前创建的generate_batch函数将成为此参数的输入。
3:shuffle:设置为True表示每次迭代都会重新排列数据。默认选项为False。
您还将创建辅助函数来评估训练和测试数据集。
from torch.utils.data import DataLoader
def train_func(sub_train_):
# Train the model
train_loss = 0
train_acc = 0
data = DataLoader(sub_train_, batch_size=BATCH_SIZE, shuffle=True,
collate_fn=generate_batch)
for i, (text, offsets, cls) in enumerate(data):
optimizer.zero_grad()
text, offsets, cls = text.to(device), offsets.to(device), cls.to(device)
output = model(text, offsets)
loss = criterion(output, cls)
train_loss += loss.item()
loss.backward()
optimizer.step()
train_acc += (output.argmax(1) == cls).sum().item()
# Adjust the learning rate
scheduler.step()
return train_loss / len(sub_train_), train_acc / len(sub_train_)
def test(data_):
loss = 0
acc = 0
data = DataLoader(data_, batch_size=BATCH_SIZE, collate_fn=generate_batch)
for text, offsets, cls in data:
text, offsets, cls = text.to(device), offsets.to(device), cls.to(device)
with torch.no_grad():
output = model(text, offsets)
loss = criterion(output, cls)
loss += loss.item()
acc += (output.argmax(1) == cls).sum().item()
return loss / len(data_), acc / len(data_)
模型建立
在构建模型之前,您必须拆分数据,这可以通过torch.utils.data.dataset实用函数中的random_split模块完成。使用随机梯度下降优化器来优化网络,考虑到这是一个分类问题,使用交叉熵作为损失函数。lr 参数指定优化器函数的学习率。最后,打印出epochs性能和所用时间。
import time
from torch.utils.data.dataset import random_split
N_EPOCHS = 5
min_valid_loss = float('inf')
criterion = torch.nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.SGD(model.parameters(), lr=4.0)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, 1, gamma=0.9)
train_len = int(len(train_dataset) * 0.95)
sub_train_, sub_valid_ = \
random_split(train_dataset, [train_len, len(train_dataset) - train_len])
for epoch in range(N_EPOCHS):
start_time = time.time()
train_loss, train_acc = train_func(sub_train_)
valid_loss, valid_acc = test(sub_valid_)
secs = int(time.time() - start_time)
mins = secs / 60
secs = secs % 60
print('Epoch: %d' %(epoch + 1), " | time in %d minutes, %d seconds" %(mins, secs))
print(f'\tLoss: {train_loss:.4f}(train)\t|\tAcc: {train_acc * 100:.1f}%(train)')
print(f'\tLoss: {valid_loss:.4f}(valid)\t|\tAcc: {valid_acc * 100:.1f}%(valid)')
输出:
Epoch: 1 | time in 18 minutes, 17 seconds
Loss: 0.0128(train) | Acc: 93.8%(train)
Loss: 0.0000(valid) | Acc: 95.0%(valid)
Epoch: 2 | time in 17 minutes, 59 seconds
Loss: 0.0080(train) | Acc: 96.1%(train)
Loss: 0.0000(valid) | Acc: 95.9%(valid)
Epoch: 3 | time in 18 minutes, 9 seconds
Loss: 0.0065(train) | Acc: 96.8%(train)
Loss: 0.0000(valid) | Acc: 96.3%(valid)
Epoch: 4 | time in 18 minutes, 19 seconds
Loss: 0.0056(train) | Acc: 97.2%(train)
Loss: 0.0000(valid) | Acc: 95.9%(valid)
Epoch: 5 | time in 18 minutes, 17 seconds
Loss: 0.0048(train) | Acc: 97.6%(train)
Loss: 0.0000(valid) | Acc: 96.4%(valid)
从上面的输出可以看出,该模型在第五个时期的准确率达到了 97.6%。接下来,在测试数据上评估模型性能。
模型评估
下面的代码行检查测试数据并显示结果。
print('Model result on test data...')
test_loss, test_acc = test(test_dataset)
print(f'\tLoss: {test_loss:.4f}(test)\t|\tAcc: {test_acc * 100:.1f}%(test)')
输出:
Model result on test data...
Loss: 0.0000(test) | Acc: 96.2%(test)
在测试数据上模型准确率为96.2%,与在训练数据上模型表现一致,说明模型取得了良好的效果。
结论
在本指南中,您学习了如何使用高性能深度学习库 PyTorch 构建文本分类模型。您学习了使用PyTorch 的torch和torchtext包构建文本分类算法的架构和关键组件。
要了解有关使用 Python 进行数据科学的更多信息,请参阅以下指南。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~