(自用)代码研读:TextCNN模型代码分析之model.py

# coding: UTF-8
import torch
import torch.nn as nn#import torch.nn as nn:导入 torch.nn 模块,并将其别名为 nn。torch.nn 模块包含了构建神经网络所需的各种组件和层,如卷积层、全连接层、激活函数等。
import torch.nn.functional as F#import torch.nn.functional as F:导入 torch.nn.functional 模块,并将其别名为 F。torch.nn.functional 模块包含了许多常用的神经网络操作,如激活函数、损失函数、卷积操作等。与 torch.nn 不同,这些操作是以函数的形式提供的,而不是以类的形式。
import numpy as np


class Config(object):#基本参数配置

    """配置参数"""
    def __init__(self, dataset, embedding):
        self.model_name = 'TextCNN'
        self.train_path = dataset + '/data/train.txt'                                # 训练集
        self.dev_path = dataset + '/data/dev.txt'                                    # 验证集
        self.test_path = dataset + '/data/test.txt'                                  # 测试集
        self.class_list = [x.strip() for x in open(
            dataset + '/data/class.txt', encoding='utf-8').readlines()]              # 类别名单
        self.vocab_path = dataset + '/data/vocab.pkl'                                # 词表
        self.save_path = dataset + '/saved_dict/' + self.model_name + '.ckpt'        # 模型训练结果
        self.log_path = dataset + '/log/' + self.model_name
        self.embedding_pretrained = torch.tensor(
            np.load(dataset + '/data/' + embedding)["embeddings"].astype('float32'))\
            if embedding != 'random' else None                                       # 预训练词向量
        self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')   # 设备

        self.dropout = 0.5                                              # 随机失活
        self.require_improvement = 1000                                 # 若超过1000batch效果还没提升,则提前结束训练
        self.num_classes = len(self.class_list)                         # 类别数
        self.n_vocab = 0                                                # 词表大小,在运行时赋值
        self.num_epochs = 20                                            # epoch数
        self.batch_size = 128                                           # mini-batch大小
        self.pad_size = 32                                              # 每句话处理成的长度(短填长切)
        self.learning_rate = 1e-3                                       # 学习率
        self.embed = self.embedding_pretrained.size(1)\
            if self.embedding_pretrained is not None else 300           # 字向量维度
        self.filter_sizes = (2, 3, 4)                                   # 卷积核尺寸
        self.num_filters = 256                                          # 卷积核数量(channels数)


'''Convolutional Neural Networks for Sentence Classification'''


class Model(nn.Module):
    def __init__(self, config):
        super(Model, self).__init__()
        if config.embedding_pretrained is not None:#如果预训练的词向量嵌入矩阵不为空,就用它
            self.embedding = nn.Embedding.from_pretrained(config.embedding_pretrained, freeze=False)#freeze=False表示可以在训练过程中更新词向量
        else:#如果为空,就随机生成,前面是词汇表大小,后面是每个词向量的维度,最后一个是比如生成一个句子的词向量矩阵,矩阵大小固定,句子长度比较小,矩阵长度不够的话进行填充时使用的词汇表中的索引
            self.embedding = nn.Embedding(config.n_vocab, config.embed, padding_idx=config.n_vocab - 1)
        self.convs = nn.ModuleList(#多个卷积层的定义:1表示输入通道数,文本表示通道即为1;输出通道数在这里就是每种过滤器数量;后面两个参数表示卷积核的大小,自定义的k大小*词向量的维度
            [nn.Conv2d(1, config.num_filters, (k, config.embed)) for k in config.filter_sizes])
        self.dropout = nn.Dropout(config.dropout)
        self.fc = nn.Linear(config.num_filters * len(config.filter_sizes), config.num_classes)#全连接层:每种卷积核数量*卷积核种类=最终送入全连接层的向量表示的维度,比如说3种,2个卷积核就是6维,因为经过卷积和池化后每一个卷积核只产生一个标量,然后每一种卷积核产生的向量维度是2,拼起来2*3=6。输出的向量维度就是分类类别数。

    def conv_and_pool(self, x, conv):
        x = F.relu(conv(x)).squeeze(3)
        x = F.max_pool1d(x, x.size(2)).squeeze(2)
        return x

    def forward(self, x):
        out = self.embedding(x[0])#1.取出批次中的第一个句子,形状为[sequence_length],将单词索引转换为对应的词向量,输出形状为[sequence_length, embedding_dim]。(为什么只取第一个?后续看了其他代码记得这里还有一个疑问****)
        out = out.unsqueeze(1)#2.加一个维度,因为卷积层的输入需要输入通道数也就是1(输入通道,输出通道,k,词向量的维度)
        out = torch.cat([self.conv_and_pool(out, conv) for conv in self.convs], 1)#3.通过torch.cat在特征维度0(即维度1)上对卷积和池化后的结果进行拼接
        out = self.dropout(out)#4.droupout
        out = self.fc(out)#5.全连接层
        return out

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值