目錄
1、環境搭建
win7_64
NVIDIA K620顯卡
安裝軟件:
anaconda4.40
Python 3.6.1
tensorflow -gpu 1.14.0
CUDA 10.0.130
cudnn v7.6.3.30
上述顯卡的驅動官網可以下載,但是速度比較慢,我會傳一份到網盤。
因爲後續cmd使用很多,建議上GitHub 下載 cmder ,用來執行cmd命令,提高效率。
2、ssd-tensorflow 項目下載
從GitHub上下載項目源文件即可。
3、文件夾建立
下載後,在項目根目錄中需要手動建立幾個文件夾:
VOC2007
├─test
│ ├─Annotations
│ ├─ImageSets
│ │ └─Main
│ └─JPEGImages
└─train
├─Annotations
├─ImageSets
│ └─Main
└─JPEGImages
文件夾作用說明:(在數據標註後用到)
將用於train的xml,放入train\Annotations ,並將對應jpg,放入train\ImageSets
將用於test的xml,放入test\Annotations ,並將對應jpg,放入test\ImageSets
4、數據標註
在GitHub上下在 labelimg軟件進行標註。
tips:
1、標註時原始圖像大小不一定是300*300或512*512的。對原始圖大小沒有要求。
2、標註後每個圖片有自己的xml描述文件。
3、標註工作的作業目錄對後面的訓練沒有影響,可以將標註完成後的文件拷貝到訓練的文件夾下。因爲最終是用的與Annotations 同級別的ImageSets中的同名字的img。
5、標註數據整理
將標註後的數據手動分成2類,一部分爲train文件,一部分爲test。
將用於train的圖片放入\train\ImageSets,用於train的圖片的xml放入\train\Annotations
同理處理test的圖片。
我是 159個訓練照片,40個test照片。
每個照片內基本都是3個目標。這3個目標可以是不同的類別。
6、源程序修改
主要目的有幾個:1、修改部分bug。2、因爲分類數量不同,要修改成自己的項目需要的狀態
修改bug:
修改dateset中的pascalvoc_to_tfrecords.py 83行: image_data = tf.gfile.FastGFile(filename, 'r').read()
爲: image_data = tf.gfile.FastGFile(filename, 'rb').read()
修改項目差異:(參考:https://www.icode9.com/content-4-45616.html)
1、/datasets/pascalvoc_common.py文件中,24-46行,第一類none不要動,其他的類修改爲自己數據集的類。我是判定鋼的不同等級,如下:一共12類。
VOC_LABELS = {
'none': (0, 'Background'),
'STEEL_C05': (1, 'STEEL'),
'STEEL_C10': (2, 'STEEL'),
'STEEL_C20': (3, 'STEEL'),
'STEEL_C30': (4, 'STEEL'),
'STEEL_B05': (5, 'STEEL'),
'STEEL_B10': (6, 'STEEL'),
'STEEL_B20': (7, 'STEEL'),
'STEEL_B30': (8, 'STEEL'),
'STEEL_A05': (9, 'STEEL'),
'STEEL_A10': (10, 'STEEL'),
'STEEL_A20': (11, 'STEEL'),
'STEEL_A30': (12, 'STEEL'),
}
2、/datasets/pascalvoc_to_tfrecords.py文件中67行,修改SAMPLES_PER_FILES爲幾張圖片轉爲一個tfrecord文件,我文件比較少,用的50個爲一組
# TFRecords convertion parameters.
RANDOM_SEED = 4242
#SAMPLES_PER_FILES = 200
SAMPLES_PER_FILES = 50
3、r/nets/ssd_vgg_300.py文件中,96-97行的num_classes和no_annotation_label改爲“類別數+1” 是13 none這個不算一類。
4、/eval_ssd_network.py 文件中,66行,修改num_classes爲“類別數+1” 是13 none這個不算一類。
5、nets/ssd_vgg_300.py
line 96,97:修改爲類別+1.
6、train_ssd_network.py
line27: 數據格式改成 NHWC 這個是用CPU 計算,如果打算用GPU 計算,不需要改這一行。
line135: 類別個數: 類別數+1
line154: 訓練步數:這個自己改了,先給的小的訓練看下loss。
7、/datasets/pascalvoc_2007.py文件中,第31行和55行的none類不要動,其他類修改爲自己數據集的類,其中括號內的第一個數爲圖片數,第二個數爲目標數(也就是bonding box數,關於如何計算目標數,我寫了一個python文件,在附錄中),52行和76行的total是所有類的總和。
統計boxing 的Python程序:
# -*- coding: utf-8 -*-
import re
import os
classes='STEEL_C05,STEEL_C10,STEEL_C20,STEEL_C30,STEEL_B05,STEEL_B10,STEEL_B20,STEEL_B30,STEEL_A05,STEEL_A10,STEEL_A20,STEEL_A30'
classAry=classes.split(',')
print(classAry[0])
#創建字典
dic_class_img={}
dic_class_box={}
for cla in classAry:
dic_class_box[cla]=0
dic_class_img[cla]=0
print(dic_class_box)
annotation_folder = './VOC2007/test/Annotations' #改爲自己標籤文件夾的路徑
list = os.listdir(annotation_folder)
img_count=0
for i in range(0, len(list)):
img_count=img_count+1
path = os.path.join(annotation_folder,list[i])
filepath=annotation_folder + '/' + os.path.basename(path)
annotation_file =open(filepath,'rb').read().decode('utf8')
for cla in classAry:
count=len(re.findall(cla, annotation_file))
dic_class_box[cla]=dic_class_box[cla]+ count
if count>0:
dic_class_img[cla]=dic_class_img[cla]+1
print('total img '+str(img_count))
print("box:")
print(dic_class_box)
print("img")
print(dic_class_img)
img_total=0
box_total=0
# print train class
for cla in classAry:
print("'"+cla+"':("+str(dic_class_img[cla])+","+str(dic_class_box[cla])+"),")
img_total=img_total+dic_class_img[cla]
box_total=box_total+dic_class_box[cla]
# cal total
# total 中的img 數量不能重複,就是train或test文件下的img數量,box數量是所有的box的總和
print("'total':("+str(img_count)+","+str(box_total)+"),")
源碼修改後的:
格式說明 '類別':(有多少個圖片含有這個類,一共有多少個是這個類的box)
所以,在total這一列:
圖片的數量 < 上面每個類的圖片數量的總和。 即 159 < 84+128+7+0+21+....
boxing的數量 = 上面每個圖片中的box數量的總和 即 476= 150+257+....
# (Images, Objects) statistics on every class.
TRAIN_STATISTICS = {
'STEEL_C05':(84,150),
'STEEL_C10':(128,257),
'STEEL_C20':(7,7),
'STEEL_C30':(0,0),
'STEEL_B05':(21,36),
'STEEL_B10':(16,26),
'STEEL_B20':(0,0),
'STEEL_B30':(0,0),
'STEEL_A05':(0,0),
'STEEL_A10':(0,0),
'STEEL_A20':(0,0),
'STEEL_A30':(0,0),
'total':(159,476),
}
TEST_STATISTICS = {
'STEEL_C05':(20,43),
'STEEL_C10':(23,51),
'STEEL_C20':(2,2),
'STEEL_C30':(1,1),
'STEEL_B05':(12,23),
'STEEL_B10':(0,0),
'STEEL_B20':(0,0),
'STEEL_B30':(0,0),
'STEEL_A05':(0,0),
'STEEL_A10':(0,0),
'STEEL_A20':(0,0),
'STEEL_A30':(0,0),
'total':(40,120),
}
SPLITS_TO_SIZES = {
#'train': 5011,
# 'test': 4952,
'train': 159,
'test': 40,
}
SPLITS_TO_STATISTICS = {
'train': TRAIN_STATISTICS,
'test': TEST_STATISTICS,
}
#NUM_CLASSES = 20
NUM_CLASSES = 12 # 不包含背景的數量
7、生成訓練數據
注意文件目錄。
1、訓練的tfrecord。在cmd中執行:
python tf_convert_data.py \
--dataset_name=pascalvoc \
--dataset_dir=./VOC2007/train/ \
--output_name=voc_2007_train \
--output_dir=./tfrecords
2、測試的tfrecord 。在cmd中執行:
python tf_convert_data.py \
--dataset_name=pascalvoc \
--dataset_dir=./VOC2007/test/ \
--output_name=voc_2007_test \
--output_dir=./tfrecords
8、訓練模型
cmd執行:其中num_classes 是自己的 類數+1
下面是GPU 計算的啓動:
python train_ssd_network.py \
--train_dir=./logs/ \
--dataset_dir=./tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=./checkpoints/ssd_300_vgg.ckpt \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--batch_size=6 \
--ignore_missing_vars=True \
--num_classes=13 \
--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 \
下面是CPU 的啓動 要注意6.6 中的數據格式修改。
python train_ssd_network.py \
--train_dir=./logs/ \
--dataset_dir=./tfrecords \
--dataset_name=pascalvoc_2007 \
--dataset_split_name=train \
--model_name=ssd_300_vgg \
--checkpoint_path=./checkpoints/ssd_300_vgg.ckpt \
--save_summaries_secs=60 \
--save_interval_secs=600 \
--weight_decay=0.0005 \
--optimizer=adam \
--learning_rate=0.001 \
--batch_size=6 \
--ignore_missing_vars=True \
--num_classes=13 \
--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 \
--device=CPU \
--data_format=NHWC \
9、訓練中
下面是GPU 計算的截圖,CPU 計算的速度很慢
計算過程數據保存在 \logs 中
10、tensorboard監控
cmd執行 tensorboard --logdir= logs 文件夾路徑
打開瀏覽器:http://localhost:6006
11、測試驗證
12、tips
tensorflow 數據類型
NCHW 用於GPU
NHWC 用於CPU