新闻文本分类任务:使用Transformer实现
Posted Chaos_Wang_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了新闻文本分类任务:使用Transformer实现相关的知识,希望对你有一定的参考价值。
新闻文本分类任务:使用Transformer实现
自然语言处理(NLP)领域中的新闻文本分类任务旨在将一段文本自动分类到某个预定义的类别中,例如体育、政治、科技、娱乐等等。这是一个重要的任务,因为在日常生活中,我们需要处理各种类型的文本,并且需要在其中找到特定的信息。新闻文本分类任务的自动化可以帮助我们更快地了解大量的文本,并提供更好的搜索和推荐服务。在本文中,我们将介绍一些新闻文本分类任务的最新研究,并探讨它们的优势和劣势。
1. 传统机器学习方法
在过去,传统的机器学习方法被广泛应用于新闻文本分类任务。这些方法通常涉及手动选择和提取文本特征,例如词袋模型和tf-idf算法,以及使用一些分类器模型,例如朴素贝叶斯(Naive Bayes)、支持向量机(Support Vector Machine,SVM)和决策树等等。在这些方法中,分类器通常被训练为通过特征集将输入文本映射到其相应的类别。
然而,这些传统的机器学习方法存在一些缺点。例如,手动提取的特征可能不足以捕捉输入文本中的所有信息,并且在实际应用中,需要对特征进行精细的调整和优化。此外,在处理大规模数据集时,这些方法的计算效率可能会受到限制。下面是一个使用传统机器学习方法进行新闻文本分类的示例。
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score
# 定义文本和标签列表
X = ['This is a positive statement.', 'I am happy today.', 'I am sad today.', 'This is a negative statement.']
y = ['Positive', 'Positive', 'Negative', 'Negative']
# 创建特征提取器
vectorizer = CountVectorizer()
# 将文本转换为特征向量
X_vec = vectorizer.fit_transform(X)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_vec, y, test_size=0.2, random_state=42)
# 训练朴素贝叶斯分类器
clf = MultinomialNB()
clf.fit(X_train, y_train)
# 在测试集上进行预测
y_pred = clf.predict(X_test)
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
2. 深度学习方法
近年来,深度学习方法已经成为新闻文本分类任务的热门技术。与传统机器学习方法不同,深度学习方法可以自动从原始数据中学习有意义的特征表示,并且可以应对更复杂的模式和关系。以下是一些深度学习方法的示例。
2.1 卷积神经网络
卷积神经网络(Convolutional Neural Networks,CNN)是一种广泛应用于图像识别和自然语言处理等领域的深度学习模型。在新闻文本分类任务中,CNN可以通过一系列卷积和池化操作来提取文本中的局部特征,并将其组合成更全局的特征表示。CNN的优点在于其可以处理不同长度的输入文本,并且可以避免手动设计特征。下面是一个使用CNN进行新闻文本分类的示例。
代码示例:
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Embedding, Conv1D, GlobalMaxPooling1D, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 定义文本和标签列表
X = ['This is a positive statement.', 'I am happy today.', 'I am sad today.', 'This is a negative statement.']
y = ['Positive', 'Positive', 'Negative', 'Negative']
# 对标签进行编码
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# 将文本转换为序列
vocab_size = 10000
max_length = 20
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=vocab_size)
tokenizer.fit_on_texts(X)
X_seq = tokenizer.texts_to_sequences(X)
X_pad = pad_sequences(X_seq, maxlen=max_length)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_pad, y, test_size=0.2, random_state=42)
# 定义CNN模型
inputs = Input(shape=(max_length,))
x = Embedding(vocab_size, 128)(inputs)
x = Conv1D(128, 5, activation='relu')(x)
x = GlobalMaxPooling1D()(x)
x = Dense(128, activation='relu')(x)
outputs = Dense(1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=outputs)
# 编译模型并训练
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
# 在测试集上进行预测
y_pred = model.predict(X_test)
y_pred = np.round(y_pred).flatten()
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
2.2 递归神经网络
递归神经网络(Recurrent Neural Networks,RNN)是一种能够处理序列数据的深度学习模型。在新闻文本分类任务中,RNN可以自动处理变长的输入文本,并且可以捕捉到文本中的时序信息。例如,在分析一篇新闻报道时,先前提到的事件可能会对后面的内容产生影响。因此,RNN在处理这种情况时可能会更加有效。
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Embedding, SimpleRNN, Dense
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 定义文本和标签列表
X = ['This is a positive statement.', 'I am happy today.', 'I am sad today.', 'This is a negative statement.']
y = ['Positive', 'Positive', 'Negative', 'Negative']
# 对标签进行编码
label_encoder = LabelEncoder()
y = label_encoder.fit_transform(y)
# 将文本转换为序列
vocab_size = 10000
max_length = 20
tokenizer = tf.keras.preprocessing.text.Tokenizer(num_words=vocab_size)
tokenizer.fit_on_texts(X)
X_seq = tokenizer.texts_to_sequences(X)
X_pad = pad_sequences(X_seq, maxlen=max_length)
# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_pad, y, test_size=0.2, random_state=42)
# 定义RNN模型
inputs = Input(shape=(max_length,))
x = Embedding(vocab_size, 128)(inputs)
x = SimpleRNN(128)(x)
x = Dense(128, activation='relu')(x)
outputs = Dense(1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=outputs)
# 编译模型并训练
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
# 在测试集上进行预测
y_pred = model.predict(X_test)
y_pred = np.round(y_pred).flatten()
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
2.3 注意力机制
注意力机制(Attention Mechanism)是一种可以为深度学习模型提供更好的上下文感知能力的技术。在新闻文本分类任务中,注意力机制可以帮助模型更好地理解文本中的关键信息,从而提高分类准确率。下面是一个使用注意力机制进行新闻文本分类的示例。
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Input, Embedding, Bidirectional, LSTM, Dense, Attention
from tensorflow.keras.models import Model
from tensorflow.keras.preprocessing.sequence import pad_sequences
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 定义注意力层
attention = Attention()
# 定义模型
inputs = Input(shape=(max_length,))
x = Embedding(vocab_size, 128)(inputs)
x = Bidirectional(LSTM(128, return_sequences=True))(x)
x = attention(x)
x = Dense(128, activation='relu')(x)
outputs = Dense(1, activation='sigmoid')(x)
model = Model(inputs=inputs, outputs=outputs)
# 编译模型并训练
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test))
# 在测试集上进行预测
y_pred = model.predict(X_test)
y_pred = np.round(y_pred).flatten()
# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print('Accuracy:', accuracy)
3. 模型对比和总结
在本文中,我们介绍了传统机器学习方法和深度学习方法在新闻文本分类任务中的应用。传统机器学习方法需要手动设计特征,并且可能无法捕捉到文本中的所有信息,但是在小数据集上的表现相对较好。深度学习方法可以自动学习特征表示,并且可以处理不同长度的输入文本,但是需要更多的数据和计算资源。在具体的应用中,需要根据数据集规模、任务复杂度和计算资源等因素选择合适的方法。
在深度学习方法中,卷积神经网络、递归神经网络和注意力机制都可以用于新闻文本分类任务。卷积神经网络适用于处理局部特征,递归神经网络适用于处理时序信息,而注意力机制可以帮助模型更好地理解文本中的关键信息。在具体的应用中,需要根据任务需求选择合适的模型。
4. 结论
新闻文本分类任务是自然语言处理领域中的重要任务之一。传统机器学习方法和深度学习方法都可以用于解决该任务,但是需要根据具体的应用需求选择合适的方法和模型。深度学习方法中的卷积神经网络、递归神经网络和注意力机制都可以用于新闻文本分类任务,并且在不同的任务中有着各自的优劣势。新闻文本分类任务的自动化可以帮助我们更快地了解大量的文本,并提供更好的搜索和推荐服务,因此在未来,这个任务还有着广阔的应用前景。
NLP文本分类TorchText实战-AG_NEWS 新闻主题分类任务(PyTorch版)
AG_NEWS 新闻主题分类任务(PyTorch版)
前言
这是TorchText官方的一个教程,更多内容.请参考官方文档:PyTorch / TorchText .
本教程说明如何使用torchtext中的文本分类数据集,包括:
- AG_NEWS,
- SogouNews,
- DBpedia,
- YelpReviewPolarity,
- YelpReviewFull,
- YahooAnswers,
- AmazonReviewPolarity,
- AmazonReviewFull
此示例显示了如何使用这些TextClassification数据集之一训练用于分类的监督学习算法。
1. 使用 N 元组加载数据
一袋 N 元组特征用于捕获有关本地单词顺序的一些部分信息。 在实践中,应用二元语法或三元语法作为单词组比仅一个单词提供更多的好处。 一个例子:
"load data with ngrams"
Bi-grams results: "load data", "data with", "with ngrams"
Tri-grams results: "load data with", "data with ngrams"
TextClassification数据集支持ngrams方法。 通过将ngrams设置为 2,数据集中的示例文本将是一个单字加二元组字符串的列表。
import torch
import torchtext
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['AG_NEWS'](
root='./.data', ngrams=NGRAMS, vocab=None)
BATCH_SIZE = 16
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
2. 安装 Torch-GPU&TorchText
1.安装 Torch-GPU版本,请参考: PyTorch 最新安装教程(2021-07-27)
2.输入以下代码进行安装 TorchText:
pip install torchtext
注意:在Pycharm中以这种方式安装Torchtext,会默认安装最新版0.10.0,其中旧版本的一些方法被弃用;另外,默认会附加安装Pytorch最新版CPU版,这可能会覆盖掉您之前安装的GPU版本的Pytorch,请参考:【PyTorch】Key already registered with the same priority: GroupSpatialSoftmax 解决方法.
原文的这个from torchtext.datasets import text_classification
代码已被弃用,而且text_classification.DATASETS['AG_NEWS']
的参数都变了,详见英文手册。
3. 访问原始数据集迭代器
Torchtext 库提供了一些原始数据集迭代器,这些迭代器产生原始文本字符串。
例如,AG_NEWS数据集迭代器产生的原始数据是标签和文本的元组。
使用此函数时train_data, test_dataset = AG_NEWS(root=path, split=('train', 'test'))
会报错:
TimeoutError: [WinError 10060] A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
这里直接打开url进行下载:
URL = {
'train': "https://raw.githubusercontent.com/mhjabreel/CharCnn_Keras/master/data/ag_news_csv/train.csv",
'test': "https://raw.githubusercontent.com/mhjabreel/CharCnn_Keras/master/data/ag_news_csv/test.csv",
}
注意:该url
内网无法打开,使用IDM下载器可能下载。
推荐:数据集可以在百度云下载,链接:https://pan.baidu.com/s/1FBkweGDEAFgnakZnPpOfLQ 提取码:5oxn
查看数据:
from torchtext.datasets import AG_NEWS
path = '... your path\\\\AG_NEWS.data'
train_data, test_dataset = AG_NEWS(root=path, split=('train', 'test'))
print(next(train_data))
print(next(train_data))
(3, "Wall St. Bears Claw Back Into the Black (Reuters) Reuters - Short-sellers, Wall Street's dwindling\\\\band of ultra-cynics, are seeing green again.")
(3, 'Carlyle Looks Toward Commercial Aerospace (Reuters) Reuters - Private investment firm Carlyle Group,\\\\which has a reputation for making well-timed and occasionally\\\\controversial plays in the defense industry, has quietly placed\\\\its bets on another part of the market.')
4. 准备数据处理管道
我们已经重新审视了torchtext库中最基本的组件,包括vocab、单词向量、tokenizer。
这些都是原始文本字符串的基本数据处理构件。
这里是一个典型的NLP数据处理的例子,使用tokenizer和词汇。
第一步是用原始训练数据集建立一个词汇表,用户可以通过在Vocab类的构造函数中设置参数来拥有一个自定义的词汇表。用户可以通过在Vocab类的构造函数中设置参数来拥有一个自定义的词汇表。例如,要包含的令牌的最小频率min_freq
对于函数lambda,此表达式是一种匿名函数,对应python中的自定义函数def.
词汇块将一个tokens列表转换成整数:
[vocab[token] for token in ['here', 'is', 'an', 'example']]
>>> [476, 22, 31, 5298]
用标记器和词汇准备文本处理管道。文本和标签流水线将用于处理来自数据集迭代器的原始数据字符串:
文本流水线根据词汇表中定义的查找表将文本字符串转换为整数列表。标签流水线将标签转换为整数。
例如:
text_pipeline('here is the an example')
>>> [475, 21, 2, 30, 5286]
label_pipeline('10')
>>> 9
5. 生成数据批次和迭代器
torch.utils.data.DataLoader
推荐给 PyTorch 用户使用(教程在这里)。它适用于实现 getitem()和 len()协议的地图式数据集,并表示从索引/键到数据样本的映射。它也适用于shuffle argumnent为False的可迭代数据集。
在发送至模型之前, collate_fn 函数对 DataLoader 中生成的一批样本进行处理。collate_fn的输入是DataLoader中批量大小的数据, collate_fn根据之前声明的数据处理管道对它们进行处理。这里要注意,一定要将 collate_fn 声明为顶层 def,这样才能保证该函数在每个 worker 中都能使用。
在这个例子中,原始数据批输入中的文本条目被打包成一个列表,并作为一个单一的张量来连接nn.EmbeddingBag的输入。偏移量是一个定界符的张量,用于表示文本张量中各个序列的起始索引。Label是一个张量,保存了indidividual文本条目的标签。
关于torch.cumsum()
函数的用法:
x = torch.arange(0, 6).view(2, 3)
print(x)
print(x.cumsum(dim=0)) # 按照列求和
print(x.cumsum(dim=1)) # 按照行依次求和
tensor([[0, 1, 2],
[3, 4, 5]])
tensor([[0, 1, 2],
[3, 5, 7]])
tensor([[ 0, 1, 3],
[ 3, 7, 12]])
个人理解collate_fn是从样本列表中过来了一个batch的数据,经过映射函数,形成一个tensor。
由于文本条目的长度不同,因此使用自定义函数generate_batch()
生成数据批(一个batch大小的数据)和偏移量。 该函数被传递到torch.utils.data.DataLoader
中的collate_fn
。 collate_fn的输入是张量列表,其大小为batch_size,collate_fn函数将它们打包成一个小批量。 请注意此处,并确保将collate_fn声明为顶级def。 这样可以确保该函数在每个工作程序中均可用。
原始数据批量输入中的文本条目打包到一个列表中,并作为单个张量级联,作为nn.EmbeddingBag的输入。 偏移量是定界符的张量,表示文本张量中各个序列的起始索引。 Label是一个张量,用于保存单个文本条目的标签。
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]
# torch.Tensor.cumsum returns the cumulative sum
# of elements in the dimension dim.
# torch.Tensor([1.0, 2.0, 3.0]).cumsum(dim=0)
offsets = torch.tensor(offsets[:-1]).cumsum(dim=0)
text = torch.cat(text)
return text, offsets, label
6. 定义模型
该模型由nn.EmbeddingBag层加上一个线性层组成,以达到分类的目的。nn.EmbeddingBag默认模式为 “mean”,计算一个 "袋 "的嵌入物的平均值。虽然这里的文本条目有不同的长度,但由于文本长度是以偏移量保存的,所以nn.EmbeddingBag模块在这里不需要填充。
另外,由于nn.EmbeddingBag
会动态累积嵌入中的平均值,因此nn.EmbeddingBag
可以提高性能和存储效率,以处理张量序列。
# 导入必备的torch模型构建工具
import torch.nn as nn
import torch.nn.functional as F
class TextSentiment(nn.Module):
"""文本分类模型"""
def __init__(self, vocab_size, embed_dim, num_class):
"""
description: 类的初始化函数
:param vocab_size: 整个语料包含的不同词汇总数
:param embed_dim: 指定词嵌入的维度
:param num_class: 文本分类的类别总数
"""
super().__init__()
# 实例化embedding层, sparse=True代表每次对该层求解梯度时, 只更新部分权重.
self.embedding = nn.EmbeddingBag(vocab_size, embed_dim, sparse=True)
# 实例化线性层, 参数分别是embed_dim和num_class.
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)
# 偏置初始化为0
self.fc.bias.data.zero_()
def forward(self, text, offsets):
"""
:param text: 文本数值映射后的结果
:return: 与类别数尺寸相同的张量, 用以判断文本类别
"""
# 获得embedding的结果embedded
# >>> embedded.shape
# (m, 32) 其中m是BATCH_SIZE大小的数据中词汇总数
embedded = self.embedding(text, offsets)
return self.fc(embedded)
关于EmbeddingBag()函数,官方文档,参数只多了一个:mode,来看这个参数的取值有三种,对应三种操作:"sum"表示普通embedding后接torch.sum(dim=0),"mean"相当于后接torch.mean(dim=0),"max"相当于后接torch.max(dim=0)
此网络输入输出的例子:
>>> # an Embedding module containing 10 tensors of size 3
>>> embedding_sum = nn.EmbeddingBag(10, 3, mode='sum')
>>> # a batch of 2 samples of 4 indices each
>>> input = torch.LongTensor([1,2,4,5,4,3,2,9])
>>> offsets = torch.LongTensor([0,4])
>>> embedding_sum(input, offsets)
tensor([[-0.8861, -5.4350, -0.0523],
[ 1.1306, -2.5798, -1.0044]])
7. 初始化一个实例
AG_NEWS数据集有四个标签,因此类的数量是四个:
1 : World
2 : Sports
3 : Business
4 : Sci/Tec
我们建立一个嵌入维度为64的模型,vocab大小等于词汇实例的长度,类的数量等于标签的数量4。
# VOCAB_SIZE = len(train_dataset.get_vocab()) 新版本已淘汰
VOCAB_SIZE = len(vocab) # 思路:去重后统计词的总数(参考下面的完整代码)
EMBED_DIM = 32
NUN_CLASS = 4
model = TextSentiment(VOCAB_SIZE, EMBED_DIM, NUN_CLASS).to(device)
8. 定义训练模型和评估结果的函数
关于调整学习率,官方文档,函数:torch.optim.lr_scheduler
提供了几种方法来调整基于epochs的学习率.
torch.optim.lr_scheduler.StepLR
每隔一个step_size epochs,将每个参数组的学习率按gamma衰减。请注意,这种衰减可以与其他来自这个调度器外部的学习率变化同时发生。当last_epoch=-1时,设置初始lr为lr
关于torch.nn.utils.clip_grad_norm_(model.parameters()
, 0.1)函数,作用是剪切参数迭代的梯度法线,官方文档,法线是在所有梯度上一起计算的,就像它们被连成一个向量一样。梯度是就地修改的,即:梯度剪切,规定了最大不能超过的max_norm
对于每一个batch预测的predited_label,是一个64*4的tensor,对于每一个label,是一个64的一维的tensor.
tensor([[ 0.4427, 0.0830, 0.0109, 0.1273],
[ 0.1601, 0.0869, -0.0540, 0.0422],
...
tensor([0, 0, 0, 3, 1, 1, 1, 3, 3, 3, 3, 3, 1, 1, 3, 1, 1, 3, 3, 3, 1, 1, 3, 3,
3, 1, 1, 2, 1, 2, 1, 1, 3, 3, 1, 1, 1, 3, 1, 3, 0, 1, 0, 0, 1, 3, 3, 3,
2, 3, 1, 3, 3, 3, 1, 3, 3, 1, 1, 2, 0, 2, 1, 3])
之前我们用的是.topk()函数,这里了解一下.argmax(1)函数:
print(predited_label.argmax(1) == label)
tensor([False, True, True, True, False, True, True, True, True, True,
True, False, True, True, True, False, True, True, True, True,
True, True, True, True, True, True, True, True, True, True,
True, False, True, False, True, True, True, True, False, True,
True, True, False, True, False, True, True, False, True, True,
True, False, False, True, True, False, True, False, False, True,
False, True, True, True])
执行以下代码输出就是一个常数:
(predited_label.argmax(1) == label).sum().item()
9. 分割数据集并运行模型
由于原AG_NEWS没有有效数据集,我们将训练数据集拆分为训练/有效集,拆分比例为0.95(训练)和0.05(有效)。这里我们使用PyTorch核心库中的torch.utils.data.dataset.random_split
函数
CrossEntropyLoss
准则将nn.LogSoftmax()和nn.NLLLoss()结合在一个类中。它在训练分类问题时非常有用。SGD实现了随机梯度下降法作为优化器。初始学习率设置为5.0。这里使用StepLR通过epochs来调整学习率
打印训练过程:
| epoch 1 | 500/ 1782 batches, accuracy 0.685
| epoch 1 | 1000/ 1782 batches, accuracy 0.852
| epoch 1 | 1500/ 1782 batches, accuracy 0.876
-----------------------------------------------------------
| end of epoch 1 | time: 15.24s | valid accuracy 0.886
-----------------------------------------------------------
| epoch 2 | 500/ 1782 batches, accuracy 0.896
| epoch 2 | 1000/ 1782 batches, accuracy 0.902
| epoch 2 | 1500/ 1782 batches, accuracy 0.902
-----------------------------------------------------------
| end of epoch 2 | time: 15.20s | valid accuracy 0.899
-----------------------------------------------------------
| epoch 3 | 500/ 1782 batches, accuracy 0.915
| epoch 3 | 1000/ 1782 batches, accuracy 0.914
| epoch 3 | 1500/ 1782 batches, accuracy 0.915
-----------------------------------------------------------
| end of epoch 3 | time: 15.22s | valid accuracy 0.904
-----以上是关于新闻文本分类任务:使用Transformer实现的主要内容,如果未能解决你的问题,请参考以下文章
NLP文本分类TorchText实战-AG_NEWS 新闻主题分类任务(PyTorch版)
Python深度学习14——Keras实现Transformer中文文本十分类