ResNet-50作为计算机视觉领域的里程碑式模型,其核心创新在于残差学习(Residual Learning)机制。这个152层的深度卷积神经网络通过引入"shortcut connections"(捷径连接)解决了传统深度网络中的梯度消失问题。具体来说,当输入为x时,传统网络直接学习H(x),而ResNet学习的是F(x)=H(x)-x,即残差函数。这种设计让网络能够更高效地训练超深层结构。
模型架构上,ResNet-50包含49个卷积层和1个全连接层,主要分为5个stage:
关键提示:ResNet-50的输入尺寸固定为224x224x3,预处理时需要将图像resize并做归一化(各通道减去[0.485, 0.456, 0.406]后除以[0.229, 0.224, 0.225])
推荐使用Python 3.8+和PyTorch 1.7+环境,安装核心依赖:
bash复制pip install torch torchvision pillow numpy
对于GPU加速,需额外安装CUDA 11.x和对应版本的cuDNN。验证GPU是否可用:
python复制import torch
print(torch.cuda.is_available()) # 应输出True
PyTorch提供三种预训练模型加载方案:
| 加载方式 | 代码示例 | 适用场景 |
|---|---|---|
| 官方预训练 | torchvision.models.resnet50(pretrained=True) |
快速验证 |
| 部分加载 | 移除最后一层后加载参数 | 迁移学习 |
| 完全自定义 | 手动构建网络结构 | 特殊改造 |
实测发现,直接加载官方预训练模型时:
python复制from torchvision import transforms
preprocess = transforms.Compose([
transforms.Resize(256), # 等比缩放短边至256
transforms.CenterCrop(224), # 中心裁剪
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)
])
python复制transforms.Pad(
padding=(0, (max_size - h)//2),
fill=0,
padding_mode='constant'
)
python复制transforms.RandomHorizontalFlip(p=0.5),
transforms.ColorJitter(
brightness=0.2,
contrast=0.2,
saturation=0.2
)
python复制import torch
from PIL import Image
def predict(image_path):
img = Image.open(image_path).convert('RGB')
input_tensor = preprocess(img).unsqueeze(0)
with torch.no_grad():
output = model(input_tensor)
probabilities = torch.nn.functional.softmax(output[0], dim=0)
return probabilities
python复制batch = torch.stack([preprocess(img) for img in images])
outputs = model(batch)
python复制model.half() # 转换权重为FP16
input_tensor = input_tensor.half()
python复制torch.onnx.export(
model,
dummy_input,
"resnet50.onnx",
opset_version=11
)
python复制import torch.nn as nn
model.fc = nn.Linear(2048, num_classes) # num_classes为自定义类别数
python复制optimizer = torch.optim.SGD([
{'params': model.conv1.parameters(), 'lr': 0.001},
{'params': model.layer1.parameters(), 'lr': 0.01},
{'params': model.fc.parameters(), 'lr': 0.1}
], momentum=0.9)
提取倒数第二层2048维特征:
python复制features = torch.nn.Sequential(
*list(model.children())[:-1]
)(input_tensor).squeeze()
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
| 输出全零 | 未调用model.eval() | 推理前设置评估模式 |
| CUDA内存不足 | 批处理尺寸过大 | 减小batch_size或使用梯度累积 |
| 准确率异常低 | 预处理不一致 | 检查归一化参数是否匹配训练时 |
python复制from torchvision.models.feature_extraction import create_feature_extractor
extractor = create_feature_extractor(
model,
return_nodes=['layer3.5.conv3']
)
features = extractor(input_tensor)
python复制for name, param in model.named_parameters():
if param.grad is None:
print(f"No gradient for {name}")
使用FastAPI创建推理服务:
python复制from fastapi import FastAPI, File
import io
app = FastAPI()
@app.post("/predict")
async def predict_api(file: bytes = File(...)):
img = Image.open(io.BytesIO(file))
# ...预处理和推理代码
return {"class_id": int(top_class)}
bash复制trtexec --onnx=resnet50.onnx \
--saveEngine=resnet50.engine \
--fp16
python复制model = torch.quantization.quantize_dynamic(
model,
{torch.nn.Linear},
dtype=torch.qint8
)
在实际部署中发现,使用TensorRT优化后: