【目標檢測】SSD+Tensorflow 300&512 配置詳解


SSD_300_vgg和SSD_512_vgg weights下載鏈接【需要科學上網~】:

Model Training data Testing data mAP FPS
SSD-300 VGG-based VOC07+12+COCO trainval VOC07 test 0.817 -
SSD-300 VGG-based VOC07+12 trainval VOC07 test 0.778 -
SSD-512 VGG-based VOC07+12+COCO trainval VOC07 test 0.837 -

我的csdn下載鏈接【沒法科學上網的同學】:

ssd-512:https://download.csdn.net/download/qq_36396104/10792340

ssd-300:https://download.csdn.net/download/qq_36396104/10792337

 

ssd源碼https://github.com/DengZhuangSouthRd/SSD-TinyObject/blob/master/COMMANDS.md

轉自:https://blog.csdn.net/liuyan20062010/article/details/78905517
1.  搭建SSD框架,下載解壓即可 

2. 下載pascalvoc數據,自己的數據根據voc格式改寫(圖片的名稱,不用拘泥於6位數字,其他命名也可以)

     解壓后不要混合在一個文件夾下,要生成三個,主要是利用訓練集測試的文件夾,VOCtrainval用來訓練,VOCtest用來測試。

    VOCtrainval 中JPEGImage文件夾中僅是訓練和驗證的圖片,Main文件夾中僅是trainval.txt,  train.txt,   val.txt

    VOCtest中JPEGImage文件夾中僅是測試圖片,Main文件夾中僅是test.txt.

3. 圖片數據重命名為6位數字

   python代碼

import os  
      
class BatchRename():  
      #  ''''' 
     #   批量重命名文件夾中的圖片文件 
     
       # '''  
        def __init__(self):  
            #我的圖片文件夾路徑horse  
            self.path = '/home/xxx/imagedata/image_xml'  
      
        def rename(self):  
            filelist = os.listdir(self.path)  
            total_num = len(filelist)  
            i = 1  
            n = 6  
            for item in filelist:  
                if item.endswith('.jpg'):  
                    n = 6 - len(str(i))  
                    src = os.path.join(os.path.abspath(self.path), item)  
                    dst = os.path.join(os.path.abspath(self.path), str(0)*n + str(i) + '.jpg')  
                    try:  
                        os.rename(src, dst)  
                        print 'converting %s to %s ...' % (src, dst)  
                        i = i + 1  
                  
                    except:  
                        continue  
            print 'total %d to rename & converted %d jpgs' % (total_num, i)  
      
if __name__ == '__main__':  
        demo = BatchRename()  
        demo.rename()  

3.標記數據

4.生成txt文件,train.txt, trainval.txt, test.txt, val.txt
python代碼

import os  
import random   
  
xmlfilepath=r'/home/xxx/subimage_xml_xiao'  
saveBasePath=r"/home/xxx/txt"  
  
trainval_percent=0.7 
train_percent=0.7  
total_xml = os.listdir(xmlfilepath)  
num=len(total_xml)    
list=range(num)    
tv=int(num*trainval_percent)    
tr=int(tv*train_percent)    
trainval= random.sample(list,tv)    
train=random.sample(trainval,tr)    
  
print("train and val size",tv)  
print("traub suze",tr)  
ftrainval = open(os.path.join(saveBasePath,'Main/trainval.txt'), 'w')    
ftest = open(os.path.join(saveBasePath,'Main/test.txt'), 'w')    
ftrain = open(os.path.join(saveBasePath,'Main/train.txt'), 'w')    
fval = open(os.path.join(saveBasePath,'Main/val.txt'), 'w')    
  
for i  in list:    
    name=total_xml[i][:-4]+'\n'    
    if i in trainval:    
        ftrainval.write(name)    
        if i in train:    
            ftrain.write(name)    
        else:    
            fval.write(name)    
    else:    
        ftest.write(name)    
    
ftrainval.close()    
ftrain.close()    
fval.close()    
ftest .close() 

5.  將訓練類別修改為和自己一樣的

   SSD-Tensorflow-master—>datasets—>pascalvoc_common.py

  根據實際情況進行修改

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'), 
} 

6.  將圖像數據轉換為tfrecods格式

   SSD-Tensorflow-master—>datasets—>pascalvoc_to_tfrecords.py 。。。然后更改文件的83行讀取方式為’rb’)

修改讀取圖片的類型:修改如下兩個地方

    “image_format = b'JPEG'”
       “filename = directory + DIRECTORY_IMAGES + name + '.jpg'”中 jpg 可以修改讀取圖片的類型

 修改67行,可以修改幾張圖片轉為一個tfrecords,如下圖

   

    在SSD-Tensorflow-master文件夾下創建tf_conver_data.sh

  1 #!/bin/bash
  2 #this is a shell script to convert pascal VOC datasets into tf-records only
  3 #directory where the original dataset is stored 
  4 
  5 DATASET_DIR=/home/xxx/imagedata/VOCdevkit/VOC2007/     #VOC數據保存的文件夾(VOC的目錄格式未改變)
  6 
  7 #output directory where to store TFRecords files
  8 OUTPUT_DIR=/home/xxx/imagedata/xingshizheng_tf  #自己建立的保存tfrecords數據的文件夾
  9   
 10 python3 ./tf_convert_data.py \
 11        --dataset_name=pascalvoc \
 12        --dataset_dir=${DATASET_DIR} \
 13        --output_name=voc_2007_train \
 14        --output_dir=${OUTPUT_DIR}
~

7. 訓練模型
train_ssd_network.py修改第154行的最大訓練步數,將None改為比如50000。(tf.contrib.slim.learning.training函數中max-step為None時訓練會無限進行。)

   train_ssd_network.py,網絡參數配置,若需要改,再此文件中進行修改

  修改如下圖中的數字600,可以改變訓練多長時間保存一次模型

需要修改的地方:

         a.   nets/ssd_vgg_300.py  (因為使用此網絡結構) ,修改87 和88行的類別

 default_params = SSDParams(
        img_shape=(300, 300),
        num_classes=21,   #根據自己的數據修改為類別+1
        no_annotation_label=21, #根據自己的數據修改為類別+1
        feat_layers=['block4', 'block7', 'block8', 'block9', 'block10', 'block11'],
        feat_shapes=[(38, 38), (19, 19), (10, 10), (5, 5), (3, 3), (1, 1)],
        anchor_size_bounds=[0.15, 0.90],
        # anchor_size_bounds=[0.20, 0.90],

        b. train_ssd_network.py,修改類別120行,GPU占用量,學習率,batch_size等 

tf.app.flags.DEFINE_integer(
    'num_classes', 21, 'Number of classes to use in the dataset.')    
#根據自己的數據修改為類別+1

     c eval_ssd_network.py 修改類別,66行

# =========================================================================== #
# Main evaluation flags.
# =========================================================================== #
tf.app.flags.DEFINE_integer(
'num_classes', 21, 'Number of classes to use in the dataset.')  
 
  #根據自己的數據修改為類別+1

     d. datasets/pascalvoc_2007.py 根據自己的訓練數據修改整個文件

TRAIN_STATISTICS = {
    'none': (0, 0),
    'aeroplane': (238, 306),  #238圖片書, 306目標總數
    'bicycle': (243, 353),
    'bird': (330, 486),
    'boat': (181, 290),
    'bottle': (244, 505),
    'bus': (186, 229),
    'car': (713, 1250),
    'cat': (337, 376),
    'chair': (445, 798),
    'cow': (141, 259),
    'diningtable': (200, 215),
    'dog': (421, 510),
    'horse': (287, 362),
    'motorbike': (245, 339),
    'person': (2008, 4690),
    'pottedplant': (245, 514),
    'sheep': (96, 257),
    'sofa': (229, 248),
    'train': (261, 297),
    'tvmonitor': (256, 324),
    'total': (5011, 12608),    //5011 為訓練的圖片書,12608為目標總數
}
TEST_STATISTICS = {
    'none': (0, 0),
    'aeroplane': (1, 1),
    'bicycle': (1, 1),
    'bird': (1, 1),
    'boat': (1, 1),
    'bottle': (1, 1),
    'bus': (1, 1),
    'car': (1, 1),
    'cat': (1, 1),
    'chair': (1, 1),
    'cow': (1, 1),
    'diningtable': (1, 1),
    'dog': (1, 1),
    'horse': (1, 1),
    'motorbike': (1, 1),
    'person': (1, 1),
    'pottedplant': (1, 1),
    'sheep': (1, 1),
    'sofa': (1, 1),
    'train': (1, 1),
    'tvmonitor': (1, 1),
    'total': (20, 20),
}
SPLITS_TO_SIZES = {
    'train': 5011,        #訓練數據量
    'test': 4952,         #測試數據量
}
SPLITS_TO_STATISTICS = {
    'train': TRAIN_STATISTICS,
    'test': TEST_STATISTICS,
}
NUM_CLASSES = 20    #類別,根據自己數據的實際類別修改(不包含背景)

方案1 從vgg開始訓練其中某些層的參數

# 通過加載預訓練好的vgg16模型,對“voc07trainval+voc2012”進行訓練
# 通過checkpoint_exclude_scopes指定哪些層的參數不需要從vgg16模型里面加載進來
# 通過trainable_scopes指定哪些層的參數是需要訓練的,未指定的參數保持不變,若注釋掉此命令,所有的參數均需要訓練
DATASET_DIR=/home/doctorimage/kindlehe/common/dataset/VOC0712/
TRAIN_DIR=.././log_files/log_finetune/train_voc0712_20170816_1654_VGG16/
CHECKPOINT_PATH=../checkpoints/vgg_16.ckpt
 
python3 ../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 \  #每60s保存一下日志
    --save_interval_secs=600 \  #每600s保存一下模型
    --weight_decay=0.0005 \     #正則化的權值衰減的系數
    --optimizer=adam \          #選取的最優化函數
    --learning_rate=0.001 \     #學習率
    --learning_rate_decay_factor=0.94 \ #學習率的衰減因子
    --batch_size=24 \   
    --gpu_memory_fraction=0.9   #指定占用gpu內存的百分比

方案2 : 從自己預訓練好的模型開始訓練(依然可以指定要訓練哪些層)

(當你的模型通過vgg訓練的模型收斂到大概o.5mAP的時候,可以進行這一步的fine-tune)
 
# 通過加載預訓練好的vgg16模型,對“voc07trainval+voc2012”進行訓練
# 通過checkpoint_exclude_scopes指定哪些層的參數不需要從vgg16模型里面加載進來
# 通過trainable_scopes指定哪些層的參數是需要訓練的,未指定的參數保持不變
DATASET_DIR=/home/doctorimage/kindlehe/common/dataset/VOC0712/
TRAIN_DIR=.././log_files/log_finetune/train_voc0712_20170816_1654_VGG16/
CHECKPOINT_PATH=./log_files/log_finetune/train_voc0712_20170712_1741_VGG16/model.ckpt-253287
 
python3 ../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 \  #每60s保存一下日志
    --save_interval_secs=600 \  #每600s保存一下模型
    --weight_decay=0.0005 \     #正則化的權值衰減的系數
    --optimizer=adam \          #選取的最優化函數
    --learning_rate=0.001 \     #學習率
    --learning_rate_decay_factor=0.94 \ #學習率的衰減因子
    --batch_size=24 \   
    --gpu_memory_fraction=0.9   #指定占用gpu內存的百分比

從自己訓練的ssd_300_vgg模型開始訓練ssd_512_vgg的模型

      因此ssd_300_vgg中沒有block12,又因為block7,block8,block9,block10,block11,中的參數張量兩個網絡模型中不匹配,因此ssd_512_vgg中這幾個模塊的參數不從ssd_300_vgg模型中繼承,因此使用checkpoint_exclude_scopes命令指出。

         因為所有的參數均需要訓練,因此不使用命令--trainable_scopes

 1 #/bin/bash
  2 DATASET_DIR=/home/data/xxx/imagedata/xing_tf/train_tf/
  3 TRAIN_DIR=/home/data/xxx/model/xing300512_model/
  4 CHECKPOINT_PATH=/home/data/xxx/model/xing300_model/model.ckpt-60000   #加載的ssd_300_vgg模型
  5 python3 ./train_ssd_network.py \
  6        --train_dir=${TRAIN_DIR} \
  7        --dataset_dir=${DATASET_DIR} \
  8        --dataset_name=pascalvoc_2007 \
  9        --dataset_split_name=train \
 10        --model_name=ssd_512_vgg \
 11        --checkpoint_path=${CHECKPOINT_PATH} \
 12        --checkpoint_model_scope=ssd_300_vgg \
 13        --checkpoint_exclude_scopes=ssd_512_vgg/block7,ssd_512_vgg/block7_box,ssd_512_vgg/block8,ssd_512_vgg/block8_box,    ssd_512_vgg/block9,ssd_512_vgg/block9_box,ssd_512_vgg/block10,ssd_512_vgg/block10_box,ssd_512_vgg/block11,ssd_512_vgg/b    lock11_box,ssd_512_vgg/block12,ssd_512_vgg/block12_box \
 14        #--trainable_scopes=ssd_300_vgg/conv6,ssd_300_vgg/conv7,ssd_300_vgg/block8,ssd_300_vgg/block9,ssd_300_vgg/block1    0,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_3    00_vgg/block10_box,ssd_300_vgg/block11_box \
 15        --save_summaries_secs=28800 \
 16        --save_interval_secs=28800 \
 17        --weight_decay=0.0005 \
 18        --optimizer=adam \
 19        --learning_rate_decay_factor=0.94 \
 20        --batch_size=16 \
 21        --num_classes=4 \
 22        -gpu_memory_fraction=0.8 \

另外由300轉512后還需修改:

1. 首先修改ssd_vgg_512.py的訓練類別

2.修改train_ssd_network.py的model_name

   修改為ssd_512_vgg

3. 修改nets/np_methods.py

    修改:將300改為512, 將類別改為自己數據的類別(+背景)

4. 修改preprocessing/ssd_vgg_preprocessing.py

    修改:將300改為512

5. 修改ssd_notbook.ipynb

   a  將文件中數字“300”改為“512”

其他修改可以參考:http://blog.csdn.net/liuyan20062010/article/details/78905517

方案3:從頭開始訓練自己的模型 

# 注釋掉CHECKPOINT_PATH,不提供初始化模型,讓模型自己隨機初始化權重,從頭訓練
# 刪除checkpoint_exclude_scopes和trainable_scopes,因為是從頭開始訓練
# CHECKPOINT_PATH=./log_files/log_finetune/train_voc0712_20170712_1741_VGG16/model.ckpt-253287
 
python3 ../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 \   #所加載模型里面的作用域名
    --save_summaries_secs=60 \  #每60s保存一下日志
    --save_interval_secs=600 \  #每600s保存一下模型
    --weight_decay=0.0005 \     #正則化的權值衰減的系數
    --optimizer=adam \          #選取的最優化函數
    --learning_rate=0.00001 \   #學習率
    --learning_rate_decay_factor=0.94 \ #學習率的衰減因子
    --batch_size=32

8. 測試或驗證

    首先將測試數據轉換為tfrecords

 1 #!/bin/bash  
      2 #this is a shell script to convert pascal VOC datasets into tf-records only  
      3 #directory where the original dataset is stored   
      4   
      5 DATASET_DIR=/home/xxx/imagedata/VOCdevkit/VOC2007/     #VOC數據保存的文件夾(VOC的目錄格式未改變)  
      6   
      7 #output directory where to store TFRecords files  
      8 OUTPUT_DIR=/home/xxx/imagedata/xingshizheng_tf  #自己建立的保存tfrecords數據的文件夾  
      9     
     10 python3 ./tf_convert_data.py \  
     11        --dataset_name=pascalvoc \  
     12        --dataset_dir=${DATASET_DIR} \  
     13        --output_name=voc_2007_test \     #注意修改為test
     14        --output_dir=${OUTPUT_DIR}   
    ~  

         在SSD-Tensorflow-master文件夾下建立一個sh文件

 #!/bin/bash
    # This is the eval script.
    DATASET_DIR=/home/xxx/voc2007_test_tfrecords/    #保存的轉換為tfrcodes格式的數據
    EVAL_DIR=/home/xxx/ssd_eval_log/   # Directory where the results are saved to    
    CHECKPOINT_PATH=/home/xxx/Downloads/SSD-Tensorflow-master/checkpoints/VGG_VOC0712_SSD_300x300_iter_120000.ckpt   #換為自己訓練的模型
 python3 ./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

9.    利用ssd_notebook.ipynb顯示訓練測試模型的結果

      修改紅框標注的位置,一個是修改為自己的模型所在的路徑,另一個是修改為自己圖片所在的路徑

10. 注意 

  • –dataset_name=pascalvoc_2007 、–dataset_split_name=train、–model_name=ssd_300_vgg這三個參數不要自己隨便取,在代碼里,這三個參數是if…else…語句,有固定的判斷值,所以要根據實際情況取選擇
  • TypeError: expected bytes, NoneType found SystemError: returned a result with an error set 這是由於CHECKPOINT_PATH定義的時候不小心多了個#號鍵,將輸入給注釋掉了,如果不想使用預訓練的模型,需要將--checkpoint_path=${CHECKPOINT_PATH} \注釋掉即可
  • SSD有在VOC07+12的訓練集上一起訓練的,用一個笨一點的辦法: pascalvoc_to_tfrecords.py文件中,改變SAMPLES_PER_FILES,減少輸出tfrecord文件的個數,再修改tf_convert_data.py的dataset參數,記得將前后兩次的輸出名改變一下,前后兩次轉換的tfrecords放在同一個文件夾下,然后手工重命名。(這里由於只是驗證論文的訓練方法是否有效,所以沒必要寫這些自動化代碼實現合並,以后要用自己的數據集訓練的時候就可以寫一些自動化腳本)
  • 有時候運行腳本會報錯,可能是之前依次運行導致顯存占滿。
  • 從pyCharm運行時,如果模型保存路徑里之前的模型未刪除,將會報錯,必須保證該文件夾為空。
  • 在TRAIN_DIR路徑下會產生四中文件: 1. checkpoint :文本文件,包含所有model.ckpt-xxxx,相當於是不同時間節點生成的所有ckpt文件的一個索引。 2. model.ckpt-2124.data-000000-of-000001:模型文件,保存模型的權重 3. model.ckpt-2124.meta: 圖文件,保存模型的網絡圖 4. model.ckpt-2124.index : 這個沒搞太清楚 5. graph.pbtxt: 用protobuf格式保存的模型的圖
  • error:Default MaxPoolingOp only supports NHWC,這有兩種原因:1、你的電腦沒有gpu(情況很少)2、你使用的tensorflow版本有問題,看看是不是使用了非gpu版的tensorflow,或者使用的虛擬環境沒切換過來。

     


免責聲明!

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



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