Tensorflow實現(xiàn)卷積神經(jīng)網(wǎng)絡

卷積神經(jīng)網(wǎng)絡(Convolutional Neural Network,CNN),一般卷積神經(jīng)網(wǎng)路由多個卷積層構(gòu)成,每個卷積層中通常會進行如下幾個操作:

(1)圖像通過多個不同的卷積核的濾波,并加偏置(bias),提取出局部特征,每一個卷積核會映射出一個新的2D圖像。

(2)將前面卷積核的濾波輸出結(jié)果,進行非線性的激活函數(shù)處理,目前最常見的是ReLu函數(shù),而以前Sigmoid函數(shù)用的比較多。

(3)對激活函數(shù)的結(jié)果再進行池化操作(即降采樣6,比如2x2的圖片降維1x1的圖片),目前一般是使用最大池化,保留最顯著的特征,并提升模型的畸變?nèi)萑棠芰Α?/p>

一個卷積層中可以有多個不同的卷積核,而每一個卷積核都對應一個濾波后映射出的新圖像,同一個新圖像中每一個像素都來自完全相同的卷積核,這就是卷積核的權(quán)值共享。卷積核的大小,一般為3X3,5X5,7X7,1x1。卷積操作是局部連接方式,比如整個圖像是1000x1000像素,卷積核是10x10,那圖像的維度就是100,一個卷積核對應一個隱藏節(jié)點,隱藏層節(jié)點就是1W個。如果只有一個卷積核,就只能提取一種卷積核濾波的結(jié)果,即只能提出一種圖片特征。我么可以增加卷積核的數(shù)量多提取一些特征。每一個卷積核濾波得到的圖像就是一類特征的映射,即一個Feature Map.

卷積的好處是,不管圖片尺寸如何,我們需要訓練的權(quán)值數(shù)量只跟卷積核大小、卷積核數(shù)量有關(guān),我們可以使用非常少的參數(shù)量處理任意大小的圖片。隱藏節(jié)點的數(shù)量只跟卷積的步長有關(guān),如果步長為1,那么隱藏節(jié)點的數(shù)量和輸入的圖像的像素數(shù)量一致;如果步長為5,那么每5X5的像素才需要一個隱藏節(jié)點,我們隱藏節(jié)點的數(shù)量就是輸入像素數(shù)量的1/25.

總結(jié)一下,卷積神經(jīng)網(wǎng)絡的要點就是局部連接、權(quán)值共享和池化層中的降采樣。其中局部連接和權(quán)值共享降低了參數(shù)量,使訓練復雜度大大下降,并減輕了過擬合。同時,權(quán)值共享還賦予了卷積網(wǎng)絡對平移的容忍性,而池化曾降采樣則進一步降低了輸出參數(shù)量,并賦予模型對輕度形變的容忍性,提高了模型的泛化能力。

======================================================================================

Tensorflow實現(xiàn)簡單的卷積神經(jīng)網(wǎng)絡

這個簡單的卷積神經(jīng)網(wǎng)絡使用兩個卷積層加一個全連接層構(gòu)建一個簡單但是非常有代表性的卷積神經(jīng)網(wǎng)絡。

首先載入MNIST數(shù)據(jù)集,并創(chuàng)建默認的interactive Session

from tensorflow.examples.tutorials.mnist import input_data

import tensorflow as tf

mnist=input_data.read_data_sets('/tmp/data',one_hot=True)

sess=tf.InteractiveSession()

接下來是實現(xiàn)這個卷積神經(jīng)網(wǎng)絡會有很多權(quán)重和偏置需要創(chuàng)建,因此我們先定義好初始化函數(shù)以便重復使用。我們需要給權(quán)重制造一些隨機的噪聲來打破完全對稱,比如截斷的正太分布噪聲,標準差為0.1.同時因為我們使用ReLu函數(shù),也給偏置增加一些小的正值(0.1)用來避免死亡節(jié)點。

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)

卷積層、池化層也是接下來重復使用的,也為他們分別定義創(chuàng)建函數(shù)。這里的tf.nn.conv2d是tensorflow中的2維卷積函數(shù),參數(shù)中x是輸入,

w是卷積參數(shù),比如[5,5,1,32]:前面兩個數(shù)字代表卷積核的尺寸;第三個數(shù)字代表有多少個channel。因為我們只有灰度單色,所以是1,如果是彩色的RGB圖片,這里應該是3;最后一個數(shù)字代表卷積核的數(shù)量,也就是這個卷積層會提取多少類的特征(多少個不同的卷積核)。

strides代表卷積模板移動的步長,都是1代表會不遺漏地劃過圖片的每一個點。strides[0]和strides[3]的兩個1是默認值,中間兩個1代表padding時在x方向運動一步,y方向運動一步。

Padding代表邊界的處理方式,這里SAME代表邊界加上Padding讓卷積的輸出和輸入保持同樣的尺寸。

tf.nn.max_pool是Tensorflow中最大池化函數(shù),這里使用2x2的最大池化,即講一個2X2的像素塊降維1x1的像素。最大池化會保留原始像素塊中灰度值最高的哪一個像素,即保留最顯著的特征。池化的核函數(shù)大小為2X2.

因為希望整體上縮小圖片尺寸,因此池化層的strides也設(shè)為橫豎兩個方向以2為步長。

def conv2d(x,w):

return tf.nn.conv2d(x,w,strides=[1,1,1,1],padding='SAME')

def max_pool_2X2(x):

return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME')

在正式設(shè)計卷積神經(jīng)網(wǎng)絡結(jié)構(gòu)之前,先定義輸入的placeholder,x是特征,y_是真實的label。因為卷積神經(jīng)網(wǎng)絡利用到空間結(jié)構(gòu)信息,因襲需要將1維的輸入向量轉(zhuǎn)為2維的圖片結(jié)構(gòu),即從1X784->28X28,同時因為只有一個顏色通道,故最終尺寸為[-1,28,28,1],前面的-1代表樣本數(shù)量不固定,最后的1代表顏色通道數(shù)量。這里使用的tensor變形函數(shù)是tf.reshape

x=tf.placeholder(tf.float32,[None,784])

y_=tf.placeholder(tf.float32,[None,10])

x_image=tf.reshape(x,[-1,28,28,1])

接下來定義我們的第一個卷積層。我們先使用前面寫好的函數(shù)進行參數(shù)初始化,包括weights和bias。這里的[5,5,1,32],代表卷積核尺寸為5X5,1個顏色通道,32個不同的卷積核。然后使用conv2d函數(shù)進行卷積操作,并加上偏置,接著再使用ReLu激活函數(shù)進行非線性處理。最后,使用最大池化函數(shù)max_pool_2x2對卷積的輸出結(jié)果進行池化操作。

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_2X2(h_conv1)

現(xiàn)在定義第二個卷積層,這個卷積層基本和第一個卷積層一樣,唯一的不同是卷積核的數(shù)量編程了64,也就是說這一層的卷積會提取64中 特征。上一層的卷積核數(shù)量為32(即輸出32個通道),所以本卷積和尺寸的第三個維度即輸入的通道數(shù)也需要調(diào)整為32

w_conv2=weight_variable([5,5,32,64])

b_conv2=bias_variable([64])

h_conv2=tf.relu(conv2d(h_pool1,w_conv2)+b_conv2)

h_pool2=max_pool_2X2(h_conv2)

因為前面經(jīng)歷了兩次步長為2x2的最大池化,所以邊長已經(jīng)只有1/4了,圖片的尺寸由28x28變成了7x7.而第二個卷積層的卷積核數(shù)量為64,其輸出的tensor尺寸即為7x7x64。我們使用tf.reshape函數(shù)對第二個卷積層的輸出tensor進行變形,將其轉(zhuǎn)成1維的向量,然后連接一個全連接層,隱層節(jié)點數(shù)為1024,并使用ReLu函數(shù)。

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層,Dropout,通過一個placeholder傳入keep_prob比率來控制。在訓練的時候,我們隨機丟棄一部分節(jié)點的數(shù)據(jù)來減輕過擬合,預測時則保留全部數(shù)據(jù)來追求最好的預測性能。

keep_prob=tf.placeholder(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)

在來定義損失函數(shù)為cross_entropy,優(yōu)化器為adam,并給一個比較小的學習速率1e-4

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)

再繼續(xù)定義評測準確率的操作

correct_prediction=tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1))

accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32))

下面開始訓練過程。首先依然是初始化所有參數(shù),設(shè)置訓練時dropout的keep_prob比率為0.5,然后使用大小為50的mini-batch,共進行20000次迭代,參與訓練的樣本數(shù)量總共為100W,其中每100次訓練,我們會對準確率進行一次評測(評測時keep_prob設(shè)為1),用以實時監(jiān)測模型的性能。

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})

全部訓練完成后,我們再最終的測試集上進行全面測試,得到整體的分類準確率。========99.16%

=====================================================================================

Tensorflow實現(xiàn)進階的卷積神經(jīng)網(wǎng)絡

使用的數(shù)據(jù)集是CIFAR-10

先下載tensorflow models庫,以便使用其中提供的CIFAR-10的數(shù)據(jù)類

git clone https://github.com/tensorflow/models.git

cd models/tutorials/image/cifar10

然后我們載入一些常用庫,并載入Tensorflow models中自動下載。讀取CIFAR-10數(shù)據(jù)的類。

import cifar10,cifar10_input

import tensorflow as tf

import numpy as np

import time

接著定義batch_size、訓練輪數(shù)max_steps,以及下載CIFAR-10數(shù)據(jù)的默認路徑。

max_steps=3000

batch_size=128

data_dir='/tmp/cifar10_data/cifar-10-batches-bin'

定義初始化的權(quán)重函數(shù),和之前一樣使用tf.truncated_normal階段的整他分布來初始化權(quán)重。但是這里我們給weight加一個L2的loss,相當于一個L2的正則化處理。

在機器學習中,因特征過多而導致過擬合,一般可以通過減少特征或者懲罰不重要特征的權(quán)重來緩解這個問題。但是通常我們并不知道該懲罰哪些特征的權(quán)重,而正則化就是版主我們懲罰特征權(quán)重的,即特征的權(quán)重也會成為模型損失函數(shù)的一部分??梢岳斫鉃?,為了使用某個特征,我們需要付出loss的代價,除非這個特征非常有效,否則就會被loss上的增加覆蓋效果。這樣我們就可以篩選出最有效的特征,減少特征權(quán)重防止過擬合。

一般來說L1正則會制造稀疏的特征,大部分無用特征的權(quán)重會被置為0,而L2正則會讓特征的權(quán)重不過大,使得特征的權(quán)重比較平均。

我們使用w1控制L2 loss的大小,使tf.nn.l2_loss函數(shù)計算weight的L2 loss,在使用tf.multiply 讓L2 loss乘以w1,得到最后的weight loss。接著我們使用tf.add_to_collection 把weight loss統(tǒng)一存到一個collection,讓這個'collection'名為‘losses’,它會在后面計算神經(jīng)網(wǎng)絡的總體loss時被用上。

def variable_with_weight_loss(shape,stddev,w1):

var=tf.Variable(tf.truncated_normal(shape,stddev=stddev))

if w1 is not None:

weight_loss=tf.multiply(tf.nn.l2_loss(var),w1,name='weight_loss')

tf.add_to_collection('losses',weight_loss)

return var

下面使用cifar10類下載數(shù)據(jù)集,并解壓,展開到其默認位置。

cifar10.maybe_download_and_extract()

再使用cifar10_inputs類中的distorted_inputs函數(shù)產(chǎn)生訓練需要使用的數(shù)據(jù),包括特征及其對應的label,這里返回的是已經(jīng)封裝好的tensor,每次執(zhí)行都會生成一個batch_size的數(shù)量的樣本。

需要注意的是我們隊數(shù)據(jù)進行了data augmentation(數(shù)據(jù)增強)。具體細節(jié)可查看cifar10_input.distorted_inputs函數(shù),其中數(shù)據(jù)增強操作包括隨機的水平翻轉(zhuǎn)(tf.image.random_flip_left_right)、隨機剪切一塊24x24代銷的圖片(tf.random_crop)、設(shè)置隨機的亮度和對比度(tf.image.random_brightness,tf.image.random_contrast),以及對數(shù)據(jù)進行標準化tf.image.per_image_whitening(對數(shù)據(jù)減去均值,除以方差,保證數(shù)據(jù)0均值,方差為1)。通過這些操作,我們可以獲得更多的樣本(帶噪聲的),原來的一張圖片樣本可以變?yōu)槎鄰垐D片,相當于擴大樣本量,對提高準確率非常有幫助。需要注意的是,我們對圖像進行數(shù)據(jù)增強的操作需要耗費大量的CPU時間,因此distorted_inputs使用了16個獨立的縣城來加速任務,函數(shù)內(nèi)部會產(chǎn)生線程池,在需要使用時會通過tensorflow queue進行調(diào)度。

images_train.labels_train=cifar10_input.distorted_inputs(data_dir=data_dir,batch_size=batch_size)

我們再使用cifar10_inputs.inputs函數(shù)生成測試數(shù)據(jù),這里不需要進行太多處理,不需要對圖片進行翻轉(zhuǎn)或修改亮度、對比度,不過需要裁剪圖片正中間的24x24大小的區(qū)塊,并進行數(shù)據(jù)標準化操作。

images_test,labels_test=cifar10_input.inputs(eval_data=True,data_dir=data_dir,batch-size=batch_size)

接下來創(chuàng)建輸入數(shù)據(jù)的placeholder,包括特征和label。在設(shè)定placeholder的數(shù)據(jù)尺寸時需要注意,因為batch_size在之后定義網(wǎng)路結(jié)構(gòu)時被用到了,所以數(shù)據(jù)尺寸中的第一個值即為樣本條數(shù)需要被預先設(shè)定,而不能像以前一樣可以設(shè)為None.而數(shù)據(jù)尺寸中的圖片尺寸為24x24,即是裁剪后的大小,而顏色通過數(shù)設(shè)為3,代表圖片是彩色有RGB三條通道。

image_holder=tf.placeholder(tf.float32,[batch_size,24,24,3])

label_holder=tf.placeholder(tf.int32,[batch_size])

準備工作做好,開始創(chuàng)建第一個卷積層。使用之前創(chuàng)建好的variable_with_weight_loss函數(shù)創(chuàng)建卷積核的參數(shù)并進行初始化。第一個卷積層使用5x5的卷積核大小,3個顏色通道,64個卷積核,同時設(shè)置weight初始化函數(shù)的標準差為0.05。我們部隊第一個卷積層的weight進行L2的正則,因此w1(weight loss)這一項設(shè)為0,下面使用tf.nn.conv2d函數(shù)對輸入數(shù)據(jù)image_holder進行卷積操作,這里的步長stride設(shè)為1,padding 模式為SAME。把這層的bias全部初始化為0,再將卷積的結(jié)果加上bias,最后使用一個ReLu激活函數(shù)進行非線性化。在relu后,我們使用一個尺寸為3x3,且步長為2x2的最大池化層處理數(shù)據(jù),注意這里最大池化的尺寸和步長不一致,這樣可以增加數(shù)據(jù)的豐富性。再之后,我們使用tf.nn.lrn函數(shù),即LRN對結(jié)果進行處理。(LRN模仿了生物神經(jīng)系統(tǒng)的‘側(cè)抑制’機制,對局部神經(jīng)元的活動創(chuàng)建競爭環(huán)境,是的其中響應比較大的值變得相對更大,并抑制其他反饋較小的神經(jīng)元,增強了模型的泛化能力。)

LRN對relu這種沒有上限邊界的激活函數(shù)會比較有用,因為它會從附近的多個卷積核的響應中挑選比價打的反饋,但不適合sigmoid這種有固定邊界并且能抑制過大值的激活函數(shù)。

weight1=variable_with_weight_loss(shape=[5,5,3,64],stddev=5e-2,w1=0.0)

kernel1=tf.nn.conv2d(image_holder,weight1,[1,1,1,1],padding='SAME')

bias1=tf.Variable(tf.constent(0.0,shape=[64]))

conv1=tf.nn.relu(tf.nn.bias_add(kernel1,bias1))

pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

norm1=tf.nn.lrn(pool1,4,bias=1.0,alpha=0.001/9.0,beta=0.75)

現(xiàn)在來創(chuàng)建第二個卷積層,這里的步驟和第一步很像,區(qū)別如下:上一層的卷積核數(shù)量為64(即輸出64個通道),所以本卷積和尺寸的第三個維度即輸入的通道數(shù)也需要調(diào)整為64。還有一個需要注意的地方是這里的bias值全部出初始化為0.1,而不是0,最后我們調(diào)換了最大池化層和LRN層的順序,先進性LRN層處理,在使用最大池化層。

weight2=variable_with_weight_loss(shape=[5,5,64,64],stddev=5e-2,w1=0.0)

kernel2=tf.nn.conv2d(norm1,weight2,[1,1,1,1],padding='SAME')

bias2=tf.Variable(tf.constant(0.1,shape=[64]))

conv2=tf.nn.relu(tf.nn.bias_add(kernel2,bias2))

norm2=tf.nn.lrn(conv2,4,bias=1.0,alpha=0.001/9.0,beta=0.75)

pool2=tf.nn.max_pool(norm2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME')

在兩個卷積層之后,將使用一個全連接層,這里先要把第二個卷積層的輸出結(jié)果flattern,使用tf.reshape函數(shù)將每個樣本都變成一維向量。我們使用get_shape函數(shù),獲取數(shù)據(jù)扁平化之后的長度。接著使用variable_with_weight_loss函數(shù)對全連接層的weight進行初始化,這里隱含節(jié)點數(shù)為384,正太分布的標準差設(shè)為0.04,bias的值也初始化為0.1。需要注意的是我們希望這個全連接層不要過擬合,因此設(shè)了一個非零的weight loss值為0.04,讓這一層的所有參數(shù)都被L2正則所約束。最后我們依然使用relu激活函數(shù)進行非線性化。

reshape=tf.reshape(pool2,[batch_size,-1])

dim=reshape.get_shape()[1].value

weight3=variable_with_weight_loss(shape=[dim,384],stddev=0.04,w1=0.04)

bias3=tf.Variable(tf.constant(0.1,shape=[384]))

local3=tf.nn.relu(tf.matmul(reshape,weight3)+bias3)

接下來這個全連接層和前一層很像,只不過其隱含節(jié)點數(shù)下降了一半,只有192個,其他的超參數(shù)保持不變。

weight4=variable_with_weight_loss(shape=[384,192],stddev=0.004,w1=0.004)

bias4=tf.Variable(tf.constant(0.1,shape=[192]))

local4=tf.nn.relu(tf.matmul(local3,weight4)+bias4)

下面是最后一層,依然先床架這一層的weight,其正太分布標準差設(shè)為上一個隱含層的節(jié)點數(shù)的倒數(shù),并且不計入L2的正則。需要注意的是,這里不像之前那樣使用softmax輸出最后的結(jié)果,這是因為我們把softmax的操作放在了計算loss部分。我們不需要對inference的輸出進行softmax處理就可以獲得最終分類結(jié)果(直接比較inference輸出的各類的數(shù)值大小即可),計算softmax主要是為了計算Loss,因此softmax操作整合到后面是比較合適的。

weight5=variable_with_weight_loss(shape=[192,10],stddev=1/192.0,w1=0.0)

bias5=tf.Variable(tf.constant(0.0,shape=[10]))

logits=tf.add(tf.matmul(local4,weight5),bias5)

卷積神經(jīng)網(wǎng)絡結(jié)構(gòu)表

layer名稱 描述

conv1 卷積層和Relu激活函數(shù)

pool1 最大池化

norm1 LRN

conv2 卷積層和relu激活函數(shù)

norm2 LRN

pool2 最大池化

local3 全連接層和relu激活函數(shù)

local4 全連接層和relu函數(shù)

logits 模型inference的輸出結(jié)果

可以觀察到,其實設(shè)計CNN主要就是安排卷積層、池化層、全連接層的分布和順序,以及其中超參數(shù)的設(shè)置、trick的使用等。設(shè)計性能良好的CNN是有一定規(guī)律可尋的,但是想要針對某個問題設(shè)計最合適的網(wǎng)絡結(jié)構(gòu),是需要大量時間摸索的。

完成了模型inference部分的構(gòu)建,接下來計算cnn的loss。這里依然使用cross entropy,需要注意的是我們把softmax的計算和cross-entropy loss 計算何在一起了,即tf.nn.sparse_softmax_cross_entropy_with_logits。這里使用tf.reduce_mean,對cross entropy 計算均值,再使用tf.add_to_collection把cross entropy 的loss添加到整體losses的collection中。最后,使用tf.add_n將整體的losses的collection中的loss全部求和,得到最終的Loss,其中包括cross entropy loss ,還有兩個全連接層中的weight 的L2 loss.

def loss(logits,labels):

labels=tf.cast(labels,tf.int64)

cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits,labels=labels,name='cross_entropy_per_example')

cross_entropy_mean=tf.reduce_mean(cross_entropy,name='cross_entropy')

tf.add_to_collection('losses',cross_entropy_mean)

return tf.add_n(tf.get_collection('losses'),name='total_loss')

接著將logits 節(jié)點和label_holder 傳入loss函數(shù)獲得最終的loss。

loss=loss(logits,label_holder)

優(yōu)化器選擇Adan optimizer,學習速率設(shè)為1e-3

train_op=tf.train.AdamOptimizer(1e-3).minimize(loss)

使用tf.nn.in_top_k函數(shù)求輸出結(jié)果中top k 的準確率,默認使用top1,也就是輸出分數(shù)最高的哪一類的準確率。

top_k_op=tf.nn.in_top_k(logits,label_holder,1)

使用tf.InteractiveSession創(chuàng)建默認的session,接著初始化全部模型參數(shù)

sess=tf.InteractiveSession()

tf.global_variables_initializer().run()

這一步是啟動前面提到的圖片數(shù)據(jù)增強的線程隊列,這里一共使用了16個縣城來進行加速。注意,如果這里不啟動縣城,那么后續(xù)的inference及訓練的操作都是無法開始的

tf.train.start_queue_runners()

現(xiàn)在正是開始訓練。在每一個step的訓練過程中,我們需要先使用session的run方法執(zhí)行images_train,labels_train的計算,獲得一個batch的訓練數(shù)據(jù),再將這個batch的數(shù)據(jù)傳入train_op和loss計算。我們記錄每一個step花費的時間,每隔10個step會計算并展示當前的loss、每秒能訓練的樣本數(shù)量,以及訓練一個batch數(shù)據(jù)所花費的時間,這樣就可以比較方便地監(jiān)控整個訓練過程。

for step in range(max_steps):

start_time=time.time()

image_batch,label_batch=sess.run([images_train,labels_train])

_,loss_value=sess.run([train_op,loss],feed_dict={image_holder:image_batch,label_holder:label_batch})

duration=time.time()-start_time

if stap%10==0:

examples_per_sec=batch_size/duration

sec_per_batch=float(duration)

format_str=('step %d,loss=%.2f (%.1f examples/sec;%.3f sec/batch)')

print format_str % (step,loss_value,examples_per_sec,sec_per_batch)

接下來評測模型在測試集上的準確率。需要注意的是,我們依然要像訓練時那樣使用固定的batch_size,然后一個batch一個batch地輸入測試數(shù)據(jù)。我們先計算一共要多少個batch才能將全部樣本評測完。同時,在每一個step中使用session的run方法獲取images_test,labels_test的batch,再執(zhí)行top_k_op計算模型在這個batch的top 1上預測正確地樣本數(shù),最后匯總所有預測正確地結(jié)果,求得全部測試樣本中預測正確的數(shù)量。

num_examples=10000

import math

num_iter=int(math.ceil(num_examples/batch_size))

true_count=0

total_sample_count=num_iter*batch_size

step=0

while step<num_iter:

image_batch,label_batch=sess.run([images_test,labels_test])

predictions=sess.run([top_k_op],feed_dict={image_holder:image_batch,label_holder:label_batch})

true_count+=np.sum(predictions)

step+=1

最后將準確率的評測結(jié)果計算并打印出來

precision=true_count/total_sample_count

print 'precision @1=%.3f' % precision

最終,在cifar-10數(shù)據(jù)集上,通過一個算時間小迭代次數(shù)的訓練,可以達到大致73%準確率。持續(xù)增加max_steps,可以期望準確率逐漸增加。如果max_steps比較大,則推薦使用學習速率衰減(decay)的SGD進行訓練,這樣訓練過程中能達到的準確率峰值會比較高,大致接近86%,而其中L2正則以及LRN層的使用都對模型準確率有所提升。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容