用tensorflow實現AlexNet網路
阿新 • • 發佈:2018-12-22
AlexNet網路:
2012年,Alex...提出了深度學習卷積神經網路模型Alexnet,其中包含了幾個當時新穎的技術點。獲得了2012年ILSVRC比賽第一名。Alexnet主要使用的技術點如下:
1.成功使用ReLU作為卷積神經網路的啟用函式,驗證了在深層卷積神經網路的效果超過Sigmoid,成功解決Sigmoid在網路較深層神經網路的梯度消失問題。
2.訓練使用dropout,忽略一部分神經元,以避免過擬合。主要是在最後的幾個全連線層使用了dropout。
3.LRN層(Local Response Normalization),提升泛化能力。實際上好像沒什麼用。而且還降低訓練速度。
4.使用最大池化,避免了平均池化的模糊效果,另外提出了讓步長比池化核小的最大池化方法。可以保證池化出的特徵有重疊,提升特徵的豐富性。
5.資料增強,隨機從256*256的原始影象中隨機擷取224*224大小的區域(並進行水平翻轉)這個操作相當於把資料量曾加了(256-224)*(256*224)*2倍=2048倍。如果沒有資料增強,只靠原始的資料量,眾多的引數會陷入過擬閤中。使用資料增強同業可以提高泛化能力。
額
第一個卷積層使用了較大的卷積核尺寸11*11,步長為4,有96個卷積核;然後是有個3*3步長為2的池化層。只有第一層卷積核比較大,後面的幾層卷積核都比較小,都是5*5或者3*3的卷積核。
#首先匯入幾個需要使用的庫 from datetime import datetime import math import time import tensorflow as tf #這裡設定一個batch為30,共100個batch的資料 batch_size = 32 num_batch = 100 #定義了一個可以列印每一層的名稱(t.op.name)並以列表的方式列印輸入尺寸資訊 def print_activation(t): print(t.op.name,'\n',t.get_shape().as_list()) #設計網路結構,以圖片作為輸入,返回pool5和所有需要訓練的模型引數 def Alexnet_structure(images): #定義一個列表 parameters = [] #定義第一層卷積層 #可以將scope段內所有定義的變數自動命名為conv1/xxx with tf.name_scope('conv1') as scope: #第一層的卷積核,11*11*3,共64個,tf.truncated_normal一種設定正態分佈的方法 kernel = tf.Variable(tf.truncated_normal([11,11,3,64],dtype=tf.float32,stddev=1e-1),name='weigths') #設定第一層卷積層,卷積核是上面初始化後的卷積核,步長為4,4,填充為SAME conv = tf.nn.conv2d(images,kernel,[1,4,4,1],padding='SAME') #設定第一層的偏置,初始值為0 biases = tf.Variable(tf.constant(0.0,shape=[64],dtype=tf.float32),trainable=True,name='biases') #設定w*x+b,之後用啟用函式處理。作為第一層的輸出 W_x_plus_b = tf.nn.bias_add(conv,biases) conv1 = tf.nn.relu(W_x_plus_b,name=scope) #啟用最開始定義的列印層資訊的函式,把輸出尺寸打印出來 print_activation(conv1) parameters += [kernel,biases] #LRN層個人感覺與PCA的效果差不多,PCA實現的是降維,把主要的特徵保留 # LRN實現的是將主要特徵的貢獻放大,將不重要的特徵縮小 #由於效果並不明顯,且執行速度回慢三倍,很多神經網路已經放棄了加入LRN層 #lrn1=tf.nn.lrn(conv1,4,bias=1.0,alpha=0.001/9,beta=0.75,name='lrn1') #pool1=tf.nn.max_pool(lrn1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool1') pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='VALID',name='pool1') print_activation(pool1) #定義第二個網路層 with tf.name_scope('conv2')as scope: #定義卷積核5*5,192個, kernel = tf.Variable(tf.truncated_normal([5,5,64,192],dtype=tf.float32,stddev=1e-1),name='weigtths') #定義了一個卷積操作,步長為1,經過這次卷積後圖像尺寸大小沒有改變 conv = tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], padding='SAME') biases = tf.Variable(tf.constant(0.0,shape=[192],dtype=tf.float32),trainable=True,name='biases') W_x_plus_b = tf.nn.bias_add(conv, biases) #同樣用了relu啟用函式 conv2 = tf.nn.relu(W_x_plus_b, name=scope) parameters += [kernel, biases] print_activation(conv2) #lrn2 = tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001 / 9, beta=0.75, name='lrn2') #pool2 = tf.nn.max_pool(lrn2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool2') #池化層,3*3,步長為2,2,池化後由 [32, 27, 27, 192]--->[32, 13, 13, 192] #這個每一層第一個引數歐式32,這個是batch_size,即每次送入的圖片的數目 pool2 = tf.nn.max_pool(conv2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool2') print_activation(pool2) #定義第三層卷積層 with tf.name_scope('conv3')as scope: kernel = tf.Variable(tf.truncated_normal([3, 3, 192, 384], dtype=tf.float32, stddev=1e-1), name='weigtths') conv = tf.nn.conv2d(pool2, kernel, [1, 1, 1, 1], padding='SAME') biases =tf.Variable(tf.constant(0.0,shape=[384],dtype=tf.float32),trainable=True,name='biases') W_x_plus_b = tf.nn.bias_add(conv, biases) conv3 = tf.nn.relu(W_x_plus_b, name=scope) parameters += [kernel, biases] print_activation(conv3) #定義第四層卷積層 with tf.name_scope('conv4')as scope: kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256], dtype=tf.float32, stddev=1e-1), name='weigtths') conv = tf.nn.conv2d(conv3, kernel, [1, 1, 1, 1], padding='SAME') biases = tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases') W_x_plus_b = tf.nn.bias_add(conv, biases) conv4 = tf.nn.relu(W_x_plus_b, name=scope) parameters += [kernel, biases] print_activation(conv4) #定義第五層卷積層 with tf.name_scope('conv5')as scope: kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256], dtype=tf.float32, stddev=1e-1), name='weigtths') conv = tf.nn.conv2d(conv4, kernel, [1, 1, 1, 1], padding='SAME') biases = tf.Variable(tf.constant(0.0,shape=[256],dtype=tf.float32),trainable=True,name='biases') W_x_plus_b = tf.nn.bias_add(conv, biases) conv5 = tf.nn.relu(W_x_plus_b, name=scope) parameters += [kernel, biases] print_activation(conv5) #根據原網路設計,第五層卷積層後緊跟一個池化層 pool5 = tf.nn.max_pool(conv5, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1], padding='VALID', name='pool5') print_activation(pool5) return pool5,parameters #評估Alexnet每輪計算時間的函式 def time_Alexnet_run(session,target,info_string): num_steps_burn_in = 10 total_duration = 0.0 total_duration_squared = 0.0 for i in range(num_batch+num_steps_burn_in): start_time = time.time() tar = session.run(target) duration = time.time()-start_time if i >= num_steps_burn_in: if not i%10: print('%s:step %d,duration=%.3f'%(datetime.now(),i-num_steps_burn_in,duration)) total_duration+=duration total_duration_squared+=duration*duration mn=total_duration/num_batch vr=total_duration_squared/num_batch-mn*mn sd=math.sqrt(vr) print('%s:s% accoss %d steps,%.3f +/-%.3f sec/batch ' % (datetime.now(), info_string,num_batch,mn,sd)) #主函式 def main(): with tf.Graph().as_default(): image_size = 224 images = tf.Variable(tf.random_normal([batch_size,image_size,image_size,3],dtype=tf.float32,stddev=1e-1)) pool5 , parmeters = Alexnet_structure(images) #初始化所有變數 init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) #統計計算時間 time_Alexnet_run(sess,pool5,"Forward") objective = tf.nn.l2_loss(pool5) grad = tf.gradients(objective,parmeters) time_Alexnet_run(sess,grad,"Forward-backward") print(len(parmeters)) main()
參考書籍:《Tensorflow實戰》黃文堅,唐源,電子工業出版社,第六章。