1. 程式人生 > >SSD-Tensorflow 訓練記錄

SSD-Tensorflow 訓練記錄

前記: 本篇部落格純屬記錄我在用VOC資料集以及自己的資料集訓練SSD-Tensorflow時遇到的一些問題以及部分問題的解決方法。

  1. 搭建SSD-Tensorflow框架,star最多的balancap大神的GitHub地址:https://github.com/balancap/SSD-Tensorflow
  2. 準備資料
    (1)VOC資料集:地址http://host.robots.ox.ac.uk/pascal/VOC/ 需翻牆獲取
    資料集下載後解壓得到一個名為VOCdevkit的資料夾,對資料夾裡的內容做一個簡單的介紹。
  • Annotation資料夾存放的是xml檔案,是圖片的標註資訊。
  • ImageSets資料夾存放的是txt檔案,這些txt將資料集的圖片分成了各種集合。如Main下的train.txt中記錄的是用於訓練的圖片集合
  • JPEGImages資料夾存放的是資料集的原圖片
  • SegmentationClass以及SegmentationObject資料夾存放的是分割後的圖片
    (2) 自己的資料集
    按照VOC資料集的格式轉化即可,網上有相應的程式碼實現,注意圖片格式要為“.jpg"
  1. 將影象資料轉化為tfrecord格式
    建立一個tf_convert_data.sh指令碼檔案,寫入以下程式碼:
    tf_convert_data.sh
DATASET_DIR=./data/VOCtrainval_06-Nov-2007/VOCdevkit/VOC2007/ #此處為你需要轉化的訓練資料
OUTPUT_DIR=./tfrecords #用於存放輸出資料的資料夾,可以自己指定
python tf_convert_data.py \
    --dataset_name=pascalvoc \
    --dataset_dir=${DATASET_DIR} \
    --output_name=voc_2007_train \  #輸出tfrecord格式前置名稱,如果是測試資料,需改為voc_2007_test
    --output_dir=${OUTPUT_DIR}

若是將自己的資料轉化為tfrecord格式需要對部分原始碼進行修改:
在SSD-Tensorflow-master—>datasets—>pascalvoc_common.py下對修改VOC_LABELS為自己的label

"""
VOC_LABELS = { 
    'none': (0, 'Background'), 
    'aeroplane': (1, 'Vehicle'), 
    'bicycle': (2, 'Vehicle'), 
    'bird': (3, 'Animal'), 
    'boat': (4, 'Vehicle'), 
    'bottle': (5, 'Indoor'), 
    'bus': (6, 'Vehicle'), 
    'car': (7, 'Vehicle'), 
    'cat': (8, 'Animal'), 
    'chair': (9, 'Indoor'), 
    'cow': (10, 'Animal'), 
    'diningtable': (11, 'Indoor'), 
    'dog': (12, 'Animal'), 
    'horse': (13, 'Animal'), 
    'motorbike': (14, 'Vehicle'), 
    'Person': (15, 'Person'), 
    'pottedplant': (16, 'Indoor'), 
    'sheep': (17, 'Animal'), 
    'sofa': (18, 'Indoor'), 
    'train': (19, 'Vehicle'), 
    'tvmonitor': (20, 'Indoor'), 
}

"""
比如只檢測人,修改為
VOC_LABELS = { 
'none': (0, 'Background'),
'person':(1, 'Person')

然後再執行上述指令碼命令。

  1. 訓練
    訓練VOC資料集
    建立一個shell檔案,命名為train_ssd_network.sh(可隨意),寫入以下指令碼命令
#此訓練為基於預訓練好的權重引數vgg_16的基礎之上進行的訓練,其中
# checkpoint_exclude_scopes:指定哪些層不需要從vgg_16.ckpt載入引數,即這些層的引數隨機初始化。
# trainable_scopes:指定需要需要訓練的層。若註釋掉,則表明所有層均需要參與訓練。

DATASET_DIR=./tfrecords/    #存放的資料集
TRAIN_DIR=./log/train_logs #用於儲存訓練過程中的權重引數,圖資訊等,可通過tensorboard --logdir顯示
CHECKPOINT_PATH=./checkpoints/vgg_16.ckpt  #預訓練好的vgg_16權重引數,也可以指定為預訓練好的ssd_300_vgg.ckpt
python train_ssd_network.py \
    --train_dir=${TRAIN_DIR} \
    --dataset_dir=${DATASET_DIR} \
    --dataset_name=pascalvoc_2007 \  #網路裡定死的資料格式,最好不要隨意修改,要與資料名稱一致.
    --dataset_split_name=train \   
    --model_name=ssd_300_vgg \
    --checkpoint_path=${CHECKPOINT_PATH} \
    --checkpoint_model_scope=vgg_16 \
    --checkpoint_exclude_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
    --trainable_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block10,ssd_300_vgg/block11,ssd_300_vgg/block4_box,ssd_300_vgg/block7_box,ssd_300_vgg/block8_box,ssd_300_vgg/block9_box,ssd_300_vgg/block10_box,ssd_300_vgg/block11_box \
    --save_summaries_secs=60 \
    --save_interval_secs=600 \
    --weight_decay=0.0005 \
    --optimizer=adam \
    --learning_rate=0.001 \
    --learning_rate_decay_factor=0.94 \
    --batch_size=32

需要在train_ssd_network.py修改第154行 設定最大訓練步數,將None設定為100000,否則會一直訓練下去。
5. 基於自己訓練的結果微調

DATASET_DIR=./tfrecords/
TRAIN_DIR=./log/fine_tuning_logs/
CHECKPOINT_PATH=./log/train_logs/model.ckpt-xxxx
python train_ssd_network.py \
    --train_dir=${TRAIN_DIR} \
    --dataset_dir=${DATASET_DIR} \
    --dataset_name=pascalvoc_2012 \
    --dataset_split_name=train \
    --model_name=ssd_300_vgg \
    --checkpoint_path=${CHECKPOINT_PATH} \
    --checkpoint_model_scope=ssd_300_vgg \
    --save_summaries_secs=60 \
    --save_interval_secs=600 \
    --weight_decay=0.0005 \
    --optimizer=adam \
    --learning_rate=0.0001 \
    --learning_rate_decay_factor=0.94 \
    --batch_size=32
  1. 對訓練結果評估
DATASET_DIR=./tfrecords/  #存放測試資料集的資料夾,提前將測試資料轉化為tfrecord格式存放在該目錄下(也可以自行指定)
EVAL_DIR=./logs/   #儲存評估結果
CHECKPOINT_PATH=./checkpoints/ssd_300_vgg.ckpt    #可設定為自己訓練的模型引數,即對自己的結果評估
python eval_ssd_network.py \
    --eval_dir=${EVAL_DIR} \
    --dataset_dir=${DATASET_DIR} \
    --dataset_name=pascalvoc_2007 \
    --dataset_split_name=test \
    --model_name=ssd_300_vgg \
    --checkpoint_path=${CHECKPOINT_PATH} \
    --batch_size=1

問題彙總:

  1. Key vgg_16/block10/conv1x1/biases not found in checkpoint
    [[Node: save_1/RestoreV2 = RestoreV2[dtypes=[DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, …, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT, DT_FLOAT], _device="/job:localhost/replica:0/task:0/device:CPU:0"](_arg_save_1/Const_0_0, save_1/RestoreV2/tensor_names, save_1/RestoreV2/shape_and_slices)]]
    解決辦法:將–checkpoint_model_scope=vgg_16 \更改為–checkpoint_model_scope=ssd_300_vgg \

  2. 在windows對下載解壓好的SSD-Tensorflow-master進行demo測試時,執行ssd_notebook.ipynb發現ssd_300_vgg.ckpt檔案始終載入不進去?
    解決辦法:看ssd_300_vgg.ckpt是否在checkpoints資料夾下,windows解壓壓縮檔案會建立一個ssd_300_vgg的資料夾,此時將ssd_300_vgg.ckpt檔案移出到checkpoints目錄下即可。linux下解壓不存在這個問題。

  3. tensorflow.python.framework.errors_impl.InternalError: Failed to create session
    解決辦法:使用nvidia-smi檢視是否GPU全部被佔用,若存在空閒GPU,指定GPU執行程式

  4. InvalidArgumentError: Assign requires shapes of both tensors to match. lhs shape= [8] rhs shape= [84]
    [[Node: save_1/Assign_4 = Assign[T=DT_FLOAT, _class=[“loc:@ssd_300_vgg/block10_box/conv_cls/biases”], use_locking=true, validate_shape=true, _device="/job:localhost/replica:0/task:0/device:CPU:0"](ssd_300_vgg/block10_box/conv_cls/biases, save_1/RestoreV2_4)]]
    解決辦法:登出掉checkpoint_model_scope=ssd_300_vgg這一行

  5. 訓練過程中loss為nan
    解決辦法:調小學習率,調小batchsize

  6. All bounding box coordinates must be in [0.0, 1.0]
    解決辦法:產生原因是圖片的標註資訊超過了圖片尺寸。將pascalvoc_to_tfrecords.py第116行程式碼修改如下:

bboxes.append((max(float(bbox.find('ymin').text) / shape[0],0.0),
                       max(float(bbox.find('xmin').text) / shape[1],0.0),
                       min(float(bbox.find('ymax').text) / shape[0],1.0),
                       min(float(bbox.find('xmax').text) / shape[1],1.0),
                       ))

參考連結
https://github.com/balancap/SSD-Tensorflow
https://blog.csdn.net/liuyan20062010/article/details/78905517#commentBox
https://blog.csdn.net/w5688414/article/details/78395177
https://my.oschina.net/u/876354/blog/1927351