一步一步學(xué)用Tensorflow構建卷積神經(jīng)網(wǎng)絡(luò )
2.6 影響層輸出大小的參數
本文引用地址:http://dyxdggzs.com/article/201711/371373.htm一般來(lái)說(shuō),神經(jīng)網(wǎng)絡(luò )的層數越多越好。我們可以添加更多的層、修改激活函數和池層,修改學(xué)習速率,以看看每個(gè)步驟是如何影響性能的。由于i層的輸入是i-1層的輸出,我們需要知道不同的參數是如何影響i-1層的輸出大小的。
要了解這一點(diǎn),可以看看conv2d()函數。
它有四個(gè)參數:
輸入圖像,維度為[batch size, image_width, image_height, image_depth]的4D張量
權重矩陣,維度為[filter_size, filter_size, image_depth, filter_depth]的4D張量
每個(gè)維度的步幅數。
填充(='SAME'/'VALID')
這四個(gè)參數決定了輸出圖像的大小。
前兩個(gè)參數分別是包含一批輸入圖像的4D張量和包含卷積濾波器權重的4D張量。
第三個(gè)參數是卷積的步幅,即卷積濾波器在四維的每一個(gè)維度中應該跳過(guò)多少個(gè)位置。這四個(gè)維度中的第一個(gè)維度表示圖像批次中的圖像編號,由于我們不想跳過(guò)任何圖像,因此始終為1。最后一個(gè)維度表示圖像深度(不是色彩的通道數;灰度為1,RGB為3),由于我們不想跳過(guò)任何顏色通道,所以這個(gè)也總是為1。第二和第三維度表示X和Y方向上的步幅(圖像寬度和高度)。如果要應用步幅,則這些是過(guò)濾器應跳過(guò)的位置的維度。因此,對于步幅為1,我們必須將步幅參數設置為[1, 1, 1, 1],如果我們希望步幅為2,則將其設置為[1,2,2,1]。以此類(lèi)推。
最后一個(gè)參數表示Tensorflow是否應該對圖像用零進(jìn)行填充,以確保對于步幅為1的輸出尺寸不會(huì )改變。如果 padding = 'SAME',則圖像用零填充(并且輸出大小不會(huì )改變),如果 padding = 'VALID',則不填充。
下面我們可以看到通過(guò)圖像(大小為28 x 28)掃描的卷積濾波器(濾波器大小為5 x 5)的兩個(gè)示例。
在左側,填充參數設置為“SAME”,圖像用零填充,最后4行/列包含在輸出圖像中。
在右側,填充參數設置為“VALID”,圖像不用零填充,最后4行/列不包括在輸出圖像中。

我們可以看到,如果沒(méi)有用零填充,則不包括最后四個(gè)單元格,因為卷積濾波器已經(jīng)到達(非零填充)圖像的末尾。這意味著(zhù),對于28 x 28的輸入大小,輸出大小變?yōu)?4 x 24 。如果 padding = 'SAME',則輸出大小為28 x 28。
如果在掃描圖像時(shí)記下過(guò)濾器在圖像上的位置(為簡(jiǎn)單起見(jiàn),只有X方向),那么這一點(diǎn)就變得更加清晰了。如果步幅為1,則X位置為0-5、1-6、2-7,等等。如果步幅為2,則X位置為0-5、2-7、4-9,等等。
如果圖像大小為28 x 28,濾鏡大小為5 x 5,并且步長(cháng)1到4,那么我們可以得到下面這個(gè)表:

可以看到,對于步幅為1,零填充輸出圖像大小為28 x 28。如果非零填充,則輸出圖像大小變?yōu)?4 x 24。對于步幅為2的過(guò)濾器,這幾個(gè)數字分別為 14 x 14 和 12 x 12,對于步幅為3的過(guò)濾器,分別為 10 x 10 和 8 x 8。以此類(lèi)推。
對于任意一個(gè)步幅S,濾波器尺寸K,圖像尺寸W和填充尺寸P,輸出尺寸將為

如果在Tensorflow中 padding = “SAME”,則分子加起來(lái)恒等于1,輸出大小僅由步幅S決定。
2.7 調整 LeNet5 的架構
在原始論文中,LeNet5架構使用了S形激活函數和平均池。 然而,現在,使用relu激活函數則更為常見(jiàn)。 所以,我們來(lái)稍稍修改一下LeNet5 CNN,看看是否能夠提高準確性。我們將稱(chēng)之為類(lèi)LeNet5架構:
LENET5_LIKE_BATCH_SIZE = 32
LENET5_LIKE_FILTER_SIZE = 5
LENET5_LIKE_FILTER_DEPTH = 16
LENET5_LIKE_NUM_HIDDEN = 120
def variables_lenet5_like(filter_size = LENET5_LIKE_FILTER_SIZE,
filter_depth = LENET5_LIKE_FILTER_DEPTH,
num_hidden = LENET5_LIKE_NUM_HIDDEN,
image_width = 28, image_depth = 1, num_labels = 10):
w1 = tf.Variable(tf.truncated_normal([filter_size, filter_size, image_depth, filter_depth], stddev=0.1))
b1 = tf.Variable(tf.zeros([filter_depth]))
w2 = tf.Variable(tf.truncated_normal([filter_size, filter_size, filter_depth, filter_depth], stddev=0.1))
b2 = tf.Variable(tf.constant(1.0, shape=[filter_depth]))
w3 = tf.Variable(tf.truncated_normal([(image_width // 4)(image_width // 4)filter_depth , num_hidden], stddev=0.1))
b3 = tf.Variable(tf.constant(1.0, shape = [num_hidden]))
w4 = tf.Variable(tf.truncated_normal([num_hidden, num_hidden], stddev=0.1))
b4 = tf.Variable(tf.constant(1.0, shape = [num_hidden]))
w5 = tf.Variable(tf.truncated_normal([num_hidden, num_labels], stddev=0.1))
b5 = tf.Variable(tf.constant(1.0, shape = [num_labels]))
variables = {
'w1': w1, 'w2': w2, 'w3': w3, 'w4': w4, 'w5': w5,
'b1': b1, 'b2': b2, 'b3': b3, 'b4': b4, 'b5': b5
}
return variables
def model_lenet5_like(data, variables):
layer1_conv = tf.nn.conv2d(data, variables['w1'], [1, 1, 1, 1], padding='SAME')
layer1_actv = tf.nn.relu(layer1_conv + variables['b1'])
layer1_pool = tf.nn.avg_pool(layer1_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
layer2_conv = tf.nn.conv2d(layer1_pool, variables['w2'], [1, 1, 1, 1], padding='SAME')
layer2_actv = tf.nn.relu(layer2_conv + variables['b2'])
layer2_pool = tf.nn.avg_pool(layer2_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
flat_layer = flatten_tf_array(layer2_pool)
layer3_fccd = tf.matmul(flat_layer, variables['w3']) + variables['b3']
layer3_actv = tf.nn.relu(layer3_fccd)
#layer3_drop = tf.nn.dropout(layer3_actv, 0.5)
layer4_fccd = tf.matmul(layer3_actv, variables['w4']) + variables['b4']
layer4_actv = tf.nn.relu(layer4_fccd)
#layer4_drop = tf.nn.dropout(layer4_actv, 0.5)
logits = tf.matmul(layer4_actv, variables['w5']) + variables['b5']
return logits
主要區別是我們使用了relu激活函數而不是S形激活函數。
除了激活函數,我們還可以改變使用的優(yōu)化器,看看不同的優(yōu)化器對精度的影響。
2.8 學(xué)習速率和優(yōu)化器的影響
讓我們來(lái)看看這些CNN在MNIST和CIFAR-10數據集上的表現。


在上面的圖中,測試集的精度是迭代次數的函數。左側為一層完全連接的NN,中間為L(cháng)eNet5 NN,右側為類(lèi)LeNet5 NN。
可以看到,LeNet5 CNN在MNIST數據集上表現得非常好。這并不是一個(gè)大驚喜,因為它專(zhuān)門(mén)就是為分類(lèi)手寫(xiě)數字而設計的。MNIST數據集很小,并沒(méi)有太大的挑戰性,所以即使是一個(gè)完全連接的網(wǎng)絡(luò )也表現的很好。
然而,在CIFAR-10數據集上,LeNet5 NN的性能顯著(zhù)下降,精度下降到了40%左右。
為了提高精度,我們可以通過(guò)應用正則化或學(xué)習速率衰減來(lái)改變優(yōu)化器,或者微調神經(jīng)網(wǎng)絡(luò )。

可以看到,AdagradOptimizer、AdamOptimizer和RMSPropOptimizer的性能比GradientDescentOptimizer更好。這些都是自適應優(yōu)化器,其性能通常比GradientDescentOptimizer更好,但需要更多的計算能力。
通過(guò)L2正則化或指數速率衰減,我們可能會(huì )得到更搞的準確性,但是要獲得更好的結果,我們需要進(jìn)一步研究。
3. Tensorflow 中的深度神經(jīng)網(wǎng)絡(luò )
到目前為止,我們已經(jīng)看到了LeNet5 CNN架構。 LeNet5包含兩個(gè)卷積層,緊接著(zhù)的是完全連接的層,因此可以稱(chēng)為淺層神經(jīng)網(wǎng)絡(luò )。那時(shí)候(1998年),GPU還沒(méi)有被用來(lái)進(jìn)行計算,而且CPU的功能也沒(méi)有那么強大,所以,在當時(shí),兩個(gè)卷積層已經(jīng)算是相當具有創(chuàng )新意義了。
后來(lái),很多其他類(lèi)型的卷積神經(jīng)網(wǎng)絡(luò )被設計出來(lái),你可以在這里查看詳細信息。
比如,由Alex Krizhevsky開(kāi)發(fā)的非常有名的AlexNet 架構(2012年),7層的ZF Net (2013),以及16層的 VGGNet (2014)。
在2015年,Google發(fā)布了一個(gè)包含初始模塊的22層的CNN(GoogLeNet),而微軟亞洲研究院構建了一個(gè)152層的CNN,被稱(chēng)為ResNet。
現在,根據我們目前已經(jīng)學(xué)到的知識,我們來(lái)看一下如何在Tensorflow中創(chuàng )建AlexNet和VGGNet16架構。
3.1 AlexNet
雖然LeNet5是第一個(gè)ConvNet,但它被認為是一個(gè)淺層神經(jīng)網(wǎng)絡(luò )。它在由大小為28 x 28的灰度圖像組成的MNIST數據集上運行良好,但是當我們嘗試分類(lèi)更大、分辨率更好、類(lèi)別更多的圖像時(shí),性能就會(huì )下降。
第一個(gè)深度CNN于2012年推出,稱(chēng)為AlexNet,其創(chuàng )始人為Alex Krizhevsky、Ilya Sutskever和Geoffrey Hinton。與最近的架構相比,AlexNet可以算是簡(jiǎn)單的了,但在當時(shí)它確實(shí)非常成功。它以令人難以置信的15.4%的測試錯誤率贏(yíng)得了ImageNet比賽(亞軍的誤差為26.2%),并在全球深度學(xué)習和人工智能領(lǐng)域掀起了一場(chǎng)革命。

它包括5個(gè)卷積層、3個(gè)最大池化層、3個(gè)完全連接層和2個(gè)丟棄層。整體架構如下所示:
第0層:大小為224 x 224 x 3的輸入圖像
第1層:具有96個(gè)濾波器(filter_depth_1 = 96)的卷積層,大小為11×11(filter_size_1 = 11),步長(cháng)為4。它包含ReLU激活函數。 緊接著(zhù)的是最大池化層和本地響應歸一化層。
第2層:具有大小為5 x 5(filter_size_2 = 5)的256個(gè)濾波器(filter_depth_2 = 256)且步幅為1的卷積層。它包含ReLU激活函數。 緊接著(zhù)的還是最大池化層和本地響應歸一化層。
第3層:具有384個(gè)濾波器的卷積層(filter_depth_3 = 384),尺寸為3×3(filter_size_3 = 3),步幅為1。它包含ReLU激活函數
第4層:與第3層相同。
第5層:具有大小為3×3(filter_size_4 = 3)的256個(gè)濾波器(filter_depth_4 = 256)且步幅為1的卷積層。它包含ReLU激活函數
第6-8層:這些卷積層之后是完全連接層,每個(gè)層具有4096個(gè)神經(jīng)元。在原始論文中,他們對1000個(gè)類(lèi)別的數據集進(jìn)行分類(lèi),但是我們將使用具有17個(gè)不同類(lèi)別(的花卉)的oxford17數據集。
請注意,由于這些數據集中的圖像太小,因此無(wú)法在MNIST或CIFAR-10數據集上使用此CNN(或其他的深度CNN)。正如我們以前看到的,一個(gè)池化層(或一個(gè)步幅為2的卷積層)將圖像大小減小了2倍。 AlexNet具有3個(gè)最大池化層和一個(gè)步長(cháng)為4的卷積層。這意味著(zhù)原始圖像尺寸會(huì )縮小2^5。 MNIST數據集中的圖像將簡(jiǎn)單地縮小到尺寸小于0。
因此,我們需要加載具有較大圖像的數據集,最好是224 x 224 x 3(如原始文件所示)。 17個(gè)類(lèi)別的花卉數據集,又名oxflower17數據集是最理想的,因為它包含了這個(gè)大小的圖像:
ox17_image_width = 224
ox17_image_height = 224
ox17_image_depth = 3
ox17_num_labels = 17
import tflearn.datasets.oxflower17 as oxflower17
train_dataset_, train_labels_ = oxflower17.load_data(one_hot=True)
train_dataset_ox17, train_labels_ox17 = train_dataset_[:1000,:,:,:], train_labels_[:1000,:]
test_dataset_ox17, test_labels_ox17 = train_dataset_[1000:,:,:,:], train_labels_[1000:,:]
print('Training set', train_dataset_ox17.shape, train_labels_ox17.shape)
print('Test set', test_dataset_ox17.shape, test_labels_ox17.shape)
讓我們試著(zhù)在A(yíng)lexNet中創(chuàng )建權重矩陣和不同的層。正如我們之前看到的,我們需要跟層數一樣多的權重矩陣和偏差矢量,并且每個(gè)權重矩陣的大小應該與其所屬層的過(guò)濾器的大小相對應。
ALEX_PATCH_DEPTH_1, ALEX_PATCH_DEPTH_2, ALEX_PATCH_DEPTH_3, ALEX_PATCH_DEPTH_4 = 96, 256, 384, 256
ALEX_PATCH_SIZE_1, ALEX_PATCH_SIZE_2, ALEX_PATCH_SIZE_3, ALEX_PATCH_SIZE_4 = 11, 5, 3, 3
ALEX_NUM_HIDDEN_1, ALEX_NUM_HIDDEN_2 = 4096, 4096
def variables_alexnet(patch_size1 = ALEX_PATCH_SIZE_1, patch_size2 = ALEX_PATCH_SIZE_2,
patch_size3 = ALEX_PATCH_SIZE_3, patch_size4 = ALEX_PATCH_SIZE_4,
patch_depth1 = ALEX_PATCH_DEPTH_1, patch_depth2 = ALEX_PATCH_DEPTH_2,
patch_depth3 = ALEX_PATCH_DEPTH_3, patch_depth4 = ALEX_PATCH_DEPTH_4,
num_hidden1 = ALEX_NUM_HIDDEN_1, num_hidden2 = ALEX_NUM_HIDDEN_2,
image_width = 224, image_height = 224, image_depth = 3, num_labels = 17):
w1 = tf.Variable(tf.truncated_normal([patch_size1, patch_size1, image_depth, patch_depth1], stddev=0.1))
b1 = tf.Variable(tf.zeros([patch_depth1]))
w2 = tf.Variable(tf.truncated_normal([patch_size2, patch_size2, patch_depth1, patch_depth2], stddev=0.1))
b2 = tf.Variable(tf.constant(1.0, shape=[patch_depth2]))
w3 = tf.Variable(tf.truncated_normal([patch_size3, patch_size3, patch_depth2, patch_depth3], stddev=0.1))
b3 = tf.Variable(tf.zeros([patch_depth3]))
w4 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth3, patch_depth3], stddev=0.1))
b4 = tf.Variable(tf.constant(1.0, shape=[patch_depth3]))
w5 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth3, patch_depth3], stddev=0.1))
b5 = tf.Variable(tf.zeros([patch_depth3]))
pool_reductions = 3
conv_reductions = 2
no_reductions = pool_reductions + conv_reductions
w6 = tf.Variable(tf.truncated_normal([(image_width // 2no_reductions)(image_height // 2no_reductions)patch_depth3, num_hidden1], stddev=0.1))
b6 = tf.Variable(tf.constant(1.0, shape = [num_hidden1]))
w7 = tf.Variable(tf.truncated_normal([num_hidden1, num_hidden2], stddev=0.1))
b7 = tf.Variable(tf.constant(1.0, shape = [num_hidden2]))
w8 = tf.Variable(tf.truncated_normal([num_hidden2, num_labels], stddev=0.1))
b8 = tf.Variable(tf.constant(1.0, shape = [num_labels]))
variables = {
'w1': w1, 'w2': w2, 'w3': w3, 'w4': w4, 'w5': w5, 'w6': w6, 'w7': w7, 'w8': w8,
'b1': b1, 'b2': b2, 'b3': b3, 'b4': b4, 'b5': b5, 'b6': b6, 'b7': b7, 'b8': b8
}
return variables
def model_alexnet(data, variables):
layer1_conv = tf.nn.conv2d(data, variables['w1'], [1, 4, 4, 1], padding='SAME')
layer1_relu = tf.nn.relu(layer1_conv + variables['b1'])
layer1_pool = tf.nn.max_pool(layer1_relu, [1, 3, 3, 1], [1, 2, 2, 1], padding='SAME')
layer1_norm = tf.nn.local_response_normalization(layer1_pool)
layer2_conv = tf.nn.conv2d(layer1_norm, variables['w2'], [1, 1, 1, 1], padding='SAME')
layer2_relu = tf.nn.relu(layer2_conv + variables['b2'])
layer2_pool = tf.nn.max_pool(layer2_relu, [1, 3, 3, 1], [1, 2, 2, 1], padding='SAME')
layer2_norm = tf.nn.local_response_normalization(layer2_pool)
layer3_conv = tf.nn.conv2d(layer2_norm, variables['w3'], [1, 1, 1, 1], padding='SAME')
layer3_relu = tf.nn.relu(layer3_conv + variables['b3'])
layer4_conv = tf.nn.conv2d(layer3_relu, variables['w4'], [1, 1, 1, 1], padding='SAME')
layer4_relu = tf.nn.relu(layer4_conv + variables['b4'])
layer5_conv = tf.nn.conv2d(layer4_relu, variables['w5'], [1, 1, 1, 1], padding='SAME')
layer5_relu = tf.nn.relu(layer5_conv + variables['b5'])
layer5_pool = tf.nn.max_pool(layer4_relu, [1, 3, 3, 1], [1, 2, 2, 1], padding='SAME')
layer5_norm = tf.nn.local_response_normalization(layer5_pool)
flat_layer = flatten_tf_array(layer5_norm)
layer6_fccd = tf.matmul(flat_layer, variables['w6']) + variables['b6']
layer6_tanh = tf.tanh(layer6_fccd)
layer6_drop = tf.nn.dropout(layer6_tanh, 0.5)
layer7_fccd = tf.matmul(layer6_drop, variables['w7']) + variables['b7']
layer7_tanh = tf.tanh(layer7_fccd)
layer7_drop = tf.nn.dropout(layer7_tanh, 0.5)
logits = tf.matmul(layer7_drop, variables['w8']) + variables['b8']
return logits
現在我們可以修改CNN模型來(lái)使用AlexNet模型的權重和層次來(lái)對圖像進(jìn)行分類(lèi)。
3.2 VGG Net-16
VGG Net于2014年由牛津大學(xué)的Karen Simonyan和Andrew Zisserman創(chuàng )建出來(lái)。 它包含了更多的層(16-19層),但是每一層的設計更為簡(jiǎn)單;所有卷積層都具有3×3以及步長(cháng)為3的過(guò)濾器,并且所有最大池化層的步長(cháng)都為2。
所以它是一個(gè)更深的CNN,但更簡(jiǎn)單。
它存在不同的配置,16層或19層。 這兩種不同配置之間的區別是在第2,第3和第4最大池化層之后對3或4個(gè)卷積層的使用(見(jiàn)下文)。

配置為16層(配置D)的結果似乎更好,所以我們試著(zhù)在Tensorflow中創(chuàng )建它。
#The VGGNET Neural Network
VGG16_PATCH_SIZE_1, VGG16_PATCH_SIZE_2, VGG16_PATCH_SIZE_3, VGG16_PATCH_SIZE_4 = 3, 3, 3, 3
VGG16_PATCH_DEPTH_1, VGG16_PATCH_DEPTH_2, VGG16_PATCH_DEPTH_3, VGG16_PATCH_DEPTH_4 = 64, 128, 256, 512
VGG16_NUM_HIDDEN_1, VGG16_NUM_HIDDEN_2 = 4096, 1000
def variables_vggnet16(patch_size1 = VGG16_PATCH_SIZE_1, patch_size2 = VGG16_PATCH_SIZE_2,
patch_size3 = VGG16_PATCH_SIZE_3, patch_size4 = VGG16_PATCH_SIZE_4,
patch_depth1 = VGG16_PATCH_DEPTH_1, patch_depth2 = VGG16_PATCH_DEPTH_2,
patch_depth3 = VGG16_PATCH_DEPTH_3, patch_depth4 = VGG16_PATCH_DEPTH_4,
num_hidden1 = VGG16_NUM_HIDDEN_1, num_hidden2 = VGG16_NUM_HIDDEN_2,
image_width = 224, image_height = 224, image_depth = 3, num_labels = 17):
w1 = tf.Variable(tf.truncated_normal([patch_size1, patch_size1, image_depth, patch_depth1], stddev=0.1))
b1 = tf.Variable(tf.zeros([patch_depth1]))
w2 = tf.Variable(tf.truncated_normal([patch_size1, patch_size1, patch_depth1, patch_depth1], stddev=0.1))
b2 = tf.Variable(tf.constant(1.0, shape=[patch_depth1]))
w3 = tf.Variable(tf.truncated_normal([patch_size2, patch_size2, patch_depth1, patch_depth2], stddev=0.1))
b3 = tf.Variable(tf.constant(1.0, shape = [patch_depth2]))
w4 = tf.Variable(tf.truncated_normal([patch_size2, patch_size2, patch_depth2, patch_depth2], stddev=0.1))
b4 = tf.Variable(tf.constant(1.0, shape = [patch_depth2]))
w5 = tf.Variable(tf.truncated_normal([patch_size3, patch_size3, patch_depth2, patch_depth3], stddev=0.1))
b5 = tf.Variable(tf.constant(1.0, shape = [patch_depth3]))
w6 = tf.Variable(tf.truncated_normal([patch_size3, patch_size3, patch_depth3, patch_depth3], stddev=0.1))
b6 = tf.Variable(tf.constant(1.0, shape = [patch_depth3]))
w7 = tf.Variable(tf.truncated_normal([patch_size3, patch_size3, patch_depth3, patch_depth3], stddev=0.1))
b7 = tf.Variable(tf.constant(1.0, shape=[patch_depth3]))
w8 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth3, patch_depth4], stddev=0.1))
b8 = tf.Variable(tf.constant(1.0, shape = [patch_depth4]))
w9 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth4, patch_depth4], stddev=0.1))
b9 = tf.Variable(tf.constant(1.0, shape = [patch_depth4]))
w10 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth4, patch_depth4], stddev=0.1))
b10 = tf.Variable(tf.constant(1.0, shape = [patch_depth4]))
w11 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth4, patch_depth4], stddev=0.1))
b11 = tf.Variable(tf.constant(1.0, shape = [patch_depth4]))
w12 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth4, patch_depth4], stddev=0.1))
b12 = tf.Variable(tf.constant(1.0, shape=[patch_depth4]))
w13 = tf.Variable(tf.truncated_normal([patch_size4, patch_size4, patch_depth4, patch_depth4], stddev=0.1))
b13 = tf.Variable(tf.constant(1.0, shape = [patch_depth4]))
no_pooling_layers = 5
w14 = tf.Variable(tf.truncated_normal([(image_width // (2no_pooling_layers))(image_height // (2no_pooling_layers))patch_depth4 , num_hidden1], stddev=0.1))
b14 = tf.Variable(tf.constant(1.0, shape = [num_hidden1]))
w15 = tf.Variable(tf.truncated_normal([num_hidden1, num_hidden2], stddev=0.1))
b15 = tf.Variable(tf.constant(1.0, shape = [num_hidden2]))
w16 = tf.Variable(tf.truncated_normal([num_hidden2, num_labels], stddev=0.1))
b16 = tf.Variable(tf.constant(1.0, shape = [num_labels]))
variables = {
'w1': w1, 'w2': w2, 'w3': w3, 'w4': w4, 'w5': w5, 'w6': w6, 'w7': w7, 'w8': w8, 'w9': w9, 'w10': w10,
'w11': w11, 'w12': w12, 'w13': w13, 'w14': w14, 'w15': w15, 'w16': w16,
'b1': b1, 'b2': b2, 'b3': b3, 'b4': b4, 'b5': b5, 'b6': b6, 'b7': b7, 'b8': b8, 'b9': b9, 'b10': b10,
'b11': b11, 'b12': b12, 'b13': b13, 'b14': b14, 'b15': b15, 'b16': b16
}
return variables
def model_vggnet16(data, variables):
layer1_conv = tf.nn.conv2d(data, variables['w1'], [1, 1, 1, 1], padding='SAME')
layer1_actv = tf.nn.relu(layer1_conv + variables['b1'])
layer2_conv = tf.nn.conv2d(layer1_actv, variables['w2'], [1, 1, 1, 1], padding='SAME')
layer2_actv = tf.nn.relu(layer2_conv + variables['b2'])
layer2_pool = tf.nn.max_pool(layer2_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
layer3_conv = tf.nn.conv2d(layer2_pool, variables['w3'], [1, 1, 1, 1], padding='SAME')
layer3_actv = tf.nn.relu(layer3_conv + variables['b3'])
layer4_conv = tf.nn.conv2d(layer3_actv, variables['w4'], [1, 1, 1, 1], padding='SAME')
layer4_actv = tf.nn.relu(layer4_conv + variables['b4'])
layer4_pool = tf.nn.max_pool(layer4_pool, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
layer5_conv = tf.nn.conv2d(layer4_pool, variables['w5'], [1, 1, 1, 1], padding='SAME')
layer5_actv = tf.nn.relu(layer5_conv + variables['b5'])
layer6_conv = tf.nn.conv2d(layer5_actv, variables['w6'], [1, 1, 1, 1], padding='SAME')
layer6_actv = tf.nn.relu(layer6_conv + variables['b6'])
layer7_conv = tf.nn.conv2d(layer6_actv, variables['w7'], [1, 1, 1, 1], padding='SAME')
layer7_actv = tf.nn.relu(layer7_conv + variables['b7'])
layer7_pool = tf.nn.max_pool(layer7_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
layer8_conv = tf.nn.conv2d(layer7_pool, variables['w8'], [1, 1, 1, 1], padding='SAME')
layer8_actv = tf.nn.relu(layer8_conv + variables['b8'])
layer9_conv = tf.nn.conv2d(layer8_actv, variables['w9'], [1, 1, 1, 1], padding='SAME')
layer9_actv = tf.nn.relu(layer9_conv + variables['b9'])
layer10_conv = tf.nn.conv2d(layer9_actv, variables['w10'], [1, 1, 1, 1], padding='SAME')
layer10_actv = tf.nn.relu(layer10_conv + variables['b10'])
layer10_pool = tf.nn.max_pool(layer10_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
layer11_conv = tf.nn.conv2d(layer10_pool, variables['w11'], [1, 1, 1, 1], padding='SAME')
layer11_actv = tf.nn.relu(layer11_conv + variables['b11'])
layer12_conv = tf.nn.conv2d(layer11_actv, variables['w12'], [1, 1, 1, 1], padding='SAME')
layer12_actv = tf.nn.relu(layer12_conv + variables['b12'])
layer13_conv = tf.nn.conv2d(layer12_actv, variables['w13'], [1, 1, 1, 1], padding='SAME')
layer13_actv = tf.nn.relu(layer13_conv + variables['b13'])
layer13_pool = tf.nn.max_pool(layer13_actv, [1, 2, 2, 1], [1, 2, 2, 1], padding='SAME')
flat_layer = flatten_tf_array(layer13_pool)
layer14_fccd = tf.matmul(flat_layer, variables['w14']) + variables['b14']
layer14_actv = tf.nn.relu(layer14_fccd)
layer14_drop = tf.nn.dropout(layer14_actv, 0.5)
layer15_fccd = tf.matmul(layer14_drop, variables['w15']) + variables['b15']
layer15_actv = tf.nn.relu(layer15_fccd)
layer15_drop = tf.nn.dropout(layer15_actv, 0.5)
logits = tf.matmul(layer15_drop, variables['w16']) + variables['b16']
return logits
3.3 AlexNet 性能
作為比較,看一下對包含了較大圖片的oxflower17數據集的LeNet5 CNN性能:

4. 結語(yǔ)
相關(guān)代碼可以在我的GitHub庫中獲得,因此可以隨意在自己的數據集上使用它。
在深度學(xué)習的世界中還有更多的知識可以去探索:循環(huán)神經(jīng)網(wǎng)絡(luò )、基于區域的CNN、GAN、加強學(xué)習等等。在未來(lái)的博客文章中,我將構建這些類(lèi)型的神經(jīng)網(wǎng)絡(luò ),并基于我們已經(jīng)學(xué)到的知識構建更有意思的應用程序。
評論