单目标检测模型的构建、训练与评估
立即解锁
发布时间: 2025-09-06 00:55:55 阅读量: 13 订阅数: 12 AIGC 


PyTorch计算机视觉实战
# 单目标检测模型的构建、训练与评估
## 1. 模型创建
### 1.1 模型概述
我们要为单目标检测问题构建一个模型,具体是预测眼部图像中中央凹中心的 x 和 y 坐标。该模型由多个卷积层和池化层组成,会接收调整大小后的 RGB 图像,并输出对应中央凹坐标的两个线性输出。若要预测边界框的宽度和高度,可将输出数量增加到四个。此模型还运用了 ResNet 论文中介绍的跳跃连接技术。
### 1.2 模型实现步骤
#### 1.2.1 加载所需包
```python
import torch.nn as nn
import torch.nn.functional as F
```
#### 1.2.2 定义模型类
```python
class Net(nn.Module):
def __init__(self, params):
super(Net, self).__init__()
def forward(self, x):
return x
```
#### 1.2.3 定义 `__init__` 函数
```python
def __init__(self, params):
super(Net, self).__init__()
C_in,H_in,W_in=params["input_shape"]
init_f=params["initial_filters"]
num_outputs=params["num_outputs"]
self.conv1 = nn.Conv2d(C_in, init_f,
kernel_size=3,stride=2,padding=1)
self.conv2 = nn.Conv2d(init_f+C_in, 2*init_f,
kernel_size=3,stride=1,padding=1)
self.conv3 = nn.Conv2d(3*init_f+C_in, 4*init_f,
kernel_size=3,padding=1)
self.conv4 = nn.Conv2d(7*init_f+C_in, 8*init_f,
kernel_size=3,padding=1)
self.conv5 = nn.Conv2d(15*init_f+C_in, 16*init_f,
kernel_size=3,padding=1)
self.fc1 = nn.Linear(16*init_f, num_outputs)
```
#### 1.2.4 定义 `forward` 函数
```python
def forward(self, x):
identity=F.avg_pool2d(x,4,4)
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, 2, 2)
x = torch.cat((x, identity), dim=1)
identity=F.avg_pool2d(x,2,2)
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2, 2)
x = torch.cat((x, identity), dim=1)
identity=F.avg_pool2d(x,2,2)
x = F.relu(self.conv3(x))
x = F.max_pool2d(x, 2, 2)
x = torch.cat((x, identity), dim=1)
identity=F.avg_pool2d(x,2,2)
x = F.relu(self.conv4(x))
x = F.max_pool2d(x, 2, 2)
x = torch.cat((x, identity), dim=1)
x = F.relu(self.conv5(x))
x=F.adaptive_avg_pool2d(x,1)
x = x.reshape(x.size(0), -1)
x = self.fc1(x)
return x
```
#### 1.2.5 重写 `Net` 类函数
```python
Net.__init__=__init__
Net.forward=forward
```
#### 1.2.6 定义 `Net` 类对象
```python
params_model={
"input_shape": (3,256,256),
"initial_filters": 16,
"num_outputs": 2,
}
model = Net(params_model)
```
#### 1.2.7 移动模型到 CUDA 设备
```python
if torch.cuda.is_available():
device = torch.device("cuda")
model=model.to(device)
```
#### 1.2.8 打印模型
```python
print(model)
```
输出结果如下:
```
Net(
(conv1): Conv2d(3, 16, kernel_size=(3, 3), stride=(2, 2),
padding=(1, 1))
(conv2): Conv2d(19, 32, kernel_size=(3, 3), stride=(1, 1),
padding=(1, 1))
(conv3): Conv2d(51, 64, kernel_size=(3, 3), stride=(1, 1),
padding=(1, 1))
(conv4): Conv2d(115, 128, kernel_size=(3, 3), stride=(1, 1),
padding=(1, 1))
(conv5): Conv2d(243, 256, kernel_size=(3, 3), stride=(1, 1),
padding=(1, 1))
(fc1): Linear(in_features=256, out_features=2, bias=True)
)
```
### 1.3 模型工作原理
- **`__init__` 函数**:定义了模型的构建块,包含五个 `nn.Conv2d` 块。设置 `padding=1` 可对输入两侧进行零填充,使输出尺寸能被 2 整除,这在构建跳跃连接网络时很重要。同时,每个 `nn.Conv2d` 层的输入通道数是前一层输出通道数与跳跃层输出通道数之和。
- **`forward` 函数**:描述了各层之间的连接方式。通过 `avg_pool2d` 获取与经过 `nn.Conv2d` 和 `F.max_pool2d` 后的 `x` 大小相同的 `identity`,再使用 `torch.cat` 沿 `dim=1` 维度将 `x` 与 `identity` 拼接。该函数中有四个跳跃连接块,最后一个卷积神经网络块是普通的 `nn.Conv2d` 层,其输出被称为提取的特征。接着使用 `adaptive_avg_pool2d` 层对提取的特征进行自适应平均池化,得到大小为 1*1 的输出。最后将特征重塑并传递给线性层,由于是预测坐标值,最终层无需激活函数。
## 2. 定义损失函数、优化器和 IOU 指标
### 2.1 损失函数
检测任务常用的损失函数有均方误差(MSE)和平滑 L1 损失。平滑 L1 损失在元素级绝对误差小于 1 时使用平方项,否则使用 L1 项,它对异常值的敏感度低于 MSE,在某些情况下可防止梯度爆炸。我们选用平滑 L1 损失。
```python
loss_func = nn.SmoothL1Loss(reduction="sum")
```
### 2.2 测试损失函数
```python
n,c=8,2
y = 0.5 * torch.ones(n, c, requires_grad=True)
print(y.shape)
target = torch.zeros(n, c, requires_grad=False)
print(target.shape)
loss = loss_func(y, target)
print(loss.item())
y = 2 * torch.ones(n, c, requires_grad=True)
target = torch.zeros(n, c, requires_grad=False)
loss = loss_func(y, target)
print(loss.item())
```
输出结果:
```
torch.Size([8, 2])
torch.Size([8, 2])
2.0
24.0
```
### 2.3 定义优化器
```python
from torch import optim
opt = optim.Adam(model.parameters(), lr=3e-4)
```
### 2.4 定义读取学习率的辅助函数
```python
def get_lr(opt):
for param_group in opt.param_groups:
return param_group['lr']
current_lr=get_lr(opt)
print('current lr={}'.format(current_lr))
```
输出学习率:
```
current lr=0.0003
```
### 2.5 定
0
0
复制全文
相关推荐










