STN:Spatial Transformer Networks,即空间变换网络,是Google旗下 DeepMind 公司的研究成果。该论文提出空间变换网络STN,分为
参数预测
、
坐标映射
、
像素采集
三大部分,可以插入到现有的CNN模型中。通过对数据进行反向空间变换来消除图片上目标的变形,从而使得分类网络的识别更加简单高效。
在我的理解里,STN是一个可以放置在CNN前面,或嵌入到CNN其中的某一环节的模块(空间变形器)。
CNN在图像分类中取得了显著的成效,主要是得益于 CNN 的深层结构具有空间不变性(spatially invariance)(平移不变性,旋转不变性),所以图像上的目标物体就算是做了平移或者旋转,CNN仍然能够准确的识别出来,这对于CNN的泛化能力是有益的。
传统CNN中使用卷积和池化操作在一定程度上实现了平移不变性,但这种人工设定的变换规则使得网络过分的依赖先验知识,既不能真正实现平移不变性(不变性对于平移的要求很高),又使得CNN对于旋转,扭曲等未人为设定的几何变换缺乏应有的特征不变性。因此提出了STN,具有以下特点:
(1) 为每一个输入提供一种对应的空间变换方式(如仿射变换)
(2) 变换作用于整个特征输入
(3) 变换的方式包括缩放、剪切、旋转、空间扭曲等等
具有可导性质的STN不需要多余的标注,能够自适应的学到对于不同数据的空间变换方式。它不仅可以对输入进行空间变换,同样可以作为网络模块插入到现有网络的任意层中实现对不同Feature map的空间变换。最终让网络模型学习了对平移、尺度变换、旋转和更多常见的扭曲的不变性,也使得模型在众多基准数据集上表现出了更好的效果。
CNN是尽力让网络适应物体的形变,而STN是直接通过空间变换将形变的物体给变回到正常的姿态,然后再给网络识别。
一些符号意义:
Localisation network决定输入所需变换的参数θ,Grid generator通过θ和定义的变换方式寻找输出与输入特征的映射T(θ),Sample结合位置映射和变换参数对输入特征进行选择并结合双线性插值进行输出,下面对于每一个组成部分进行具体介绍。
Localisation net输入为一张Feature map;经过若干卷积或全链接操作后接一个回归层回归输出变换参数θ。θ的维度取决于网络选择的具体变换类型。θ的值决定了网络选择的空间变换的”幅度大小”。
由上图可知,无论是平移,还是旋转、缩放、剪切,都可以由a,b,c,d,e,f六个参数控制。坐标映射这一步可以理解为找到原图包围内容的边框,并通过变换使其变成“正”的图像,如下图所示:
经过以上的两步操作后,输出的Feature map上每一个像素点都会通过空间变换对应到输入Feature map的某个像素位置,但是由于feature score对于feature position的偏导数无法计算,因而我们需要构造一种position->score的映射,且该映射具有可导的性质,从而满足反向传播的条件。
这篇文章提出的空间变换结构能够很方便的嵌入到现有的CNN模型中去,并且实现端到端的训练,通过对数据进行反向空间变换来消除图片上目标的变形,从而使得分类网络的识别更加简单高效。现在的CNN的已经非常强大了,但是STN仍然能过通过增强空间不变性来提高性能表现。空间变换实际上是一种attention机制,可以用于目标检测,目标追踪等问题,还可以构建半监督模。
1.《Spatial Transformer Networks》
2.
https://blog.csdn.net/qq_39422642/article/details/78870629
3.
https://zhuanlan.zhihu.com/p/41738716
4.
https://arleyzhang.github.io/articles/7c7952f0/
文章目录1. STN是什么2. 问题的提出——CNN的平移不变性3. STN基本结构3.1 Localisation network(参数预测)3.2 Grid generator(坐标映射)3.3 Sampler(像素采集)4. 总结5. 参考文献1. STN是什么STN:Spatial Transformer Networks,即空间变换网络,是Google旗下 DeepMind 公司的研...
作者Email: alec@yuyangsemi.com 摘要:本文介绍了彩色
STN-
LCD模块的内部结构、主要器件,以及设计选用要求。 关键词:彩色
STN-
LCD模块 LCM LED 电荷泵 升压器 LDO 背光板 越来越多的手机、PDA、数码相机和视屏游戏机采用
STN-
LCD全彩色显示器,因此,
STN-
LCD彩屏模块(LCM—LCD Module)的需求量激增,国产的LCD液晶显示器的质量已可与国外的媲美,许多手机设计、生产厂商开始要求使用国内LCD厂家生产的LCD彩屏模块。2001年全世界生产手机3.8亿部,2003年将增长到4.3亿部,2005年将增长到
空间
变换
网络
(Spatial Transformer Network)包括三个组成部分:定位
网络
(Localisation net)、格点生成器(Grid generator)以及采样器(Sampler)[15] 。其中,定位
网络
用于参数预测,格点生成器用于坐标映射,采样器用于像素采集。
如图1所示,将特征图U输入
空间
转换器之后,首先由定位
网络
采用卷积操作提取特征,进而使用一些隐藏的
网络
层推理出
空间
变换
的参数θ,随后由格点生成器根据参数θ得到
变换
前后像素点坐标的对应关系;最终使用采样器以双线性插值的方式,
越来越多的手机、PDA、数码相机和视屏游戏机采用
STN-
LCD全彩色显示器,因此,
STN-
LCD彩屏模块(LCM—LCD Module)的需求量激增,国产的LCD液晶显示器的质量已可与国外的媲美,许多手机设计、生产厂商开始要求使用国内LCD厂家生产的LCD彩屏模块。 2001年全世界生产手机3.8亿部,2003年将增长到4.3亿部,2005年将增长到5.2亿部。2004年LCM彩屏手机会占整个手机产量的35- 40%,因此
STN-
LCD彩屏模块(LCM)的年需求量会增长到几亿块。
LCM内部结构
STN-
LCD彩屏模块的内部结构如图1
或使用运行时生成的图像进行训练
python main.py -m train -r
将为每个SAVE_STEPS步骤保存模型检查点。 将针对每个VALIDATE_EPOCHS时期执行验证。
生成测试图像
python gen_plates.py -s .\test -n 200
恢复检查点进行测试
python main.py -m test -c [checkpioint]
python main.py
目标检测
之
空间
变形
网络
(STN)
一、STN定义
STN:是一个可以放置在CNN前面,或嵌入到CNN其中的某一环节的模块(
空间
变形器),是Google旗下 DeepMind 公司的研究成果。该论文提出
空间
变换
网络
STN,分为参数预测、坐标映射、像素采集三大部分,可以插入到现有的CNN模型中。通过对数据进行反向
空间
变换
来消除图片上目标的变形,从而使得分类
网络
的识别更加简单高效。
二、CNN的平移不变性
普通的CNN能够显示的学习平移不变性,以及隐式的学习旋转不变性,所以图像上的目标物体就算是做了平移或者旋转,
这篇文章是15年谷歌DeepMind团队推出的一个可以学习一种
变换
,这种
变换
可以将进行了仿射
变换
的目标进行矫正的
网络
——Spatial Transformer Network(STN)。STN具有
空间
不变性特点,也就是说STN可以使图片经过各种
变换
后的识别效果和未
变换
前的识别效果保持不变。
Note:
空间
不变性:旋转、平移、缩放、裁剪不变性。
传统的池化方式(Max Pooling/Average Pooling)所带来卷积
网络
的位移不变性和旋转不变性只是局部的和固定的(池化的大小一般都很小,比如3×.
负样本是指不包含任务所要识别的目标的图像,也叫负图像(Negtive Image)。以识别限速牌为例,如下所示,左图包含限速牌,为正样本,右图不包含限速牌,为背景图,即负样本。
2.为什么要训练负样本
训练负样本的目的是为了降低误检测率、误识别率,提高
网络
模型的泛化能力。通俗地讲就是告诉检测器,这些“不是你要检测的目标”。
Improving Pedestrian Attribute Recognition With Weakly-Supervised Multi-Scale Attribute-Specific Localization
文章:https://arxiv.org/abs/1910.04562
代码:https://github.com/chufengt/iccv19_attribute
1、行人属性识别任务
行人属性识别任务本质上是一个分类任务,输入一个人的图像,得到人的性别、年龄、穿衣等的属性。相比
STN-
LCD彩屏模块的内部结构如图1所示,它的上部是一块由偏光片、玻璃、液晶组成的LCD屏,其下是白光LED和背光板,还包括LCD的驱动IC和给LCD驱动IC提供一个稳定电源的低压差稳压器(LD0),2~8个白光LED及驱动白光LED的升压稳压IC。
图1
STN-
LCD彩屏模块的内部结构图
液晶显示模块
STN-
LCD彩屏模块的电路结构如图2所示,外来电源Ucc经LDO降压稳压,向LCD驱动IC(如三星的S6B33B0A)提供工作电压,用以驱动彩色
STN-
LCD,并显示图形和文字;外来电源Ucc经电荷泵升压稳压,向白光LED(如99-21UWC)提供恒压、恒流电源
要查看格式更完美的配图文章,请前去 http://studyai.com/pytorch-1.4/intermediate/spatial_transformer_tutorial.html
在本教程中,您将学习如何使用一种称为
空间
变换
器
网络
的视觉注意机制来增强您的
网络
。 您可以在 DeepMind paper 中更多地阅读有关
空间
变换
器
网络
的内容。
空间
变换
器
网络
(Spatial transfo...
Localisation net\color{blue}Localisation\;netLocalisationnet(参数预测):
Localisation net模块通过CNNCNNCNN提取图像的特征来预测
变换
矩阵θ\thetaθ
Grid generator\color{
文章是Google DeepMind在2015年提出的Spatial Transformer Networks(STN),该模型能够让卷积
网络
学会数据的形状
变换
,能够对经过平移、旋转、缩放及裁剪等操作的图片得到与未经
变换
前相同的检测结果。STN作为一种独立的模块可以在
网络
的任意位置插入使得
网络
具有
空间
不变性。
文章链接:Spatial Transformer Networks
参考目录:
仿射
变换
和双线性插值:Spatial Transformer Networks
pytorch源码:SPATIAL T.
self.conv1 = nn.Conv1d(k, 64, 1)
self.conv2 = nn.Conv1d(64, 128, 1)
self.conv3 = nn.Conv1d(128, 1024, 1)
self.fc1 = nn.Linear(1024, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, k*k)
self.bn1 = nn.BatchNorm1d(64)
self.bn2 = nn.BatchNorm1d(128)
self.bn3 = nn.BatchNorm1d(1024)
self.bn4 = nn.BatchNorm1d(512)
self.bn5 = nn.BatchNorm1d(256)
self.transform = nn.Parameter(torch.eye(k).unsqueeze(0))
def forward(self, x):
batchsize = x.size()[0]
x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
x = F.relu(self.bn3(self.conv3(x)))
x = torch.max(x, 2, keepdim=True)[0]
x = x.view(-1, 1024)
x = F.relu(self.bn4(self.fc1(x)))
x = F.relu(self.bn5(self.fc2(x)))
x = self.fc3(x)
iden = torch.eye(self.k).view(1, self.k*self.k).repeat(batchsize, 1)
if x.is_cuda:
iden = iden.cuda()
x = x + iden
x = x.view(-1, self.k, self.k)
return x
class STN3d(nn.Module):
def __init__(self, k=3):
super(STN3d, self).__init__()
self.k = k
self.conv1 = nn.Conv1d(k, 64, 1)
self.conv2 = nn.Conv1d(64, 128, 1)
self.conv3 = nn.Conv1d(128, 1024, 1)
self.fc1 = nn.Linear(1024, 512)
self.fc2 = nn.Linear(512, 256)
self.fc3 = nn.Linear(256, k*k)
self.bn1 = nn.BatchNorm1d(64)
self.bn2 = nn.BatchNorm1d(128)
self.bn3 = nn.BatchNorm1d(1024)
self.bn4 = nn.BatchNorm1d(512)
self.bn5 = nn.BatchNorm1d(256)
self.transform = nn.Parameter(torch.zeros(batchsize, self.k, self.k))
nn.init.constant_(self.transform, 0)
def forward(self, x):
batchsize = x.size()[0]
x = F.relu(self.bn1(self.conv1(x)))
x = F.relu(self.bn2(self.conv2(x)))
x = F.relu(self.bn3(self.conv3(x)))
x = torch.max(x, 2, keepdim=True)[0]
x = x.view(-1, 1024)
x = F.relu(self.bn4(self.fc1(x)))
x = F.relu(self.bn5(self.fc2(x)))
x = self.fc3(x)
iden = torch.eye(self.k).view(1, self.k*self.k).repeat(batchsize, 1)
if x.is_cuda:
iden = iden.cuda()
x = x + iden
x = x.view(-1, self.k, self.k)
return x
class PointNetEncoder(nn.Module):
def __init__(self, global_feat=True, feature_transform=False):
super(PointNetEncoder, self).__init__()
self.stn = STN3d()
self.conv1 = nn.Conv1d(3, 64, 1)
self.conv2 = nn.Conv1d(64, 128, 1)
self.conv3 = nn.Conv1d(128, 1024, 1)
self.bn1 = nn.BatchNorm1d(64)
self.bn2 = nn.BatchNorm1d(128)
self.bn3 = nn.BatchNorm1d(1024)
self.global_feat = global_feat
self.feature_transform = feature_transform
if self.feature_transform:
self.fstn = TNet(k=64)
def forward(self, x):
n_pts = x.size()[2]
trans = self.stn(x)
x = x.transpose(2, 1)
x = torch.bmm(x, trans)
x = x.transpose(2, 1)
x = F.relu(self.bn1(self.conv1(x)))
if self.feature_transform:
trans_feat = self.fstn(x)
x = x.transpose(2,1)
x = torch.bmm(x, trans_feat)
x = x.transpose(2,1)
else:
trans_feat = None
x = F.relu(self.bn2(self.conv2(x)))
x = self.bn3(self.conv3(x))
x = torch.max(x, 2, keepdim=True)[0]
x = x.view(-1, 1024)
if self.global_feat:
return x, trans, trans_feat
else:
x = x.view(-1, 1024, 1).repeat(1, 1, n_pts)
return torch.cat([x, trans], 1), trans_feat
class PointNetDecoder(nn.Module):
def __init__(self, feature_transform=False):
super(PointNetDecoder, self).__init__()
self.feature_transform = feature_transform
if self.feature_transform:
self.fstn = TNet(k=128)
self.conv1 = nn.Conv1d(1088, 512, 1)
self.conv2 = nn.Conv1d(512, 256, 1)
self.conv3 = nn.Conv1d(256, 128, 1)
self.conv4 = nn.Conv1d(128, 3, 1)
self.bn1 = nn.BatchNorm1d(512)
self.bn2 = nn.BatchNorm1d(256)
self.bn3 = nn.BatchNorm1d(128)
def forward(self, x, trans, trans_feat):
n_pts = x.size()[2]
x = F.relu(self.bn1(self.conv1(x)))
if self.feature_transform:
x = x.transpose(2,1)
trans_feat = self.fstn(x)
x = x.transpose(2,1)
x = F.relu(self.bn2(self.conv2(x)))
x = F.relu(self.bn3(self.conv3(x)))
x = self.conv4(x)
x = x.transpose(2,1)
x = torch.bmm(x, trans)
x = x.transpose(2,1)
return x
class PointNet(nn.Module):
def __init__(self, feature_transform=False):
super(PointNet, self).__init__()
self.feature_transform = feature_transform
self.encoder = PointNetEncoder(global_feat=True, feature_transform=self.feature_transform)
self.decoder = PointNetDecoder(feature_transform=self.feature_transform)
def forward(self, x):
x, trans, trans_feat = self.encoder(x)
x = self.decoder(x, trans, trans_feat)
return x
这个代码实现了一个PointNet深度学习
网络
,可以用于点云分类、分割和重建等任务。