zoukankan      html  css  js  c++  java
  • 记初次调试CNN做文本向量表示

    心得:
    卷积操作在图像处理的领域应用广泛,图像做卷积处理有一个天然的好处,即:每个像素点的位置与相邻位置相对固定,也就是说,除了边缘,每一个节点都有相同数量的相邻节点。所以卷积操作相对容易。

    但是,随着文本表示的发展,用向量来表示文本的思想应用的越来越广泛深入。textCNN是我理解的卷积在文本表示学习的开山之作,我们知道,图像领域的卷积操作,可以通过不同的卷积核收取一副或一组图像(向量)中的多个特征,那么类比来说,文本上的卷积操作,同样也是向量的卷积操作,一样可以提取文本向量的特征。

    textCNN把文本描述成:词嵌入的序列,卷积操作不再左右滑动,而是只上下滑动,每次卷积操作都涉及到了上下几行(与卷积核的尺寸有关)特征也就是单词,所以我们说卷积操作可以提取到文本的上下文信息,可以更好的表示文本信息。

    操作:
    torch框架作为流行的深度智能框架,配置简单,操作更加适合大众思维。因此尝试使用CNN做文本的向量表示:

    (1) textCNN class
    这个是搭建的建议CNN框架,包含基础的conv层、ReLU、MeanPooling层。代码如下

      import sys
      
      sys.path.append('/home/student/xxx/project/Branch1/')
      # sys.path.append('E:/for_study/pythonMLSpace/Branch1/')
      from torch import nn as nn
      import torch
      import math
      
      
      class bTextCNN(nn.Module):
          def __init__(self, param):
              super(bTextCNN, self).__init__()
              ci = 1  # RGB的通道数 文本的话相当于灰度图只一个通道
              kernel_num = param['kernel_num']  # 卷积核数量,输出向量维度
              kernel_size = param['kernel_size']  # 卷积核尺寸
              vocab_size = param['vocab_size']  # 文本长度n,word-level
              embed_dim = param['embed_dim']  # 输入词嵌入的维度
              dropout = param['dropout']  # dropout比率
              padding = param['padding']
              # class_num = param['class_num']  # 分类数量
              self.param = param
      
              # 两层卷积
              # self.conv1 = nn.Conv2d(in_channels=ci, out_channels=kernel_num, kernel_size=(kernel_size[0], embed_dim))
              # self.relu1 = nn.ReLU(True)
              # self.avgpool1 = nn.AvgPool2d(kernel_size=16)
      
      
      
              layer1 = nn.Sequential()
              layer1.add_module('CONV1', nn.Conv2d(in_channels=ci, out_channels=kernel_num, kernel_size=(kernel_size[0], embed_dim), padding=padding))
              layer1.add_module('RELU1', nn.ReLU(True))
              layer1.add_module('POOL1', nn.AvgPool2d(kernel_size=vocab_size))
              self.layer1 = layer1
      
              layer2 = nn.Sequential()
              layer2.add_module('CONV2', nn.Conv2d(in_channels=ci, out_channels=kernel_num, kernel_size=(kernel_size[0], kernel_num)))
              layer2.add_module('RELU2', nn.ReLU(True))
              layer2.add_module('POOL2', nn.AvgPool2d(kernel_size=vocab_size))
              self.layer2 = layer2
      
              dropoutlayer = nn.Sequential()
              dropoutlayer.add_module('DROPOUT', nn.Dropout(dropout))
              self.dropoutlayer = dropoutlayer
      
              # self.fc1 = nn.Linear(len(kernel_size) * kernel_num, class_num)  # 全连接层
      
          def forward(self, x):
              x = x.unsqueeze(0)  # 增加一个维度,使之适应CNN
              x = x.unsqueeze(0)  # 增加一个维度,使之适应CNN
              # print('input尺寸:' + str(x.size()))
              # out = self.conv1(x)
              # print('conv后尺寸:' + str(out.size()))
              # out = self.relu1(out)
              # print('relu后尺寸:' + str(out.size()))
              # out = self.avgpool1(out)
              # print('pooling后尺寸:' + str(out.size()))
              out = self.layer1(x)
              # out = self.layer2(out)
              out = self.dropoutlayer(out)
              return out
      
          def init_weight(self):
              for m in self.modules():
                  if isinstance(m, nn.Conv2d):
                      n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels
                      m.weight.data.normal_(0, math.sqrt(2. / n))
                      if m.bias is not None:
                          m.bias.data.zero_()
                  elif isinstance(m, nn.BatchNorm2d):
                      m.weight.data.fill_(1)
                      m.bias.data.zero_()
                  elif isinstance(m, nn.Linear):
                      m.weight.data.normal_(0, 0.01)
                      m.bias.data.zero_()
    

    (2) CNN结构设计好之后,需要考虑卷积等的参数:
    param如下:

      textCNN_params = {
          "vocab_siz"': 1000,  # 文本长度,word-level
          "embed_dim": 100,  # 词向量维度
          "kernel_num": 128,  # 卷积核数量
          "kernel_size": [3],  # 卷积核尺寸
          "dropout": 0.2,  # dropout比例
          "padding": 1    # 添加边缘
      }
    

    参数的vocab_size其实不需要设计,但是padding参数,如果补设为1,执行到小于卷积核尺寸的词向量序列时,会报错,报错信息如下:

      RuntimeError: cuDNN error: CUDNN_STATUS_BAD_PARAM
    

    (3) 传入的词嵌入序列:

      curr_word_vec1 = torch.from_numpy(np.array(question_vec_secqence[0:textCNN_params['vocab_size']]))
    

    curr_word_vec1 的结构是二维数组:[[w1的嵌入], [w2的嵌入], [w3的嵌入]...]

  • 相关阅读:
    poj1328
    xml入门简介--两天学会xml
    php的一些特殊用法
    数据结构(一)
    队列的 基本操作
    栈的 基本操作
    线性表----单链表
    线性表----顺序表
    数据结构
    链式队列
  • 原文地址:https://www.cnblogs.com/MaggieForest/p/13236780.html
Copyright © 2011-2022 走看看