一步一步學(xué)用Tensorflow構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)
2.6 影響層輸出大小的參數(shù)
本文引用地址:http://butianyuan.cn/article/201711/371373.htm一般來說,神經(jīng)網(wǎng)絡(luò)的層數(shù)越多越好。我們可以添加更多的層、修改激活函數(shù)和池層,修改學(xué)習(xí)速率,以看看每個步驟是如何影響性能的。由于i層的輸入是i-1層的輸出,我們需要知道不同的參數(shù)是如何影響i-1層的輸出大小的。
要了解這一點,可以看看conv2d()函數(shù)。
它有四個參數(shù):
輸入圖像,維度為[batch size, image_width, image_height, image_depth]的4D張量
權(quán)重矩陣,維度為[filter_size, filter_size, image_depth, filter_depth]的4D張量
每個維度的步幅數(shù)。
填充(='SAME'/'VALID')
這四個參數(shù)決定了輸出圖像的大小。
前兩個參數(shù)分別是包含一批輸入圖像的4D張量和包含卷積濾波器權(quán)重的4D張量。
第三個參數(shù)是卷積的步幅,即卷積濾波器在四維的每一個維度中應(yīng)該跳過多少個位置。這四個維度中的第一個維度表示圖像批次中的圖像編號,由于我們不想跳過任何圖像,因此始終為1。最后一個維度表示圖像深度(不是色彩的通道數(shù);灰度為1,RGB為3),由于我們不想跳過任何顏色通道,所以這個也總是為1。第二和第三維度表示X和Y方向上的步幅(圖像寬度和高度)。如果要應(yīng)用步幅,則這些是過濾器應(yīng)跳過的位置的維度。因此,對于步幅為1,我們必須將步幅參數(shù)設(shè)置為[1, 1, 1, 1],如果我們希望步幅為2,則將其設(shè)置為[1,2,2,1]。以此類推。
最后一個參數(shù)表示Tensorflow是否應(yīng)該對圖像用零進行填充,以確保對于步幅為1的輸出尺寸不會改變。如果 padding = 'SAME',則圖像用零填充(并且輸出大小不會改變),如果 padding = 'VALID',則不填充。
下面我們可以看到通過圖像(大小為28 x 28)掃描的卷積濾波器(濾波器大小為5 x 5)的兩個示例。
在左側(cè),填充參數(shù)設(shè)置為“SAME”,圖像用零填充,最后4行/列包含在輸出圖像中。
在右側(cè),填充參數(shù)設(shè)置為“VALID”,圖像不用零填充,最后4行/列不包括在輸出圖像中。
我們可以看到,如果沒有用零填充,則不包括最后四個單元格,因為卷積濾波器已經(jīng)到達(非零填充)圖像的末尾。這意味著,對于28 x 28的輸入大小,輸出大小變?yōu)?4 x 24 。如果 padding = 'SAME',則輸出大小為28 x 28。
如果在掃描圖像時記下過濾器在圖像上的位置(為簡單起見,只有X方向),那么這一點就變得更加清晰了。如果步幅為1,則X位置為0-5、1-6、2-7,等等。如果步幅為2,則X位置為0-5、2-7、4-9,等等。
如果圖像大小為28 x 28,濾鏡大小為5 x 5,并且步長1到4,那么我們可以得到下面這個表:
可以看到,對于步幅為1,零填充輸出圖像大小為28 x 28。如果非零填充,則輸出圖像大小變?yōu)?4 x 24。對于步幅為2的過濾器,這幾個數(shù)字分別為 14 x 14 和 12 x 12,對于步幅為3的過濾器,分別為 10 x 10 和 8 x 8。以此類推。
對于任意一個步幅S,濾波器尺寸K,圖像尺寸W和填充尺寸P,輸出尺寸將為
如果在Tensorflow中 padding = “SAME”,則分子加起來恒等于1,輸出大小僅由步幅S決定。
2.7 調(diào)整 LeNet5 的架構(gòu)
在原始論文中,LeNet5架構(gòu)使用了S形激活函數(shù)和平均池。 然而,現(xiàn)在,使用relu激活函數(shù)則更為常見。 所以,我們來稍稍修改一下LeNet5 CNN,看看是否能夠提高準確性。我們將稱之為類LeNet5架構(gòu):
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
主要區(qū)別是我們使用了relu激活函數(shù)而不是S形激活函數(shù)。
除了激活函數(shù),我們還可以改變使用的優(yōu)化器,看看不同的優(yōu)化器對精度的影響。
2.8 學(xué)習(xí)速率和優(yōu)化器的影響
讓我們來看看這些CNN在MNIST和CIFAR-10數(shù)據(jù)集上的表現(xiàn)。
在上面的圖中,測試集的精度是迭代次數(shù)的函數(shù)。左側(cè)為一層完全連接的NN,中間為LeNet5 NN,右側(cè)為類LeNet5 NN。
可以看到,LeNet5 CNN在MNIST數(shù)據(jù)集上表現(xiàn)得非常好。這并不是一個大驚喜,因為它專門就是為分類手寫數(shù)字而設(shè)計的。MNIST數(shù)據(jù)集很小,并沒有太大的挑戰(zhàn)性,所以即使是一個完全連接的網(wǎng)絡(luò)也表現(xiàn)的很好。
然而,在CIFAR-10數(shù)據(jù)集上,LeNet5 NN的性能顯著下降,精度下降到了40%左右。
為了提高精度,我們可以通過應(yīng)用正則化或?qū)W習(xí)速率衰減來改變優(yōu)化器,或者微調(diào)神經(jīng)網(wǎng)絡(luò)。
可以看到,AdagradOptimizer、AdamOptimizer和RMSPropOptimizer的性能比GradientDescentOptimizer更好。這些都是自適應(yīng)優(yōu)化器,其性能通常比GradientDescentOptimizer更好,但需要更多的計算能力。
通過L2正則化或指數(shù)速率衰減,我們可能會得到更搞的準確性,但是要獲得更好的結(jié)果,我們需要進一步研究。
3. Tensorflow 中的深度神經(jīng)網(wǎng)絡(luò)
到目前為止,我們已經(jīng)看到了LeNet5 CNN架構(gòu)。 LeNet5包含兩個卷積層,緊接著的是完全連接的層,因此可以稱為淺層神經(jīng)網(wǎng)絡(luò)。那時候(1998年),GPU還沒有被用來進行計算,而且CPU的功能也沒有那么強大,所以,在當時,兩個卷積層已經(jīng)算是相當具有創(chuàng)新意義了。
后來,很多其他類型的卷積神經(jīng)網(wǎng)絡(luò)被設(shè)計出來,你可以在這里查看詳細信息。
比如,由Alex Krizhevsky開發(fā)的非常有名的AlexNet 架構(gòu)(2012年),7層的ZF Net (2013),以及16層的 VGGNet (2014)。
在2015年,Google發(fā)布了一個包含初始模塊的22層的CNN(GoogLeNet),而微軟亞洲研究院構(gòu)建了一個152層的CNN,被稱為ResNet。
現(xiàn)在,根據(jù)我們目前已經(jīng)學(xué)到的知識,我們來看一下如何在Tensorflow中創(chuàng)建AlexNet和VGGNet16架構(gòu)。
3.1 AlexNet
雖然LeNet5是第一個ConvNet,但它被認為是一個淺層神經(jīng)網(wǎng)絡(luò)。它在由大小為28 x 28的灰度圖像組成的MNIST數(shù)據(jù)集上運行良好,但是當我們嘗試分類更大、分辨率更好、類別更多的圖像時,性能就會下降。
第一個深度CNN于2012年推出,稱為AlexNet,其創(chuàng)始人為Alex Krizhevsky、Ilya Sutskever和Geoffrey Hinton。與最近的架構(gòu)相比,AlexNet可以算是簡單的了,但在當時它確實非常成功。它以令人難以置信的15.4%的測試錯誤率贏得了ImageNet比賽(亞軍的誤差為26.2%),并在全球深度學(xué)習(xí)和人工智能領(lǐng)域掀起了一場革命。
它包括5個卷積層、3個最大池化層、3個完全連接層和2個丟棄層。整體架構(gòu)如下所示:
第0層:大小為224 x 224 x 3的輸入圖像
第1層:具有96個濾波器(filter_depth_1 = 96)的卷積層,大小為11×11(filter_size_1 = 11),步長為4。它包含ReLU激活函數(shù)。 緊接著的是最大池化層和本地響應(yīng)歸一化層。
第2層:具有大小為5 x 5(filter_size_2 = 5)的256個濾波器(filter_depth_2 = 256)且步幅為1的卷積層。它包含ReLU激活函數(shù)。 緊接著的還是最大池化層和本地響應(yīng)歸一化層。
第3層:具有384個濾波器的卷積層(filter_depth_3 = 384),尺寸為3×3(filter_size_3 = 3),步幅為1。它包含ReLU激活函數(shù)
第4層:與第3層相同。
第5層:具有大小為3×3(filter_size_4 = 3)的256個濾波器(filter_depth_4 = 256)且步幅為1的卷積層。它包含ReLU激活函數(shù)
第6-8層:這些卷積層之后是完全連接層,每個層具有4096個神經(jīng)元。在原始論文中,他們對1000個類別的數(shù)據(jù)集進行分類,但是我們將使用具有17個不同類別(的花卉)的oxford17數(shù)據(jù)集。
請注意,由于這些數(shù)據(jù)集中的圖像太小,因此無法在MNIST或CIFAR-10數(shù)據(jù)集上使用此CNN(或其他的深度CNN)。正如我們以前看到的,一個池化層(或一個步幅為2的卷積層)將圖像大小減小了2倍。 AlexNet具有3個最大池化層和一個步長為4的卷積層。這意味著原始圖像尺寸會縮小2^5。 MNIST數(shù)據(jù)集中的圖像將簡單地縮小到尺寸小于0。
因此,我們需要加載具有較大圖像的數(shù)據(jù)集,最好是224 x 224 x 3(如原始文件所示)。 17個類別的花卉數(shù)據(jù)集,又名oxflower17數(shù)據(jù)集是最理想的,因為它包含了這個大小的圖像:
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)
讓我們試著在AlexNet中創(chuàng)建權(quán)重矩陣和不同的層。正如我們之前看到的,我們需要跟層數(shù)一樣多的權(quán)重矩陣和偏差矢量,并且每個權(quán)重矩陣的大小應(yīng)該與其所屬層的過濾器的大小相對應(yīng)。
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
現(xiàn)在我們可以修改CNN模型來使用AlexNet模型的權(quán)重和層次來對圖像進行分類。
3.2 VGG Net-16
VGG Net于2014年由牛津大學(xué)的Karen Simonyan和Andrew Zisserman創(chuàng)建出來。 它包含了更多的層(16-19層),但是每一層的設(shè)計更為簡單;所有卷積層都具有3×3以及步長為3的過濾器,并且所有最大池化層的步長都為2。
所以它是一個更深的CNN,但更簡單。
它存在不同的配置,16層或19層。 這兩種不同配置之間的區(qū)別是在第2,第3和第4最大池化層之后對3或4個卷積層的使用(見下文)。
配置為16層(配置D)的結(jié)果似乎更好,所以我們試著在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數(shù)據(jù)集的LeNet5 CNN性能:
4. 結(jié)語
相關(guān)代碼可以在我的GitHub庫中獲得,因此可以隨意在自己的數(shù)據(jù)集上使用它。
在深度學(xué)習(xí)的世界中還有更多的知識可以去探索:循環(huán)神經(jīng)網(wǎng)絡(luò)、基于區(qū)域的CNN、GAN、加強學(xué)習(xí)等等。在未來的博客文章中,我將構(gòu)建這些類型的神經(jīng)網(wǎng)絡(luò),并基于我們已經(jīng)學(xué)到的知識構(gòu)建更有意思的應(yīng)用程序。
評論