MobileNetV2工件表面缺陷检测算法毕业论文【轻量级网络代码】

博主简介:擅长数据搜集与处理、建模仿真、程序设计、仿真代码、论文写作与指导,毕业论文、期刊论文经验交流。

 ✅ 具体问题可以私信或扫描文章底部二维码。


(1)基于MobileNetV2的轻量级网络模型设计。本文以MobileNetV2为基础,针对其逆残差结构中可能存在的特征信息流动不足和细节丢失问题,提出了一种新型轻量级网络缺陷检测模型Efficient-LightNet。该模型在MobileNetV2的骨干网络上进行了多项改进:首先,引入了通道注意力机制,通过在逆残差块末尾添加压缩激励模块,自动学习特征通道的重要性权重,增强缺陷相关特征的响应,抑制无关背景干扰。具体而言,该机制对特征图进行全局平均池化,再通过两个全连接层生成通道权重,与原始特征相乘,实现特征重标定,从而提升模型对微小缺陷的敏感度。其次,将原网络中的ReLU激活函数替换为Swish激活函数,即f(x)=x·sigmoid(x),利用其平滑非单调特性改善梯度流动,增强模型的非线性表达能力,尤其在处理复杂纹理缺陷时表现更优。此外,对深度可分离卷积进行了优化,在深度卷积后增加点卷积前的特征复用机制,通过跳跃连接将浅层特征与深层特征融合,避免信息丢失,同时保持计算效率。网络整体采用狭窄的瓶颈设计,减少参数数量,但通过多层次特征聚合模块,在多个尺度上提取缺陷特征。该模块利用不同扩张率的空洞卷积并行处理特征图,捕获多尺度上下文信息,适应不同大小的缺陷区域。最后,为了进一步降低计算成本,在网络浅层使用分组卷积替代部分标准卷积,并结合通道洗牌操作促进组间信息交换,确保特征表达的丰富性。Efficient-LightNet的整体结构包含初始卷积层、多个改进的逆残差块、注意力模块和多尺度聚合层,最终通过全局池化和全连接层输出分类结果。该设计将模型参数量控制在2M以内,浮点运算量低于50MFLOPs,兼顾了轻量化和高精度需求。

(2)基于公开数据集的分类性能评估。为验证Efficient-LightNet的有效性,本文选用NEU表面缺陷数据集进行实验,该数据集包含热轧带钢的六类常见缺陷(如裂纹、夹杂、斑块等),每类样本300张灰度图像,分辨率200×200像素。实验从目标分类角度出发,对比了支持向量机(使用HOG特征)、经典卷积神经网络(AlexNet、GoogleNet、ResNet-50)及轻量级网络(MobileNetV2、ShuffleNetV2、EfficientNet-B0)。训练设置方面,所有深度学习模型均采用Adam优化器,初始学习率0.001,批次大小32,训练周期100,并应用随机水平翻转和亮度调整进行数据增强。Efficient-LightNet在测试集上达到98.75%的分类准确率,优于SVM的85.2%、AlexNet的94.3%、GoogleNet的96.8%、ResNet-50的97.1%,以及MobileNetV2的97.9%、ShuffleNetV2的98.1%和EfficientNet-B0的98.5%。在模型效率方面,Efficient-LightNet的参数量仅为1.98×10^6,相较于AlexNet的57.02×10^6降低了28.8倍,比ResNet-50的23.52×10^6降低了11.9倍;计算成本为45.3MFLOPs,远低于ResNet-50的4109.5MFLOPs(降低90.7倍)和MobileNetV2的300MFLOPs(降低6.6倍)。消融实验进一步分析了各改进组件的贡献:单独使用注意力机制可使基础MobileNetV2准确率提升1.5%,添加Swish激活函数再提升0.8%,多尺度聚合模块贡献1.2%的增益。结果表明,Efficient-LightNet在精度和效率间取得了良好平衡,尤其适合低算力环境。此外,模型对裂纹和小尺度夹杂等难样本的检测鲁棒性较强,误报率低于2%。

(3)实际工业芯片缺陷检测系统设计与部署。将Efficient-LightNet扩展至目标检测任务,构建了一套完整芯片表面缺陷检测系统。系统硬件由2000万像素工业相机、环形LED光源和机械传送带组成,软件部分集成图像采集、预处理、模型推理和后处理模块。针对芯片缺陷(如划痕、崩边、污染),首先通过图像预处理模块进行灰度化、直方图均衡化和高斯滤波,增强对比度并降噪。由于真实样本稀缺,使用生成对抗网络进行数据扩充,生成2000张合成缺陷图像,并结合旋转、缩放等传统增强手段,将数据集扩展至5000张标注图像。标注工具采用LabelImg,缺陷区域用矩形框标注。检测模型基于Efficient-LightNet骨干网络,结合单阶段检测器SSD框架,在多个特征层上设置先验框,适应不同缺陷尺寸。为缓解正负样本不平衡问题,损失函数引入Focal Loss,聚焦难分类样本,参数α=0.25,γ=2。训练时使用带动量的SGD优化器,学习率余弦退火调度,批次大小16。后处理采用非极大值抑制,阈值0.5,消除重叠检测框

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader
import torch.optim as optim
from torchvision import transforms
import cv2
import os
import numpy as np

class AttentionModule(nn.Module):
    def __init__(self, channels, reduction=16):
        super(AttentionModule, self).__init__()
        self.global_pool = nn.AdaptiveAvgPool2d(1)
        self.fc1 = nn.Linear(channels, channels // reduction)
        self.fc2 = nn.Linear(channels // reduction, channels)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        batch, channels, _, _ = x.size()
        out = self.global_pool(x).view(batch, channels)
        out = F.relu(self.fc1(out))
        out = self.sigmoid(self.fc2(out)).view(batch, channels, 1, 1)
        return x * out

class InvertedResidual(nn.Module):
    def __init__(self, inp, oup, stride, expand_ratio):
        super(InvertedResidual, self).__init__()
        self.stride = stride
        assert stride in [1, 2]
        hidden_dim = int(round(inp * expand_ratio))
        self.use_res_connect = self.stride == 1 and inp == oup
        layers = []
        if expand_ratio != 1:
            layers.append(nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False))
            layers.append(nn.BatchNorm2d(hidden_dim))
            layers.append(nn.SiLU())
        layers.extend([
            nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),
            nn.BatchNorm2d(hidden_dim),
            nn.SiLU(),
            nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
            nn.BatchNorm2d(oup),
        ])
        self.conv = nn.Sequential(*layers)
        self.attention = AttentionModule(oup)

    def forward(self, x):
        if self.use_res_connect:
            return x + self.attention(self.conv(x))
        else:
            return self.attention(self.conv(x))

class MultiScaleModule(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(MultiScaleModule, self).__init__()
        self.branch1 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, 3, padding=1, dilation=1, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.SiLU()
        )
        self.branch2 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, 3, padding=2, dilation=2, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.SiLU()
        )
        self.branch3 = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, 3, padding=3, dilation=3, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.SiLU()
        )
        self.fuse = nn.Conv2d(out_channels * 3, out_channels, 1, bias=False)

    def forward(self, x):
        out1 = self.branch1(x)
        out2 = self.branch2(x)
        out3 = self.branch3(x)
        out = torch.cat([out1, out2, out3], dim=1)
        out = self.fuse(out)
        return out

class EfficientLightNet(nn.Module):
    def __init__(self, num_classes=6):
        super(EfficientLightNet, self).__init__()
        self.first_conv = nn.Sequential(
            nn.Conv2d(1, 32, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(32),
            nn.SiLU()
        )
        self.inverted_residual_blocks = nn.Sequential(
            InvertedResidual(32, 16, 1, 1),
            InvertedResidual(16, 24, 2, 6),
            InvertedResidual(24, 24, 1, 6),
            InvertedResidual(24, 32, 2, 6),
            InvertedResidual(32, 32, 1, 6),
            InvertedResidual(32, 32, 1, 6),
            InvertedResidual(32, 64, 2, 6),
            InvertedResidual(64, 64, 1, 6),
            InvertedResidual(64, 64, 1, 6),
            InvertedResidual(64, 96, 1, 6),
            InvertedResidual(96, 96, 1, 6),
            InvertedResidual(96, 96, 1, 6),
            InvertedResidual(96, 160, 2, 6),
            InvertedResidual(160, 160, 1, 6),
            InvertedResidual(160, 160, 1, 6),
            InvertedResidual(160, 320, 1, 6)
        )
        self.multiscale = MultiScaleModule(320, 1280)
        self.final_conv = nn.Sequential(
            nn.Conv2d(1280, 1280, 1, bias=False),
            nn.BatchNorm2d(1280),
            nn.SiLU()
        )
        self.global_pool = nn.AdaptiveAvgPool2d(1)
        self.classifier = nn.Linear(1280, num_classes)

    def forward(self, x):
        x = self.first_conv(x)
        x = self.inverted_residual_blocks(x)
        x = self.multiscale(x)
        x = self.final_conv(x)
        x = self.global_pool(x)
        x = x.view(x.size(0), -1)
        x = self.classifier(x)
        return x

class DefectDataset(Dataset):
    def __init__(self, image_dir, label_file, transform=None):
        self.image_dir = image_dir
        self.labels = np.loadtxt(label_file, dtype=int)
        self.transform = transform

    def __len__(self):
        return len(self.labels)

    def __getitem__(self, idx):
        img_name = os.path.join(self.image_dir, f"{idx}.jpg")
        image = cv2.imread(img_name, cv2.IMREAD_GRAYSCALE)
        image = image.astype(np.float32) / 255.0
        image = np.expand_dims(image, axis=0)
        label = self.labels[idx]
        if self.transform:
            image = self.transform(image)
        return torch.tensor(image, dtype=torch.float32), torch.tensor(label, dtype=torch.long)

def train_model():
    device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
    model = EfficientLightNet(num_classes=6)
    model.to(device)
    transform = transforms.Compose([transforms.ToTensor()])
    dataset = DefectDataset("images", "labels.txt", transform=transform)
    dataloader = DataLoader(dataset, batch_size=32, shuffle=True)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.001)
    for epoch in range(100):
        model.train()
        running_loss = 0.0
        for i, (inputs, labels) in enumerate(dataloader):
            inputs, labels = inputs.to(device), labels.to(device)
            optimizer.zero_grad()
            outputs = model(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()
            running_loss += loss.item()
        print(f"Epoch {epoch+1}, Loss: {running_loss/len(dataloader)}")
    torch.save(model.state_dict(), "efficient_lightnet.pth")

if __name__ == "__main__":
    train_model()


如有问题,可以直接沟通

👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇👇

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坷拉博士

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值