AI技术实战:从零搭建图像分类系统全流程详解

AI技术实战:从零搭建图像分类系统全流程详解


在这里插入图片描述

人工智能学习 https://www.captainbed.cn/ccc

前言

本文将以图像分类任务为切入点,手把手教你完成AI模型从数据准备到工业部署的全链路开发。通过一个完整的Kaggle猫狗分类项目(代码兼容PyTorch/TensorFlow),覆盖以下核心技能:

  • 数据清洗与增强的工程化实现
  • 模型构建与训练技巧
  • 模型压缩与TensorRT部署优化
  • 可视化监控与性能调优

所有代码均提供可运行的Colab链接,建议边阅读边实践。


目录

  1. 环境搭建与数据准备

    • 1.1 本地/云端开发环境配置
    • 1.2 数据爬取与清洗脚本开发
    • 1.3 自动化标注工具实战
  2. 图像分类模型实战

    • 2.1 手写CNN模型构建(带可运行代码)
    • 2.2 迁移学习Fine-tuning技巧
    • 2.3 训练过程可视化监控
  3. 模型优化与部署

    • 3.1 模型剪枝与量化压缩
    • 3.2 ONNX格式转换与TensorRT加速
    • 3.3 RESTful API服务封装
  4. 工业级增强技巧

    • 4.1 解决类别不平衡问题
    • 4.2 应对小样本学习的策略
    • 4.3 模型热更新方案

1. 环境搭建与数据准备

1.1 开发环境配置(PyTorch示例)

# 创建虚拟环境
conda create -n ai_tutorial python=3.8
conda activate ai_tutorial# 安装核心依赖
pip install torch==1.12.1+cu113 torchvision==0.13.1+cu113 --extra-index-url https://download.pytorch.org/whl/cu113
pip install opencv-python albumentations pandas

1.2 数据爬取实战

# 使用Bing图片下载API批量获取数据
import requestsdef download_images(keyword, count=100):headers = {'Ocp-Apim-Subscription-Key': 'YOUR_API_KEY'}params = {'q': keyword, 'count': count}response = requests.get('https://api.bing.microsoft.com/v7.0/images/search', headers=headers, params=params)for idx, img in enumerate(response.json()['value']):img_data = requests.get(img['contentUrl']).contentwith open(f'dataset/{keyword}_{idx}.jpg', 'wb') as f:f.write(img_data)# 执行下载
download_images('cat')
download_images('dog')

1.3 自动化数据清洗

# 使用OpenCV过滤损坏图片
import cv2
import osdef clean_dataset(folder):valid_extensions = ['.jpg', '.jpeg', '.png']for filename in os.listdir(folder):filepath = os.path.join(folder, filename)try:img = cv2.imread(filepath)if img is None or img.size == 0:os.remove(filepath)elif os.path.splitext(filename)[1].lower() not in valid_extensions:os.remove(filepath)except Exception as e:print(f"删除损坏文件: {filename}")os.remove(filepath)clean_dataset('dataset/train')

2. 图像分类模型实战

2.1 自定义CNN模型(PyTorch实现)

import torch.nn as nnclass SimpleCNN(nn.Module):def __init__(self, num_classes=2):super().__init__()self.features = nn.Sequential(nn.Conv2d(3, 32, kernel_size=3, padding=1), # 输入3通道nn.ReLU(),nn.MaxPool2d(2),nn.Conv2d(32, 64, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2),nn.Conv2d(64, 128, kernel_size=3, padding=1),nn.ReLU(),nn.MaxPool2d(2))self.classifier = nn.Sequential(nn.Linear(128 * 28 * 28, 512), # 根据输入尺寸调整nn.ReLU(),nn.Dropout(0.5),nn.Linear(512, num_classes))def forward(self, x):x = self.features(x)x = x.view(x.size(0), -1)return self.classifier(x)

2.2 迁移学习实战(ResNet50微调)

from torchvision import models# 加载预训练模型
model = models.resnet50(pretrained=True)# 替换最后一层全连接
num_ftrs = model.fc.in_features
model.fc = nn.Sequential(nn.Linear(num_ftrs, 256),nn.ReLU(),nn.Dropout(0.4),nn.Linear(256, 2)
)# 冻结早期层参数
for param in model.parameters():param.requires_grad = False
for param in model.layer4.parameters():param.requires_grad = True

2.3 训练过程可视化(TensorBoard集成)

from torch.utils.tensorboard import SummaryWriterwriter = SummaryWriter()for epoch in range(epochs):# 训练代码...writer.add_scalar('Loss/train', loss.item(), epoch)writer.add_scalar('Accuracy/train', acc, epoch)# 可视化特征图if epoch % 10 == 0:writer.add_images('Feature Maps', model.features[0](images[:4]), epoch)

3. 模型优化与部署

3.1 模型剪枝实战

import torch.nn.utils.prune as prune# 对卷积层进行L1非结构化剪枝
parameters_to_prune = ((model.features[0], 'weight'),(model.features[3], 'weight'),
)prune.global_unstructured(parameters_to_prune,pruning_method=prune.L1Unstructured,amount=0.2, # 剪枝20%的权重
)

3.2 TensorRT加速部署

# 导出ONNX模型
torch.onnx.export(model, dummy_input, "model.onnx",opset_version=11)# 使用TensorRT转换
trt_cmd = f"""
trtexec --onnx=model.onnx \--saveEngine=model.trt \--fp16 \--workspace=2048
"""
os.system(trt_cmd)

3.3 封装Flask API服务

from flask import Flask, request
import trt_inference  # 自定义TRT推理模块app = Flask(__name__)@app.route('/predict', methods=['POST'])
def predict():file = request.files['image']img = preprocess(file.read())output = trt_inference.run(img)return {'class_id': int(output.argmax())}if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

4. 工业级增强技巧

4.1 类别不平衡解决方案

# 使用加权采样器
from torch.utils.data import WeightedRandomSamplerclass_counts = [num_cat, num_dog] 
weights = 1. / torch.tensor(class_counts, dtype=torch.float)
samples_weights = weights[labels]sampler = WeightedRandomSampler(weights=samples_weights,num_samples=len(samples_weights),replacement=True
)

4.2 小样本学习方案

# 使用MixUp数据增强
def mixup_data(x, y, alpha=0.2):lam = np.random.beta(alpha, alpha)batch_size = x.size()[0]index = torch.randperm(batch_size)mixed_x = lam * x + (1 - lam) * x[index]y_a, y_b = y, y[index]return mixed_x, y_a, y_b, lam# 修改损失函数
criterion = nn.CrossEntropyLoss()
loss = lam * criterion(output, y_a) + (1 - lam) * criterion(output, y_b)

在这里插入图片描述

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

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

相关文章

NIPS2024论文 End-to-End Ontology Learning with Large Language Models

文章所谓的端到端本体学习,指的是从输入到目标本体这个完整过程。在很多其他文章中,是把本体学习这个任务肢解了来做的,同样也是肢解了之后评估。 文章号称的贡献,不但对通用本体学习提供所谓的baseline,而且还给出了验…

【NLP】18. Encoder 和 Decoder

1. Encoder 和 Decoder 概述 在序列到序列(sequence-to-sequence,简称 seq2seq)的模型中,整个系统通常分为两大部分:Encoder(编码器)和 Decoder(解码器)。 Encoder&…

Deepseek Bart模型相比Bert的优势

BART(Bidirectional and Auto-Regressive Transformers)与BERT(Bidirectional Encoder Representations from Transformers)虽然均基于Transformer架构,但在模型设计、任务适配性和应用场景上存在显著差异。以下是BART…

在人工智能与计算机技术融合的框架下探索高中教育数字化教学模式的创新路径

一、引言 1.1 研究背景 在数字中国战略与《中国教育现代化 2035》的政策导向下,人工智能与计算机技术的深度融合正深刻地重构着教育生态。随着科技的飞速发展,全球范围内的高中教育都面临着培养具备数字化素养人才的紧迫需求,传统的教学模式…

深度探索 C 语言:指针与内存管理的精妙艺术

C 语言作为一门历史悠久且功能强大的编程语言,以其高效的性能和灵活的底层控制能力,在计算机科学领域占据着举足轻重的地位。 指针和内存管理是 C 语言的核心特性,也是其最具挑战性和魅力的部分。深入理解指针与内存管理,不仅能够…

QQ邮箱授权码如何获取 QQ邮箱授权码获取方法介绍

QQ邮箱授权码如何获取 QQ邮箱授权码获取方法介绍 https://app.ali213.net/gl/857287.html

jupyter4.4安装使用

一、chrome谷歌浏览器 1. 安装 1.1 下载地址: 下载地址: https://www.google.cn/intl/zh-CN_ALL/chrome/fallback/ 2 插件markdown-viewer 2.1 下载地址: 下载地址:https://github.com/simov/markdown-viewer/releases 2.2…

STM32 HAL库RTC实时时钟超细详解

一、引言 在嵌入式系统的应用中,实时时钟(RTC)是一个非常重要的功能模块。它能够独立于主系统提供精确的时间和日期信息,即使在系统断电的情况下,也可以依靠备用电池继续运行。STM32F407 是一款性能强大的微控制器&am…

vdso概念及原理,vdso_fault缺页异常,vdso符号的获取

一、背景 vdso的全称是Virtual Dynamic Shared Object,它是一个特殊的共享库,是在编译内核时生成,并在内核镜像里某一段地址段作为该共享库的内容。vdso的前身是vsyscall,为了兼容一些旧的程序,x86上还是默认加载了vs…

Linux中的文件传输(附加详细实验案例)

一、实验环境的设置 ①该实验需要两台主机,虚拟机名称为 L2 和 L3 ,在终端分别更改主机名为 node1 和 node2,在实验过程能够更好分辨。 然后再重新打开终端,主机名便都更改了相应的名称。 ②用 ip a 的命令分别查看两个主机的 …

【从0到1学Elasticsearch】Elasticsearch从入门到精通(上)

黑马商城作为一个电商项目,商品的搜索肯定是访问频率最高的页面之一。目前搜索功能是基于数据库的模糊搜索来实现的,存在很多问题。 首先,查询效率较低。 由于数据库模糊查询不走索引,在数据量较大的时候,查询性能很差…

图论基础理论

在我看来,想要掌握图的基础应用,仅需要三步走。 什么是图(基本概念)、图的构造(打地基)、图的遍历方式(应用的基础) 只要能OK的掌握这三步、就算图论入门了!&#xff0…

详细解读react框架中的hooks

React Hooks 是 React 16.8 引入的一项革命性特性,它允许你在函数组件中使用状态(state)和其他 React 特性,而无需编写 class 组件。下面将详细解读 React Hooks 的核心概念、常用 Hooks 及其工作原理。 一、Hooks 的核心概念 1. 什么是 Hooks Hooks …

主机IP动态变化时如何通过固定host.docker.internal访问本机服务

场景需求——主机IP动态变化时,通过固定的 http://host.docker.internal:11555 访问本机服务,核心问题在于 host.docker.internal 的解析逻辑与动态IP的适配。以下是分步解决方案: 一、核心原理:host.docker.internal 的本质与局…

插值算法 - 最近邻插值实现

目录 1. 导入必要的库 2. nearest_neighbor_interpolation 3. 测试代码 数学原理 完整代码 本文实现了基于最近邻插值算法的图像缩放功能。 它使用 Python 编写,主要依赖于NumPy和PIL(Python Imaging Library)库。 NumPy用于高效的数值计算,而PIL仅用于图像的加载和…

windows中搭建Ubuntu子系统

windows中搭建虚拟环境 1.配置2.windows中搭建Ubuntu子系统2.1windows配置2.1.1 确认启用私有化2.1.2 将wsl2设置为默认版本2.1.3 确认开启相关配置2.1.4重启windows以加载更改配置 2.2 搭建Ubuntu子系统2.2.1 下载Ubuntu2.2.2 迁移位置 3.Ubuntu子系统搭建docker环境3.1安装do…

MySQL事务机制

目录 原子性 持久性 隔离性 隔离级别(并发事务之间的关系) 读未提交 读已提交 可重复读 串行化(最严格的隔离级别) 一致性 问题 不可重复读性(已经提交的数据) 什么是脏读问题(未提交的数据)? 幻读 保存点 自动提交机制--autocommit 会话隔离级别与全局隔离级…

Cadence学习笔记之---直插元件的封装制作

目录 01 | 引 言 02 | 环境描述 03 | 操作步骤 04 | 结 语 01 | 引 言 在之前发布的Cadence小记中,已经讲述了怎样制作热风焊盘,贴片(SMD)焊盘、通孔、过孔,以及贴片元件的封装。 本篇关于Cadence的小记主要讲如何制作直插元件的封装。 …

【第四十周】文献阅读:用于检索-增强大语言模型的查询与重写

目录 摘要Abstract用于检索-增强大语言模型的查询与重写研究背景方法论基于冻结LLM的重写方案基于可训练重写器的方案重写器预热训练(Rewriter Warm-up)强化学习(Reinforcement Learning) 创新性实验结果局限性总结 摘要 这篇论文…

java学习总结(if switch for)

一.基本结构 1.单分支if int num 10; if (num > 5) {System.out.println("num 大于 5"); } 2.双分支if-else int score 60; if (score > 60) {System.out.println("及格"); } else {System.out.println("不及格"); } 3.多分支 int…