Fork me on GitHub

CNN的入门demo

一、CNN的源代码

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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
#author:victor
#import module

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data


#input MNIST_data

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

sess = tf.InteractiveSession()



#define placeholder for inputs to network
x = tf.placeholder(tf.float32, shape=[None, 784])#28*28
y_ = tf.placeholder(tf.float32, shape=[None, 10])#0~9共10个数字


#define weights(神经元的权重)
def weight_variable(shape):

#tf.truncated_normal(shape,mean,stddev)
#shape:表示生成张量的维度
#mean:表示均值
#stddev:表示标准差
#这是一个截断产生正太分布的函数
#tf.truncated_normal与tf.random_normal的区别是:
#这两个输入参数几乎完全一致,都是正态分布产生函数
#tf.truncated_normal截断的标准差是2倍的stddev
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)



#define biases(神经元的偏置常量)
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)



#define conv(卷积层)
#padding有两个值,一个SAME,一个VALID
#padding设置为SAME:说明输入图片和输出图片大小一致
#padding设置为VALID:说明图片经过滤波器filter后可能会变小
#设置conv的滑动步长strides为1,1,1,1

#define convolutional layer
#x:x为image的所有信息
#W:Weight
#strides的前后都为1,然后第二个,第三个,表示,x方向,y方向都为1
#strides=[1,x_movement,y_movement,1]
#must have strides[0]=strides[3]=1
def conv2d(x, W):
return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding="SAME")


#define pooling(池化层)
##pooling的方式是max pooling
#设置它的滑动步长strides为1,2,2,1
#use max_pool method
#ksize:也就是kernel size
#strides=[1,x_movement,y_movement,1]
#strides[1]=strides[2]=2,也就是隔2个像素移动一下
def max_pool_2x2(x):
return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")

##conv1 layer卷积层##
#W_conv1就是Weights
#patch 5*5,in size=1是image的厚度,out size=32
W_conv1 = weight_variable([5, 5, 1, 32])

#b_conv1就是biases,32就是卷积核的个数,按照经验取值
b_conv1 = bias_variable([32])

#-1:是把数据扁平化,28*28就是所有像素点784,1由于这个MNIST里的图片全都是黑白的所有只有1,如果是彩色的就可以有其他的值
x_image = tf.reshape(x, [-1, 28, 28, 1])
#print(x_image,shape)#[n_samples,28,28,1]

#非线性化处理
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)#output size 282832之前的步长是1,1

##pooling layer池化层##
h_pool1 = max_pool_2x2(h_conv1)#output size 141432,pooling的步长是2,2,则就是原来基础上除以2
##conv1 layer##


#conv2 layer卷积层##
W_conv2 = weight_variable([5, 5, 32, 64])#patch 5*5,in size 32,out size 64
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)#output size 141464,第二层的输入是第一层的输出,输出的pooling是14*14,步长是1,1


##pooling layer池化层##
h_pool2 = max_pool_2x2(h_conv2)#output size然后步长是2,2,所以就是7764
##conv2 layer##


##func1 layer全连接层##
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

##转换##
h_pool2_flat = tf.reshape(h_pool2, [-1, 7 * 7 * 64])#[n_samples,7,7,64]转换为[n_samples,7764]

h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

#define keep_prob
keep_prob = tf.placeholder("float")

#use dropout solve overfitting(使用dropout防止过拟合)keep_prob为0~1之间数
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)#考虑到有overfitting,加一个dropout处理

##func1 layer##
##func2 layer全连接层##
#第二层的input=1024是第一层的输出1024,第二层的输出为10因为是有0~9,10个数字

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

#prediction
y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

#use cross_entropy交叉熵
#the error between prediction and real data

cross_entropy = -tf.reduce_sum(y_ * tf.log(y_conv))

#对于庞大的神经网络使用AdamOptimizer不适用GradientDescentOptimizer了train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))


#import step
sess.run(tf.global_variables_initializer())
for i in range(20000):
batch = mnist.train.next_batch(50)
if i % 100 == 0:

#控制它的keep_prob为1.0也就是所有元素全部保留
train_accuracy = accuracy.eval(feed_dict={
x: batch[0], y: batch[1], keep_prob: 1.0})
print("step %d, training accuracy %g" % (i, train_accuracy))
train_step.run(feed_dict={x: batch[0], y: batch[1], keep_prob: 0.5})

print("test accuracy %g" % accuracy.eval(feed_dict={
x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

二、运行效果

  • 刚开始训练精度并不高,在90%左右

start training

  • 随着慢慢的训练5000步左右的时候,精度逐渐增加到99%左右

cnn

  • 等过万的时候,精确度已经很高了,接近于100%

cnn

  • 训练到15000步,精确度已经很高,几乎100%

    cnn

  • 训练结束后的结果

    cnn

    对比上一节的MNIST入门的Demo利用GradientDescentOptimizer直接进行训练,利用CNN训练,精确度基本上99%

    ps:由于设置的循环range为20000,训练次数比较大,跑起来比较耗时,我安装的是CPU版本的Tensorflow,跑了大概1个小时训练结束。