首页 > 其他分享 >基于卷积神经网络的图像二分类检测模型训练与推理实现教程 | 幽络源

基于卷积神经网络的图像二分类检测模型训练与推理实现教程 | 幽络源

时间:2024-12-16 18:29:06浏览次数:8  
标签:冲沟 IMG 训练 卷积 模型 img 神经网络 幽络源 train

前言

对于本教程,说白了,就是期望能通过一个程序判断一张图片是否为某个物体,或者说判断一张图片是否为某个缺陷。因为本教程是针对二分类问题,因此主要处理 是 与 不是 的问题,比如我的模型是判断一张图片是否为苹果,那么拿一张图片给模型去推理,他会得出这张图是苹果的概率,如果概率大于0.5(这个概率在0~1之间),那么就判断为是苹果。

教程内容

使用了Python的 TensorFlow 和 Keras 库 构建卷积神经网络来完成二分类模型训练,以及使用模型完成对一张图片的推理。原文链接:基于卷积神经网络的图像二分类检测模型训练与推理实现教程 | 幽络源

大致步骤

1.确定环境与库

2.准备数据集并且划分

3.数据集的命名问题注意事项

4.编写训练代码完成模型训练

5.编写推理代码

6.测试二分类检测结果

7.根据结果优化数据集

步骤1.确定环境与库

Python环境是必备的,我这里所使用的Python版本为3.12.3

其次还需要以下库,依次执行如下命令即可

pip install tensorflow
pip install pillow
pip install scipy

如图

1

2

步骤2.准备数据集并且划分

我这里以判断图片是否为冲沟缺陷 来准备数据集,首先创建数据集的目录结构,结构如下

data/
    train/
        true_sample/ 
        false_sample/  
    val/
        true_sample/
        false_sample/

QQ_1734065732662

目录解释:

data:作为数据集的根目录

train和val分别为训练集、验证集目录

true_sample:正类样本,也就是我这里需要把含有冲沟缺陷的图放到这个目录

false_sample:负类样本,也就是这里需要将不含有冲沟缺陷的图片放进这个目录

如图,我向train和val的true_sample目录加入了一些含有冲沟缺陷的图片

3

对于负类样本,也不是无脑的只要不是冲沟就往里面放,而是放置你认为训练出的模型可能会将什么识别为正类样本。比如滑坡和冲沟其实是有联系的,但不完全等同于,所以我需要将滑坡相关的,但是没有冲沟情况的图片放入false_sample中,期望模型不要误判。再比如一个苹果,你可能需要把红色气球作为父类样本,防止模型将红气球判断为是苹果,如图是我的负类样本

4

步骤3.数据集的命名问题注意事项

关于数据集的命名,这里其实有一个坑,但是先说避免坑的做法:就像步骤2一样,你的正类样本所放置的目录命名为true_sample、负类样本所放置的目录命名为false_sample就行了。(如果看不懂下面的解释,按照这里做法做就是了)

然后我来解释下是什么坑,对于这个二分类模型训练,训练出来的模型,无非是识别 是 与 不是 的问题,但是模型怎么区分我的哪个目录放置的为是,哪个目录放置的为不是呢,步骤4会给出训练代码,训练代码中的加载数据集时有一行如下代码

class_mode='binary'  # 二分类(冲沟缺陷 vs. 非冲沟缺陷)

这表示我们要做二分类模型训练,加上这行代码,在加载数据集时,Keras 会自动将这些文件夹的名称作为标签,分别命名为1 和 0,如果被命名为标签1 的目录,则在推理时,概率越接近于1,则越表示是标为1的目录的样本,反之概率越接近于0,则越表示是标为0的目录的样本。而keras自动命名标签1和0时是根据目录名首字母的顺序来的字,字母靠前的标为0,后者为1,true_sample的首字母为t,false_sample的首字母为f,因此false_sample标为0,true_sample标为1,这是符合我们的正常预期的。

反面例子:

如果我把正类样本放置于名为defect的目录,负类样本放置于no_defect目录会怎样呢,按照如上解释,defect目录会被标为0,no_defect目录会被标为1,这就和我们预期相反了,什么意思呢。我把正类样本放置defect目录中,其推理结果将会是越接近0,则越表示为正类了,因此这里特别需要注意(如果你要自定义目录名的话)。

步骤4.编写训练代码完成模型训练

先直接上训练代码

from tensorflow.keras import layers, models
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import tensorflow as tf


train_dir='data/train'
val_dir='data/val'

# 设置图像的尺寸和批量大小,不用改,保持150是最平衡的
IMG_HEIGHT = 150
IMG_WIDTH = 150
BATCH_SIZE = 12

# 数据预处理与增强
train_datagen = ImageDataGenerator(
    rescale=1./255,  # 将像素值归一化到 [0, 1] 区间
    shear_range=0.2,
    zoom_range=0.2,
    horizontal_flip=True
)

validation_datagen = ImageDataGenerator(rescale=1./255)

# 加载训练和验证数据
train_generator = train_datagen.flow_from_directory(
    train_dir,  # 训练数据目录
    target_size=(IMG_HEIGHT, IMG_WIDTH),  # 图像尺寸
    batch_size=BATCH_SIZE,
    class_mode='binary'  # 二分类(冲沟缺陷 vs. 非冲沟缺陷)
)

train_class_labels = train_generator.class_indices
print("训练集自动标签映射关系为:"+str(train_class_labels))

validation_generator = validation_datagen.flow_from_directory(
    val_dir,  # 验证数据目录
    target_size=(IMG_HEIGHT, IMG_WIDTH),
    batch_size=BATCH_SIZE,
    class_mode='binary'
)

val_class_labels = validation_generator.class_indices
print("测试集自动标签映射关系为:"+str(val_class_labels))

# 将数据生成器转换为 tf.data.Dataset 并应用 repeat() 方法
train_dataset = tf.data.Dataset.from_generator(
    lambda: train_generator,
    output_signature=(
        tf.TensorSpec(shape=(None, IMG_HEIGHT, IMG_WIDTH, 3), dtype=tf.float32),
        tf.TensorSpec(shape=(None,), dtype=tf.int32)
    )
)
train_dataset = train_dataset.repeat()  # 确保数据重复

validation_dataset = tf.data.Dataset.from_generator(
    lambda: validation_generator,
    output_signature=(
        tf.TensorSpec(shape=(None, IMG_HEIGHT, IMG_WIDTH, 3), dtype=tf.float32),
        tf.TensorSpec(shape=(None,), dtype=tf.int32)
    )
)
validation_dataset = validation_dataset.repeat()  # 确保数据重复

# 构建模型
model = models.Sequential([
    layers.InputLayer(shape=(IMG_HEIGHT, IMG_WIDTH, 3)),  # 添加 Input 层
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Flatten(),
    layers.Dense(128, activation='relu'),
    layers.Dense(1, activation='sigmoid')  # 输出层,二分类问题
])

# 编译模型
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# 训练模型
model.fit(
    train_dataset,
    steps_per_epoch=train_generator.samples // BATCH_SIZE,
    epochs=30,
    validation_data=validation_dataset,
    validation_steps=validation_generator.samples // BATCH_SIZE
)

# 保存模型
model.save('defect_detector_model.keras')  # 使用 .keras 格式保存模型

使用这段代码训练数据集你唯一需要注意的是保持代码文件于数据集文件在同一目录,或者使用绝对路径,如图

QQ_1734070943655

我们启动训练代码,可以看到控制台在按照规定的轮次30在训练中,而且可以看到我在训练代码中加入了输出标签映射关系来确保正类与负类的映射关系正确,如图

QQ_1734071390702

训练后,你会得到一个名为defect_detector_nodel.keras的文件,推理时会使用该模型进行推理

步骤5.编写推理代码

代码如下:

import os
from tensorflow.keras.models import load_model
import numpy as np
from tensorflow.keras.preprocessing import image

# 加载训练好的模型
model = load_model('defect_detector_model.keras')  # 注意加载的是 .keras 格式

# 设置输入图像的目标尺寸(与训练时相同)
IMG_HEIGHT = 150
IMG_WIDTH = 150


# 定义函数来加载并预测图像
def predict_image(img_path):
    # 加载图像并进行预处理
    img = image.load_img(img_path, target_size=(IMG_HEIGHT, IMG_WIDTH))
    img_array = image.img_to_array(img)  # 将图像转换为数组
    img_array = np.expand_dims(img_array, axis=0)  # 扩展维度,成为一个 batch
    img_array = img_array / 255.0  # 归一化处理(与训练时一致)

    # 预测图像类别
    prediction = model.predict(img_array)  # 返回的是一个包含概率的数组
    return prediction[0][0]  # 提取预测的概率值

picPath=r"测试图.jpg"
confidence = predict_image(picPath)
print("有冲沟缺陷的概率为:"+str(confidence))

这段推理代码中,我们加载了刚才训练出的模型,然后使用了一张名为测试图.jpg的图片来进行推理,然后输出他有缺陷的概率

步骤6.测试二分类检测结果

我这里就不用一张图片来测试了,我这里指定一个目录,进行整个目录来测试里面的图片,还是附上我这个推理代码吧

import os
from tensorflow.keras.models import load_model
import numpy as np
from tensorflow.keras.preprocessing import image

# 加载训练好的模型
model = load_model('defect_detector_model.keras')  # 注意加载的是 .keras 格式

# 设置输入图像的目标尺寸(与训练时相同)
IMG_HEIGHT = 150
IMG_WIDTH = 150


# 定义函数来加载并预测图像
def predict_image(img_path):
    # 加载图像并进行预处理
    img = image.load_img(img_path, target_size=(IMG_HEIGHT, IMG_WIDTH))
    img_array = image.img_to_array(img)  # 将图像转换为数组
    img_array = np.expand_dims(img_array, axis=0)  # 扩展维度,成为一个 batch
    img_array = img_array / 255.0  # 归一化处理(与训练时一致)

    # 预测图像类别
    prediction = model.predict(img_array)  # 返回的是一个包含概率的数组
    return prediction[0][0]  # 提取预测的概率值


# 测试目录,包含要进行推理的图像
testDir = r"D:\virtualTemp\pythonProject\CNN分类检测\data\train\true_sample"
pics = os.listdir(testDir)
# 遍历目录中的所有图片并进行预测
for pic in pics:
    picPath = os.path.join(testDir, pic)  # 获取图片的完整路径
    # 获取预测结果的置信度
    confidence = predict_image(picPath)
    # 输出图像的置信度和类别
    print(f"{pic} 置信度: {confidence:.4f}, 预测结果: {'有缺陷' if confidence >= 0.5 else '无缺陷'}")

我先使用正类样本来测试,先看看拿训练的数据如何,然后再用另外的图片来测试

结果如下图,正类样本中只有一张图判定为了无冲沟,但是我正类样本中其实都应当是冲沟,而我有101张图,因此这里正确率为99.009%

QQ_1734071615033

拿训练的数据来说话可能没有说服力,现在我使用爬图器来批量的爬取一些图片,需要的可以这里拿=> 幽络源爬图器

如图我爬取了3轮桥梁破损图,2轮冲沟地貌图,对于冲沟图,最好是手动删一些莫名奇妙的图,便于验证

QQ_1734072068792

QQ_1734072170259

ok,然后先测试桥梁破损,如果足够符合预期,足够表示模型很好,那么推理出的有缺陷数量应该没有或者很少才对,结果如下

QQ_1734072462049

看起来结果并不好,90张图中,居然有44张判定为了有冲沟缺陷,正确率只有46/90=51.11%,再测试下正类检测呢,如图48张图中只有11张判定为了无,还是不错的。

步骤7.根据结果优化数据集

在步骤6的测试中可知,所训练的模型对正类比较适应,对负类的学习还有所欠缺,处理方法有如下

1.调整判定指标confidence,一般为0.5,可以调大以提高正确率,但是不推荐这么做

2.加大训练轮次

3.训练时的父类样本图片多加一些

ok,方法1我不是很推荐,现在首先加大训练次数到100,然后多爬取一些非冲沟图加入到负类样本之中,当然,桥梁破损的图也放进去一些,然后重新训练获取模型。

训练完后还是按照步骤6中来测试桥梁破损,如图,这一次,90张图中判定为有缺陷的只有7个了,非常不错,正确率提高到了82/90=91.11%

QQ_1734073419635

结语

以上是幽络源的基于卷积神经网络的图像二分类检测模型训练与推理实现教程,对Python、Java感兴趣的小伙伴可加群交流

标签:冲沟,IMG,训练,卷积,模型,img,神经网络,幽络源,train
From: https://blog.csdn.net/m0_73873732/article/details/144450948

相关文章

  • 第三章 3.10 构建更深的神经网络 比较有0、1、2隐含层的神经网络
     比较有0、1、2隐含层的神经网络,发现层多时,过拟合#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch###################ChapterThree###########################......
  • 线性神经网络(线性回归)
    1.什么是线性回归?线性回归是一种用于预测的统计方法,它通过建立自变量(特征)与因变量(目标值)之间的线性关系来进行建模。简单来说,线性回归试图找到一条直线,使得这条直线能够尽可能接近所有的数据点。 1.1现实例子某公司希望根据房屋的面积和房龄来估算房屋价格。为了开发一个......
  • Yolo11改进策略:卷积篇|DSConv,高效卷积算子|附代码|即插即用
    摘要论文介绍研究背景:神经网络量化是提升速度和降低内存使用量的常用方法,但无标记数据的量化问题受到的关注较少。研究目的:引入DSConv卷积算子,旨在生成更小且推理速度更快的神经网络,同时保持高精度。实验验证:在最流行的神经网络架构(ResNet、DenseNet、GoogLeNet、AlexNet......
  • 基于图神经网络的大语言模型检索增强生成框架研究:面向知识图谱推理的优化与扩展
    在大型语言模型(LLMs)相关的人工智能突破中,图神经网络(GNNs)与LLMs的融合已成为一个极具前景的研究方向。这两类模型的结合展现出显著的互补性,能够协同增强LLMs的推理能力和上下文理解能力。通过从知识图谱(KGs)存储的海量信息中进行智能化检索,该结合能够生成准确且不含幻觉的答案......
  • 深度学习卷积(Convolution)
    图像卷积importtorchimporttorch.nnasnnimporttorch.optimasoptimimporttorchvisionimporttorchvision.transformsastransformsfromtorch.utils.dataimportDataLoader#使用GPU(如果可用),否则使用CPUdevice=torch.device("cuda"iftorch.cuda.is_avail......
  • 毕业设计:python车牌识别系统 CNN算法 卷积神经网络网络 深度学习 tensorflow(源码)✅
    python车牌识别系统CNN算法卷积神经网络网络深度学习tensorflow(源码)1、项目介绍技术栈:Python语言、CNN算法、tensorflow和keras、深度学习、opencv、pyqt5图形界面2、项目界面(1)上传图像进行车牌识别1(2)上传图像进行车牌识别2(3)上传图像进行车牌识别3(4)上传视......
  • 【深度学习】 零基础介绍卷积神经网络(CNN)
    零基础介绍卷积神经网络(CNN,ConvolutionalNeuralNetwork)是深度学习中的一种神经网络,特别擅长处理图像和视频等有空间结构的数据。假设我们在做一个“照片分类”的任务,比如判断一张照片中是猫还是狗。下面用一个通俗的例子来解释CNN的工作原理。看图的方式:模拟人眼当我......
  • 第三章 3.4 训练神经网络
     代码:#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch#https://github.com/PacktPublishing/Modern-Computer-Vision-with-PyTorch###################ChapterThree########################################第三章读取数据集并显示......
  • 基于Huffman树的层次化Softmax:面向大规模神经网络的高效概率计算方法
    1、理论基础算法本质与背景层次化(Hierarchial)Softmax算法是在深度学习领域中解决大规模词嵌入训练效率问题的重要突破。该算法通过引入Huffman树结构,有效地将传统Softmax的计算复杂度从线性降至对数级别,从而在处理大规模词汇表时表现出显著的优势。在传统的神经网络词嵌......
  • 深度学习入门笔记——神经网络的构建和使用
    神经网络的整体构建神经网络的基本骨架首先可以在Pytorch官网的PythonAPI中查看torch.nn的使用,如下所示。可以看到神经网络包括Container(基本骨架)、卷积层、池化层、Padding层、非线性激活等等。构建一个神经网络首先要先构建起基本骨架,也就是Containersnn.Moudle的使用这......