这里我们将介绍如何实现常见的卷积层和池化层
这里我们以二维数据为例进行介绍
第1步:引入相应的库并创建计算图会话
import tensorflow as tf
import numpy as np
#创建计算图会话
sess = tf.Session()
第2步:创建数据并初始化占位符,这里输入数据shape = [10,10]
#准备数据
data_size = [10,10]
data_2d = np.random.normal(size=data_size)
#占位符
x_input_2d = tf.placeholder(tf.float32,shape=data_size)
第3步:声明卷积层函数,这里采用TensorFlow内建函数tf.nn.conv2d(),由于该函数需要输入4维数据(批量大小,宽度,高度,颜色通道),因此首先需要对输入数据进行扩维。tf.expand.dims函数为扩维函数,其作用是在给定位置增加一维。例如输入数据shape = [10,10],则tf.expand_dims(input_2d,0)的shape为[1,10,10]。
其次配置相应的滤波器,步长stride以及padding
滤波器选用外部输入滤波器参数myfilter,步长为两个方向为2,padding为VALID。
最后采用tf.squeeze函数将卷积后的数据shape转换为2维数据
#声明卷积层
#由于conv2d()函数为4维数据设计,包括[batch_size,width,height,channels],所以需要4维数据
def conv_layer_2d(input_2d , myfilter):
#将数据转化为4维
input_3d = tf.expand_dims(input_2d,0) #shape = [1,10,10]
input_4d = tf.expand_dims(input_3d,3) #shape = [1,10,10,1]
#卷积操作
#这里设置两个方向上的补偿,padding选择no padding,myfileter采用2*2,因此10*10 ==>5*5
conv_out = tf.nn.conv2d(input=input_4d,filter=myfilter,strides=[1,2,2,1],padding='VALID')
#维度还原
conv_out_2d = tf.squeeze(conv_out) #shape = [5,5]
return conv_out_2d
这里定义滤波器大小为2X2,经过上述创建的卷积层后,输出数据shape为[5,5]
myfilter = tf.Variable(tf.random_normal(shape=[2,2,1,1]))
my_convolution_output = conv_layer_2d(x_input_2d,myfilter)
第4步:声明激励函数,激励函数是针对逐个元素的,创建激励函数并初始化后将上述卷积层后得到的数据通过激励函数。
#激励函数
#这里选择ReLu作为激活函数
def activation(input_2d):
return tf.nn.relu(input_2d)
my_activation_output = activation(my_convolution_output)
第5步:池化层
输入为经激活函数后的数据,shape=[5,5]
池化层仍采用TensorFlow内建函数,其处理方式与卷积层类似,仍然先扩维,然后通过池化函数tf.nn.max_pool,最后降维得到输出数据,这里池化层步长为1,宽和高为2X2,shape变为[4,4]
def max_pool(input_2d,width,height):
#先将数据扩展为4维
input_3d = tf.expand_dims(input_2d,0) #shape = [1,5,5]
input_4d = tf.expand_dims(input_3d,3) #shape = [1,5,5,1]
#池化操作
pool_output = tf.nn.max_pool(input_4d,ksize=[1,height,width,1],strides=[1,1,1,1],padding='VALID')
#降维
pool_output_2d = tf.squeeze(pool_output)#shape = [4,4]
return pool_output_2d
my_maxpool_output = max_pool(my_activation_output,width=2,height=2)
第6步:全连接层
输入为经池化层后的数据,shape = [4,4]以及需要连接的神经元个数num_outputs = 5
这里为保证所有数据均能够与神经元相连接,首先将数据转化为一维向量,并计算y=wx+b中w和b的shape
输入数据的shape变为[16],我们通过tf.shape得到该shape,然后通过tf.stack将输入shape与神经元个数连接得到shape为[[16],[5]],最后通过tf.squeeze得到w的shape为[16,5],b的shape为5
最后由于y=wx+b为矩阵运算,需要将数据扩维至2维数据,经计算后再通过降维还原回一维数据,这里输出为5个神经元的值
#全连接层
def fully_connected(input_layer,num_outputs):
#首先将数据转化为一维向量,以实现每项连接到每个输出
flat_input = tf.reshape(input_layer,[-1])
#创建w和b
#确定w和b的shape
#tf.shape得到数据的大小例如4*4的数据变为向量,则shape=16,
#tf.stack为矩阵拼接,设num_outputs = 5,则其结果为[[16],[5]]
#tf.squeeze降维,使其结果为[16,5]满足shape输入格式要求
weight_shape = tf.squeeze(tf.stack([tf.shape(flat_input),[num_outputs]]))
weight = tf.random_normal(shape=weight_shape,stddev=0.1)
bias = tf.random_normal(shape=[num_outputs])
#将数据转化为2维以完成矩阵乘法
input_2d = tf.expand_dims(flat_input,0)
#进行计算y=wx+b
fully_output = tf.add(tf.matmul(input_2d,weight),bias)
#降维
fully_output_result = tf.squeeze(fully_output)
return fully_output_result
my_full_output = fully_connected(my_maxpool_output,num_outputs=5)
第7步:初始化变量并写入计算图中,然后打印出来
#初始化变量
init = tf.initialize_all_variables()
sess.run(init)
feed_dict = {x_input_2d:data_2d}
#打印各层
#卷积层
print('Input = [10 10] array')
print('Convolution [2,2],stride size = [2,2], results in the [5,5] array:')
print(sess.run(my_convolution_output,feed_dict=feed_dict))
#激活函数输出
print('Input = the above [5,5] array ')
print('ReLU element wise returns the [5,5] array ')
print(sess.run(my_activation_output,feed_dict=feed_dict))
#池化层输出
print('Input = the above [5,5] array ')
print('Maxpool,stride size = [1,1], results in the [4,4] array ')
print(sess.run(my_maxpool_output,feed_dict=feed_dict))
#全连接层输出
print('Input = the above [4,4] array ')
print('Fully connected layer on all four rows with five outputs:')
print(sess.run(my_full_output,feed_dict=feed_dict))
下面是打印结果:
Input = [10 10] array
Convolution [2,2],stride size = [2,2], results in the [5,5] array:
[[ 1.32886136 -1.47333026 -1.44128537 -0.95050871 -1.80972886]
[-2.82501674 -0.35346282 -0.06931959 1.9739815 -0.84173405]
[ 0.5519557 -1.66942024 0.56509626 -2.68546128 0.71953934]
[-3.13675737 -1.81401241 1.47897935 -0.1665355 0.05618015]
[ 2.81271505 -4.40996552 -1.39324057 1.17697966 -2.26855183]]
Input = the above [5,5] array
ReLU element wise returns the [5,5] array
[[ 1.32886136 0. 0. 0. 0. ]
[ 0. 0. 0. 1.9739815 0. ]
[ 0.5519557 0. 0.56509626 0. 0.71953934]
[ 0. 0. 1.47897935 0. 0.05618015]
[ 2.81271505 0. 0. 1.17697966 0. ]]
Input = the above [5,5] array
Maxpool,stride size = [1,1], results in the [4,4] array
[[ 1.32886136 0. 1.9739815 1.9739815 ]
[ 0.5519557 0.56509626 1.9739815 1.9739815 ]
[ 0.5519557 1.47897935 1.47897935 0.71953934]
[ 2.81271505 1.47897935 1.47897935 1.17697966]]
Input = the above [4,4] array
Fully connected layer on all four rows with five outputs:
[-1.14044487 0.18718313 2.26356006 -0.60274446 0.6560365 ]