尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

迁移学习在计算机视觉中的工程实践:从预训练模型到API部署

迁移学习在计算机视觉中的工程实践:从预训练模型到API部署 迁移学习这几年在计算机视觉里的地位基本等同于“省力杠杆”——同样一个图像分类任务从零训练 ResNet 可能要好几天才能收敛加载 ImageNet 预训练权重之后往往几个 epoch 就能达到可用效果。这篇文章不聊概念堆砌直接讲清楚迁移学习在视觉任务里的落地方案怎么选预训练模型、怎么改分类头、怎么冻结特征层、怎么在少量数据集上做微调以及最终如何把训练好的模型封装成 API 接口和批量推理流程。如果你想做图像分类、目标检测或者特征提取又不想从零开始烧算力这篇文章可以直接收藏。迁移学习最核心的价值有三点第一预训练模型已经学到了通用的边缘、纹理、形状等底层特征这些特征在不同视觉任务之间是可复用的第二微调阶段的训练时间通常是从零训练的十分之一甚至更短对硬件要求也更友好第三即使只有几百张甚至几十张标注图片也能训练出可用的视觉模型。本文会用 PyTorch 和 Torchvision 作为主技术栈走一遍从加载预训练权重到模型微调、效果验证、服务部署的完整流程。文章里涉及的具体操作包括环境准备与依赖安装、预训练模型加载与结构查看、分类头替换、特征层冻结、全参数微调、数据增强策略、损失函数与优化器配置、模型保存与推理测试、FastAPI 封装接口、批量推理脚本编写以及资源占用观察和常见问题排查。整套流程跑通之后你手里就有一套可以横向迁移到其他视觉任务的工程模板。1. 核心能力速览迁移学习在计算机视觉中的应用本质上是一套方法论加工程组合不是某个单一的开源工具。为了让读者快速判断自己是否需要用迁移学习下面把它拆成能力维度来看能力项说明核心作用利用预训练模型权重加速视觉任务训练降低数据量和算力要求适用任务图像分类、目标检测、图像分割、特征提取、相似度检索、OCR 预处理常用预训练模型ResNet、VGG、EfficientNet、MobileNet、ViT、ConvNeXt 等主流微调方式冻结特征层只训练分类头、全参数微调、线性探测、渐进解冻显存需求根据模型和 batch size 变化通常 4G 到 24G 不等硬件要求支持 CPU 推理和训练但 GPU 能显著提升效率开发框架PyTorch、Torchvision、TensorFlow、Keras数据要求最少每类几十张图片即可启动微调效果随数据量递增接口能力训练完成后可导出为 ONNX、TorchScript或用 FastAPI 封装批量任务支持文件夹级批量推理、批量特征提取、批量预测结果导出适合场景小样本分类、工业质检、医学影像辅助分析、安防识别、风格迁移这套能力组合决定了迁移学习在视觉项目里几乎是“默认起手式”。无论是做算法验证还是上线部署直接拿预训练权重做初始化都能省掉大量无效训练时间。2. 适用场景与使用边界迁移学习不是万能药它在很多场景下表现优秀但也有明确的适用边界。搞清楚这些边界能避免在错误的方向上浪费时间。2.1 适合什么场景标注数据有限。工业场景里有缺陷的样本往往很少有些类别的图片可能只有几十张。这种情况下从零训练容易过拟合迁移学习可以借用预训练模型已经学到的通用视觉特征在小数据上依然得到可接受的效果。任务与 ImageNet 或其他大型数据集分布接近。通用图像分类、物体识别、场景理解等任务底层特征高度相似迁移效果明显。需要快速出原型。算法验证阶段从预训练模型出发微调往往几十分钟内就能看到一个 baseline 效果方便快速评估可行性。算力资源有限。加载预训练权重后用较小的学习率微调通常只需要单张中端 GPU 甚至 CPU 就能完成。2.2 不适合什么场景图像分布与预训练数据差异极大。比如医学 CT 影像、卫星遥感雷达图、工业 X 光图像这类图像跟自然图像在底层特征上差异很大直接复用 ImageNet 权重未必有明显收益甚至可能引入噪声。需要极高精度的专业领域任务。对于病灶分割、特定零部件检测等任务单纯做分类头微调往往不够需要额外的领域预训练或自监督学习。数据集本身足够大。如果每类有上万张图片数据分布又比较独特从零训练或重新预训练的效果可能更好迁移学习的优势会被削弱。2.3 使用边界与合规要求使用预训练模型时需要注意模型的开源协议不同的模型有不同的商用许可限制。涉及人脸、车辆、医疗影像等敏感数据时必须确保数据的来源合法、脱敏合规并对模型输出进行人工复核。模型训练和部署应当限定在授权测试环境和生产环境范围内不能未经授权采集或使用他人图像数据。3. 环境准备与前置条件迁移学习在计算机视觉中的工程实践推荐使用 Python 3.8 及以上版本搭配 PyTorch 2.x 和 Torchvision。GPU 不是硬性要求CPU 也能跑但训练速度和显存占用表现会有差异。3.1 硬件环境参考GPU建议 NVIDIA 显卡显存 4G 以上显存越高可以支持更大的 batch size 和输入分辨率。CPU支持训练和推理但速度会慢很多适合调试和小批量验证。内存16G 以上比较稳妥。磁盘空间预训练模型权重文件加数据集预留 20G 以上空间比较合适。3.2 软件环境清单依赖项推荐版本用途Python3.8 - 3.11开发语言PyTorch2.0 及以上深度学习框架Torchvision0.15 及以上预训练模型和数据集工具CUDA11.8 或 12.1GPU 加速fastapi最新稳定版接口服务封装uvicorn最新稳定版API 服务启动Pillow最新稳定版图像读取处理tensorboard最新稳定版训练过程可视化3.3 环境安装命令# 创建 Python 虚拟环境 python -m venv venv source venv/bin/activate # Windows 下使用 venv\Scripts\activate # 安装 PyTorch GPU 版本请根据实际 CUDA 版本调整命令 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118 # 安装常用依赖 pip install fastapi uvicorn pillow tensorboard安装完成后可以用下面的代码验证 GPU 是否可用import torch print(torch.__version__) print(torch.cuda.is_available()) print(torch.cuda.get_device_name(0) if torch.cuda.is_available() else CPU mode)这里建议在开始训练前先确认 PyTorch 能正常调用 GPU。如果输出cuda.is_available()为False需要检查显卡驱动和 CUDA 版本的匹配关系或者在 CPU 模式下运行。4. 安装部署与模型加载这一部分从代码层面演示迁移学习的核心操作加载预训练模型、替换分类头、冻结特征层。全部代码基于 PyTorch 和 Torchvision。4.1 加载预训练模型Torchvision 提供了很多常用的视觉模型和预训练权重使用weights参数可以直接下载并加载。下面以 ResNet18 为例import torchvision.models as models # 加载 ResNet18 预训练权重 weights models.ResNet18_Weights.DEFAULT model models.resnet18(weightsweights) # 查看模型结构 print(model)第一次运行时PyTorch 会自动下载权重文件到本机缓存目录。下载完成后后续加载会直接使用缓存不再重复下载。权重文件默认存放在用户目录下的.cache/torch/hub/checkpoints文件夹Windows 下一般在C:\Users\用户名\.cache\torch\hub\checkpoints。除了 ResNet18Torchvision 还支持多种常用模型模型参数量特点适用场景ResNet18/34/5011M - 25M精度和速度平衡通用分类、特征提取MobileNetV34M - 6M轻量级移动端、嵌入式设备EfficientNet-B05M高精度高效率资源受限场景ViT-B/1686MTransformer 架构大规模数据微调ConvNeXt28M - 350M现代 CNN高精度任务Swin Transformer28M - 88M层级注意力检测、分割模型选择的核心原则是先用轻量级模型跑通流程再根据精度需求逐步换更大的模型。不要一上来就用最大模型否则显存和训练时间都会失控。4.2 替换分类头预训练模型默认输出是 1000 类对应 ImageNet 的分类任务。如果我们的任务是二分类或者自定义类别数需要把最后一层全连接层替换掉。import torch.nn as nn import torchvision.models as models weights models.ResNet18_Weights.DEFAULT model models.resnet18(weightsweights) # 获取模型的特征提取层输出维度 num_features model.fc.in_features print(f特征维度: {num_features}) # 替换全连接层输出自定义类别数 num_classes 10 # 这里用 10 分类做示例 model.fc nn.Linear(num_features, num_classes) print(model.fc)替换分类头是整个迁移学习流程中最重要的步骤之一。无论原来的模型结构多复杂只需要修改这一层就能让预训练特征复用到新的分类任务上。4.3 冻结特征层冻结特征层的意思是让预训练提取特征的参数在反向传播时不更新只训练新加的分类头。这种方式适合数据量很少的情况可以显著降低过拟合风险同时减少训练时间。# 先冻结所有层 for param in model.parameters(): param.requires_grad False # 只让分类头参与训练 for param in model.fc.parameters(): param.requires_grad True上面这种方式就是经典的“冻结特征层 训练分类头”在迁移学习中被称为线性探测的一种变体。好处是训练速度快、不容易过拟合缺点是由于底层特征不做适配精度上限可能稍低一些。如果想做全参数微调也就是让所有层都参与训练那么不使用上面的冻结逻辑直接定义优化器时传入所有参数即可。全参数微调适合数据量比较充足的情况效果通常更好。5. 功能测试与效果验证迁移学习最终要落在真实数据集上才能验证效果。这一节用 CIFAR-10 数据集演示完整的微调流程包括数据加载、训练、验证和推理。5.1 准备数据集为了方便演示直接使用 Torchvision 内置的 CIFAR-10 数据集。如果是自定义数据只需要用ImageFolder方式加载目录数据即可。import torch import torchvision import torchvision.transforms as transforms from torch.utils.data import DataLoader # 数据预处理训练集和验证集使用不同的增强策略 transform_train transforms.Compose([ transforms.RandomResizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) transform_val transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) # 加载 CIFAR-10 train_dataset torchvision.datasets.CIFAR10( root./data, trainTrue, downloadTrue, transformtransform_train ) val_dataset torchvision.datasets.CIFAR10( root./data, trainFalse, downloadTrue, transformtransform_val ) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue, num_workers2) val_loader DataLoader(val_dataset, batch_size32, shuffleFalse, num_workers2)这里的核心点在于Normalize层使用的 mean 和 std 是 ImageNet 数据集的统计值。因为预训练模型是在 ImageNet 上训练的数据标准化应该使用相同的统计值否则预训练特征分布会被破坏。5.2 训练分类头下面演示冻结特征层只训练分类头的方式。这种方式在少量数据上非常稳定。import torch.nn as nn import torch.optim as optim import torchvision.models as models from tqdm import tqdm device torch.device(cuda if torch.cuda.is_available() else cpu) # 加载预训练模型 weights models.ResNet18_Weights.DEFAULT model models.resnet18(weightsweights) num_features model.fc.in_features model.fc nn.Linear(num_features, 10) model model.to(device) # 冻结特征层 for param in model.parameters(): param.requires_grad False for param in model.fc.parameters(): param.requires_grad True # 损失函数和优化器 criterion nn.CrossEntropyLoss() optimizer optim.Adam(model.fc.parameters(), lr0.001) # 训练分类头 epochs 5 for epoch in range(epochs): model.train() running_loss 0.0 correct 0 total 0 pbar tqdm(train_loader, descfEpoch {epoch 1}/{epochs}) for images, labels in pbar: images images.to(device) labels labels.to(device) optimizer.zero_grad() outputs model(images) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() pbar.set_postfix(lossloss.item(), acc100.0 * correct / total) epoch_acc 100.0 * correct / total epoch_loss running_loss / len(train_loader) print(fEpoch {epoch 1}: loss{epoch_loss:.4f}, acc{epoch_acc:.2f}%)这段代码直接在训练过程中打印 loss 和 accuracy可以在终端直观看到模型收敛情况。由于只训练分类头参数数量很少训练速度非常快。在 CIFAR-10 上即使只训练 5 个 epoch准确率通常也能达到比较可观的水平。5.3 评估验证集训练完成后需要在验证集上评估模型效果避免过拟合判断出错。# 验证模型 model.eval() correct 0 total 0 with torch.no_grad(): for images, labels in val_loader: images images.to(device) labels labels.to(device) outputs model(images) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() val_acc 100.0 * correct / total print(f验证集准确率: {val_acc:.2f}%)5.4 自定义数据集加载如果使用自己的目录数据集目录结构需要满足下面的格式data/ train/ class1/ 1.jpg 2.jpg class2/ 1.jpg 2.jpg val/ class1/ 1.jpg class2/ 1.jpg对应的加载方式from torchvision.datasets import ImageFolder train_dataset ImageFolder(rootdata/train, transformtransform_train) val_dataset ImageFolder(rootdata/val, transformtransform_val) print(train_dataset.classes) print(train_dataset.class_to_idx)ImageFolder会按照子目录名称自动生成类别标签使用起来非常方便。分类头的输出类别数需要根据len(train_dataset.classes)动态设置。5.5 推理测试训练完成后对单张图片做推理测试的完整代码from PIL import Image import torchvision.transforms as transforms # 图片预处理 def preprocess_image(image_path): transform transforms.Compose([ transforms.Resize(256), 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_path).convert(RGB) return transform(image).unsqueeze(0) # 推理 model.eval() image_tensor preprocess_image(test.jpg).to(device) with torch.no_grad(): outputs model(image_tensor) _, predicted torch.max(outputs, 1) print(f预测类别索引: {predicted.item()})如果想知道具体的类别名称可以用val_dataset.classes[predicted.item()]映射回原始类别名。6. 接口 API 与批量任务模型训练完成之后实际工程中很少直接在训练脚本里做推理更多是把模型封装成接口服务或者批量推理脚本。这一部分演示两种方式FastAPI 封装和批量推理。6.1 FastAPI 封装模型接口封装成 HTTP 接口之后其他系统可以通过请求直接调用模型便于集成到业务系统里。import io import torch import torchvision.models as models from fastapi import FastAPI, UploadFile, File from PIL import Image import torchvision.transforms as transforms app FastAPI() # 定义设备 device torch.device(cuda if torch.cuda.is_available() else cpu) # 加载训练好的模型 model models.resnet18(weightsmodels.ResNet18_Weights.DEFAULT) num_features model.fc.in_features model.fc torch.nn.Linear(num_features, 10) model.load_state_dict(torch.load(resnet18_cifar10.pth)) model model.to(device) model.eval() # 类别名称 classes [airplane, automobile, bird, cat, deer, dog, frog, horse, ship, truck] # 图像预处理 transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) app.post(/predict) async def predict(file: UploadFile File(...)): image Image.open(io.BytesIO(await file.read())).convert(RGB) image_tensor transform(image).unsqueeze(0).to(device) with torch.no_grad(): outputs model(image_tensor) probabilities torch.nn.functional.softmax(outputs[0], dim0) confidence, predicted torch.max(probabilities, 0) return { class_id: predicted.item(), class_name: classes[predicted.item()], confidence: round(confidence.item(), 4) } # 启动: uvicorn main:app --host 0.0.0.0 --port 8000业务系统可以直接用requests调用这个接口import requests url http://127.0.0.1:8000/predict files {file: open(test.jpg, rb)} response requests.post(url, filesfiles, timeout30) print(response.json())返回结果示例{ class_id: 3, class_name: cat, confidence: 0.9234 }接口封装的核心思路很简单加载模型、预处理输入、推理、返回结果。生产环境还需要考虑并发限制、超时设置和日志记录这里给出的是最小可运行版本。6.2 批量推理脚本批量推理是视觉任务中最高频的需求之一。比如给一个文件夹里几千张图片做分类需要写一个脚本自动遍历图片、执行推理、保存结果。import os import csv import torch import torchvision.models as models from PIL import Image import torchvision.transforms as transforms device torch.device(cuda if torch.cuda.is_available() else cpu) # 加载模型 model models.resnet18(weightsmodels.ResNet18_Weights.DEFAULT) num_features model.fc.in_features model.fc torch.nn.Linear(num_features, 10) model.load_state_dict(torch.load(resnet18_cifar10.pth)) model model.to(device) model.eval() transform transforms.Compose([ transforms.Resize(256), transforms.CenterCrop(224), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) def predict_image(model, image_path, device): image Image.open(image_path).convert(RGB) image_tensor transform(image).unsqueeze(0).to(device) with torch.no_grad(): outputs model(image_tensor) _, predicted torch.max(outputs, 1) return predicted.item() # 批量处理 input_dir ./images output_file ./predictions.csv results [] for filename in os.listdir(input_dir): if filename.lower().endswith((.jpg, .jpeg, .png)): image_path os.path.join(input_dir, filename) try: class_id predict_image(model, image_path, device) results.append([filename, class_id]) print(f{filename} - class {class_id}) except Exception as e: print(f处理 {filename} 失败: {e}) # 保存结果 with open(output_file, w, newline) as f: writer csv.writer(f) writer.writerow([filename, class_id]) writer.writerows(results) print(f结果已保存到 {output_file})批量推理的关键在于容错处理。单张图片损坏、格式异常或者网络中断都不应该导致整个批处理任务崩溃。上面代码中加入了try-except结构单张图片失败时记录日志并继续处理下一张。6.3 批量任务设计建议如果图片数量很大比如几万张需要考虑以下优化策略使用 DataLoader 替代单张循环利用batch_size提升吞吐。将推理结果分批写入 CSV 或数据库而不是全部攒在内存里。多进程并行处理不同文件夹或分片。推理前先做图片大小压缩和去重减少无效计算。设置失败重试机制对超时或异常任务重新处理。7. 资源占用与性能观察迁移学习虽然在训练效率上远胜从零训练但依然需要关注资源占用。这一部分给出观察方法和优化思路。7.1 显存占用观察在训练过程中可以用 NVIDIA 提供的命令实时查看显存占用nvidia-smi如果希望更精确地监控 PyTorch 的显存分配情况可以在代码里加入以下逻辑import torch # 查看当前 PyTorch 缓存占用的显存 print(fallocated: {torch.cuda.memory_allocated() / 1024 ** 2:.2f} MB) print(fcached: {torch.cuda.memory_cached() / 1024 ** 2:.2f} MB)显存占用的主要影响因素包括输入图片的分辨率分辨率越高中间特征图占用的显存越大。batch size 越大显存占用线性增长。模型的层数和宽度ResNet50 比 ResNet18 显存占用高很多。是否使用混合精度训练使用 AMP 可以降低显存占用。7.2 CPU 与 GPU 训练差异CPU 可以完成迁移学习的完整流程但速度会慢很多。以 ResNet18 在 CIFAR-10 上训练为例GPU 训练一个 epoch 可能只需要几十秒CPU 可能要好几分钟甚至十几分钟具体取决于 CPU 核心数和内存带宽。如果 CPU 资源有限建议降低输入分辨率、减小 batch size、简化数据增强或者直接使用 MobileNet 这类轻量模型。7.3 降低显存占用的常用方法降低分辨率。从 224 降到 160 或 128显存占用会大幅下降。减小 batch size。一次处理 8 张和一次处理 32 张显存占用差异非常明显。使用混合精度训练。PyTorch 的torch.cuda.amp可以将部分计算转为 FP16显存占用和训练速度都有改善。使用梯度累积。在小 batch size 下模拟较大 batch size 的训练效果。选择更轻量的模型。MobileNetV3 明显比 ResNet50 省显存。7.4 混精度训练示例from torch.cuda.amp import autocast, GradScaler scaler GradScaler() for epoch in range(epochs): model.train() for images, labels in train_loader: images images.to(device) labels labels.to(device) optimizer.zero_grad() with autocast(): outputs model(images) loss criterion(outputs, labels) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()混合精度训练在 NVIDIA 显卡上通常能带来明显加速和显存节省尤其是 Turing 架构及以上的 GPU 效果更明显。8. 常见问题与排查方法迁移学习在视觉任务中踩坑的地方不少下面整理了一份高频率问题清单。问题现象可能原因排查方式解决方案模型加载时报错预训练权重版本与模型结构不匹配检查 torchvision 版本和 weights 参数升级 torchvision 或改用不带 weights 加载后手动加载权重训练时显存溢出batch size 太大或分辨率过高用 nvidia-smi 查看显存占用减小 batch size、降低分辨率、使用梯度累积CPU 训练速度极慢数据加载线程数不足或模型太大查看 CPU 利用率和内存占用增加 num_workers使用轻量模型验证集准确率远低于训练集过拟合对比训练集和验证集准确率增加数据增强、降低模型复杂度、增加 dropout图像分类结果全是某一类类别不均衡或学习率过大打印每个类别的预测分布使用类别权重、降低学习率、检查数据标签模型输出 NaN 丢失学习率过高或数据有异常打印 loss 曲线降低学习率、检查数据标准化、清除异常数据接口服务请求超时推理时间过长或并发过高检查单张推理耗时和并发连接数使用异步推理、增加 batch 推理、横向扩展服务换数据集后模型效果很差新数据分布与预训练数据差异大检查数据标准化和类别分布使用更小的学习率、全参数微调、或做领域预训练冻结层后效果不如预期分类头能力有限检查底层特征是否适配改为全参数微调或渐进解冻预训练权重下载失败网络问题或镜像站不可达检查网络连通性和缓存目录手动下载权重文件放到缓存目录对于多分类任务中类别不均衡的问题可以在损失函数中传入权重class_counts [5000, 500, 50] # 每个类别的样本数量 total_samples sum(class_counts) class_weights [total_samples / count for count in class_counts] class_weights torch.tensor(class_weights, devicedevice) criterion nn.CrossEntropyLoss(weightclass_weights)这种方式会提高小类别样本在损失函数中的权重从而缓解模型偏向大类别的问题。9. 最佳实践与使用建议迁移学习的工程化落地建议从一开始就建立起一套规范的流程避免后期返工。第一第一次跑通流程时使用小数据集、小模型和较小分辨率。比如先拿每类 100 张图片、ResNet18、128 分辨率跑通全流程确认代码没有问题后再扩展到完整数据和更大模型。这样能大幅缩短调试时间也让资源占用保持在可控范围。第二数据目录、模型权重和训练日志要分目录管理。推荐的目录结构如下project/ data/ train/ val/ test/ models/ checkpoints/ logs/ scripts/ train.py predict.py api.py output/ predictions.csv第三批量任务必须加日志和失败重试机制。实际项目中图片文件损坏、格式异常、网络中断等情况经常发生。代码里要有完整的try-except结构和日志记录单张图片失败不能导致整个任务终止。第四接口服务要限制访问范围。如果是内网使用可以绑定内网 IP 启动服务如果需要暴露到公网必须在前面加鉴权层防止接口被滥用。# 只监听本机地址不暴露到外部网络 uvicorn main:app --host 127.0.0.1 --port 8000第五涉及人脸、车辆、医疗影像等数据时必须确保数据来源合法已完成脱敏处理并确认符合相关法规要求。模型输出只能作为辅助判断不能直接替代人的决策。第六每次训练都要保存模型结构和超参数配置。建议使用配置字典或 YAML 文件记录 batch size、学习率、优化器、数据增强方式等信息方便后续复现实验。# config.yaml 示例 model: name: resnet18 pretrained: true num_classes: 10 training: batch_size: 32 epochs: 10 learning_rate: 0.001 freeze_backbone: true mixed_precision: true data: train_dir: data/train val_dir: data/val image_size: 224第七模型发布前要做效果复核。可以准备一份独立的测试集验证模型在未见数据上的表现。如果模型对某些特定场景表现不佳需要针对性地补充数据或者调整模型结构。10. 总结与下一步迁移学习在计算机视觉里的实用价值非常直接用预训练模型省时间、省数据、省算力同时还能得到不错的精度。这篇文章从环境准备、模型加载、分类头替换、特征冻结、全参数微调、自定义数据集训练、API 封装、批量推理、资源占用和问题排查走完了一整套视觉任务的迁移学习流程。最先应该验证的功能是预训练模型加载和分类头替换这两步跑通之后后续的整套流程都能顺畅推进。最容易踩的坑是数据标准化不一致、分类头输出类别数不匹配、显存溢出这三个点遇到问题优先检查这三项。后续可以继续扩展的方向包括引入更强的基础模型如 ConvNeXt 或 ViT、使用更大的输入分辨率、加入数据增强策略如 MixUp 和 CutMix、在目标检测和语义分割任务中复现同样的迁移学习思路以及把模型导出为 ONNX 格式部署到生产环境。迁移学习不仅是一个方法更是一套可以复用的工程模板值得花时间搭好。
返回列表