链接:https://blog.csdn.net/spring_willow/article/details/80199975
背景介绍
本文内容是使用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模型图
图片来源:论文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])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
代码来源: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]
1
2
3
4
5
6
7
8
9
10
11
③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’得到的输出特征图跟输入特征图形状不相同。