卷积神经网络想必大家都不陌生,这里之前很早写的卷积神经网络的程序,拿出来和大家分享一下
卷积神经网络的tensorflow实现
What
卷积神经网络是一种用卷积操作代替全连接的神经网络形式,他具有平移不变性,参数共享等优点。
下面针对卷积神经网络在tensorflow中的实现代码进行讲解。
其中网络由两层卷积神经网络层以及两层全连接层组成。
How
主文件:Convolutional_Neural_Network.py
首先导入头文件以及导入数据
导入
from modular.random_choose import corresponding_choose
from tensorflow import Session,global_variables_initializer,transpose,keras
from modular.cnn_define import cnn_layer2
from modular.compute_accuracy import compute_accuracy
(train_x_image, train_y), (test_x_image, test_y) = keras.datasets.mnist.load_data(path='/home/xiaoshumiao/.keras/datasets/mnist.npz')
train_y = keras.utils.to_categorical(train_y)
test_y=keras.utils.to_categorical(test_y)
然后是定义卷积神经网络类:
n = cnn_layer2(28,28,10)
其他定义
init = global_variables_initializer()
with Session() as sess:
sess.run(init)
for i in range(2000):
train_data = corresponding_choose(train_x_image, 500,m=0)
train_x_betch = train_data.row_2(train_x_image)/255.
train_y_betch = train_data.row(train_y)
sess.run(n.train_step,feed_dict={n.xs:train_x_betch,n.ys:train_y_betch,n.keep_prob:0.5})
if i % 200 == 0:
test_data = corresponding_choose(test_x_image,1000, m=0)
test_x_betch = test_data.row_2(test_x_image)/255.
test_y_betch = test_data.row(test_y)
b = sess.run(n.fnn2, feed_dict={n.xs: test_x_betch, n.keep_prob: 1})
c = sess.run(compute_accuracy(b, transpose(test_y_betch)))
print(c)
支持文件:cnn_define.py
cnn_layer2
### cnn_layer2
```python
class cnn_layer2(object):
def __init__(self,in_size_x,in_size_y,out_size):
self.xs = placeholder(float32,[None,in_size_x,in_size_y])
self.ys = placeholder(float32,[None,out_size])#!!!!!!!!!!!!!!!!!!!!!!transform format
self.keep_prob = placeholder(float32)
self.x_image = reshape(self.xs,[-1,28,28,1])#-1 means batch;28,28 means picture's size;1 means channel
self.cnn1 = add_layer_5x5(self.x_image, 1, 32)
self.cnn2 = add_layer_5x5(self.cnn1, 32, 64)
self.fnn1 = add_layer_dropput(transpose(reshape(self.cnn2,[-1,7*7*64])),7*7*64, 100,keep_prob=self.keep_prob,activation_function=nn.sigmoid) # !!!!!!!!!!!!!!!transform formatprint(self.cnn2)
self.fnn2 = add_layer_dropput(self.fnn1,100,10,keep_prob = self.keep_prob,activation_function=nn.softmax)
self.loss = reduce_mean(-reduce_sum(multiply(transpose(self.ys),log(self.fnn2)),reduction_indices=[0])) #cross_entropy
self.train_step = train.AdamOptimizer(0.00009).minimize(self.loss)
这里的前三行,是正常的定义输入数据格式,输入数据是二维图片格式,与上面的数据格式相对应,以及dropout参数。
self.xs = placeholder(float32,[None,in_size_x,in_size_y])
self.ys = placeholder(float32,[None,out_size])
self.keep_prob = placeholder(float32)
定义神经网络的输入数据格式
self.x_image = reshape(self.xs,[-1,28,28,1])#-1 means batch;28,28 means picture's size;1 means channel
定义两层卷积网络层
self.cnn1 = add_layer_5x5(self.x_image, 1, 32)
self.cnn2 = add_layer_5x5(self.cnn1, 32, 64)
定义两层全连接层
self.fnn1 = add_layer_dropput(transpose(reshape(self.cnn2,[-1,7*7*64])),7*7*64, 100,keep_prob=self.keep_prob,activation_function=nn.sigmoid) # !!!!!!!!!!!!!!!transform formatprint(self.cnn2)
self.fnn2 = add_layer_dropput(self.fnn1,100,10,keep_prob = self.keep_prob,activation_function=nn.softmax)
定义损失和训练函数
self.loss = reduce_mean(-reduce_sum(multiply(transpose(self.ys),log(self.fnn2)),reduction_indices=[0])) #cross_entropy
self.train_step = train.AdamOptimizer(0.00009).minimize(self.loss)
add_layer_5x5
然后主要来看卷积神经网络层的定义
def add_layer_5x5(x,in_layer,out_layer):
W_conv = weight_variable([5,5,in_layer,out_layer])#《深度学习》p212,patch: 5*5; in_put layer: 1; out_put layer: 32
b_conv = bias_variable([out_layer])
output = nn.relu(conv2d_conventional(x,W_conv)+b_conv)
a = max_pool_2x2_nonrepeat(output)
return a
可以看出我们首先定义卷积核大小为5x5大小,输入通道为1,输出通道为32。然后经过卷积操作以及RELU以后,经过2x2的最大池化输出。
conv2d_conventional
然后我们再来看卷积函数的定义
def conv2d_conventional(x,W):
return nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME')
关于stride的格式如下:
strides:卷积移动步长,是一个有四个元素的1维Tensor,strides=[b,h,w,c],
b:决定对哪些图片进行卷积,默认为1,即对所有图片卷积;
h:卷积核在每张图片高度方向的移动步长;
w:卷积核在每张图片宽度方向的移动步长;
c:决定对每张图片的哪些通道进行卷积,默认为1,即对所有通道进行卷积;
通常都是strides=[1,h,w,1],对所有图片的所有通道卷积
tensorflow中二维卷积函数tf.nn.conv2d()解析
所以在这里我们就是全卷积,并且padding为same,即图像的长宽与输入数据相比不变,输出通道数与之无关,可以增加或者减少。
根据卷积网络层的定义,接下来我们要看池化层的定义
max_pool_2x2_nonrepeat
def max_pool_2x2_nonrepeat(x):
return nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')
这里我们采用池化的尺寸是2x2,同时步幅也是两个方向都是2的大小。因此对于池化来说,没有重复。因此在图像格式上来看,图像的长宽缩小为原来的两倍。
接下来给出一些其他定义
其他定义
from tensorflow import truncated_normal,Variable,constant,nn,train,placeholder,reshape,float32,reshape,reduce_sum,reduce_mean,multiply,log,transpose,random_normal
from modular.add_layer import add_layer_dropput,add_layer
def weight_variable(shape):
inital = truncated_normal(shape,stddev=0.1)
return Variable(inital)
def bias_variable(shape):
inital = constant(0.1,shape=shape)
return Variable(inital)
结果与小结
在这个实验中,分别经过了
cnn1: 28x28x32 --> pool: 14x14x32
cnn2: 14x14x64 --> poll: 7x7x64
这样尺寸的变化,并在最后将卷积展开,变为一维进行全连接网络
7x7x64 --> 100 --> 10
最后交叉熵损失训练。
关于非线性激活函数,这里有4个:
首先在每个卷积操作以后跟一个relu,然后第一全连接后跟着一个sigmod,第二个是softmax。