热轧钢带表面缺陷分类

基于 PaddleClas的热轧钢带表面缺陷分类

  • 任务目标:针对热轧钢带表面缺陷数据进行缺陷分类
  • 背景介绍:
    • 随着人工智能技术的兴起,我国的制造业也迎来了新的转型时机。融合使用新一代信息技术和人工智能技术已成为制造业重要发展趋势,对制造业未来的发展方向和模式产生了深远的影响。钢铁行业作为传统制造业一直发展到现在,正面临着越来越严峻的生存环境,安全、成本、质量等都是目前急需解决的难题和难点,而中国制造2025战略背景下智慧制造显然是转型升级新的机遇窗口。制造业与人工智能结合应运而生。
    • 在热轧带钢的生产过程中受制造工艺、生产条件和原材料质量等相关问题的制约,生产出的工业产品往往存在缺陷。热轧带钢表面缺陷种类较多,其中常见的六种典型表面缺陷即轧制氧化皮,斑块,开裂,点蚀表面,内含物和划痕。这些缺陷会在带钢后续产品的使用过程中造成隐患,导致制造产品质量下降。因此准确、清楚且快速的了解缺陷的类型、位置和形状,对其做出检测和判断是非常有必要的。
    • 在实际操作的过程中,我们往往不需要一步到位定位缺陷的位置,在初期质检中仅需要判断缺陷种类满足当下快速的质检工艺即可。因此考虑使用Paddlecla搭建热轧钢带表面缺陷分类模型。
  • 最终效果:笔者尝试使用PaddleClas对东北大学热轧钢带数据集中的6类表面缺陷进行分类,经过调试最终在测试集上可达100%的准确率。

1. 数据集简介

  • 收集了热轧钢带的六种典型表面缺陷即轧制氧化皮(RS),斑块(Pa),开裂(Cr),点蚀表面(PS),内含物(In)和划痕(Sc)。该数据库包括 1,800 个灰度图像:六种不同类型的典型表面缺陷中的每一个300 个样本,图像的原始分辨率为 200×200。

  • 下表列出了六种典型表面缺陷的类型与外观特征:

缺陷类型 外观特征
轧制氧化皮 通常呈小斑点、鱼鳞状、条状、块状不规则分布于带钢上、下表面的全部或局部,常伴有粗糙的麻点状表面。
斑块 在带钢的表面呈现片状或大面积的斑迹,个别的情况下在某个角度上有向外辐射的迹象。
点蚀表面 带钢表面有局部的或连续的粗糙面,严重时呈桔皮状。在上下表面都可能出现,而且在整个带钢长度方向上的密度不均。
开裂 轧件表面一种不连续的裂纹,它以某点为中心,以闪电状向外发散。
内含物 板带钢表面的薄层折叠,缺陷常呈灰白色,其大小、形状不一,不规则分布于板带钢表面。
划痕 轧件表面的机械损伤,其长度、宽度、深度各异。主要出现在沿轧制方向或垂直于轧制方向上。
  • 如图展示了六种典型表面缺陷的样本图像。类内缺陷在外观上存在很大差异,例如,划痕(最后一列)可能是水平划痕,垂直划痕和倾斜划痕等。同样,类间缺陷也具有类似情况,例如,氧化皮,裂纹和表面凹痕。另外,由于照明和材料变化的影响,类内缺陷图像的灰度是变化的。
  • 简而言之,NEU 表面缺陷数据库包括两个困难的挑战,即类内缺陷在外观上存在较大差异,类间缺陷具有相似问题。
image

2. PaddleClas

本项目中我们尝试使用 PaddleClas 图像分类套件对热轧钢带表面缺陷分类,最终在测试集图像上达到了 100% 的准确率。

PaddleClas图像分类开发套件,内置丰富的模型库,支持高阶优化(模型压缩与数据增广),特色拓展应用,工业级部署工具。

image

获取PaddleClas , 可以使用git clone https://github.com/paddlepaddle/paddleclas下载PaddleClas,也可以使用本项目已下载好的PaddleClas

!unzip -q data/data47421/PaddleClas.zip

3. 数据处理

解压数据集,将数据集移动至指定位置,生成训练集与测试集

  • 需要注意的是:
    • 数据集存放的位置与生成的数据列表文件中的数据路径需要与配置文件对应,这也是初学者时常出现问题的地方。
    • 数据列表文件中路径与标签之间的分割符号,行与行之间的换行符号
    • 有些特定字符转义之后出现问题
!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()

查看一下标签列表格式

! head PaddleClas/dataset/NEU-CLS/train.txt

整体思路

  1. 选择使用的模型,根据自己的任务难度及数据的特点,选择适合自己数据的模型进行训练,本文选择ResNet_vd模型训练关于ResNet网络结构的代码分析可移步这里查看ResNet网络结构代码分析
  2. 根据选定的模型更改PaddleClas/configs下对应的配置文件参数。例如类别数,迭代次数,batch_size,数据集路径等等。为了查看方便本文将PaddleClas/configs/ResNet/ResNet50_vd.yaml移只根目录改名为neu.yaml,在训练时,修改配置文件的路径即可。
  3. 利用更改后的配置文件训练模型,使用训练技巧与不同的参数设置调优模型并选择最优模型进行推理预测(更多的训练技巧与参数设置,可以关注 https://paddleclas.readthedocs.io/zh_CN/latest/models/Tricks.html 其对相关参数进行了详细的解释说明)
  • 下面逐步说明各部分:

4. 训练模型

训练模型分为一下几个步骤:

  1. 修改配置文件。查看使用模型对应的配置文件并修改配置文件中一些必要的参数,本项目已经根据数据集适配了配置文件neu.yaml
  2. 切换路径,设置环境变量
  3. 训练模型

配置文件说明

下面展示了配置文件中不同模块参数的含义

基础配置

mode: "train"  运行模式 2中选择["train"," valid"]
ARCHITECTURE: 模型结构名字
    name: 'ResNet50_vd'
pretrained_model: "" 预训练模型路径
model_save_dir: "./output/" 保存模型路径
classes_num: 6 分类数
total_images: 1800 总图片数
save_interval: 10 每隔多少个epoch保存模型
validate: True 是否在训练时进行评估
valid_interval: 10 每隔多少个epoch进行模型评估
epochs: 400 训练总epoch数
topk: 5 评估指标K值大小
image_shape: [3, 224, 224] 图片大小
use_mix: True 是否启用mixup
ls_epsilon: 0.1 label_smoothing epsilon值

学习率与优化配置

LEARNING_RATE:
    function: 'Cosine' decay方法名  ["Linear", "Cosine","Piecewise", "CosineWarmup"]         
    params: 初始学习率     大部分的神经网络选择的初始学习率为0.1,batch_size是256,所以根据实际的模型大小和显存情况,可以将学习率设置为0.1*k,batch_size设置为256*k              
        lr: 0.1   
*还可设置的参数
params:
    decayepochs  piecewisedecay中衰减学习率的milestone
params:
    gamma       piecewisedecay中gamma值   
params:
    warmupepoch  warmup轮数   
parmas:
    steps       lineardecay衰减steps数 
params:
    endlr       lineardecayendlr值   

OPTIMIZER:
    function: 'Momentum' 优化器方法名 ["Momentum", "RmsProp"]
    params:
        momentum: 0.9 momentum值
    regularizer:
        function: 'L2' 正则化方法名   
        factor: 0.000070 正则化系数

训练配置

TRAIN:
    batch_size: 32 批大小
    num_workers: 4 数据读取器worker数量
    file_list: "./dataset/NEU-CLS/train.txt" train文件列表
    data_dir: "./dataset/NEU-CLS" train文件路径
    shuffle_seed: 0 用来进行shuffle的seed值
    transforms: 数据处理
        - DecodeImage:
            to_rgb: True 数据转RGB
            to_np: False 数据转numpy
            channel_first: False 按CHW排列的图片数据
        - RandCropImage: 随机裁剪
            size: 224
        - RandFlipImage: 随机翻转
            flip_code: 1
        - NormalizeImage:
            scale: 1./255. 归一化scale值
            mean: [0.485, 0.456, 0.406] 归一化均值
            std: [0.229, 0.224, 0.225] 归一化方差
            order: '' 归一化顺序
        - ToCHWImage: 调整为CHW
    mix:                       
        - MixupOperator:    
            alpha: 0.2      
*还可设置的参数
-CropImage  
    size:   裁剪大小
-ResizeImage    
    resize_short:   按短边调整大小

测试配置

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:

设置环境变量

%cd PaddleClas
import os 
os.environ['PYTHONPATH']="/home/aistudio/PaddleClas"

关于预训练模型

  • 如需使用预训练模型,则执行下面的脚本,并在训练脚本后增加 -o pretrained_model=./ResNet50_vd_pretrained,不使用预训练模型则跳过下面的执行语句。
!python ../download_model.py ResNet50_vd_pretrained
!mv ../ResNet50_vd_pretrained ./

开始训练

  • 执行训练脚本,使用已经配置好的neu.yaml文件
  • 训练脚本指令如下:PaddleClas通过launch方式启动多卡多进程训练 通过设置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. 模型评估

首先需要修改评估所需的配置文件,修改方式有两种,

  1. 直接修改configs/eval.yaml
  2. -o参数更新配置
  • 这里建议直接修改configs/eval.yaml,使用-o设置需要评估的模型路径 较为方便

  • 评估脚本代码如下:需要注意的是加载模型时,需要指定模型的前缀,如模型参数所在的文件夹为output/ResNet50_vd/19,模型参数的名称为output/ResNet50_vd/19/ppcls.pdparams,则pretrained_model参数需要指定为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

评估结果展示

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"]

上面展示的结果是笔者训练50个epochs,在测试集上top1的准确率为0.9000,经过测试在进行400次迭代之后会达到100%的准确率。

关于PaddlePaddle模型的保存方式

  1. persistable 模型(fluid.save_persistabels保存的模型) 一般做为模型的 checkpoint,可以加载后重新训练。persistable 模型保存的是零散的权重文件,每个文件代表模型中的一个 Variable,这些零散的文件不包含结构信息,需要结合模型的结构一起使用。
  2. inference 模型(fluid.io.save_inference_model保存的模型) 一般是模型训练完成后保存的固化模型,用于预测部署。与 persistable 模型相比,inference 模型会额外保存模型的结构信息,用于配合权重文件构成完整的模型。如下所示,model 中保存的即为模型的结构信息。

6. 模型推理

由于模型的保存方式以及选择引擎的不同,PaddlePaddle衍生出三种方式进行预测推理:

  • 预测引擎 + inference 模型
  • 训练引擎 + persistable 模型
  • 训练引擎 + inference 模型

本文选择使用 预测引擎 + inference模型 的方式进行推理,执行步骤如下:

  1. 对训练好的模型进行转换固化
  2. 通过预测引擎和inference模型进行推理

保存 inference 模型

在训练过程中保存的persistable 模型中选择最优模型,本文设置在训练的同时进行模型评估并保存效果最好的persistable模型,命令如下:

python tools/export_model.py --m=模型名称 --p=persistable 模型路径 --o=model和params保存路径

预测引擎 + inference 模型推理预测:

命令如下:

python ./tools/infer/predict.py -i=./test.jpeg -m=./resnet50-vd/model -p=./resnet50-vd/params --use_gpu=1

需要注意的是对应的模型权重文件路径需要确认,其他的参数设置如下所示:

参数说明:

  • image_file(简写 i):待预测的图片文件路径,如 ./test.jpeg
  • model_file(简写 m):模型文件路径,如 ./resnet50-vd/model
  • params_file(简写 p):权重文件路径,如 ./resnet50-vd/params
  • batch_size(简写 b):批大小,如 1
  • ir_optim:是否使用 IR 优化,默认值:True
  • use_tensorrt:是否使用 TesorRT 预测引擎,默认值:True
  • gpu_mem: 初始分配GPU显存,以M单位
  • use_gpu:是否使用 GPU 预测,默认值:True
  • enable_benchmark:是否启用benchmark,默认值:False
  • model_name:模型名字
  • 注意: 当启用benchmark时,默认开启tersorrt进行预测
!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(氧化皮)瑕疵的图片:
my.jpg

预测结果展示:

2020-08-03 15:58:48,332-INFO: class: 3
2020-08-03 15:58:48,332-INFO: score: 0.8259640336036682

可以看到预测正确,Rs的标签为3

7. 总结

  1. 本文使用了PaddleClas在热轧钢带表面缺陷数据进行训练
  2. 使用训练好的ResNet_vd模型对热轧钢带表面图片数据进行分类预测

本文转自百度的aistudio上的文章,原作者的主页:zhou_lu的主页

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,376评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,126评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,966评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,432评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,519评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,792评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,933评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,701评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,143评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,488评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,626评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,292评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,896评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,742评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,324评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,494评论 2 348

推荐阅读更多精彩内容

  • 夜莺2517阅读 127,717评论 1 9
  • 我是黑夜里大雨纷飞的人啊 1 “又到一年六月,有人笑有人哭,有人欢乐有人忧愁,有人惊喜有人失落,有的觉得收获满满有...
    陌忘宇阅读 8,529评论 28 53
  • 兔子虽然是枚小硕 但学校的硕士四人寝不够 就被分到了博士楼里 两人一间 在学校的最西边 靠山 兔子的室友身体不好 ...
    待业的兔子阅读 2,593评论 2 9
  • 信任包括信任自己和信任他人 很多时候,很多事情,失败、遗憾、错过,源于不自信,不信任他人 觉得自己做不成,别人做不...
    吴氵晃阅读 6,186评论 4 8