新闻文本分类 TextCNN

首先附上我的Gitee地址: News_Classification
我将整个项目中的东西都上传上去了,只要安装好了python,以及 pytorch, jieba, gensim 应该就可以运行

我这篇博客基本啥也没讲,有些东西说不清楚,建议看我的代码,都有注释,我也刚学深度学习,花了一星期才写完

TextCNN模型示意图

在这里插入图片描述

TextCNN模型定义

Config = {
    'kernel_size': (3, 4, 5),  # 卷积核的不同尺寸
    'output_channels': 200,  # 每种尺寸的卷积核有多少个
    'class_num': 12,  # 分类数量,见data_loader.categories
    'linear_one': 250,  # 第一个全连接层的输出节点数
    'dropout': 0.5,  # 随机丢失节点占比
    'vocab_size': 283302,  # 词库大小,即词的数量, len(model.wv.index_to_key))是word2vec模型中的词库大小
    'vector_size': 100  # 每个词的词向量的长度, word = [.....]
}

# in_channels 就是词向量的维度, out_channels则是卷积核(每个kernel_size都一样多)的数量
# 对于一种尺寸的卷积核  kernel_size = 3,in_channels=100,out_channels=50时,
# 设 x = [32][100]即一个新闻数据, 进行卷积操作前,先对x维度进行变换->[100][32],即每一列是一个词向量,conv1d卷积层左右扫描即可
# x经过卷积操作后会得到[50][30], 分别对应50个卷积核分别对x运算得到的一维数据的结果,即[out_channels][in_channels-kernel_size + 1],
# 然后进行 relu运算,形状不变
# 紧接着进行最大池化操作,每个卷积核运算结果中选出一个最大值,即[30]中选出一个, -> max = [50][1]
# 接着将max转为一维数据 ->[50], 即[out_channels]
# 由于有len(kernel_size)种尺寸的卷积核,所以经过卷积层,池化层有 len(kernel_size) * output_channels 个输出
class NewsModel(nn.Module):
    def __init__(self, config):
        super(NewsModel, self).__init__()
        self.kernel_size = config.get('kernel_size')
        self.output_channels = config.get('output_channels')
        self.class_num = config.get('class_num')
        self.liner_one = config.get('linear_one')
        # self.liner_two = config.get('linear_two')
        self.dropout = config.get('dropout')
        self.vocab_size = config.get('vocab_size')
        self.vector_size = config.get('vector_size')

        # 也可以这么写,不用调用 init_embedding方法,利用已有的word2vec预训练模型中初始化
        # self.embedding = nn.Embedding.from_pretrained(torch.tensor(config.get('embedding_weight')), freeze=False)
        self.embedding = nn.Embedding(num_embeddings=self.vocab_size, embedding_dim=self.vector_size, padding_idx=0)
        # 这里是不同kernel_size的conv1d
        self.convs = [nn.Conv1d(in_channels=self.embedding.embedding_dim, out_channels=self.output_channels,
                                kernel_size=size, stride=1, padding=0).to(device)
                      for size in self.kernel_size]
        self.fc1 = nn.Linear(len(self.kernel_size) * self.output_channels, self.liner_one)
        # self.fc2 = nn.Linear(self.liner_one, self.liner_two)
        self.fc2 = nn.Linear(self.liner_one, self.class_num)
        self.dropout = nn.Dropout(self.dropout)

    # embedding_matrix就是word2vec的get_vector_weight,这个函数自己手动调用,不调用就随机
    def init_embedding(self, embedding_matrix):
        self.embedding.weight = nn.Parameter(torch.tensor(embedding_matrix).to(device))

    # x = torch.tensor([[word1_index, word2_index,..],[],[]])
    # forward这个函数定义了前向传播的运算
    def forward(self, x):
        x = self.embedding(x)  # 词索引经过词嵌入层转化为词向量, [word_index1,word_index2]->[[vector1][vector2]],
        x = x.permute(0, 2, 1)  # 将(news_num, words_num, vector_size)换为(news_num,vector_size,word_num),方便卷积层运算
        # 将所有经过卷积、池化的结果拼接在一起
        x = torch.cat([self.conv_and_pool(x, conv) for conv in self.convs], 1)
        # 展开,[news_num][..]
        x = x.view(-1, len(self.kernel_size) * self.output_channels)
        x = self.dropout(x)
        x = F.relu(self.fc1(x))
        return self.fc2(x)

    @staticmethod
    def conv_and_pool(x, conv):
        x = F.relu(conv(x))
        x = F.max_pool1d(x, x.size(2))  # 最大池化
        x = x.squeeze(2)  # 只保存2维
        return x
  • 2
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值