ResNet18实战教程:服装分类系统开发

ResNet18实战教程:服装分类系统开发

1. 引言

1.1 学习目标

本文将带你从零开始,使用ResNet-18模型构建一个完整的服装图像分类系统。你将掌握: - 如何加载并微调预训练的 ResNet-18 模型 - 构建数据管道与图像增强策略 - 训练流程设计与性能监控 - 部署为本地 WebUI 界面供交互使用 - 在 CPU 上实现高效推理优化

最终成果是一个可上传图片、实时返回 Top-3 分类结果(含置信度)的可视化系统,适用于服装电商、智能穿搭推荐等场景。

1.2 前置知识

建议具备以下基础: - Python 编程能力 - PyTorch 基础操作(张量、模型定义) - 图像分类任务基本概念(如类别标签、损失函数)

无需从头训练模型,我们将基于TorchVision 官方 ResNet-18进行迁移学习,大幅提升开发效率和稳定性。

1.3 教程价值

本教程不同于简单调用 API 的“黑箱”方案,而是: -全流程闭环:涵盖数据 → 模型 → 训练 → 部署 -真实可运行代码:所有代码均可直接执行 -CPU 友好设计:专为无 GPU 环境优化,适合边缘设备部署 -WebUI 集成:提供用户友好的交互界面


2. 环境准备与项目结构

2.1 依赖安装

pip install torch torchvision flask pillow numpy matplotlib tqdm

⚠️ 推荐使用 Python 3.8+ 和 PyTorch 1.12+ 版本以确保兼容性。

2.2 项目目录结构

fashion_classifier/ │ ├── data/ # 数据集存放路径 │ └── fashion_mnist/ # 示例数据(可替换为自定义服装数据) │ ├── model/ │ └── resnet18_fashion.pth # 训练后保存的模型权重 │ ├── app.py # Flask WebUI 主程序 ├── train.py # 模型训练脚本 ├── inference.py # 推理逻辑封装 └── requirements.txt # 依赖列表

2.3 数据集说明

我们以Fashion-MNIST为例(10 类服装),但方法同样适用于自定义服装数据集(如 T-shirt, Dress, Jeans 等)。

类别编号名称
0T-shirt/top
1Trouser
2Pullover
3Dress
4Coat
5Sandal
6Shirt
7Sneaker
8Bag
9Ankle boot

3. 模型构建与迁移学习

3.1 加载预训练 ResNet-18

虽然 ResNet-18 原始模型在 ImageNet 上训练用于通用物体识别,但我们可以通过迁移学习将其适配到服装分类任务。

# train.py import torch import torch.nn as nn from torchvision import models def create_model(num_classes=10): # 加载官方预训练 ResNet-18 model = models.resnet18(pretrained=True) # 冻结特征提取层(可选) for param in model.parameters(): param.requires_grad = False # 修改全连接层以适应 10 类服装分类 model.fc = nn.Linear(model.fc.in_features, num_classes) return model

pretrained=True表示加载 TorchVision 官方提供的 ImageNet 预训练权重,具备强大泛化能力。

3.2 数据增强与加载器

# train.py from torchvision import transforms, datasets from torch.utils.data import DataLoader transform_train = transforms.Compose([ transforms.Resize(224), # 统一分辨率 transforms.RandomHorizontalFlip(), # 数据增强 transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], # ImageNet 标准化 std=[0.229, 0.224, 0.225]) ]) transform_test = transforms.Compose([ transforms.Resize(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) # 加载 Fashion-MNIST(需转换为三通道) train_dataset = datasets.FashionMNIST(root='./data', train=True, transform=transforms.ToTensor(), download=True) test_dataset = datasets.FashionMNIST(root='./data', train=False, transform=transforms.ToTensor()) # 扩展为三通道(模拟 RGB) class ToRGB: def __call__(self, x): return x.repeat(3, 1, 1) # 重新包装 transform train_dataset.transform = transforms.Compose([transforms.ToPILImage(), transforms.Resize(224), transforms.RandomHorizontalFlip(), ToRGB(), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]) test_dataset.transform = transforms.Compose([transforms.ToPILImage(), transforms.Resize(224), ToRGB(), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])]) train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True) test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)

3.3 模型训练流程

# train.py import torch.optim as optim from tqdm import tqdm def train_model(): device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = create_model().to(device) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.fc.parameters(), lr=1e-3) # 仅训练最后全连接层 epochs = 10 for epoch in range(epochs): model.train() running_loss = 0.0 correct = 0 total = 0 with tqdm(train_loader, desc=f"Epoch {epoch+1}/{epochs}") as pbar: for images, labels in pbar: images, labels = images.to(device), labels.to(device) optimizer.zero_grad() outputs = model(images) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() _, predicted = outputs.max(1) total += labels.size(0) correct += predicted.eq(labels).sum().item() pbar.set_postfix(loss=running_loss/len(train_loader), acc=100.*correct/total) print(f"Train Acc: {100.*correct/total:.2f}%") # 保存模型 torch.save(model.state_dict(), "./model/resnet18_fashion.pth") print("✅ 模型已保存至 ./model/resnet18_fashion.pth")

运行python train.py即可完成训练,通常 5~10 轮即可达到 90%+ 准确率。


4. 推理模块与 WebUI 集成

4.1 推理逻辑封装

# inference.py import torch from torchvision import models, transforms from PIL import Image import json # 类别映射表 class_names = [ "T-shirt/top", "Trouser", "Pullover", "Dress", "Coat", "Sandal", "Shirt", "Sneaker", "Bag", "Ankle boot" ] def load_model(model_path="./model/resnet18_fashion.pth", num_classes=10): model = models.resnet18(pretrained=False) model.fc = torch.nn.Linear(model.fc.in_features, num_classes) model.load_state_dict(torch.load(model_path, map_location='cpu')) model.eval() # 切换为评估模式 return model def transform_image(image_bytes): transform = transforms.Compose([ transforms.Resize(224), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) ]) image = Image.open(image_bytes).convert('RGB') return transform(image).unsqueeze(0) # 增加 batch 维度 def get_prediction(image_bytes): model = load_model() tensor = transform_image(image_bytes) outputs = model(tensor) probs = torch.nn.functional.softmax(outputs, dim=1) top3_prob, top3_idx = torch.topk(probs, 3) result = [] for i in range(3): label = class_names[top3_idx[0][i].item()] prob = top3_prob[0][i].item() result.append({"label": label, "confidence": round(prob * 100, 2)}) return result

4.2 WebUI 界面开发(Flask)

# app.py from flask import Flask, request, render_template, jsonify, send_from_directory import os from inference import get_prediction app = Flask(__name__) UPLOAD_FOLDER = 'uploads' os.makedirs(UPLOAD_FOLDER, exist_ok=True) app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER @app.route('/') def index(): return render_template('index.html') @app.route('/upload', methods=['POST']) def upload_file(): if 'file' not in request.files: return jsonify({"error": "未选择文件"}), 400 file = request.files['file'] if file.filename == '': return jsonify({"error": "未选择文件"}), 400 filepath = os.path.join(app.config['UPLOAD_FOLDER'], file.filename) file.save(filepath) try: with open(filepath, 'rb') as f: results = get_prediction(f) return jsonify(results) except Exception as e: return jsonify({"error": str(e)}), 500 @app.route('/uploads/<filename>') def uploaded_file(filename): return send_from_directory(app.config['UPLOAD_FOLDER'], filename) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=False)

4.3 HTML 前端页面

创建templates/index.html

<!DOCTYPE html> <html> <head> <title>👗 服装分类系统</title> <style> body { font-family: Arial; text-align: center; margin: 40px; } .upload-box { border: 2px dashed #ccc; padding: 30px; margin: 20px auto; width: 400px; cursor: pointer; } .result { margin-top: 20px; font-size: 1.2em; } img { max-width: 300px; margin: 10px; } button { padding: 10px 20px; font-size: 16px; } </style> </head> <body> <h1>👗 基于 ResNet-18 的服装分类系统</h1> <div class="upload-box" onclick="document.getElementById('file-input').click()"> <p>点击上传图片或拖拽至此</p> <input type="file" id="file-input" onchange="handleFile(this.files)" style="display: none;" accept="image/*"> </div> <img id="preview" style="display:none;"> <button onclick="startRecognition()" disabled id="btn-analyze">🔍 开始识别</button> <div class="result" id="result"></div> <script> let selectedFile; function handleFile(files) { selectedFile = files[0]; if (!selectedFile) return; const reader = new FileReader(); reader.onload = function(e) { document.getElementById('preview').src = e.target.result; document.getElementById('preview').style.display = 'block'; document.getElementById('btn-analyze').disabled = false; }; reader.readAsDataURL(selectedFile); } function startRecognition() { const formData = new FormData(); formData.append('file', selectedFile); fetch('/upload', { method: 'POST', body: formData }) .then(res => res.json()) .then(data => { if (data.error) throw new Error(data.error); let html = "<h3>🎯 识别结果:</h3>"; data.forEach(item => { html += `<p>${item.label}: <strong>${item.confidence}%</strong></p>`; }); document.getElementById('result').innerHTML = html; }) .catch(err => { document.getElementById('result').innerHTML = `<p style="color:red;">❌ 错误: ${err.message}</p>`; }); } </script> </body> </html>

5. 启动与使用说明

5.1 启动服务

# 第一步:训练模型(首次运行) python train.py # 第二步:启动 Web 服务 python app.py

访问http://localhost:5000即可进入交互界面。

5.2 使用流程

  1. 点击上传区域选择一张服装图片(支持 JPG/PNG)
  2. 图片自动预览
  3. 点击“🔍 开始识别”
  4. 系统返回 Top-3 最可能的服装类别及置信度

💡 实测案例:上传一件连衣裙照片,系统准确识别为 "Dress"(置信度 92.3%),第二候选为 "Pullover"(5.1%)。


6. 性能优化与最佳实践

6.1 CPU 推理加速技巧

  • 模型量化:将 FP32 权重转为 INT8,体积减半,速度提升 2~3 倍
# 量化示例 model.qconfig = torch.quantization.get_default_qconfig('fbgemm') model_quantized = torch.quantization.prepare(model, inplace=False) model_quantized = torch.quantization.convert(model_quantized, inplace=False)
  • 禁用梯度计算:推理时务必使用torch.no_grad()
  • 减少日志输出:关闭调试信息,提升响应速度

6.2 避坑指南

问题解决方案
图像尺寸不匹配统一 resize 到 224×224
灰度图报错使用convert('RGB')强制三通道
内存溢出减小 batch size 或启用流式处理
模型加载慢使用.pth而非.pt格式,避免保存 optimizer

6.3 扩展建议

  • 替换为更大模型(如 ResNet-50)提升精度
  • 添加摄像头实时识别功能
  • 支持多语言输出(中英文切换)
  • 集成到微信小程序或移动端 App

7. 总结

7.1 核心收获

通过本文,你已经成功构建了一个完整的ResNet-18 服装分类系统,掌握了: - 基于 TorchVision 的迁移学习方法 - 数据预处理与增强策略 - 模型训练与保存流程 - Flask WebUI 集成技术 - CPU 友好型推理优化手段

该系统具备高稳定性、低资源消耗、易部署等优势,特别适合中小企业或个人开发者快速落地 AI 图像分类应用。

7.2 下一步建议

  • 尝试在自定义服装数据集上微调模型
  • 接入 ONNX Runtime 提升跨平台兼容性
  • 使用 Docker 容器化部署服务
  • 探索轻量级替代模型(如 MobileNetV3)

💡获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/1146884.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ResNet18应用解析:智能交通管理系统

ResNet18应用解析&#xff1a;智能交通管理系统 1. 技术背景与应用场景 随着城市化进程的加速&#xff0c;交通管理正面临前所未有的挑战。传统的监控系统依赖人工值守和规则化检测&#xff0c;难以应对复杂多变的交通场景。近年来&#xff0c;深度学习技术的突破为智能交通系…

ResNet18性能测试:CPU环境下的推理速度对比

ResNet18性能测试&#xff1a;CPU环境下的推理速度对比 1. 背景与应用场景 在边缘计算、嵌入式设备和资源受限的生产环境中&#xff0c;深度学习模型的CPU推理性能成为决定其能否落地的关键因素。尽管GPU在训练和高并发推理中表现优异&#xff0c;但CPU因其普适性、低成本和低…

多层板PCB生产流程实例分析:常见缺陷及改善措施

多层板PCB生产全流程实战解析&#xff1a;从缺陷溯源到工艺优化你有没有遇到过这样的情况&#xff1f;一块设计完美的16层服务器主板&#xff0c;在回流焊后突然出现间歇性通信故障。FA&#xff08;失效分析&#xff09;拆解发现&#xff0c;问题竟出在第8层一个不起眼的微孔—…

ResNet18部署详解:Kubernetes集群部署方案

ResNet18部署详解&#xff1a;Kubernetes集群部署方案 1. 背景与技术选型 1.1 通用物体识别的工程需求 在当前AI服务快速落地的背景下&#xff0c;通用图像分类作为计算机视觉的基础能力&#xff0c;广泛应用于内容审核、智能相册、AR交互和自动化标注等场景。其中&#xff…

ResNet18应用案例:智能垃圾分类系统

ResNet18应用案例&#xff1a;智能垃圾分类系统 1. 引言&#xff1a;通用物体识别与ResNet-18的工程价值 在智能城市和环保科技快速发展的背景下&#xff0c;自动化垃圾分类系统正从实验室走向实际应用场景。传统依赖人工分拣或规则匹配的方式效率低、成本高&#xff0c;而基…

ResNet18性能测试:批量处理能力评测

ResNet18性能测试&#xff1a;批量处理能力评测 1. 引言&#xff1a;通用物体识别中的ResNet-18价值定位 在当前AI视觉应用广泛落地的背景下&#xff0c;高效、稳定、可离线运行的图像分类模型成为边缘计算与本地化部署的关键需求。ResNet-18作为深度残差网络&#xff08;Dee…

ResNet18入门指南:零代码实现物体识别WebUI

ResNet18入门指南&#xff1a;零代码实现物体识别WebUI 1. 引言&#xff1a;走进通用图像分类的基石——ResNet18 在计算机视觉领域&#xff0c;图像分类是许多高级任务&#xff08;如目标检测、图像描述生成&#xff09;的基础。而 ResNet18 作为深度残差网络家族中最轻量级…

ResNet18应用实例:零售货架商品识别系统

ResNet18应用实例&#xff1a;零售货架商品识别系统 1. 引言&#xff1a;通用物体识别与ResNet-18的工程价值 在智能零售、自动化巡检和视觉监控等场景中&#xff0c;快速、稳定、低成本的通用物体识别能力是实现智能化升级的关键基础。传统方案依赖云API调用或复杂部署流程&…

ResNet18代码实例:Python调用图像分类API详细教程

ResNet18代码实例&#xff1a;Python调用图像分类API详细教程 1. 引言 1.1 通用物体识别的现实需求 在智能安防、内容审核、自动驾驶和智能家居等场景中&#xff0c;快速准确地识别图像中的物体是AI系统的基础能力。尽管当前已有大量深度学习模型可供选择&#xff0c;但许多…

ResNet18性能优化:CPU推理速度提升5倍的详细步骤

ResNet18性能优化&#xff1a;CPU推理速度提升5倍的详细步骤 1. 背景与挑战&#xff1a;通用物体识别中的效率瓶颈 在边缘计算和本地化部署场景中&#xff0c;深度学习模型的推理效率直接决定了用户体验和系统可用性。尽管ResNet-18作为轻量级图像分类模型被广泛使用&#xf…

无源蜂鸣器驱动电路工作原理深度剖析

无源蜂鸣器驱动电路&#xff1a;从原理到实战的完整指南你有没有遇到过这样的场景&#xff1f;系统报警了&#xff0c;蜂鸣器却“哑火”&#xff1b;或者声音忽大忽小、频率不准&#xff0c;甚至烧掉了三极管&#xff1f;别急——问题很可能出在那个看似简单的无源蜂鸣器驱动电…

超详细版:并行计算加速科学仿真的实战案例

并行计算如何让科学仿真快如闪电&#xff1f;一个热传导仿真的实战拆解你有没有过这样的经历&#xff1a;跑一次仿真&#xff0c;等了整整一晚上&#xff0c;结果早上一看——收敛失败&#xff0c;还得重来&#xff1f;在科研和工程领域&#xff0c;这种“算力焦虑”太常见了。…

ResNet18物体识别详解:模型部署常见问题

ResNet18物体识别详解&#xff1a;模型部署常见问题 1. 引言&#xff1a;通用物体识别中的ResNet-18价值 在当前AI应用快速落地的背景下&#xff0c;通用图像分类已成为智能监控、内容审核、辅助诊断等多个领域的基础能力。其中&#xff0c;ResNet-18作为深度残差网络&#x…

ResNet18优化教程:早停策略应用

ResNet18优化教程&#xff1a;早停策略应用 1. 引言&#xff1a;通用物体识别中的ResNet-18 在现代计算机视觉任务中&#xff0c;通用物体识别是基础且关键的一环。无论是智能相册分类、自动驾驶环境感知&#xff0c;还是内容审核系统&#xff0c;都需要一个稳定、高效、准确…

ResNet18实战:智能家居物品识别系统

ResNet18实战&#xff1a;智能家居物品识别系统 1. 引言&#xff1a;通用物体识别与ResNet-18的工程价值 在智能家居场景中&#xff0c;设备对环境的理解能力正从“被动响应”向“主动感知”演进。其中&#xff0c;通用物体识别作为视觉感知的核心技术&#xff0c;能够帮助系…

ResNet18实战教程:工业机器人视觉系统搭建

ResNet18实战教程&#xff1a;工业机器人视觉系统搭建 1. 教程目标与背景 在智能制造和自动化产线中&#xff0c;工业机器人的环境感知能力正从“机械执行”向“智能决策”演进。其中&#xff0c;视觉识别是实现抓取、分拣、质检等任务的核心前提。然而&#xff0c;许多企业面…

ResNet18性能对比:与ResNet50差异分析

ResNet18性能对比&#xff1a;与ResNet50差异分析 1. 引言&#xff1a;为何关注ResNet18与ResNet50的性能差异&#xff1f; 在深度学习图像分类任务中&#xff0c;ResNet&#xff08;残差网络&#xff09; 自2015年提出以来&#xff0c;已成为计算机视觉领域的基石模型之一。…

工业高温环境下蜂鸣器驱动电路稳定性研究

高温工况下蜂鸣器为何“哑火”&#xff1f;一文讲透工业级驱动电路的稳定性设计你有没有遇到过这样的情况&#xff1a;设备在实验室测试时报警响得震天响&#xff0c;可一放到变频柜、配电箱或者户外机柜里&#xff0c;高温运行几小时后&#xff0c;蜂鸣器声音越来越小&#xf…

嵌入式Linux中ioctl接口的完整指南

嵌入式Linux中ioctl接口的实战解析&#xff1a;从入门到避坑 你有没有遇到过这样的场景&#xff1f;想通过程序设置串口波特率&#xff0c;却发现 write() 函数无能为力&#xff1b;或者要读取一个传感器的状态寄存器&#xff0c;但 read() 只能返回原始数据流。这时候&…

ResNet18应用开发:零售客流量分析系统

ResNet18应用开发&#xff1a;零售客流量分析系统 1. 引言&#xff1a;通用物体识别与ResNet-18的工程价值 在智能零售、安防监控和商业数据分析场景中&#xff0c;精准感知环境中的物体与人群行为是实现自动化决策的基础。传统方法依赖人工标注或规则引擎&#xff0c;成本高…