基于 PaddleClas的熱軋鋼帶表面缺陷分類
- 任務(wù)目標(biāo):針對熱軋鋼帶表面缺陷數(shù)據(jù)進(jìn)行缺陷分類
- 背景介紹:
- 隨著人工智能技術(shù)的興起舌界,我國的制造業(yè)也迎來了新的轉(zhuǎn)型時機九妈。融合使用新一代信息技術(shù)和人工智能技術(shù)已成為制造業(yè)重要發(fā)展趨勢,對制造業(yè)未來的發(fā)展方向和模式產(chǎn)生了深遠(yuǎn)的影響猎拨。鋼鐵行業(yè)作為傳統(tǒng)制造業(yè)一直發(fā)展到現(xiàn)在膀藐,正面臨著越來越嚴(yán)峻的生存環(huán)境,安全红省、成本额各、質(zhì)量等都是目前急需解決的難題和難點,而中國制造2025戰(zhàn)略背景下智慧制造顯然是轉(zhuǎn)型升級新的機遇窗口吧恃。制造業(yè)與人工智能結(jié)合應(yīng)運而生臊泰。
- 在熱軋帶鋼的生產(chǎn)過程中受制造工藝、生產(chǎn)條件和原材料質(zhì)量等相關(guān)問題的制約蚜枢,生產(chǎn)出的工業(yè)產(chǎn)品往往存在缺陷缸逃。熱軋帶鋼表面缺陷種類較多,其中常見的六種典型表面缺陷即軋制氧化皮厂抽,斑塊需频,開裂,點蝕表面筷凤,內(nèi)含物和劃痕昭殉。這些缺陷會在帶鋼后續(xù)產(chǎn)品的使用過程中造成隱患,導(dǎo)致制造產(chǎn)品質(zhì)量下降藐守。因此準(zhǔn)確挪丢、清楚且快速的了解缺陷的類型、位置和形狀卢厂,對其做出檢測和判斷是非常有必要的乾蓬。
- 在實際操作的過程中,我們往往不需要一步到位定位缺陷的位置慎恒,在初期質(zhì)檢中僅需要判斷缺陷種類滿足當(dāng)下快速的質(zhì)檢工藝即可任内。因此考慮使用Paddlecla搭建熱軋鋼帶表面缺陷分類模型。
- 最終效果:筆者嘗試使用PaddleClas對東北大學(xué)熱軋鋼帶數(shù)據(jù)集中的6類表面缺陷進(jìn)行分類融柬,經(jīng)過調(diào)試最終在測試集上可達(dá)100%的準(zhǔn)確率死嗦。
1. 數(shù)據(jù)集簡介
收集了熱軋鋼帶的六種典型表面缺陷即軋制氧化皮(RS),斑塊(Pa)粒氧,開裂(Cr)越除,點蝕表面(PS),內(nèi)含物(In)和劃痕(Sc)。該數(shù)據(jù)庫包括 1,800 個灰度圖像:六種不同類型的典型表面缺陷中的每一個300 個樣本摘盆,圖像的原始分辨率為 200×200翼雀。
下表列出了六種典型表面缺陷的類型與外觀特征:
缺陷類型 | 外觀特征 |
---|---|
軋制氧化皮 | 通常呈小斑點、魚鱗狀骡澈、條狀锅纺、塊狀不規(guī)則分布于帶鋼上掷空、下表面的全部或局部肋殴,常伴有粗糙的麻點狀表面。 |
斑塊 | 在帶鋼的表面呈現(xiàn)片狀或大面積的斑跡坦弟,個別的情況下在某個角度上有向外輻射的跡象护锤。 |
點蝕表面 | 帶鋼表面有局部的或連續(xù)的粗糙面,嚴(yán)重時呈桔皮狀酿傍。在上下表面都可能出現(xiàn)烙懦,而且在整個帶鋼長度方向上的密度不均。 |
開裂 | 軋件表面一種不連續(xù)的裂紋赤炒,它以某點為中心氯析,以閃電狀向外發(fā)散。 |
內(nèi)含物 | 板帶鋼表面的薄層折疊莺褒,缺陷常呈灰白色掩缓,其大小、形狀不一遵岩,不規(guī)則分布于板帶鋼表面你辣。 |
劃痕 | 軋件表面的機械損傷,其長度尘执、寬度舍哄、深度各異。主要出現(xiàn)在沿軋制方向或垂直于軋制方向上誊锭。 |
- 如圖展示了六種典型表面缺陷的樣本圖像表悬。類內(nèi)缺陷在外觀上存在很大差異,例如丧靡,劃痕(最后一列)可能是水平劃痕签孔,垂直劃痕和傾斜劃痕等。同樣窘行,類間缺陷也具有類似情況饥追,例如,氧化皮罐盔,裂紋和表面凹痕但绕。另外,由于照明和材料變化的影響,類內(nèi)缺陷圖像的灰度是變化的捏顺。
- 簡而言之六孵,NEU 表面缺陷數(shù)據(jù)庫包括兩個困難的挑戰(zhàn),即類內(nèi)缺陷在外觀上存在較大差異幅骄,類間缺陷具有相似問題劫窒。
2. PaddleClas
本項目中我們嘗試使用 PaddleClas 圖像分類套件對熱軋鋼帶表面缺陷分類,最終在測試集圖像上達(dá)到了 100% 的準(zhǔn)確率拆座。
PaddleClas圖像分類開發(fā)套件主巍,內(nèi)置豐富的模型庫,支持高階優(yōu)化(模型壓縮與數(shù)據(jù)增廣)挪凑,特色拓展應(yīng)用孕索,工業(yè)級部署工具。
image
獲取PaddleClas 躏碳, 可以使用git clone https://github.com/paddlepaddle/paddleclas
下載PaddleClas搞旭,也可以使用本項目已下載好的PaddleClas
!unzip -q data/data47421/PaddleClas.zip
3. 數(shù)據(jù)處理
解壓數(shù)據(jù)集,將數(shù)據(jù)集移動至指定位置菇绵,生成訓(xùn)練集與測試集
- 需要注意的是:
- 數(shù)據(jù)集存放的位置與生成的數(shù)據(jù)列表文件中的數(shù)據(jù)路徑需要與配置文件對應(yīng)肄渗,這也是初學(xué)者時常出現(xiàn)問題的地方。
- 數(shù)據(jù)列表文件中路徑與標(biāo)簽之間的分割符號咬最,行與行之間的換行符號
- 有些特定字符轉(zhuǎn)義之后出現(xiàn)問題
!unzip -q data/data47260/NEU-CLS.zip
!mv NEU-CLS PaddleClas/dataset
import codecs
import os
import random
import shutil
from PIL import Image
train_ratio = 4.0 / 5
all_file_dir = 'PaddleClas/dataset/NEU-CLS'
class_list = [c for c in os.listdir(all_file_dir) if os.path.isdir(os.path.join(all_file_dir, c)) and not c.endswith('Set') and not c.startswith('.')]
class_list.sort()
print(class_list)
train_image_dir = os.path.join(all_file_dir, "trainImageSet")
if not os.path.exists(train_image_dir):
os.makedirs(train_image_dir)
eval_image_dir = os.path.join(all_file_dir, "evalImageSet")
if not os.path.exists(eval_image_dir):
os.makedirs(eval_image_dir)
train_file = codecs.open(os.path.join(all_file_dir, "train.txt"), 'w')
eval_file = codecs.open(os.path.join(all_file_dir, "eval.txt"), 'w')
with codecs.open(os.path.join(all_file_dir, "label_list.txt"), "w") as label_list:
label_id = 0
for class_dir in class_list:
label_list.write("{0}\t{1}\n".format(label_id, class_dir))
image_path_pre = os.path.join(all_file_dir, class_dir)
for file in os.listdir(image_path_pre):
try:
img = Image.open(os.path.join(image_path_pre, file))
if random.uniform(0, 1) <= train_ratio:
shutil.copyfile(os.path.join(image_path_pre, file), os.path.join(train_image_dir, file))
train_file.write("{0} {1}\n".format(os.path.join("trainImageSet", file), label_id))
else:
shutil.copyfile(os.path.join(image_path_pre, file), os.path.join(eval_image_dir, file))
eval_file.write("{0} {1}\n".format(os.path.join("evalImageSet", file), label_id))
except Exception as e:
pass
# 存在一些文件打不開翎嫡,此處需要稍作清洗
label_id += 1
train_file.close()
eval_file.close()
查看一下標(biāo)簽列表格式
! head PaddleClas/dataset/NEU-CLS/train.txt
整體思路
- 選擇使用的模型,根據(jù)自己的任務(wù)難度及數(shù)據(jù)的特點丹诀,選擇適合自己數(shù)據(jù)的模型進(jìn)行訓(xùn)練钝的,本文選擇ResNet_vd模型訓(xùn)練關(guān)于ResNet網(wǎng)絡(luò)結(jié)構(gòu)的代碼分析可移步這里查看ResNet網(wǎng)絡(luò)結(jié)構(gòu)代碼分析
- 根據(jù)選定的模型更改PaddleClas/configs下對應(yīng)的配置文件參數(shù)。例如類別數(shù)铆遭,迭代次數(shù)硝桩,batch_size,數(shù)據(jù)集路徑等等枚荣。為了查看方便本文將PaddleClas/configs/ResNet/ResNet50_vd.yaml移只根目錄改名為neu.yaml碗脊,在訓(xùn)練時,修改配置文件的路徑即可橄妆。
- 利用更改后的配置文件訓(xùn)練模型衙伶,使用訓(xùn)練技巧與不同的參數(shù)設(shè)置調(diào)優(yōu)模型并選擇最優(yōu)模型進(jìn)行推理預(yù)測(更多的訓(xùn)練技巧與參數(shù)設(shè)置,可以關(guān)注 https://paddleclas.readthedocs.io/zh_CN/latest/models/Tricks.html 其對相關(guān)參數(shù)進(jìn)行了詳細(xì)的解釋說明)
- 下面逐步說明各部分:
4. 訓(xùn)練模型
訓(xùn)練模型分為一下幾個步驟:
- 修改配置文件害碾。查看使用模型對應(yīng)的配置文件并修改配置文件中一些必要的參數(shù)矢劲,本項目已經(jīng)根據(jù)數(shù)據(jù)集適配了配置文件neu.yaml
- 切換路徑,設(shè)置環(huán)境變量
- 訓(xùn)練模型
配置文件說明
下面展示了配置文件中不同模塊參數(shù)的含義
基礎(chǔ)配置
mode: "train" 運行模式 2中選擇["train"," valid"]
ARCHITECTURE: 模型結(jié)構(gòu)名字
name: 'ResNet50_vd'
pretrained_model: "" 預(yù)訓(xùn)練模型路徑
model_save_dir: "./output/" 保存模型路徑
classes_num: 6 分類數(shù)
total_images: 1800 總圖片數(shù)
save_interval: 10 每隔多少個epoch保存模型
validate: True 是否在訓(xùn)練時進(jìn)行評估
valid_interval: 10 每隔多少個epoch進(jìn)行模型評估
epochs: 400 訓(xùn)練總epoch數(shù)
topk: 5 評估指標(biāo)K值大小
image_shape: [3, 224, 224] 圖片大小
use_mix: True 是否啟用mixup
ls_epsilon: 0.1 label_smoothing epsilon值
學(xué)習(xí)率與優(yōu)化配置
LEARNING_RATE:
function: 'Cosine' decay方法名 ["Linear", "Cosine","Piecewise", "CosineWarmup"]
params: 初始學(xué)習(xí)率 大部分的神經(jīng)網(wǎng)絡(luò)選擇的初始學(xué)習(xí)率為0.1慌随,batch_size是256芬沉,所以根據(jù)實際的模型大小和顯存情況躺同,可以將學(xué)習(xí)率設(shè)置為0.1*k,batch_size設(shè)置為256*k
lr: 0.1
*還可設(shè)置的參數(shù)
params:
decayepochs piecewisedecay中衰減學(xué)習(xí)率的milestone
params:
gamma piecewisedecay中g(shù)amma值
params:
warmupepoch warmup輪數(shù)
parmas:
steps lineardecay衰減steps數(shù)
params:
endlr lineardecayendlr值
OPTIMIZER:
function: 'Momentum' 優(yōu)化器方法名 ["Momentum", "RmsProp"]
params:
momentum: 0.9 momentum值
regularizer:
function: 'L2' 正則化方法名
factor: 0.000070 正則化系數(shù)
訓(xùn)練配置
TRAIN:
batch_size: 32 批大小
num_workers: 4 數(shù)據(jù)讀取器worker數(shù)量
file_list: "./dataset/NEU-CLS/train.txt" train文件列表
data_dir: "./dataset/NEU-CLS" train文件路徑
shuffle_seed: 0 用來進(jìn)行shuffle的seed值
transforms: 數(shù)據(jù)處理
- DecodeImage:
to_rgb: True 數(shù)據(jù)轉(zhuǎn)RGB
to_np: False 數(shù)據(jù)轉(zhuǎn)numpy
channel_first: False 按CHW排列的圖片數(shù)據(jù)
- RandCropImage: 隨機裁剪
size: 224
- RandFlipImage: 隨機翻轉(zhuǎn)
flip_code: 1
- NormalizeImage:
scale: 1./255. 歸一化scale值
mean: [0.485, 0.456, 0.406] 歸一化均值
std: [0.229, 0.224, 0.225] 歸一化方差
order: '' 歸一化順序
- ToCHWImage: 調(diào)整為CHW
mix:
- MixupOperator:
alpha: 0.2
*還可設(shè)置的參數(shù)
-CropImage
size: 裁剪大小
-ResizeImage
resize_short: 按短邊調(diào)整大小
測試配置
VALID:
batch_size: 64
num_workers: 4
file_list: "./dataset/NEU-CLS/eval.txt"
data_dir: "./dataset/NEU-CLS"
shuffle_seed: 0
transforms:
- DecodeImage:
to_rgb: True
to_np: False
channel_first: False
- ResizeImage:
resize_short: 256
- CropImage:
size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [0.485, 0.456, 0.406]
std: [0.229, 0.224, 0.225]
order: ''
- ToCHWImage:
設(shè)置環(huán)境變量
%cd PaddleClas
import os
os.environ['PYTHONPATH']="/home/aistudio/PaddleClas"
關(guān)于預(yù)訓(xùn)練模型
- 如需使用預(yù)訓(xùn)練模型,則執(zhí)行下面的腳本,并在訓(xùn)練腳本后增加
-o pretrained_model=./ResNet50_vd_pretrained
丸逸,不使用預(yù)訓(xùn)練模型則跳過下面的執(zhí)行語句蹋艺。
!python ../download_model.py ResNet50_vd_pretrained
!mv ../ResNet50_vd_pretrained ./
開始訓(xùn)練
- 執(zhí)行訓(xùn)練腳本,使用已經(jīng)配置好的neu.yaml文件
- 訓(xùn)練腳本指令如下:PaddleClas通過launch方式啟動多卡多進(jìn)程訓(xùn)練 通過設(shè)置FLAGS_selected_gpus 指定GPU運行卡號
python -m paddle.distributed.launch --selected_gpus="0" tools/train.py -c ./configs/ResNet/ResNet50_vd.yaml
!python -m paddle.distributed.launch --selected_gpus="0" tools/train.py -c ../neu.yaml
5. 模型評估
首先需要修改評估所需的配置文件黄刚,修改方式有兩種捎谨,
- 直接修改configs/eval.yaml
- -o參數(shù)更新配置
這里建議直接修改configs/eval.yaml,使用-o設(shè)置需要評估的模型路徑 較為方便
評估腳本代碼如下:需要注意的是加載模型時憔维,需要指定模型的前綴涛救,如模型參數(shù)所在的文件夾為output/ResNet50_vd/19,模型參數(shù)的名稱為output/ResNet50_vd/19/ppcls.pdparams埋同,則pretrained_model參數(shù)需要指定為output/ResNet50_vd/19/ppcls州叠,PaddleClas會自動補齊.pdparams的后綴棵红。
!python -m paddle.distributed.launch --selected_gpus="0" tools/eval.py \
-c ./configs/eval.yaml \
-o pretrained_model=output/ResNet50_vd/best_model/ppcls
評估模型
!python -m paddle.distributed.launch --selected_gpus="0" tools/eval.py \
-c ../eval.yaml \
-o pretrained_model=output/ResNet50_vd/best_model/ppcls
評估結(jié)果展示
2020-08-03 23:58:36 INFO: eval step:0 loss: 0.4387 top1: 0.8906 top5: 1.0000 elapse: 0.690s
2020-08-03 23:58:37 INFO: END eval loss_avg: 0.6619 top1_avg: 0.9000 top5_avg: 0.9969 elapse_sum: 1.102ss
INFO 2020-08-03 15:58:39,735 launch.py:223] Local procs complete, POD info:rank:0 id:None addr:127.0.0.1 port:None visible_gpu:[] trainers:["gpu:['0'] endpoint:127.0.0.1:56541 rank:0"]
上面展示的結(jié)果是筆者訓(xùn)練50個epochs凶赁,在測試集上top1的準(zhǔn)確率為0.9000,經(jīng)過測試在進(jìn)行400次迭代之后會達(dá)到100%的準(zhǔn)確率逆甜。
關(guān)于PaddlePaddle模型的保存方式
- persistable 模型(fluid.save_persistabels保存的模型) 一般做為模型的 checkpoint虱肄,可以加載后重新訓(xùn)練。persistable 模型保存的是零散的權(quán)重文件交煞,每個文件代表模型中的一個 Variable咏窿,這些零散的文件不包含結(jié)構(gòu)信息,需要結(jié)合模型的結(jié)構(gòu)一起使用素征。
- inference 模型(fluid.io.save_inference_model保存的模型) 一般是模型訓(xùn)練完成后保存的固化模型集嵌,用于預(yù)測部署。與 persistable 模型相比御毅,inference 模型會額外保存模型的結(jié)構(gòu)信息根欧,用于配合權(quán)重文件構(gòu)成完整的模型。如下所示端蛆,model 中保存的即為模型的結(jié)構(gòu)信息凤粗。
6. 模型推理
由于模型的保存方式以及選擇引擎的不同,PaddlePaddle衍生出三種方式進(jìn)行預(yù)測推理:
- 預(yù)測引擎 + inference 模型
- 訓(xùn)練引擎 + persistable 模型
- 訓(xùn)練引擎 + inference 模型
本文選擇使用 預(yù)測引擎 + inference模型 的方式進(jìn)行推理今豆,執(zhí)行步驟如下:
- 對訓(xùn)練好的模型進(jìn)行轉(zhuǎn)換固化
- 通過預(yù)測引擎和inference模型進(jìn)行推理
保存 inference 模型:
在訓(xùn)練過程中保存的persistable 模型中選擇最優(yōu)模型嫌拣,本文設(shè)置在訓(xùn)練的同時進(jìn)行模型評估并保存效果最好的persistable模型,命令如下:
python tools/export_model.py --m=模型名稱 --p=persistable 模型路徑 --o=model和params保存路徑
預(yù)測引擎 + inference 模型推理預(yù)測:
命令如下:
python ./tools/infer/predict.py -i=./test.jpeg -m=./resnet50-vd/model -p=./resnet50-vd/params --use_gpu=1
需要注意的是對應(yīng)的模型權(quán)重文件路徑需要確認(rèn)呆躲,其他的參數(shù)設(shè)置如下所示:
參數(shù)說明:
- image_file(簡寫 i):待預(yù)測的圖片文件路徑异逐,如 ./test.jpeg
- model_file(簡寫 m):模型文件路徑,如 ./resnet50-vd/model
- params_file(簡寫 p):權(quán)重文件路徑插掂,如 ./resnet50-vd/params
- batch_size(簡寫 b):批大小灰瞻,如 1
- ir_optim:是否使用 IR 優(yōu)化,默認(rèn)值:True
- use_tensorrt:是否使用 TesorRT 預(yù)測引擎,默認(rèn)值:True
- gpu_mem: 初始分配GPU顯存箩祥,以M單位
- use_gpu:是否使用 GPU 預(yù)測院崇,默認(rèn)值:True
- enable_benchmark:是否啟用benchmark,默認(rèn)值:False
- model_name:模型名字
- 注意: 當(dāng)啟用benchmark時袍祖,默認(rèn)開啟tersorrt進(jìn)行預(yù)測
!python tools/export_model.py \
--model='ResNet50_vd' \
--pretrained_model=output/ResNet50_vd/best_model/ppcls \
--output_path=./inference
!python tools/infer/predict.py \
-m inference/model \
-p inference/params \
-i "dataset/NEU-CLS/Rs/RS_5.bmp" \
--use_gpu=1
- 下面為Rs(氧化皮)瑕疵的圖片:
預(yù)測結(jié)果展示:
2020-08-03 15:58:48,332-INFO: class: 3
2020-08-03 15:58:48,332-INFO: score: 0.8259640336036682
可以看到預(yù)測正確底瓣,Rs的標(biāo)簽為3
7. 總結(jié)
- 本文使用了PaddleClas在熱軋鋼帶表面缺陷數(shù)據(jù)進(jìn)行訓(xùn)練
- 使用訓(xùn)練好的ResNet_vd模型對熱軋鋼帶表面圖片數(shù)據(jù)進(jìn)行分類預(yù)測
本文轉(zhuǎn)自百度的aistudio上的文章,原作者的主頁:zhou_lu的主頁