背景介绍

本文内容是使用CNN进行文本分类,主要记录文本分类问题中使用tensorflow进行神经网络构建的内容。此篇承接上一篇的NLP-使用tensorflow构建神经网络——嵌入层细节部分说明。

目录


  • 背景介绍
  • 目录
  • 一、CNN模型图
  • 二、卷积和池化代码
  • 三、细节说明之tf.truncated_normal;tf.concat;tf.reshape
  • ①tf.truncated_normal(shape, mean, stddev)
  • ②tf.concat(values,axis,name=”concat”)
  • 四、细节说明之relu
  • ①神经网络中的激活函数
  • ②激活函数ReLu
  • ③优化神经网络
  • 五、细节说明之tf.nn.conv2d和tf.nn.max_pool
  • ①tf.nn.conv2d(input,filter,strides, padding,use_cudnn_on_gpu=None, name=None)
  • ②tf.nn.max_pool(value, ksize, strides, padding, name=None)



一、CNN模型图

神经网络nlp和cv nlp神经网络模型_ide


图片来源:论文Convolutional Neural Networks for Sentence Classification


二、卷积和池化代码

# Create a convolution + maxpool layer for each filter size
        pooled_outputs = []#初始化空的list
        for i, filter_size in enumerate(filter_sizes):#遍历卷积核种类,size=2、size=3、、、
            with tf.name_scope("conv-maxpool-%s" % filter_size):
                #建立一个名称为’conv-maxpool-‘的模块
                #  Convolution Layer
                filter_shape = [filter_size, embedding_size, 1, num_filters]
                #卷积核参数:高*宽*通道*卷积核个数,图片中最左侧所示
                W = tf.Variable(tf.truncated_normal(filter_shape, stddev=0.1), name="W")
                # W表示截断产生正态分布数据,方差为0.1,变量维度为filter_shape的张量
                b = tf.Variable(tf.constant(0.1, shape=[num_filters]), name="b")
                # b表示变量维度为卷积核个数,数值为0.1的张量
                conv = tf.nn.conv2d(#实现卷积
                    self.embedded_chars_expanded,
                    W,
                    strides=[1, 1, 1, 1],
                    padding="VALID",
                    name="conv")
                # Apply nonlinearity
                h = tf.nn.relu(tf.nn.bias_add(conv, b), name="relu")#加入偏置,进入relu
                # Maxpooling over the outputs
                pooled = tf.nn.max_pool(#池化操作
                    h,
                    ksize=[1, sequence_length - filter_size + 1, 1, 1],
                    strides=[1, 1, 1, 1],
                    padding='VALID',
                    name="pool")
                pooled_outputs.append(pooled)
                #一个pooled是一种卷积核处理一个样本之后得到的一个值,如果有三种卷积核,则append了三次

        # Combine all the pooled features
        num_filters_total = num_filters * len(filter_sizes)
        # 每种卷积核的个数与卷积核的种类乘积,等于全部的卷积核个数
        self.h_pool = tf.concat(pooled_outputs, 3)
        #将pooled_outputs在第四维度上进行拼接
        self.h_pool_flat = tf.reshape(self.h_pool, [-1, num_filters_total])

代码来源:https://github.com/dennybritz/cnn-text-classification-tf


三、细节说明之tf.truncated_normal;tf.concat;tf.reshape

tf.truncated_normal(shape, mean, stddev)

shape表示要生成的张量的维度,mean为均值,stddev为标准差,截断产生正态分布,数值与均值的差值不超过两倍的标准差。

tf.concat(values,axis,name=”concat”)

value是要进行拼接的张量,axis表示在哪一维度上进行拼接,0表示第一维度,1表示第二维度,依次往后,但是axis+1的值不能超过原本拼接数组本身的维度,例如对于二维数组,axis的值只能为0和1。

# a shape [2, 3]  
# b shape [2, 3]  
tf.shape(tf.concat([a, b],0)) ==> [4, 3]  
tf.shape(tf.concat([a, b],1)) ==> [2, 6]  
-----------------------------------
#a shape [2,3,4]
#b shape [2,3,4]
tf.shape(tf.concat([a,b],0))==> [4, 3,4]  
tf.shape(tf.concat([a,b],1))==> [2,6,4] 
tf.shape(tf.concat([a,b],2))==> [2,3,8]
tf.shape(tf.concat([a,a,a],0))==> [6,3,4]

tf.reshape(tensor,shape,name=None)
tensor为要调整维度的张量,shape为要调整的形状。shape里允许最多有一个维度的值可以是-1,表示未知,根据其他维度的值自动进行计算,和np.reshape()一样。


四、细节说明之relu

①神经网络中的激活函数

如果不使用激励函数,则每一层的输出是上一层输入的线性函数,相当于没有隐藏层,只是矩阵相乘的结果。所以引入非线性函数作为激励函数,可以逼近任何函数,其作用是优化整个神经网络。

②激活函数ReLu

激活函数有好几种,如Sigmoid函数,tanh函数,这些都是比较老旧的激活函数,目前ReLu是最常用的激活函数,它有以下几个优点:

  • 相比于其他函数计算量小(非指数运算)
  • sigmoid函数反向传播时,容易梯度消失造成信息丢失(饱和区倒数为0)
  • Relu使得一部分神经元输出为0,缓解了过拟合现象
③优化神经网络

优化神经网络的方法是反向传播:计算输出层的loss,将loss的导数不断向上一层网络传递,修正相应的参数来降低loss值。
更多关于激活函数的信息点击这个链接,解决了我很多疑问。


五、细节说明之tf.nn.conv2d和tf.nn.max_pool

tf.nn.conv2d(input,filter,strides, padding,use_cudnn_on_gpu=None, name=None)
  • input:要进行卷积的tensor,其shape为[batch, height, width, channels],在文本处理中,输入的tensor是文本词向量,shape为batch_size*seq_len*em_size*channel(=1)的4维tensor。
  • filter:卷积核tensor,其shape为[filter_height, filter_width, in_channels, out_channels],第三个参数 in_channels与input中in_channels值一样。在本文中,tensor的初始值是截断正态分布,shape为filter_size*em_size*channel(=1)*num_filters。
  • strides:步长,一个长度为4的一维向量,分别表示每一维的步长,一般是[1, stride,stride, 1]。
  • padding:”SAME”或”VALID”,表示不同的卷积方式。
  • use_cudnn_on_gpu:使用cudnn加速,默认为true。

举例说明:

tf.nn.max_pool(value, ksize, strides, padding, name=None)
  • value:进行池化的张量,其shape为[batch, height, width, channels].
  • ksize:池化窗口的大小,参数为四维向量,跟输入数据的格式对应,即[batch,height,wide, channels],通常取[1, height, width, 1],因为我们不想在batch和channels上做池化,所以这两个维度设为了1。
  • strides:窗口在每个维度上移动的步长,参数为4维向量,跟输入的格式相对应,一般也是[1, stride,stride, 1]。
  • padding:表示是否填充,与卷积层的padding意思相同,对input张量进行填充0,使得输出的结果shape改变。如果是’SAME’,则得到的输出特征图跟输入特征图形状相同,’VALID’得到的输出特征图跟输入特征图形状不相同。