卷积神经网络实战——钢材缺陷数据的分类检测

新星杯·14天创作挑战营·第17期 10w+人浏览 488人参与

在草稿箱发现了这篇写到一半的文章,最近要备赛,又逢期中有考试,所以放在草稿箱没有动。今天把这个实战记录下来,也供大家学习。当然,如果我写的有什么不对,大家可以评论区交流指导我。钢材缺陷的数据集在各大网站都是公开的,但是数据是混在一起的。因为我们做的是分类任务,训练过程中6类钢材缺陷的训练集要分类好,也就是要做一步整合,代码很简单。当然,为了方便小伙伴们学习,处理好的数据集我放在资源里面了,需要的小伙伴可以自行下载。

数据集:

https://download.youkuaiyun.com/download/luoying189/92393727

一、理解模型

一开始本来不想写,但是我觉得理解底层原理是很重要的。用模型很简单,直接导包用,但是用了又不知道怎么个事,所以这里写一下供自己理解,也供大家学习。如果想直接实战的小伙伴移步数据预处理就好啦。

卷积神经网络是一种专门为处理图像、视频等网格结构数据而设计的深度学习模型。它的核心思想是:通过卷积操作,自动提取图像中的局部特征,并逐层组合成更高级、更抽象的特征,最终完成分类、检测或分割等任务。

举个简单的小例子:

我这里有一些小猫的图片

第一层CNN会识别出边缘(比如猫的轮廓)。

第二层会组合边缘,识别出耳朵、眼睛、鼻子。

第三层会进一步组合,识别出这是一只小猫咪。

整个过程不需要我来告诉它猫有尖尖的小耳朵,长长的胡须之类的,它自己从大量图片中学会了这些特征。

卷积神经网络有三个核心的东西:

1、卷积层

我们把图像切成很多小块,用同一组数字跟卷积核做“乘加”运算,得到一张新图。想象一下,你拿着手电筒在图像上逐格滑动,每照一个小区间就得到一个小数值,全部滑完就拼成一张特征图。

这里手写一个计算过程,供大家理解卷积层是怎么运算的(字有点丑,勿喷)

2、池化层

对每张特征图做压缩,把 2×2(或 3×3)窗口压成 1 个数,长宽减半、深度不变,甩掉冗余信息。在池化层,我们一般选取最大值,在特征图里,数值越大代表这个地方跟卷积核越匹配,也就是特征越强烈,我们就把同一片小区域里最强的那个数保留下来。

也是写一个计算过程。

3、全连接层

前面卷积+池化已经把图像变成了若干张“特征图”,全连接层的工作只有三步:

首先是拉直
把所有特征图按顺序排成一条长向量,不再保留二维形状。
比如呢,2×2 的图拉直后就是 4 个数字的一维列表。

然后加权投票
每个输出神经元都要跟这 4 个数字分别做一次“乘加”:结果 = w₁×x₁ + w₂×x₂ + w₃×x₃ + w₄×x₄ + b

然后激活输出
把投票结果送进激活函数(常用 ReLU 或 Softmax),得到最终概率。如果是分类任务,最后一层 Softmax 会把概率和调成 1,谁最大就判给谁。

二、数据预处理

相信你已经有点理解卷积神经网络的原理了,那么接下来我们开始实战。数据集移步我的资源:https://download.youkuaiyun.com/download/luoying189/92393727

1、导包

import numpy as np

import pandas as pd

import matplotlib.pyplot as plt

from sklearn.preprocessing import MinMaxScaler

from sklearn.model_selection import train_test_split

from tensorflow import keras

from tensorflow.keras.layers import Dense,Flatten,Conv2D,MaxPool2D

from tensorflow.python.keras.utils.np_utils import to_categorical

from sklearn.metrics import classification_report

plt.rcParams['font.sans-serif']=['SimHei']  # 用来正常显示中文标签

plt.rcParams['axes.unicode_minus']=False  # 用来正常显示负号

import warnings

warnings.filterwarnings("ignore")

import pathlib

2、导入数据集,给数据类别放到列表当中

data_train = './NEU/train'

data_train = pathlib.Path(data_train)

# 读取验证集的数据

data_test = './NEU/test'

data_test = pathlib.Path(data_test)
# 给数据类别放到列表当中
CLASS_NAMES = np.array(['Cr','In','Pa','ps','Rs','SC'])

3、设置片大小和批次数,给整个训练流程定统一规格和一次喂多少张图

# 设置图片大小和批次数
BATCH_SIZE = 64
IMG_HEIGHT = 32
IM_WIDTH = 32

4、数据归一化处理

卷积核权重初始都是小数(-0.2~0.8 左右),如果输入像素 0~255,数值太大就会梯度爆炸。所以先把像素压到 0~1,与权重同一量级,方便梯度稳定下降。

image_generator = keras.preprocessing.image.ImageDataGenerator(rescale=1.0/255)

5、数据生成器

# 训练集生成器
train_data_gen = image_generator.flow_from_directory(directory=
                                                     str(data_train),
                                                     batch_size=BATCH_SIZE,
                                                     shuffle=True,
                                                     target_size=(IMG_HEIGHT,IM_WIDTH),
                                                     classes=list(CLASS_NAMES))
# 验证集生成器
test_data_gen = image_generator.flow_from_directory(directory=
                                                     str(data_test),
                                                     batch_size=BATCH_SIZE,
                                                     shuffle=True,
                                                     target_size=(IMG_HEIGHT,IM_WIDTH),
                                                     classes=list(CLASS_NAMES))

三、模型搭建

卷积层—池化层—卷积层—池化层—卷积层

第一次 Conv2D(6, 5×5),输出 28×28×6
第一次 MaxPool2D(2×2, strides=2),28×28×6 → 14×14×6
第二次 Conv2D(16, 5×5),10×10×16
第二次 MaxPool2D(2×2, strides=2),10×10×16 → 5×5×16
第三次 Conv2D(120, 5×5),1×1×120

接着拉直变成一维,1×1×120 →120

接着我们搭建全连接层,把 120 个数先压缩成 84 个高层特征,再映射成 6 个是哪类缺陷的概率,完成最终分类。

# 利用keras搭建卷积神经网络
model = keras.Sequential()
# 卷积核的数量filters,卷积的尺寸kernel_size
model.add(Conv2D(filters=6,kernel_size=5,input_shape=(32,32,3),activation='relu'))
# strides步幅
model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))

model.add(Conv2D(filters=16,kernel_size=5,activation='relu'))

model.add(MaxPool2D(pool_size=(2,2),strides=(2,2)))

model.add(Conv2D(filters=120,kernel_size=5,activation='relu'))

model.add(Flatten())
# 全连接层
model.add(Dense(84,activation='relu'))
model.add(Dense(6,activation='softmax'))

最后编译卷积神经网络

# 编译卷积神经网络
# Adam优化器
model.compile(loss='binary_crossentropy',optimizer='Adam',metrics=['accuracy'])

四、模型训练并保存

history = model.fit(train_data_gen,validation_data=test_data_gen,epochs=50)
model.save('model.h5')

五、可视化

我们可视化一下模型的损失值和精确度,由图可以看出来到最后,模型的准确度保持在0.9左右,还是蛮不错的。

plt.plot(history.history['loss'],label='train')
plt.plot(history.history['val_loss'],label='val')
plt.title('CNN神经网络loss图')
plt.legend()
plt.show()

plt.plot(history.history['accuracy'],label='train')
plt.plot(history.history['val_accuracy'],label='val')
plt.title('CNN神经网络accuracy图')
plt.legend()
plt.show()

六、模型验证

新建一个test.ipynb用于模型的验证

1、导包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from tensorflow import keras
import tensorflow as tf
from tensorflow.keras.layers import Dense,Flatten,Conv2D,MaxPool2D
from tensorflow.python.keras.utils.np_utils import to_categorical
from sklearn.metrics import classification_report
plt.rcParams['font.sans-serif']=['SimHei']  # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False  # 用来正常显示负号
import warnings
warnings.filterwarnings("ignore")
import pathlib
import cv2
from keras.models import load_model

2、预处理

# 给数据类别放到列表当中
CLASS_NAMES = np.array(['Cr','In','Pa','ps','Rs','SC'])
IMG_HEIGHT = 32
IM_WIDTH = 32

3、加载模型

我们选取测试集(test)的任意一张图片进行测试,看看出来的结果是不是正确的,路径你们自己改好。

# 加载模型
model = load_model('model.h5')
src = cv2.imread('./NEU/test/Rs/rolled-in_scale_14.jpg')
src = cv2.resize(src,(32,32))
src = src.astype('int32')
src = src/255

# 扩充数据的维度
test_img = tf.expand_dims(src,0)
print(test_img.shape)

4、模型测试

preds = model.predict(test_img)
print(preds)

我们可以打印6个分类的概率分数,更加直观地看到

score = preds[0]

score

概率越大,就越证明该钢材是属于这个分类。所以我们输出概率最大的分类名称。回到测试集选取的图片是Rs/rolled-in_scale_14.jpg,和预测结果是不是一样的呢,这就表明预测成功啦,该钢材缺陷标签为Rs的概率大约是0.998

那么整个实战到这里就结束了,相信你一定有所体会啦

结束,完结撒花

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值