Tensorflow学习6:卷积神经网络CNN

用卷积神经网络进行手写数字识别

1
2
3
4
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
PWS_DIR = "C:/Users/lenovo/Desktop/Python WORK SPACE/"
LOG_DIR = "D:/Tensorflow/logs/"

1 普通代码

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
mnist = input_data.read_data_sets(PWS_DIR + "DATASET/MNIST_data", one_hot=True)

batch_size = 100

n_batch = mnist.train.num_examples // batch_size

# 初始化权值
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)

#初始化偏置
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)

#卷积层
def conv2d(x, W):
# x input tensor of shape [batch, in_height, in_width, in_channels]
# W filter / kernel tensor of shape [filter_height, filter_weight, in_channels, out_channels]
# "strides[0] = strides[3] = 1", strides[1]代表x方向的步长,strides[2]代表y方向的步长
# padding: A "string" from: "SAME", "VALID" ,由于SAME补0,所以卷积后不改变尺寸大小
return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")

#池化层
def max_pool_2x2(x):
# ksize [1,x,y,1] 窗口大小,同上0,3位要设置为1
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")

#定义2个placeholder
x = tf.placeholder(tf.float32, [None, 784]) # 28*28
y = tf.placeholder(tf.float32, [None, 10])

#改变x的shape为4维数据 [batch, in_height, in_width, in_channels]
x_image = tf.reshape(x, [-1,28,28,1])

#初始化第一个卷积层的权值和偏置
W_conv1 = weight_variable([5,5,1,32]) #代表5*5的卷积核,1的输入深度,32的输出个数(即32个特征平面)
b_conv1 = bias_variable([32]) # 一个卷积核对应一个偏置值,所以有32个

#第一次卷积、池化操作
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

#初始化第二个卷积层的权值和偏置
W_conv2 = weight_variable([5,5,32,64]) #代表5*5的卷积核,32的输入深度,64的输出个数(即64个特征平面)
b_conv2 = bias_variable([64]) # 一个卷积核对应一个偏置值,所以有64个

#第二次卷积、池化操作
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

'''
28*28的图片,
第一次卷积后为28*28,第一次池化后为14*14
第二次卷积后为14*14,第二次池化后为7*7
最后得到64张7*7的平面
'''
#把第二次池化的输出降为1维
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])

#初始化第一个全连接层的权值和偏置
W_fc1 = weight_variable([7*7*64, 1024]) #上一层有7*7*64个神经元,全连接层有1024个神经元
b_fc1 = bias_variable([1024])

#计算第一个全连接层
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

#定义比率keep_prob用来控制dropout
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

#初始化第二个全连接层的权值和偏置
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

#计算第二个全连接层
predict = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

#使用交叉熵代价函数
loss_cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=predict))
#使用AdamOptimizer进行优化
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss_cross_entropy)
#结果放在一个BOOL型列表中
predict_bool = tf.equal(tf.argmax(y, 1), tf.argmax(predict, 1))
#求准确率
accuracy = tf.reduce_mean(tf.cast(predict_bool, tf.float32))

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for epoch in range(6):
for batch in range(n_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys, keep_prob:0.7})

acc = sess.run(accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels, keep_prob:1.0})
print("Iter" + str(epoch) + ", Testing Accuracy= " + str(acc))

Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\train-images-idx3-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\train-labels-idx1-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\t10k-images-idx3-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\t10k-labels-idx1-ubyte.gz
Iter0, Testing Accuracy= 0.8614
Iter1, Testing Accuracy= 0.9578
Iter2, Testing Accuracy= 0.9769
Iter3, Testing Accuracy= 0.9819
Iter4, Testing Accuracy= 0.9836
Iter5, Testing Accuracy= 0.9857

2 结构化代码

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
mnist = input_data.read_data_sets(PWS_DIR + "DATASET/MNIST_data", one_hot=True)

batch_size = 100

n_batch = mnist.train.num_examples // batch_size

# 设计统计函数,用于计算传入的张量的各种统计量
def variable_summary(var):
with tf.name_scope("summary"):
mean = tf.reduce_mean(var)
tf.summary.scalar("mean", mean) #平均值
with tf.name_scope("stddev"):
stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
tf.summary.scalar("stddev", stddev) #标准差
tf.summary.scalar("max", tf.reduce_max(var)) #最大值
tf.summary.scalar("min", tf.reduce_min(var)) #最小值
tf.summary.histogram("histogram", var) #直方图

# 初始化权值
def weight_variable(shape):
initial = tf.truncated_normal(shape, stddev=0.1)
return tf.Variable(initial)

#初始化偏置
def bias_variable(shape):
initial = tf.constant(0.1, shape=shape)
return tf.Variable(initial)

#卷积层
def conv2d(x, W):
# x input tensor of shape [batch, in_height, in_width, in_channels]
# W filter / kernel tensor of shape [filter_height, filter_weight, in_channels, out_channels]
# "strides[0] = strides[3] = 1", strides[1]代表x方向的步长,strides[2]代表y方向的步长
# padding: A "string" from: "SAME", "VALID" ,由于SAME补0,所以卷积后不改变尺寸大小
return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")

#池化层
def max_pool_2x2(x):
# ksize [1,x,y,1] 窗口大小,同上0,3位要设置为1
return tf.nn.max_pool(x, ksize=[1,2,2,1], strides=[1,2,2,1], padding="SAME")

with tf.name_scope("input"):
#定义2个placeholder
x = tf.placeholder(tf.float32, [None, 784]) # 28*28
y = tf.placeholder(tf.float32, [None, 10])
with tf.name_scope("x_image"):
#改变x的shape为4维数据 [batch, in_height, in_width, in_channels]
x_image = tf.reshape(x, [-1,28,28,1])


with tf.name_scope("Conv1"):
#初始化第一个卷积层的权值和偏置
with tf.name_scope("W_conv1"):
W_conv1 = weight_variable([5,5,1,32]) #代表5*5的卷积核,1的输入深度,32的输出个数(即32个特征平面)
with tf.name_scope("b_conv1"):
b_conv1 = bias_variable([32]) # 一个卷积核对应一个偏置值,所以有32个

#第一次卷积、池化操作
with tf.name_scope("h_conv1"):
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
with tf.name_scope("h_pool1"):
h_pool1 = max_pool_2x2(h_conv1)

with tf.name_scope("Conv2"):
#初始化第二个卷积层的权值和偏置
with tf.name_scope("W_conv2"):
W_conv2 = weight_variable([5,5,32,64]) #代表5*5的卷积核,32的输入深度,64的输出个数(即64个特征平面)
with tf.name_scope("b_conv2"):
b_conv2 = bias_variable([64]) # 一个卷积核对应一个偏置值,所以有64个

#第二次卷积、池化操作
with tf.name_scope("h_conv2"):
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
with tf.name_scope("h_pool2"):
h_pool2 = max_pool_2x2(h_conv2)


'''
with tf.name_scope(""):
28*28的图片,
第一次卷积后为28*28,第一次池化后为14*14
第二次卷积后为14*14,第二次池化后为7*7
最后得到64张7*7的平面
'''

with tf.name_scope("fc1"):
#把第二次池化的输出降为1维
with tf.name_scope("h_pool2_flat"):
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])

#初始化第一个全连接层的权值和偏置
with tf.name_scope("W_fc1"):
W_fc1 = weight_variable([7*7*64, 1024]) #上一层有7*7*64个神经元,全连接层有1024个神经元
with tf.name_scope("b_fc1"):
b_fc1 = bias_variable([1024])

#计算第一个全连接层
with tf.name_scope("h_fc1_relu"):
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

#定义比率keep_prob用来控制dropout
with tf.name_scope("h_fc1_drop"):
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

with tf.name_scope("fc2"):
#初始化第二个全连接层的权值和偏置
with tf.name_scope("W_fc2"):
W_fc2 = weight_variable([1024, 10])
with tf.name_scope("b_fc2"):
b_fc2 = bias_variable([10])
#计算第二个全连接层
with tf.name_scope("h_fc2_softmax"):
predict = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

with tf.name_scope("loss_cross_entropy"):
#使用交叉熵代价函数
loss_cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y, logits=predict))
_loss = tf.summary.scalar("loss_cross_entropy", loss_cross_entropy)

#使用AdamOptimizer进行优化
with tf.name_scope("train"):
train_step = tf.train.AdamOptimizer(1e-4).minimize(loss_cross_entropy)

#求准确率
with tf.name_scope("accuracy"):
#结果放在一个BOOL型列表中
predict_bool = tf.equal(tf.argmax(y, 1), tf.argmax(predict, 1))
accuracy = tf.reduce_mean(tf.cast(predict_bool, tf.float32))
_accuracy = tf.summary.scalar("accuracy", accuracy)

# merged = tf.summary.merge 这里训练看loss,测试看accuracy,不用合并

with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
train_writer = tf.summary.FileWriter(LOG_DIR + "train", sess.graph)
test_writer = tf.summary.FileWriter(LOG_DIR + "test", sess.graph)
for epoch in range(6):
for batch in range(n_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
sess.run(train_step, feed_dict={x:batch_xs, y:batch_ys, keep_prob:0.7})
train_summary = sess.run(summary_loss, feed_dict={x:batch_xs, y:batch_ys, keep_prob:1.0})
train_writer.add_summary(train_summary, batch)

acc = sess.run(accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels, keep_prob:1.0})
test_summary = sess.run(summary_accuracy, feed_dict={x:mnist.test.images, y:mnist.test.labels, keep_prob:1.0})
test_writer.add_summary(test_summary, epoch)
print("Iter" + str(epoch) + ", Testing Accuracy= " + str(acc))

Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\train-images-idx3-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\train-labels-idx1-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\t10k-images-idx3-ubyte.gz
Extracting C:/Users/lenovo/Desktop/Python WORK SPACE/DATASET/MNIST_data\t10k-labels-idx1-ubyte.gz
Iter0, Testing Accuracy= 0.9401
Iter1, Testing Accuracy= 0.974
Iter2, Testing Accuracy= 0.9781
Iter3, Testing Accuracy= 0.9823
Iter4, Testing Accuracy= 0.9839
Iter5, Testing Accuracy= 0.9853

꧁༺The༒End༻꧂