1.安裝環境 一定要注意版本問題
因為版本對不上,花了好多時間猜正确的版本。
系統:Ubantu16.04
nvidia驅動版本 410.78
python 版本 3.5.2
tensorflow-gpu版本 1.14.0
CUDA : 10.0
cudnn: 7.6.5
labelme 3.9
2.安裝deeplabV3+項目
下載下傳後解壓 下載下傳解壓的檔案夾名字叫 /models-master,為了友善,我改了名字為 /models
以下位址中的所有/models 就是/models-master
測試安裝是否成功 打開終端進入 models/research 執行:
export PYTHONPATH=$PYTHONPATH:/path-to/models/research/slim
這個代碼每次打開終端都需要執行一次 或者 直接寫在 ~/.bashrc裡,并 source ~/.bashrc
然後測試安裝是否成功 在 models/research 目錄下執行
python deeplab/model_test.py
如果成功會顯示
失敗的話可能是相關包沒裝齊全,根據提示裝相關包就好。一般是ImportError :no modual name "XXX",其他的錯誤我沒遇到。 如果是tensorflow的包沒有,那基本是tensorflow版本問題,不是太新就是太舊,按照第一步版本重裝就好。
3.制作資料集
3.1 labelme
用的labelme 版本是3.9.0
labelme 版本不對 會出現
attributeerror: module 'labelme.utils' has no attribute 'draw_label'
labelme對圖檔進行多變形标注後,會出現 圖檔以及相關的json檔案
而deeplabV3+的資料集需要這些json檔案 将這些json 檔案放在一起。我放在 testdata 檔案夾
3.2 json_to_mask
然後是将這些json換成deeplab所需要的mask_label.
這裡需要根據自己的需求改代碼,代碼不難,容易看懂
會直接生成image和mask檔案夾
image放的原圖格式 .jpg,mask放的是label圖 格式 .png 。
需要的是第一張原圖和第二張黑的label圖,第三張圖是label的可視化,因為第二張全黑不容易知道是否有标簽值在裡面。
如圖,滑鼠在圖檔對應位置滑動,右下角顯示label的id[2,2,2] ,說明這個圖檔不是全黑,是有label值的,标号錯了可以自己修改前面的labelme_to_mask.py。
3.3建構資料集目錄
自己建立,官方不自帶
放在這個路徑下#models/research/deeplab/datasets
-testdata
+ image
+ mask
+ index
- train.txt
- trainval.txt
- val.txt
+ tfrecord
image裡放所有原圖 ,mask裡放label所有标簽。 注意,原圖名字和label名字要一一對應
index裡放的是train.txt val.txt train.txt,靠這些txt檔案區分訓練集和測試集,可以用這個檔案制作:
制作完成後,train.txt裡放的是訓練集圖檔的名,不包括路徑和擴充名,其他以此類推,vis是測試集。trainval我沒用上。
tfrecord檔案夾裡放的是tfrecord,
打開終端進入/models/research ,在該路徑下執行python deeplab/datasets/build_voc2012_data.py \
--image_folder="models/research/deeplab/datasets/testdata/image" \
--semantic_segmentation_folder="/models/research/deeplab/datasets/testdata/mask" \
--list_folder="/models/research/deeplab/datasets/testdata/index" \
--image_format="jpg" \
--label_format="png" \
--output_dir="models/research/deeplab/datasets/testdata/tfrecord"
build_voc2012_data.py 是官方程式自帶的。
--image_folder 上一步的image檔案夾路徑
--semantic_segmentation_folder 上一步的mask路徑
--list_folder index路徑
--image_format 原圖圖檔格式,我的是jpg 應該可以是别的格式
--label_format 标簽圖檔格式
--output_dir tfrecord路徑
資料集制作完畢
4.訓練前代碼改動
注冊資料集
在/models/research/deeplab/datasets 路徑的data_generator.py 第93行:_MYDATA_INFORMATION = DatasetDescriptor(
splits_to_sizes={
'train':44, # num of samples in images/training train.txt的行數
'val':27, # num of samples in images/validation val.txt的行數
},
num_classes=6, # 我的标簽是5類(包括background),加上ignore_label總共六類
ignore_label=255,
)
然後找到 _DATASETS_INFORMATION ,加上mydata....一行_DATASETS_INFORMATION = {
'cityscapes': _CITYSCAPES_INFORMATION,
'pascal_voc_seg': _PASCAL_VOC_SEG_INFORMATION,
'ade20k': _ADE20K_INFORMATION,
'mydata': _MYDATA_INFORMATION, #注冊上面的資料集 加粗部分一緻,前面的mydata随意取
}
同樣在models/research/deeplab/deprecated下的segmentation_dataset.py檔案進行同樣的操作
train_utils.py
在models/research/deeplab/utils/train_utils.py的213行左右exclude_list = ['global_step','logits'] #本來隻有global_step ,現在加上 logits,表示不加載邏輯層的參數
if not initialize_last_layer:
exclude_list.extend(last_layers)
train.py
在models/research/deeplab/train.py裡 156行左右# Set to False if one does not want to re-use the trained classifier weights.
flags.DEFINE_boolean('initialize_last_layer', False, 'Initialize the last layer.') #這個本來是True設定為False
flags.DEFINE_boolean('last_layers_contain_logits_only', True, 'Only consider logits as last layers or not.')#這個設定為True
解釋:
input_preprocess.pymodels/research/deeplab/input_preprocess.py 128行左右
# Randomly crop the image and label.
if is_trainingand labelis not None:
processed_image, label = preprocess_utils.random_crop([processed_image, label], crop_height, crop_width)
為這個if加一個else,下面的代碼顯示得不好,不過在連結裡也有else:
rr = tf.minimum(tf.cast(crop_height, tf.float32) / tf.cast(image_height, tf.float32), \
tf.cast(crop_width, tf.float32) / tf.cast(image_width, tf.float32))
newh = tf.cast(tf.cast(image_height, tf.float32) * rr, tf.int32)
neww = tf.cast((tf.cast(image_width, tf.float32) * rr), tf.int32)
processed_image = tf.image.resize_images(processed_image, (newh, neww), method=tf.image.ResizeMethod.BILINEAR, align_corners=True)
processed_image = preprocess_utils.pad_to_bounding_box(processed_image, 0, 0, crop_height, crop_width, mean_pixel)
不加這一段在運作vis.py和eval的時候會報錯
類似
InvalidArgumentError (see above for traceback): padded_shape[1]=128 is not divisible by block_shape[1]=12
Invalid argument: padded_shape[1]=69 is not divisible by block_shape[1]=2
這種錯基本都是這樣解決
5.train vis eval
打開終端 ,進入 models/research路徑
5.1 train.py
執行python deeplab/train.py \
--logtostderr \
--training_number_of_steps=200 \
--train_split="train" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--train_crop_size=317,385 \
--train_batch_size=2 \
--dataset="mydata" \
--tf_initial_checkpoint='models/research/deeplab/backbone/deeplabv3_cityscapes_train/model.ckpt' \
--train_logdir='models/research/deeplab/exp/train_on_train_set/train' \
--dataset_dir='models/research/deeplab/datasets/testdata/tfrecord'
--training_number_of_steps=200 這裡是訓練步數,自己設定訓練多少次
--model_variant="xception_65" 選擇backbone 有别的,但我沒看。
--train_crop_size=317,385 設定圖檔裁剪大小,( height,width)這裡盡可能大可以提高準度
這裡要說的是我的訓練集圖檔大小不一,沒有進行統一尺寸修改。圖檔最小的尺寸是316×384 我都加了1,因為别的部落格裡說是要
(height/width - 1)/ 4 要是整數。
--train_batch_size=2 記憶體不夠可以将這個調小。
--dataset="mydata" 這個mydata是上面注冊資料集時取的名字
--tf_initial_checkpoint 初始權重,就是官方預訓練過的權重 路徑
解壓在任意位置,路徑對的上就行。
--train_logdir 訓練出來的檔案的儲存路徑,自己建立,/exp/train_on_train_set/train 這三個檔案夾都是我參考别人部落格建立的。
--dataset_dir 這個就是上面tfrecord的路徑
其他沒解釋的
不出錯的話是
錯誤記錄:
Invalid argument: Nan in summary histogram for: image_pooling/BatchNorm/moving_variance_1
這個問題出現在我把batch_size設定成1,解決方案為設定為2,參考連結:
解釋在:
官方解決方法是增加loss的範圍,可是沒說怎麼加
5.2 vis.py
這個用于檢視訓練結果python deeplab/vis.py \
--logtostderr \
--vis_split="val" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--vis_crop_size=317,384 \
--dataset="mydata" \
--checkpoint_dir='models/research/deeplab/exp/train_on_train_set/train' \
--vis_logdir="models/research/deeplab/exp/train_on_train_set/vis" \
--dataset_dir="models/research/deeplab/datasets/testdata/tfrecord"
--vis_crop_size 這裡決定輸出的label預測圖大小,可以設定為資料庫裡最大的圖檔。
--checkpoint_dir 這個路徑就是上面訓練指令的--train_logdir 表示你要用訓練好的權重
--vis_logdir 訓練結果圖檔要存的位置,自己建立。
如果不出錯,會顯示
在--vis_logdir 路徑下會看到分割結果的圖檔。
5.3 eval.pypython deeplab/eval.py \
--logtostderr \
--eval_split="val" \
--model_variant="xception_65" \
--atrous_rates=6 \
--atrous_rates=12 \
--atrous_rates=18 \
--output_stride=16 \
--decoder_output_stride=4 \
--eval_crop_size=317,365 \
--dataset="mydata" \
--checkpoint_dir="models/research/deeplab/exp/train_on_train_set/train" \
--eval_logdir="models/research/deeplab/exp/train_on_train_set/eval" \
--dataset_dir="models/research/deeplab/datasets/testdata/tfrecord" \
--eval_crop_size 一樣
--eval_logdir 輸出檔案路徑,自己建立
正常輸出 官方版本版本不一樣可能有些差距。
我暫時就做到這裡了,剩下的步驟可以參考别的部落格。
參考連結:
最後這個不是打廣告,隻是有很多沒有遇到的bug要是真的沒法解決,不如買個網課,去問一下老師,老師很快就回複我了,還給了qq交流。
80不貴解君愁。