differentiable spatial to numerical (DSNT)介绍与使用

本文详细介绍DSNT网络用于坐标点回归的任务,包括模型构建、训练及预测过程,通过小浣熊眼睛定位实例展示了DSNT在关键点检测上的应用。

论文地址:https://arxiv.org/abs/1801.07372
开源地址:https://github.com/anibali/dsntnn

DSNT主要为了解决

DSNT usage guide

下面通过一个坐标点回归任务来学习dsnt的使用

下面首先创建一个简单的FCN模型,

import torch 
torch.manual_seed(12345)
from torch import nn
import dsntnn

class FCN(nn.Module):
    def __init__(self):
        super().__init__()

        self.layers = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
        )

    def forward(self, x):
        return self.layers(x)

DSNT层可以很方便的扩展到任何的FCN网络后面,来处理坐标点回归任务,下面就是一个例子

class CoordRegressionNetwork(nn.Module):
    def __init__(self, n_locations):
        super().__init__()
        self.fcn = FCN()
        self.hm_conv = nn.Conv2d(16, n_locations, kernel_size=1, bias=False)

    def forward(self, images):
        # 1. Run the images through our FCN
        fcn_out = self.fcn(images)
        # 2. Use a 1x1 conv to get one unnormalized heatmap per location
        unnormalized_heatmaps = self.hm_conv(fcn_out)
        # 3. Normalize the heatmaps
        heatmaps = dsntnn.flat_softmax(unnormalized_heatmaps)
        # 4. Calculate the coordinates
        coords = dsntnn.dsnt(heatmaps)

        return coords, heatmaps

训练模型

为了训练模型下面创建了一个小浣熊单只眼睛的图像

from torch import optim
import matplotlib.pyplot as plt
import scipy.misc as sm

image_size = [40, 40]
raccoon_face = sm.imresize(scipy.misc.face()[200:400, 600:800, :], image_size)  # (40, 40, 3)
eye_x, eye_y = 24, 26

plt.imshow(raccoon_face)
plt.scatter([eye_x], [eye_y], color='red', marker='X')
plt.show()

由于DSNT输出的坐标范围是(-1, 1),所以需要将target的坐标也归一化到这个范围

raccoon_face_tensor = torch.from_numpy(raccoon_face).permute(2, 0, 1).float()  # torch.Size([3, 40, 40])
input_tensor = raccoon_face_tensor.div(255).unsqueeze(0)  # torch.Size([1, 3, 40, 40])
input_var = input_tensor.cuda()

eye_coords_tensor = torch.Tensor([[[eye_x, eye_y]]])  # shape = [1, 1, 2],value=[[[24., 26.]]]
target_tensor = (eye_coords_tensor * 2 + 1) / torch.Tensor(image_size) - 1  # shape = [1, 1, 2],value=[[[0.2250, 0.3250]]]
target_var = target_tensor.cuda()

print('Target: {:0.4f}, {:0.4f}'.format(*list(target_tensor.squeeze())))

现在我们训练模型,让模型在小浣熊的眼睛点出过拟合,全部的代码如下

 

import scipy
import scipy.misc as sm
import matplotlib.pyplot as plt
import torch
torch.manual_seed(12345)
from torch import nn
import dsntnn
import torch.optim as optim

class FCN(nn.Module):
    def __init__(self):
        super().__init__()

        self.layers = nn.Sequential(
            nn.Conv2d(3, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
            nn.ReLU(),
            nn.BatchNorm2d(16),
            nn.Conv2d(16, 16, kernel_size=3, padding=1),
        )

    def forward(self, x):
        return self.layers(x)
class CoordRegressionNetwork(nn.Module):
    def __init__(self, n_locations):
        super().__init__()
        self.fcn = FCN()
        self.hm_conv = nn.Conv2d(16, n_locations, kernel_size=1, bias=False)

    def forward(self, images):
        # 1. Run the images through our FCN
        fcn_out = self.fcn(images)
        # 2. Use a 1x1 conv to get one unnormalized heatmap per location
        unnormalized_heatmaps = self.hm_conv(fcn_out)
        # 3. Normalize the heatmaps
        heatmaps = dsntnn.flat_softmax(unnormalized_heatmaps)
        # 4. Calculate the coordinates
        coords = dsntnn.dsnt(heatmaps)

        return coords, heatmaps

image_size = [40, 40]
raccoon_face = sm.imresize(scipy.misc.face()[200:400, 600:800, :], image_size)      # (40, 40, 3)
eye_x, eye_y = 24, 26

plt.imshow(raccoon_face)
plt.scatter([eye_x], [eye_y], color='red', marker='X')
plt.show()
raccoon_face_tensor = torch.from_numpy(raccoon_face).permute(2, 0, 1).float()   # torch.Size([3, 40, 40])
input_tensor = raccoon_face_tensor.div(255).unsqueeze(0)    # torch.Size([1, 3, 40, 40])
input_var = input_tensor.cuda()

eye_coords_tensor = torch.Tensor([[[eye_x, eye_y]]])    # # shape = [1, 1, 2],value=[[[24., 26.]]]
target_tensor = (eye_coords_tensor * 2 + 1) / torch.Tensor(image_size) - 1  # shape = [1, 1, 2],value=[[[0.2250, 0.3250]]]
target_var = target_tensor.cuda()

print('Target: {:0.4f}, {:0.4f}'.format(*list(target_tensor.squeeze())))
model = CoordRegressionNetwork(n_locations=1).cuda()    # n_locations=keypoint num=1
# coords, heatmaps = model(input_var)

# print('Initial prediction: {:0.4f}, {:0.4f}'.format(*list(coords[0, 0])))
# plt.imshow(heatmaps[0, 0].detach().cpu().numpy())
# plt.show()

optimizer = optim.RMSprop(model.parameters(), lr=2.5e-4)

for i in range(400):
    # Forward pass
    coords, heatmaps = model(input_var)
    # coords:shape=[1, 1, 2], value=[[[0.0323, 0.0566]]]; heatmaps:shape=[1, 1, 40, 40]
    # Per-location euclidean losses
    euc_losses = dsntnn.euclidean_losses(coords, target_var)
    # Per-location regularization losses
    reg_losses = dsntnn.js_reg_losses(heatmaps, target_var, sigma_t=1.0)
    # Combine losses into an overall loss
    loss = dsntnn.average_loss(euc_losses + reg_losses)

    # Calculate gradients
    optimizer.zero_grad()
    loss.backward()

    # Update model parameters with RMSprop
    optimizer.step()

# Predictions after training
print('Predicted coords: {:0.4f}, {:0.4f}'.format(*list(coords[0, 0])))
plt.imshow(heatmaps[0, 0].detach().cpu().numpy())
plt.show()

 

在IT领域,可微性主要在机器学习和深度学习领域有重要应用,尤其是在神经网络的训练过程中。 ### 可微性的基本概念 在数学中,可微性描述了函数在某点处的局部线性逼近特性。对于一个多元函数,如果它在某点处可微,那么它在该点附近可以用一个线性函数来近似表示。在IT中,特别是深度学习里,要求模型的损失函数和激活函数等具有可微性,这是因为可微性允许使用梯度下降等优化算法来更新模型的参数。 ### 可微性在深度学习中的应用 在深度学习中,神经网络的训练依赖于反向传播算法,而反向传播算法的基础就是计算梯度。只有当函数是可微的,才能通过链式法则计算梯度,从而更新模型的权重和偏置。例如,常见的激活函数如Sigmoid函数: ```python import numpy as np def sigmoid(x): return 1 / (1 + np.exp(-x)) x = np.array([1, 2, 3]) output = sigmoid(x) print(output) ``` Sigmoid函数是可微的,其导数可以通过公式 $\sigma'(x) = \sigma(x)(1 - \sigma(x))$ 计算,这使得在反向传播过程中能够计算梯度。 ### 可微性优化算法 可微性使得梯度下降等优化算法能够有效地工作。梯度下降算法通过计算损失函数关于模型参数的梯度,并沿着梯度的反方向更新参数,以最小化损失函数。例如,简单的梯度下降更新公式为: $\theta = \theta - \alpha \nabla J(\theta)$ 其中,$\theta$ 是模型的参数,$\alpha$ 是学习率,$\nabla J(\theta)$ 是损失函数 $J(\theta)$ 关于 $\theta$ 的梯度。 ### 不可微函数的处理 在实际应用中,也会遇到一些不可微的函数。例如,ReLU(Rectified Linear Unit)函数在 $x = 0$ 处不可微: ```python import numpy as np def relu(x): return np.maximum(0, x) x = np.array([-1, 0, 1]) output = relu(x) print(output) ``` 对于这种情况,通常采用次梯度(subgradient)等方法来近似处理,使得优化算法仍然能够工作。
评论 4
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值