TensorFlow學習筆記--自定義圖像識別


零、學習目標

本篇文章主要講解自己的圖像數據如何在TnesorFlow上訓練,主要從數據准備、訓練模型、驗證准確率和導出模型並對圖片分類。重點如下:

  1. 微調
  2. 導出模型並對圖片分類

一、微調

  1. 原理
    對於新手來說,在自己的數據集上訓練一個模型時,最簡單的方法是在ImageNet的模型上進行微調。什么是微調呢?以VGG16為例,它的結構為5部分卷積層共13層(conv1 ~ conv5)和3層的全連接層(fc6 ~ fc8),一共16層,因此被稱為VGG16。
    如果將VGG16的結構用於一個新的數據集,就要去掉最后一層的全連接層,因為最后一層全連接層的輸入是前一層的特征,輸出的是1000類的概率,正好對應了ImageNet中的1000個類別,但是在這里,我們的類別只有6種,所以要去掉最后一層全連接層,采用一個更符合數據類別的全連接層。
    這時,網絡參數的初始化值就不是隨機生成的了,而是利用VGG16在ImageNet上已經訓練好的參數作為訓練的初始值。因為ImageNet訓練集上的VGG16已經包含了大量有用的卷積過濾器,使用已存在的參數不久節約時間,也有助於提高分類器的性能。

  2. 訓練范圍
    在載入參數后,我們可以指定訓練層數范圍,訓練層數可選范圍如下:

  3. 只訓練fc8這一層,保持其他層的參數不變,將VGG16作為一個特征提取器,用fc7層提起的特征做Softmax分類,這樣做有利提高訓練速度,但是性能不是最佳的;

  4. 訓練所有參數,對網絡中的所有參數都進行訓練,性能得以提高,深度模型得以充分發揮,但是速度太慢;

  5. 訓練部分參數,固定淺層參數不變,訓練深層參數。

以上這三種方法就是神經網絡的微調,通過微調可以將神經網絡通過以有模型應用到自己的數據集上。

  1. 數據處理
    我們首先將數據分為訓練集和驗證集,之后將圖片轉化為tfrecord格式【注1】。將文件夾 data_preoare 復制到項目的根部錄下。這個文件夾中由所需的數據集和代碼。data_preoare/pic/train 目錄是訓練文件所在的目錄,data_preoare/pic/validation 目錄是驗證文件所在的目錄。兩個目錄下又以不同分類划分了6種類別,分別為:農田、冰川、城市地區、森林、水域和岩石,每個文件夾中存放的圖片為jpg格式的圖片。
    由於神經網絡無法識別jpg格式的數據,所以需要將圖片數據轉為tfrecord格式的數據。 切換到 data_preoare 文件夾下,在命令行輸入如下命令進行格式轉換:
python data_convert.py -t pic/ --train-shards 2 --validation-shards 2 --num-threads 2 --dataset-name satellite

解釋一下上面參數的含義:

參數 含義
-t pic/ 指定要轉換的數據所在的文件夾,這個文件夾下必須有一個訓練目錄和一個驗證目錄,並且每個目錄按類別存放圖片數據
–train-shards 2 將訓練數據集分為兩塊,也就是說轉換完格式后訓練數據集將會是兩個tfrecord格式的文件【注2】
–validation-shards 2 將驗證數據集分為兩塊
–num-threads 2 采用兩個線程生產數據【注3】
–dataset-name:satellite 給轉換后的數據集起一個名字

運行命令后,pic文件夾下會出現五個新的數據文件,以 satellite_train_ 開頭的訓練據文件和以 satellite_validation_ 開頭的驗證數據文件,並且還包含一個label.txt文件,表示圖片的標簽數字到真實類別字符串的映射順序。例如tfrecod中圖片標簽為0,就代表類別為label.txt中的第一行類別。

注1:
文件下載地址:下載文件

注2:
如果訓練數據集較大,則可以將訓練數據集划分為多個數據塊

注3:
線程數量必須能整除train-shars和validation-shards,這樣才能抱枕每個線程中數據塊的數量相等

  1. 下載TensorFlow Slim 源代碼
    下載TensorFlow Slim 是Google提供的圖像分類工具。里面提供了圖像分類的接口、常用的網絡結構和預訓練模型。
    利用git下載Slim源碼:git clone ht仁ps://github.corn/tensorflow/models.git,我所提供的下載地址中也有Slim源碼。將 Slim 文件夾復制到根目錄下即可。代碼結構如下:
文件名/文件夾名 說明
datasets/ 訓練時需要用到的數據庫,訓練自己的數據時必須在這里進行定義自己的數據庫
nets/ 常用的網絡結構
preprocessing/ 針對不同網絡定義了不同的預處理數據的方法
scripts/ 訓練示例腳本
train_image_classificer.py 訓練模型入口
eval_image_classificer.py 驗證模型性能入口
download_and_convert_data.py 下載並轉換數據及各式入口
  1. 定義dataset
    slim/datasets 目錄下創建 satellite.py 文件,將 flowers.py 文件中的內容復制進去。修改部分代碼:
  2. _FILE_PATTERN、SPLITS_TO_SIZE、_NUM_CLASSES
# 數據的文件名
_FILE_PATTERN = 'satellite_%s_*.tfrecord'
# 訓練集和驗證集的數量
SPLITS_TO_SIZE = {'train':4800,'validation':1200}
# 數據集中圖片的類別數目
_NUM_CLASSES = 6

  1. image/format
# 設定圖片格式
'image/format' : tf.FixedLenFeature((),tf.string,default_value = 'jpg')

  1. 修改dataset_factory.py
from datasets import cifar10
from datasets import flowers
from datasets import imagenet
from datasets import mnist
# 將satellite模塊添加進來
from datasets import satellite

# satellite 數據庫加入進來
datasets_map = {
  'cifar10':cifar10,
  'flowers':flowers,
  'imagenet':imagenet,
  'mnist':mnist,
  'satellite':satellite
}

  1. 准備訓練文件夾
    在slim文件夾下新建 satellite 目錄、satellite/data(訓練和驗證數據文件夾)、satellite/train_dir(保存訓練日志和模型文件夾)、satellite/pretrained。創建完目錄后需要完成以下工作:

  2. 將轉換好格式的數據(包括label.txt)復制 satellite/data 文件夾

  3. 下載Inception V3模型,下載地址是:下載地址,解壓后,將inception_v3.ckpt文件復制到 satellite/pretrained

  4. 訓練程序
    在slim文件夾下啟動命令行,輸入如下命令開始訓練(代碼需要在TensorFlow GPU版本上運行):

python train_image_classifier.py --train_dir=satellite/train_dir --dataset_name=satellite --dataset_split_name=train --dataset_dir=satellite/data --model_name=inception_v3 --checkpoint_path=satellite/pretrained/inception_v3.ckpt --checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits --trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits --max_number_of_steps=100000 --batch_size=32 --learning_rate=0.001 --learning_rate_decay_type=fixed --save_interval_secs=300 --save_summaries_secs=2 --log_every_n_steps=10 --optimizer=rmsprop --weight_decay=0.00004

解釋一下上面參數的含義:

參數 說明
–trainable_scopes=InceptionV3/Logits,InceptionV3/AuxLogits 指定模型微調變量的范圍。這里指設定表示只對 InceptionV3/Logits 和 InceptionV3/AuxLogits 兩個變量微調,也就是對fc8進行微調,如果不設置此參數,將會對所有參數進行訓練。
–train_dir=satellite/train_dir 在 satellite/train_dir 目錄下保存日志和模型文件(heckpoint)
–dataset_name=satellite、–datasets_split_name=train 指定訓練數據集
–dataset_dir=satellite/data 訓練數據集保存的位置
–model_name=inception_v3 使用的模型名稱
–checkpoint_path=satellite/pretrained/inception_v3.ckpt 預訓練模型保存的位置
–checkpoint_exclude_scopes=InceptionV3/Logits,InceptionV3/AuxLogits 恢復預訓練模型時不回復這兩層,因為這兩層模型對應着ImageNet數據集的1000類,與當前數據集不符,所以不要恢復他
–max_number_of_steps 100000 最大執行步數
–batch_size=32 每步的batch數量
–learning_rate=0.001 學習率
–learning_rate_decay_type=fixed 學習率是否下降,此處固定學習率
–save_interval_secs=300 每隔300秒保存一次模型,保存到train_dir目錄下
–save_summaries_secs=2 每隔2秒保存一次日志
–log_every_n_steps=10 每隔10步在屏幕上打印出訓練信息
–optimizer=rmsprop 指定優化器
–weight_decay=0.00004 設定weight_decay,即模型中所有參數的二次正則化超參數

注4:
開始訓練時,如果訓練文件夾(satellite/train_dir)里沒有保存的模型,就會自動加載 checkpoint_path 中的預訓練模型,然后程序會把初始模型保存在train_dir中,命名為 model.ckpt-0,0表示第0步。之后每隔300秒就會保存一次模型,由於模型較大,所以只會保留最新的5個模型。如果中斷程序運行后再次運行,會首先檢查train_dir文件夾中是否存在模型,如果存在則接着存在的模型開始訓練。

  1. 驗證模型
    要查看模型的准確率,可以使用 eval_image_classifier.py 來驗證,在命令行輸入如下命令:
python eval_image_classifier.py --checkpoint_path=satellite/train_dir --eval_dir=statellite/eval_dir --dataset_name=satellite --dataset_split_name=validation --dataset_dir=satellite/data --model_name=inception_v3

下面來解釋一下參數

參數 說明
–checkpoint_path=satellite/train_dir 參數可以接收目錄路徑或者文件路徑。如果是一個目錄路徑,則會查找這個目錄下最新的模型
–eval_dir=satellite/eval_dir 執行結果日志的保存目錄
–dataset_dir=satellite/data 驗證數據集保存位置
–model_name=inception_v3 使用的模型

執行后會打印出如下內容:

eval/Accuracy[0.51]
eval/Recall_5[0.973333336]

Accuracy表示模型的分類准確率,Recall_5表示前5次的准確率

  1. TensorBoard 可視化與超參數選擇
    使用TnesorBoard 有助於設定訓練模型的方式以及超參數,命令行輸入如下參數:
tensorboard --logdir satellite/train_dir

在TensorBoard中可以查看損失變化曲線,損失變化曲線有助於調整參數。如果損失曲線比動較大,無法收斂,就有可能時學習率過大,適當減小學習率就行了。
現在做如下操作:

  1. train_dir 中建立兩個文件夾,分別存放只微調fc8和微調整個網絡的模型。通過調整 train_dir 參數將這兩種模型分別存入新建的文件夾中,之后使用命令:
tensorboard --logdir satellite/train_dir

瀏覽器打開TensorBoard就可以看到狂歌模型的損失曲線,上方的為只訓練末端的損失數,下方為訓練所有層的損失函數。看損失函數可以看出訓練所有層比只訓練末端要好。

二、到處模型並分類圖片

模型訓練完之后,將會進行部署。這里提供了兩個文件 freeze_graph.pyclassify_image_inception_v3.py 前者用於導出識別模型,后者用於識別單張圖片。在slim文件夾下執行如下命令:

python export_inference_graph.py --alsologtostderr --model_name=inception_v3 --output_file=satellite/inception_v3_inf_graph.pb --dataset_name satellite

命令執行后,會在satellite文件夾下生成一個 inception_v3_inf_graph.pb 文件,但是這個文件不包含訓練獲得的模型參數,需要將cheeckpoint中的模型參數保存進來,方法是使用freeze_graph.py:

python freeze_graph.py --input_graph slim/satellite/inception_v3export_inference_graph.pb --input_checkpoint slim/satellite/train_dir/model.ckpt-5271 --input_binary true --output_node_names InceptionV3/Predictions/Reshape_1 --output_graph slim/satellite/frozen_graph.pb

這里講解一下參數:

參數 說明
–input_graph slim/satellite/inception_v3_inf_graph.pb 使用的網絡結構文件(前一步已經導出)
–input_checkpoint slim/satellite/train_dir/model.ckpt-5271 指定載入到網絡結構中的checkpoint參數
–input_binary true 使用網絡結構文件是二進制還是文本形式
–output_node_names InceptionV3/Predictions/Reshape_1 是Inception V3最后的輸出層
–output_graph slim/satellite/frozen_graph.pb 導出模型的文件

下面開始對圖片進行識別。命令行執行腳本 classify_image_inception_v3.py ,運行如下命令:

python classify_image_inception_v3.py --model_path slim/statellite/frozen_graph.pb --label_path data_preoare/pic/label.txt --image_file test_image.jpg

講解參數:

參數 說明
–model_path slim/statellite/frozen_graph.pb 導入訓練好的模型
–label_path data_preoare/pic/label.txt 將–model_path輸出的結果轉換為對應的名稱
–image_file test_image.jpg 要識別的圖片

執行完參數后,將輸出每種類別的概率。

三、總結

首先簡要介紹了微調神經網絡的基本原理,接着詳細介紹了如何使用 TensorFlow Slim 微調預訓練模型,包括數據准備、定義新的 datasets 文件、訓練、 驗證 、 導出模型井測試單張圖片等。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM