尧图精选

《动手学深度学习》textCNN 文本情感分类实战:一维卷积与时序最大池化详解

🕒 发布时间:2026/10/2 2:14:56 📁 来源:尧图网络
人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载导读文本情感分类Sentiment Analysis是自然语言处理的经典任务本篇文章基于《动手学深度学习》d2l-zh仓库中的 textCNN 章节系统讲解如何将一维卷积神经网络应用于 IMDb 电影评论的情感二分类。你将掌握一维互相关运算的原理与实现、时序最大池化层的设计动机、textCNN 模型的完整结构以及从 IMDb 数据集预处理、GloVe 预训练词向量加载到模型训练与预测的端到端实战流程。背景从图像卷积到文本卷积在仓库的卷积神经网络章节中我们已探究过如何使用二维卷积神经网络处理二维图像数据例如 通道相关概念 中介绍的多输入多输出通道。而在语言模型和文本分类任务里文本数据通常被看作只有一个维度的时间序列自然倾向于使用循环神经网络RNN来建模。textCNN 开创性地指出文本也可以被当作一维图像从而用一维卷积神经网络来捕捉相邻词之间的局部关联。本节介绍的就是将卷积神经网络应用到文本分析的开创性工作之一textCNNKim, 2014[1]。开始实验前首先导入所需的包与模块以仓库contrib/to-rm-mx-contrib-text中保留的 d2lzh 旧版接口为例import d2lzh as d2l from d2lzh import text from mxnet import gluon, init, nd from mxnet.gluon import data as gdata, loss as gloss, nn一维卷积层一维互相关运算的工作原理与二维卷积层类似一维卷积层使用一维的互相关运算卷积窗口从输入数组的最左方开始按从左往右的顺序依次在输入数组上滑动。当窗口滑动到某一位置时窗口中的输入子数组与核数组按元素相乘并求和得到输出数组中相应位置的元素。如下图所示输入是一个宽为 7 的一维数组核数组的宽为 2输出宽度为 $7-216$其中第一个元素由输入最左侧宽为 2 的子数组与核数组按元素相乘再相加得到$0\times11\times22$。手写实现 corr1d下面将一维互相关运算实现在corr1d函数中它接受输入数组X和核数组K输出数组Ydef corr1d(X, K): w K.shape[0] Y nd.zeros((X.shape[0] - w 1)) for i in range(Y.shape[0]): Y[i] (X[i: i w] * K).sum() return Y复现上图的结果X, K nd.array([0, 1, 2, 3, 4, 5, 6]), nd.array([1, 2]) corr1d(X, K)输出为[ 2. 5. 8. 11. 14. 17.]与手工计算一致。多输入通道的一维互相关运算多输入通道的一维互相关运算与多输入通道的二维互相关运算类似在每个通道上将核与相应输入做一维互相关运算然后把各通道结果相加得到最终输出。下图展示了含 3 个输入通道的一维互相关运算阴影部分为第一个输出元素及其计算所用元素$0\times11\times21\times32\times42\times(-1)3\times(-3)2$。复现该结果def corr1d_multi_in(X, K): # 首先沿着X和K的第0维通道维遍历。然后使用*将结果列表变成add_n函数的位置参数 #positional argument来进行相加 return nd.add_n(*[corr1d(x, k) for x, k in zip(X, K)]) X nd.array([[0, 1, 2, 3, 4, 5, 6], [1, 2, 3, 4, 5, 6, 7], [2, 3, 4, 5, 6, 7, 8]]) K nd.array([[1, 2], [3, 4], [-1, -3]]) corr1d_multi_in(X, K)输出为[ 2. 8. 14. 20. 26. 32.]。一维与二维互相关运算的等价关系由二维互相关运算的定义可知多输入通道的一维互相关运算可以等价看作单输入通道的二维互相关运算。如下图所示将图 10.5 的多输入通道一维运算按等价形式呈现这里核的高等于输入的高阴影部分计算结果 $2\times(-1)3\times(-3)1\times32\times40\times11\times22$图 10.4 和图 10.5 中的输出都只有一个通道。在 多输入通道和多输出通道 一节中我们介绍了如何在二维卷积层中指定多个输出通道。类似地也可以在一维卷积层中指定多个输出通道从而拓展卷积层中的模型参数——这正是 textCNN 使用多组不同宽度卷积核的基础。时序最大池化层与一维卷积层对应textCNN 中使用的**时序最大池化max-over-time pooling**层实际上等价于一维全局最大池化层假设输入包含多个通道各通道由不同时间步上的数值组成每个通道的输出即该通道所有时间步中的最大值。因此时序最大池化层的输入在各个通道上的时间步数可以不同——这是它与普通池化的关键区别也是 textCNN 能处理不同长度文本的原因。在实际训练中为了提升计算性能常常将不同长度的时序样本组成一个小批量并通过在较短序列后附加特殊字符如 0令批量中各样本长度一致。这些人为添加的特殊字符显然是无意义的。由于时序最大池化的目的是抓取时序中最重要的特征它通常能使模型不受人为添加填充字符的影响。读取和预处理 IMDb 数据集数据集下载与读取继续使用 IMDb 影评数据集做情感分析。下载、读取与预处理的流程与循环神经网络情感分类章节相同batch_size 64 d2l.download_imdb() train_data, test_data d2l.read_imdb(train), d2l.read_imdb(test) vocab d2l.get_vocab_imdb(train_data) train_iter gdata.DataLoader(gdata.ArrayDataset( *d2l.preprocess_imdb(train_data, vocab)), batch_size, shuffleTrue) test_iter gdata.DataLoader(gdata.ArrayDataset( *d2l.preprocess_imdb(test_data, vocab)), batch_size)从仓库源码contrib/to-rm-mx-contrib-text/d2lzh/utils.py可以还原上述每个步骤的底层实现细节download_imdbutils.py#L119-L125从 Stanford 站点下载aclImdb_v1.tar.gz使用 SHA-1 哈希01ada507287d82875905620988597833ad4e0903校验完整性后解压到../data目录。read_imdbutils.py#L356-L366遍历pos正面标签 1和neg负面标签 0两个目录下的所有评论文本统一转为小写并去除换行最后随机打乱后返回[评论, 标签]列表。get_vocab_imdbutils.py#L195-L200先经get_tokenized_imdb按空格切分单词再用collections.Counter统计词频构建词表时设置min_freq5出现次数少于 5 次的词丢弃并预留pad填充符。preprocess_imdbutils.py#L342-L353将每条评论截断或填充至统一长度max_l 500——短于 500 的用pad补齐长于 500 的直接截断再转为词索引数组和标签数组。现代版 d2l 实现对照当前仓库主干版本d2l/mxnet.py将上述流程整合为统一的load_data_imdbmxnet.py#L2398-L2415一次调用即可返回训练/测试数据迭代器和词表def load_data_imdb(batch_size, num_steps500): data_dir d2l.download_extract(aclImdb, aclImdb) train_data read_imdb(data_dir, True) test_data read_imdb(data_dir, False) train_tokens d2l.tokenize(train_data[0], tokenword) test_tokens d2l.tokenize(test_data[0], tokenword) vocab d2l.Vocab(train_tokens, min_freq5) train_features np.array([d2l.truncate_pad( vocab[line], num_steps, vocab[pad]) for line in train_tokens]) ...其中tokenizemxnet.py#L502-L511负责按空格或字符切分truncate_padmxnet.py#L818-L824负责截断/填充load_arraymxnet.py#L158负责构造数据加载器——填充长度num_steps500与旧版max_l500完全一致。textCNN 模型模型设计思想textCNN 模型主要使用一维卷积层和时序最大池化层。假设输入文本序列由 $n$ 个词组成每个词用 $d$ 维词向量表示那么输入样本的宽为 $n$、高为 1、输入通道数为 $d$。textCNN 的计算分三步多核卷积定义多个不同宽度的一维卷积核分别对输入做卷积。宽度不同的卷积核可以捕捉不同个数相邻词之间的相关性例如二元组、三元组、四元组级别的局部语义。时序最大池化对输出的所有通道分别做时序最大池化再将各通道的池化输出连结为一个向量。全连接分类通过全连接层将连结后的向量变换为各类别输出中间可插入丢弃层dropout以应对过拟合。下图用一个具体例子说明 textCNN 的设计输入是一个含 11 个词的句子每个词用 6 维词向量表示因此输入宽为 11、通道数为 6。给定 2 个一维卷积核核宽分别为 2 和 4输出通道数分别设为 4 和 5。一维卷积后4 个输出通道的宽为 $11-2110$另外 5 个通道的宽为 $11-418$。尽管各通道宽度不同仍可对每个通道做时序最大池化并把 9 个通道的池化输出连结成一个 9 维向量最终用全连接层将 9 维向量变换为 2 维输出即正面、负面情感的预测。TextCNN 类的实现下面实现 textCNN 模型。与循环神经网络版相比除了用一维卷积层替换 RNN 外这里还使用了两个嵌入层一个权重参与训练embedding另一个权重固定constant_embedding二者共同提供词向量表示class TextCNN(nn.Block): def __init__(self, vocab, embed_size, kernel_sizes, num_channels, **kwargs): super(TextCNN, self).__init__(**kwargs) self.embedding nn.Embedding(len(vocab), embed_size) # 不参与训练的嵌入层 self.constant_embedding nn.Embedding(len(vocab), embed_size) self.dropout nn.Dropout(0.5) self.decoder nn.Dense(2) # 时序最大池化层没有权重所以可以共用一个实例 self.pool nn.GlobalMaxPool1D() self.convs nn.Sequential() # 创建多个一维卷积层 for c, k in zip(num_channels, kernel_sizes): self.convs.add(nn.Conv1D(c, k, activationrelu)) def forward(self, inputs): # 将两个形状是(批量大小, 词数, 词向量维度)的嵌入层的输出按词向量连结 embeddings nd.concat( self.embedding(inputs), self.constant_embedding(inputs), dim2) # 根据Conv1D要求的输入格式将词向量维即一维卷积层的通道维变换到前一维 embeddings embeddings.transpose((0, 2, 1)) # 对于每个一维卷积层在时序最大池化后会得到一个形状为(批量大小, 通道大小, 1)的 # NDArray。使用flatten函数去掉最后一维然后在通道维上连结 encoding nd.concat(*[nd.flatten( self.pool(conv(embeddings))) for conv in self.convs], dim1) # 应用暂退法后使用全连接层得到输出 outputs self.decoder(self.dropout(encoding)) return outputs实现要点逐条拆解双嵌入层embedding与constant_embedding的输出沿词向量维dim2连结维度翻倍embed_size * 2。训练时前者可被更新后者梯度置空从而引入静态动态两种词向量信息。维度转置embeddings.transpose((0, 2, 1))将形状从(批量大小, 词数, 词向量维度)变为(批量大小, 词向量维度, 词数)把词向量维映射为Conv1D要求的通道维。共享池化实例nn.GlobalMaxPool1D()无权重因此所有卷积层可共用一个实例对应上节所说的各通道时间步数可以不同。多核融合对每个(conv, pool)对池化输出经flatten去掉宽为 1 的维度再沿通道维dim1连结形成定长的文本表示向量。创建一个TextCNN实例3 个卷积层核宽分别为 3、4、5输出通道数均为 100embed_size, kernel_sizes, nums_channels 100, [3, 4, 5], [100, 100, 100] ctx d2l.try_all_gpus() net TextCNN(vocab, embed_size, kernel_sizes, nums_channels) net.initialize(init.Xavier(), ctxctx)加载预训练词向量与上一节相同加载预训练的 100 维 GloVe 词向量glove.6B.100d.txt分别初始化两个嵌入层——embedding权重参与训练constant_embedding权重固定glove_embedding text.embedding.create( glove, pretrained_file_nameglove.6B.100d.txt, vocabularyvocab) net.embedding.weight.set_data(glove_embedding.idx_to_vec) net.constant_embedding.weight.set_data(glove_embedding.idx_to_vec) net.constant_embedding.collect_params().setattr(grad_req, null)关键点set_data将 GloVe 向量按词表索引写入嵌入层权重setattr(grad_req, null)将固定嵌入层的梯度需求置空使训练时该层权重保持冻结。训练模型使用 Adam 优化器与 Softmax 交叉熵损失训练 5 轮lr, num_epochs 0.001, 5 trainer gluon.Trainer(net.collect_params(), adam, {learning_rate: lr}) loss gloss.SoftmaxCrossEntropyLoss() d2l.train(train_iter, test_iter, net, loss, trainer, ctx, num_epochs)训练完成后用模型对两个简单句子做情感预测d2l.predict_sentiment(net, vocab, [this, movie, is, so, great]) # 预期输出positive d2l.predict_sentiment(net, vocab, [this, movie, is, so, bad]) # 预期输出negativepredict_sentiment的底层逻辑见仓库源码utils.py#L335-L339把句子分词后经vocab.to_indices转成索引数组reshape 为(1, -1)送入网络取argmax得到类别标签 1 判为positive0 判为negative。现代版实现d2l/mxnet.py#L2417-L2423逻辑一致只是改用 numpy 数组接口。小结可以使用一维卷积来表征时序数据把文本当作一维图像处理。多输入通道的一维互相关运算可以看作单输入通道的二维互相关运算。时序最大池化层的输入在各个通道上的时间步数可以不同因此能自然应对变长文本。textCNN 主要使用一维卷积层和时序最大池化层配合预训练词向量即可完成情感分类任务。练习与延伸动手调参从精度和运行效率两个维度对比情感分析的循环神经网络方法与卷积神经网络方法的差异。精度提升尝试上一节练习中介绍的三种方法——调节超参数、使用更大的预训练词向量、使用 spaCy 分词工具——观察测试集精度能否进一步提高。任务迁移思考 textCNN 还能应用于自然语言处理的哪些任务如文本分类、意图识别、关键词提取等。参考文献[1] Kim, Y. (2014). Convolutional neural networks for sentence classification. arXiv preprint arXiv:1408.5882.赞分享人工智能深度学习机器学习教程【免费下载链接】d2l-zh《动手学深度学习》面向中文读者、能运行、可讨论。中英文版被70多个国家的500多所大学用于教学。项目地址https://gitcode.com/GitHub_Trending/d2/d2l-zh点击查看免费下载相关推荐动手学深度学习基于 textCNN 的一维卷积神经网络情感分析实战动手学深度学习基于 textCNN 的一维卷积神经网络情感分析实战 导读 本节围绕《动手学深度学习》d2l zh中的情感分析任务完整讲解如何使用 tex人工智能深度学习机器学习教程《动手学深度学习》d2l-zh实战用 textCNN 卷积神经网络进行情感分析《动手学深度学习》d2l zh实战用 textCNN 卷积神经网络进行情感分析 导读 本文基于《动手学深度学习》d2l zh仓库 chapter_na人工智能深度学习机器学习教程textCNN 情感分析实战基于一维卷积与 Max-Over-Time 池化的文本分类模型d2l-en 多框架实现解析textCNN 情感分析实战基于一维卷积与 Max Over Time 池化的文本分类模型d2l en 多框架实现解析 导读 本文围绕《动手学深度学习》文档教程人工智能深度学习NLP计算机视觉强化学习上一篇3分钟解锁Twitch订阅专属直播回放你的免费通行证下一篇KMS_VL_ALL_AIO3分钟完成Windows和Office终极激活的完整方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →