《自然语言处理指南》- 卷积神经网络在文本分类上的应用(更新中)

TextCNN模型结构

参考文章

卷积操作在文本上的应用

数据源定义
  • 数据为 128 * 30 的文本转索引的数据 即 128行, 单个句子为30个词的文本

  • batch_size = 128max_seq_len = 30

数据embedding
  • num_embeddings : 文本中所有不重复单词的个数
  • embedding层会生成 num_embeddings * embedding_dim 的二维文本向量矩阵
self.embedding = nn.Embedding(num_embeddings=num_embeddings, embedding_dim=64)
  • 最终经过embedding层数据会变成 [batch_size, max_seq_len, embedding_dim] => [128, 30, 64]
卷积层操作
  • 注意 : 卷积层的输入是 单个句子的长度 max_seq_len
  • 卷积层输出out_channels为32, 卷积核kernel_size大小为3, 步长stride为2
self.conv1d = nn.Conv1d(in_channels=30, out_channels=32, kernel_size=3, stride=2)
  • 卷积核输出大小 : [batch_size, out_channels, out]
  • 计算公式如下 :

KaTeX parse error: No such environment: equation at position 8: \begin{̲e̲q̲u̲a̲t̲i̲o̲n̲}̲ L_{\text {out …

  • L i n L_in Lin 是 embedding_dim, 每个单词的向量维度

  • padding 是需要对数据填充的大小, 默认为 0

  • dilation : 默认为 1 目前不知道是干嘛的

  • 输入数据 [128, 30, 64] 经过卷积层后 输出结果为 [128, 32, 31]

池化层操作

  • 定义池化层卷积核大小为31, 步长为 1
  • 池化层的作用是缩减特征, 取卷积核范围内最大的值作为新的特征
  • MaxPool1d 一维池化, 对应卷积核就是 kernel_size * 1, 如果是 MaxPool2d 就是 kernel_size * kernel_size
self.pool = nn.MaxPool1d(kernel_size=31, stride=1)

image-20211102195902390

  • 最终池化结果为 [128, 32, 1]

全连接层

完整代码

# -*- coding: utf-8 -*-
# @Time    : 2021/11/2 15:21
# @Author  : 王天赐
# @Email   : 15565946702@163.com
# @File    : classification_model.py
# @Software: PyCharm
import torch
from torch import nn
import numpy as np
from torch.nn import functional
from torch.utils.data import DataLoader
from twitter_datasets import TwitterDatasets


class TextCNN(nn.Module):
    def __init__(self, num_embeddings):
        super(TextCNN, self).__init__()
        # Embedding的输入是 : [batch_size, seq_len] = 128 * 30
        # 输出 :  [batch_size, seq_len, embedding_dim]
        self.embedding = nn.Embedding(num_embeddings=num_embeddings, embedding_dim=64)
        # in_channels 这个是单个句子的长度 seq_len
        # in_channels : 30 , embedded = [128, 30, 64]
        # out_channels : [128, 32, 62]
        self.conv1d = nn.Conv1d(in_channels=30, out_channels=32, kernel_size=3, stride=2)
        # kernel_size 对应的是最后一维, 获取每一行的特征中的最大值
        self.pool = nn.MaxPool1d(kernel_size=31, stride=1)
        self.decoder = nn.Linear(32, 2)

    def forward(self, inputs):
        # inputs : [128, 30] , embedded : [128, 30, 64]

        embedded = self.embedding(inputs)  # [batch_size, seq_len, embedding_dim]

        # 输出通道宽 :  embedding_dim - kernel_size + 1
        # 输出 : [batch_size, out_channels, L_out]
        # L_out = { (embedding_dim + 2 * padding(默认是0) - dilation(默认是1) * (kernel_size - 1) - 1 } / stride + 1
        # out.size = (64 + 2 * 0 - 1 * (3 - 1) - 1) / 2 + 1 = 31

        out = self.conv1d(embedded)
        # torch.Size([128, 32, 31])
        print(out.size())
        out = self.pool(out)
        # torch.Size([128, 32, 1])
        print(out.size())
        # 去除最后一列
        out = torch.squeeze(out, -1)
        # torch.Size([128, 32])
        print(out.size())
        out = self.decoder(out)
        # [128, 32] *  [32, 2] => [128, 2]
        # torch.Size([128, 2])
        print(out.size())
        return out


if __name__ == '__main__':
    datasets = TwitterDatasets()
    train_loader = DataLoader(datasets, batch_size=128, shuffle=True)
    model = TextCNN(len(datasets.vocab_dict))

    for i, batch in enumerate(train_loader):
        out = model.forward(batch[1])
        print(out.size())

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

兀坐晴窗独饮茶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值