TextCNN pytorch实现

本文介绍了TextCNN的结构,包括embedding、卷积层、MaxPooling和全连接层,并提供了PyTorch实现的代码示例。通过卷积神经网络捕捉文本局部特征,应用于IMDB电影评论情感分析。在训练和优化模型时,讨论了滤波器尺寸、数量、激活函数、正则化等关键参数的选择和调整策略。
摘要由CSDN通过智能技术生成

TextCNN结构

以下为原论文中的模型结构图:
在这里插入图片描述

  1. embedding
  2. 卷积层
  3. MaxPooling
  4. Flatten
  5. 全连接层

卷积操作

  • 在卷积神经网络中仅涉及离散卷积的情形。
  • 卷积运算的作用就类似与滤波,因此也称卷积核为filter滤波器。
  • 卷积神经网络的核心思想是捕捉局部特征(n-gram)。CNN的优势在于能够自动地对g-gram特征进行组合和筛选,获得不同抽象层次的语义信息。
  • 下图为用于文本分类任务的TextCNN结构描述(这里详细解释了TextCNN架构以及词向量矩阵是如何做卷积的)
    在这里插入图片描述
  1. 输入层: n ∗ k n*k nk的矩阵,n为句子中的单词数,k为embedding_size。(为了使向量长度一致,对原句进行了padding操作)
  2. 卷积层:在NLP中输入层是一个由词向量拼成的词矩阵,且卷积核的宽和该词矩阵的宽相同,该宽度即为词向量大小,且卷积核只会在高度方向移动。输入层的矩阵与我们的filter进行convolution,然后经过激活函数得到feature map。filter这里有三种大小(3,4,5)。
  3. 池化层:max-pooling
  4. softmax输出结果。

简单代码实现

import torch
import numpy as np
import torch.nn as nn
import torch.optim as optim
import torch.utils.data as Data
import torch.nn.functional as F

dtype = torch.FloatTensor
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# 3 words sentences (=sequence_length is 3)
sentences = ["i love you", "he loves me", "she likes baseball", "i hate you", "sorry for that", "this is awful"]
labels = [1, 1, 1, 0, 0, 0]  # 1 is good, 0 is not good.

embedding_size = 2
sequence_length = len(sentences[0])
num_classes = len(set(labels))
batch_size = 3

word_list = " ".join(sentences).split()
vocab = list(set(word_list))
word2idx = {
   w:i for i,w in enumerate(vocab)}
vocab_size = len(vocab)
def make_data(sentences, labels):
    inputs = []
    for sen in sentences:
        inputs.append([word2idx[n] for n in sen.split()])

    targets = []
    for out in labels:
        targets.append(out)

    return inputs, targets
input_batch, target_batch = make_data(sentences, labels)
input_batch, target_batch = torch.LongTensor(input_batch), torch.LongTensor(target_batch)

dataset = Data.TensorDataset(input_batch,target_batch)
loader = Data.DataLoader(dataset, batch_size, True)
class TextCNN(nn.Module):

    def __init__(self):
        super(TextCNN, self).__init__()
        self.W = nn.Embedding(vocab_size, embedding_size)
        output_channel = 3
        self.conv = nn.Sequential(nn.Conv2d(1, output_channel, (2,embedding_size)), # inpu_channel, output_channel, 卷积核高和宽 n-gram 和 embedding_size
                                nn.ReLU(),
                                nn.MaxPool2d((2,1)))
        self.fc = nn.Linear(output_channel,num_classes)

    def forward(self, X):
      '''
      X: [batch_size, sequence_length]
      '''
      batch_size = X.shape[0]
      embedding_X = self.W(X) # [batch_size, sequence_length, embedding_size]
      embedding_X = embedding_X.unsqueeze(1) # add channel(=1) [batch, channel(=1), sequence_length, embedding_size]
      conved = self.conv(embedding_X) # [batch_size, output_channel,1,1]
      flatten = conved.view(batch_size, -1)# [batch_size, output_channel*1*1]
      output = self.fc(flatten)
      return output

维度变换

  1. 输入X:[batch_size, sequence_length]
  2. embedding:相当于把单词增加了一个维度。[batch_size, sequence_length, embedding_size];然后我们对它做了一个unsqueeze(1)操作,原因是卷积操作的需要。[batch_size, channel(=1), sequence_length, embedding_size]
  3. conved:我们这了进行了一个二维卷积,input_channel为1,output_channel为3,filter_size为(2,embedding_size),相当于bi-gram。
    [batch_size, output_channel,sequence_len-1, 1]

卷积输出的高和宽的计算公式:
h e i g h

以下是基于Pytorch实现textcnn文本分类模型的代码,其中使用了CNN对文本进行卷积和池化,再经过全连接层进行分类。具体代码如下: ```python import torch import torch.nn as nn import torch.nn.functional as F class TextCNN(nn.Module): def __init__(self, vocab_size, embedding_dim, num_classes, filter_sizes, num_filters): super(TextCNN, self).__init__() self.embeddings = nn.Embedding(vocab_size, embedding_dim) self.convs = nn.ModuleList([ nn.Conv2d(1, num_filters, (fs, embedding_dim)) for fs in filter_sizes ]) self.fc = nn.Linear(num_filters * len(filter_sizes), num_classes) def forward(self, x): x = self.embeddings(x) # (batch_size, seq_len, embedding_dim) x = x.unsqueeze(1) # (batch_size, 1, seq_len, embedding_dim) x = [F.relu(conv(x)).squeeze(3) for conv in self.convs] # [(batch_size, num_filters, seq_len - filter_size + 1), ...] x = [F.max_pool1d(conv, conv.shape[2]).squeeze(2) for conv in x] # [(batch_size, num_filters), ...] x = torch.cat(x, 1) # (batch_size, num_filters * len(filter_sizes)) x = self.fc(x) # (batch_size, num_classes) return x ``` 其中,`vocab_size`表示词汇表大小,`embedding_dim`表示词向量维度,`num_classes`表示分类数目,`filter_sizes`表示卷积核大小,`num_filters`表示卷积核个数。 在`forward`函数中,首先将输入的文本通过词向量层进行转换,得到(batch_size, seq_len, embedding_dim)的张量。然后通过卷积层和池化层对文本进行特征提取,得到形状为(batch_size, num_filters * len(filter_sizes))的张量,最后通过全连接层进行分类。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值