用cifar10訓練一個卷積神經網路
阿新 • • 發佈:2018-12-23
今天按照教程搭建了一個神經網路,這裡總結一下。搭建神經網路的結構如下所示:
我們搭建自己的網路時,一般先確定自己的網路架構,然後計算個層引數,做好這些預備工作之後就可以開始寫程式碼了。
#匯入所需要的包 import cifar10,cifar10_input import tensorflow as tf import numpy as np import time import math max_step=3000#迭代3000次 batch_size=128#每次迭代使用128張圖片 #下載cifar10的預設路徑 data_dir='/tmp/cifar10_data/cifar-10-batches-bin' #定義權重函式 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把weight loss統一存到一個collection,這個collection名為"losses",它會在後面計算神經網路總體loss時被用上 tf.add_to_collection("losses", weight_loss) return var # 下載cifar10類的資料集,並解壓,展開到其預設位置 cifar10.maybe_download_and_extract() #按每一批次來讀取資料 images_train,labels_train=cifar10_input.distorted_inputs( data_dir=data_dir, batch_size=batch_size) images_test,labels_test=cifar10_input.inputs(eval_data=True, data_dir=data_dir, batch_size=batch_size) # 因為batch_size在之後定義網路結構時被用到了,所以資料尺寸中的第一個值即樣本條數需要被預先設定,而不能像以前那樣設定為None # 而資料尺寸中的圖片尺寸為24*24即是剪裁後的大小,顏色通道數則設為3 # 這裡寫batch_size而不是None 因為後面程式碼中get_shape會拿到這裡面的batch_size #訓練集多少行,就有多少個Label image_holder=tf.placeholder(tf.float32,[batch_size,24,24,3]) labels_holder=tf.placeholder(tf.int32,[batch_size]) #第一個卷積層,64個卷積核,卷積核大小是5*5,3通道 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.constant(0.0,shape=[64]))#初始化引數 conv1=tf.nn.relu(tf.nn.bias_add(kernel1,bias1))#使用啟用函式啟用 # 使用尺寸3*3步長2*2的最大池化層處理資料,這裡最大池化的尺寸和步長不一樣,可以增加資料的豐富性 pool1=tf.nn.max_pool(conv1,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME') # 使用LRN對結果進行處理 norm1=tf.nn.lrn(pool1,4,bias=0.1,alpha=0.001/9.0,beta=0.75) #第二個卷積層 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))#使用啟用函式啟用 # 使用LRN對結果進行處理 norm2=tf.nn.lrn(conv2,4,bias=0.1,alpha=0.001/9.0,beta=0.75) # 使用尺寸3*3步長2*2的最大池化層處理資料,這裡最大池化的尺寸和步長不一樣,可以增加資料的豐富性 pool2=tf.nn.max_pool(norm2,ksize=[1,3,3,1],strides=[1,2,2,1],padding='SAME') #全連線層 #使用tf.reshape函式將每個樣本都變成一維向量,使用get_shape函式獲取資料扁平化之後的長度 reshape=tf.reshape(pool2,[batch_size,-1]) dim=reshape.get_shape()[1].value # 接著初始化權值,隱含節點384個,正太分佈的標準差設為0.04,bias的值也初始化為0.1 # 注意這裡我們希望這個全連線層不要過擬合,因此設了一個非零的weight loss值0.04,讓這一層具有L2正則所約束。 weight3=variable_with_weight_loss(shape=[dim,384],stddev=0.04,w1=0.004) bias3=tf.Variable(tf.constant(0.1,shape=[384]))#寫0.1是為了Relu小於0時全為0,所以給0.1不至於成為死亡神經元 # 最後我們依然使用ReLU啟用函式進行非線性化 local3=tf.nn.relu(tf.matmul(reshape,weight3)+bias3) #第二個全連線層 weight4=variable_with_weight_loss(shape=[384,192],stddev=1/192.0,w1=0.0) bias4=tf.Variable(tf.constant(0.0,shape=[192])) local4=tf.nn.relu(tf.matmul(local3,weight4)+bias4) #最後一層(輸出層) 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) #定義loss函式 def loss(logits,labels): labels=tf.cast(labels,tf.int64) #把softmax的計算和cross_entropy的計算合在了一起 cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits( logits=logits,labels=labels,name='cross_entropy_per_example') #對 cross entropy計算均值 cross_entropy_mean=tf.reduce_mean(cross_entropy,name='cross_entropy') #使用tf.add_n將整體losses的collection集合中的全部loss求和,得到最終的loss tf.add_to_collection('losses',cross_entropy_mean) return tf.add_n(tf.get_collection('losses'),name='total_loss') loss=loss(logits,labels_holder)#logits輸出的結果 train_op=tf.train.AdamOptimizer(1e-3).minimize(loss) # 使用 tf.nn.in_top_k()函式求輸出結果中 top k的準確率,預設使用top 1,也就是輸出分數最高的那一類的準確率 top_k_op=tf.nn.in_top_k(logits,labels_holder,1) sess=tf.InteractiveSession() tf.global_variables_initializer().run() # 啟動圖片資料增強的執行緒佇列,這裡一共使用了16個執行緒來進行加速,如果不啟動執行緒,那麼後續inference以及訓練的操作都是無法開始的 tf.train.start_queue_runners() #訓練 for step in range(max_step): 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,labels_holder:label_batch}) duration=time.time()-start_time if step %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)) #評測模型在測試集上的準確率 num_examples=10000 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,labels_holder:label_batch})#有多少個相同的結果預測出的和真實的比較 true_count+=np.sum(predictions) step+=1 precision=true_count/total_sample_count#預測對的和總的樣本數 print('precision @ 1=%.3f'%precision)