CNN最大的特點在于卷積的權值共享結構,可以大幅減少神經網絡的參數量,防止過擬合的同時又降低了神經網絡模型的復雜度。在CNN中,第一個卷積層會直接接受圖像像素級的輸入,每一個卷積操作只處理一小塊圖像,進行卷積變化后再傳到后面的網絡,每一層卷積都會提取數據中最有效的特征。這種方法可以提取到圖像中最基礎的特征,比如不同方向的邊或者拐角,而后再進行組合和抽象形成更高階的特征。
一般的卷積神經網絡由多個卷積層構成,每個卷積層中通常會進行如下幾個操作:
- 圖像通過多個不同的卷積核的濾波,并加偏置(bias),特取出局部特征,每個卷積核會映射出一個新的2D圖像。
- 將前面卷積核的濾波輸出結果,進行非線性的激活函數處理。目前最常見的是使用ReLU函數,而以前Sigmoid函數用得比較多。
- 對激活函數的結果再進行池化操作(即降采樣,比如將2*2的圖片將為1*1的圖片),目前一般是使用最大池化,保留最顯著的特征,并提升模型的畸變容忍能力。
總結一下,CNN的要點是局部連接(local Connection)、權值共享(Weight Sharing)和池化層(Pooling)中的降采樣(Down-Sampling)。
本文將使用Tensorflow實現一個簡單的卷積神經網絡,使用的數據集是MNIST,網絡結構:兩個卷積層加一個全連接層。
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
|
from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf # 載入MNIST數據集,并創建默認的Interactive Session。 mnist = input_data.read_data_sets( "MNIST_data/" , one_hot = True ) sess = tf.InteractiveSession() # 創建權重和偏置,以便重復使用。我們需要給權重制造一些隨機的噪聲來打破完全對稱,比如截斷的正態分布噪聲,標準差設為0.1 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): return tf.nn.conv2d(x, W, strides = [ 1 , 1 , 1 , 1 ], padding = 'SAME' ) def max_pool(x): return tf.nn.max_pool(x, ksize = [ 1 , 2 , 2 , 1 ], strides = [ 1 , 2 , 2 , 1 ], padding = 'SAME' ) # 定義輸入的placeholder x = tf.placeholder(tf.float32, [ None , 784 ]) y_ = tf.placeholder(tf.float32, [ None , 10 ]) x_image = tf.reshape(x, [ - 1 , 28 , 28 , 1 ]) # 定義第一個卷積層 W_conv1 = weight_variable([ 5 , 5 , 1 , 32 ]) b_conv1 = bias_variable([ 32 ]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) h_pool1 = max_pool(h_conv1) # 定義第二個卷積層 W_conv2 = weight_variable([ 5 , 5 , 32 , 64 ]) b_conv2 = bias_variable([ 64 ]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) h_pool2 = max_pool(h_conv2) # 定義全連接層。由于第二個卷積層輸出的tensor是7*7*64,我們使用tf.reshape函數對其進行變形 W_fc1 = weight_variable([ 7 * 7 * 64 , 1024 ]) b_fc1 = bias_variable([ 1024 ]) h_pool2_flat = tf.reshape(h_pool2, [ - 1 , 7 * 7 * 64 ]) h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) # 為了減輕過擬合,下面使用一個Dropout層。通過一個placeholder傳入keep_prob比率來控制的。在訓練時,我們隨機丟棄一部分節點 # 的數據來減輕過擬合,預測時則保留全部數據來追求最好的預測性能。 keep_prob = tf.placeholder(dtype = tf.float32) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) # 最后我們將Dropout層的輸出連接一個Softmax層,得到最后的概率輸出 W_fc2 = weight_variable([ 1024 , 10 ]) b_fc2 = bias_variable([ 10 ]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) # 定義損失函數為cross entropy和優化器 cross_entropy = tf.reduce_mean( - tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices = [ 1 ])) 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, tf.float32)) # 下面開始訓練 tf.global_variables_initializer().run() for i in range ( 20000 ): batch = mnist.train.next_batch( 50 ) if i % 100 = = 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 })) # 載入MNIST數據集,并創建默認的Interactive Session。 mnist = input_data.read_data_sets( "MNIST_data/" , one_hot = True ) sess = tf.InteractiveSession() # 創建權重和偏置,以便重復使用。我們需要給權重制造一些隨機的噪聲來打破完全對稱,比如截斷的正態分布噪聲,標準差設為0.1 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): return tf.nn.conv2d(x, W, strides = [ 1 , 1 , 1 , 1 ], padding = 'SAME' ) def max_pool(x): return tf.nn.max_pool(x, ksize = [ 1 , 2 , 2 , 1 ], strides = [ 1 , 2 , 2 , 1 ], padding = 'SAME' ) # 定義輸入的placeholder x = tf.placeholder(tf.float32, [ None , 784 ]) y_ = tf.placeholder(tf.float32, [ None , 10 ]) x_image = tf.reshape(x, [ - 1 , 28 , 28 , 1 ]) # 定義第一個卷積層 W_conv1 = weight_variable([ 5 , 5 , 1 , 32 ]) b_conv1 = bias_variable([ 32 ]) h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1) h_pool1 = max_pool(h_conv1) # 定義第二個卷積層 W_conv2 = weight_variable([ 5 , 5 , 32 , 64 ]) b_conv2 = bias_variable([ 64 ]) h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2) h_pool2 = max_pool(h_conv2) # 定義全連接層。由于第二個卷積層輸出的tensor是7*7*64,我們使用tf.reshape函數對其進行變形 W_fc1 = weight_variable([ 7 * 7 * 64 , 1024 ]) b_fc1 = bias_variable([ 1024 ]) h_pool2_flat = tf.reshape(h_pool2, [ - 1 , 7 * 7 * 64 ]) h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1) # 為了減輕過擬合,下面使用一個Dropout層。通過一個placeholder傳入keep_prob比率來控制的。在訓練時,我們隨機丟棄一部分節點 # 的數據來減輕過擬合,預測時則保留全部數據來追求最好的預測性能。 keep_prob = tf.placeholder(dtype = tf.float32) h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob) # 最后我們將Dropout層的輸出連接一個Softmax層,得到最后的概率輸出 W_fc2 = weight_variable([ 1024 , 10 ]) b_fc2 = bias_variable([ 10 ]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2) # 定義損失函數為cross entropy和優化器 cross_entropy = tf.reduce_mean( - tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices = [ 1 ])) 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, tf.float32)) # 下面開始訓練 tf.global_variables_initializer().run() for i in range ( 20000 ): batch = mnist.train.next_batch( 50 ) if i % 100 = = 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 })) |
運行結果:
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持服務器之家。
原文鏈接:https://blog.csdn.net/xjy104165/article/details/78559129