TensroFlow學習——第三章(三)
阿新 • • 發佈:2018-12-05
卷積神經網路遷移學習
基於訓練好的Inception-v3的模型,對flower_photos資料集進行分類
訓練結果如下,測試集的準確率為91.0082%
演算法如下:
import os import random import numpy as np import tensorflow as tf from tensorflow.python.platform import gfile import matplotlib.pyplot as plt # Inception-v3模型瓶頸層的極點個數 BOTTLENECK_TENSOR_SIZE=2048 # Inceotion-v3模型中代表瓶頸層結果的張量名稱 # 在谷歌提供的Inception-v3模型中,這個張量名稱為‘pool_3/_reshape:0’ BOTTLENECK_TENSOR_NAME='pool_3/_reshape:0' # 影象輸入張量所對應的名稱 JPEG_DATA_TENSOR_NAME='DecodeJpeg/contents:0' # 下載好的谷歌訓練好的模型 MODEL_PATH='./data/classify_image_graph_def.pb' # 將通過Inception_v3提取的特徵儲存在檔案中 Feature_path='./image.txt' # 訓練樣本路徑 Input_path='./data/flower_photos' # 驗證、測試資料百分比 VALIDATION_PERCENTAGE=0.1 TEST_PERCENTAGE=0.1 # 設定神經網路引數 LEARNING_RATE=0.01 STEPS=4000 BATCHSIZE=100 # 類別 LABELS={'daisy':0, 'dandelion':1, 'roses':2, 'sunflowers':3, 'tulips':4} # 提取圖片資料,並分為訓練集、驗證集和測試集 def create_image_list(): all_images,all_labels=[],[] label_list=os.listdir(Input_path) for file_name in label_list: image_dir=os.path.join(Input_path,file_name) image_list=os.listdir(image_dir) for name in image_list: image_name=os.path.join(image_dir,name) labels=np.zeros(len(LABELS),dtype=np.float32) labels[LABELS[file_name]]=1.0 all_images.append(image_name) all_labels.append(labels) return all_images,all_labels # 讀取提取的特徵向量作為訓練資料 def get_features(test_percentage,vaildation_percentage): # 讀取特徵資料 images,labels=[],[] with open(Feature_path,'r') as file: string=file.readlines() for one_line in string: one_line=one_line.split('|') images.append([float(x) for x in one_line[0].split(',')]) labels.append([float(x) for x in one_line[1].split(',')]) # 分為訓練集、驗證集和測試集 sum=list(zip(images,labels)) random.shuffle(sum) images[:],labels[:]=zip(*sum) LEN1=int(test_percentage*len(images)) LEN2=int(vaildation_percentage*len(images)) # 返回的順序分別為test,valid,train return images[:LEN1],labels[:LEN1],images[LEN1:LEN1+LEN2],labels[LEN1:LEN1+LEN2],images[LEN1+LEN2:],labels[LEN1+LEN2:] # 從訓練資料中批量取出資料 def random_get_batch_data(batch_size,images,labels): batch_image,batch_label=[],[] for i in range(batch_size): index=random.randint(0,len(images)-1) batch_image.append(images[index]) batch_label.append(labels[index]) return batch_image,batch_label def main(argv=None): images,labels=create_image_list() train_datas=[] # 讀取訓練好的Inception-v3模型 with gfile.FastGFile(MODEL_PATH,'rb') as f: graph_def=tf.GraphDef() graph_def.ParseFromString(f.read()) # 載入讀取的Inception-v3模型,並返回資料輸入所對應的張量以及計算瓶頸層結果對應的張量 bottle_tensor,jpeg_data_tensor=tf.import_graph_def(graph_def,return_elements=[BOTTLENECK_TENSOR_NAME,JPEG_DATA_TENSOR_NAME]) if 0:#此部分備註掉是因為,用Inception-v3模型提取特徵後,會寫入檔案,因此在調整全連線層的引數時,可以不用再進行提取特徵操作 # 提取特徵向量 with tf.Session() as sess: for img in images: image=gfile.FastGFile(img,'rb').read() bottleneck_value=sess.run(bottle_tensor,feed_dict={jpeg_data_tensor:image}) # 將四維張量轉化成以為陣列 bottleneck_value=np.squeeze(bottleneck_value) train_datas.append(bottleneck_value) # 寫入檔案 with open('./image.txt', 'w') as file: for i in range(len(train_datas)): string=','.join(str(x) for x in train_datas[i])+'|'+','.join(str(x) for x in labels[i])+'\n' file.write(string) # 讀取特徵量 test_image,test_label,valid_image,valid_label,train_image,train_label=get_features(TEST_PERCENTAGE,VALIDATION_PERCENTAGE) n_classes=len(LABELS) # 定義新的神經網路輸入,這輸入是新的圖片經過Inception-v3模型向前傳播到達瓶頸層時的節點取值 bottle_input=tf.placeholder(tf.float32,[None,BOTTLENECK_TENSOR_SIZE],name='BottleneckInputPlaceholder') ground_truth_input=tf.placeholder(tf.float32,[None,n_classes],name='GroundTruthInput') # 定義全連線層,用於將特徵分類 with tf.name_scope('Final_training_ops'): weights=tf.Variable(tf.truncated_normal([BOTTLENECK_TENSOR_SIZE,n_classes],stddev=0.001)) biases=tf.Variable(tf.zeros([n_classes])) logits=tf.matmul(bottle_input,weights)+biases final_tensor=tf.nn.softmax(logits) # 交叉熵損失函式 cross_entropy=tf.nn.softmax_cross_entropy_with_logits(logits=final_tensor,labels=ground_truth_input) cross_entropy_mean=tf.reduce_mean(cross_entropy) train_step=tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean) # 計算正確率 with tf.name_scope('evalution'): correct_prediction=tf.equal(tf.arg_max(final_tensor,1),tf.arg_max(ground_truth_input,1)) accuracy=tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) train_loss,train_acc=[],[] val_loss,val_acc=[],[] with tf.Session() as sess: init=tf.initialize_all_variables() sess.run(init) for epoch in range(STEPS): batch_image,batch_label=random_get_batch_data(BATCHSIZE,train_image,train_label) _,loss,acc=sess.run([train_step,cross_entropy_mean,accuracy],feed_dict={bottle_input:batch_image,ground_truth_input:batch_label}) if (epoch+1)%100==0: print('<=%d=>,loss:%g,acc:%g%%'%(epoch+1,loss,acc*100.0)) train_loss.append(loss) train_acc.append(acc) loss,acc=sess.run([cross_entropy_mean,accuracy],feed_dict={bottle_input:valid_image,ground_truth_input:valid_label}) val_loss.append(loss) val_acc.append(acc) loss,acc=sess.run([cross_entropy_mean, accuracy],feed_dict={bottle_input:test_image,ground_truth_input:test_label}) print('Test loss:%g,acc:%g%%'%(loss,acc*100.0)) epochs=[i for i in range(len(train_acc))] plt.figure(1) plt.grid(True) plt.plot(epochs,train_loss,color='red',label='train_loss') plt.plot(epochs,val_loss,color='blue',label='valid_loss') plt.plot(epochs,train_acc,color='black',label='train_acc') plt.plot(epochs,val_acc,color='green',label='valid_acc') plt.legend() plt.xlabel('Epochs',fontsize=15) plt.ylabel('Y',fontsize=15) plt.title('LOSS AND ACC',fontsize=15) plt.show() if __name__=='__main__': tf.app.run()