问题总结
- 当模型准确率已经较高时,如何判断自己的改动是否提升了性能。因为可能每一次准确率变化都不太大,而且每次训练的模型最后准确率也会有波动,多运行几次取准确率平均值做比较吗?
- 在想要提高性能的改进过程中,有很多改变可能都对性能的提升有些许的帮助。这个过程是一种一种方法的尝试,不断累积提升了性能的改变吗。比如先改了batch_size,找到了一个合适的大小,然后就固定使用这个大小,再调整优化器损失函数之类的?在调整的时候总有一种虽然当前的尝试没有提高性能,但说不定和别的组合在一起可能会变好的想法,简直要进行排列组合。
代码练习
MobileNet V1
-
如何判断nn.Conv2d(3, 3)是做的图一运算而不是图二?
通过Conv2d函数中的groups参数区别。groups取值范围为1 - in_channels。groups=1时做图二运算,groups=3时做图一运算。
若groups=x,则将输入通道分为x份,输出通道分为x份,对应每份分别做全卷积。
举例:nn.Conv2d(in_channels=6, out_channels=6, kernel_size=1, groups=3)
卷积核大小为torch.Size([6, 2, 1, 1])
pytorch的conv2d函数groups分组卷积使用及理解
MobileNet V2
-
“MobileNet V1 的主要问题: Depthwise Conv确实是大大降低了计算量,但实际中,发现不少训练出来的kernel是空的。”
因为Depthwise每个kernel dim 相对于vanilla conv要小得多, 过小的kernel dim, 加上ReLU的激活影响下, 使得神经元输出很容易变为0, 所以就学废了。ReLU对于0的输出的梯度为0, 所以一旦陷入了0输出, 就没法恢复了。
HybridSN
class HybridSN(nn.Module):
def __init__(self):
super(HybridSN, self).__init__()
self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0)
self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0)
self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0)
self.conv4 = nn.Conv2d(576, 64, kernel_size=3, stride=1, padding=0)
self.bn1 = nn.BatchNorm2d(64)
self.fc1 = nn.Linear(18496, 256)
self.dropout1 = nn.Dropout(p=0.4)
self.fc2 = nn.Linear(256, 128)
self.dropout2 = nn.Dropout(p=0.4)
self.fc3 = nn.Linear(128, class_num)
def forward(self, x):
out = self.conv1(x)
out = self.conv2(out)
out = self.conv3(out)
#print(batch)
out = out.reshape(batch, 576, 19, 19)
out = self.conv4(out)
out = self.bn1(out)
out = F.relu(out)
out = out.view(-1, 64 * 17 * 17)
out = self.fc1(out)
out = F.relu(out)
out = self.dropout1(out)
out = self.fc2(out)
out = F.relu(out)
out = self.dropout2(out)
out = self.fc3(out)
return out
-
每次分类的结果都不一样
在model(test)之前,需要加上model.eval(),其作用是为了固定BN和dropout层,使得偏置参数不随着发生变化。否则的话,有输入数据,即使不训练,它也会改变权值。这是model中含有batch normalization层所带来的的性质。
BN的作用主要是对网络中间的每层进行归一化处理,并且使用变换重构(Batch Normalization Transform)保证每层提取的特征分布不会被破坏。
训练时是针对每个mini-batch的,但是测试是针对单张图片的,即不存在batch的概念。在做one classification的时候,训练集和测试集的样本分布是不一样的。
Dropout在train时随机选择神经元而predict要使用全部神经元并且要乘一个补偿系数。
BN在train时每个batch做了不同的归一化因此也对应了不同的参数,相应predict时实际用的参数是每个batch下参数的移动平均。
加上model.eval()后准确率不再变化,但第一次测试分类准确率会变,因为model.eval()固定了dropout层,使用全部神经元而不是随机选择,所以准确率会发生一次变化。
-
进一步提升高光谱图像的分类性能
-
HybridSN准确率 95.28% 98.05% 97.75%
-
二维卷积层改为深度可分离卷积 98.76% 98.59% 98.71%
-
转为二维+三维 98.07% 98.48% 98.30%
#二维卷积层改为深度可分离卷积 class HybridSN(nn.Module): def __init__(self): super(HybridSN, self).__init__() self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0) self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0) self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0) # Depthwise 卷积,3*3 的卷积核,分为 in_planes,即各层单独进行卷积 self.conv4 = nn.Conv2d(576, 576, kernel_size=3, stride=1, padding=0, groups=576, bias=False) self.bn1 = nn.BatchNorm2d(576) # Pointwise 卷积,1*1 的卷积核 self.conv5 = nn.Conv2d(576, 64, kernel_size=1, stride=1, padding=0, bias=False) self.bn2 = nn.BatchNorm2d(64) self.fc1 = nn.Linear(18496, 256) self.dropout1 = nn.Dropout(p=0.4) self.fc2 = nn.Linear(256, 128) self.dropout2 = nn.Dropout(p=0.4) self.fc3 = nn.Linear(128, class_num) def forward(self, x): out = F.relu(self.conv1(x)) out = F.relu(self.conv2(out)) out = F.relu(self.conv3(out)) out = out.reshape(batch, 576, 19, 19) out = F.relu(self.bn1(self.conv4(out))) out = F.relu(self.bn2(self.conv5(out))) out = out.view(-1, 64 * 17 * 17) out = self.fc1(out) out = F.relu(out) out = self.dropout1(out) out = self.fc2(out) out = F.relu(out) out = self.dropout2(out) out = self.fc3(out) return out
#转为二维+三维 class HybridSN(nn.Module): def __init__(self): super(HybridSN, self).__init__() self.conv4 = nn.Conv2d(30, 64, kernel_size=3, stride=1, padding=0) self.bn1 = nn.BatchNorm2d(64) self.conv1 = nn.Conv3d(1, 8, (7, 3, 3), stride=1, padding=0) self.conv2 = nn.Conv3d(8, 16, (5, 3, 3), stride=1, padding=0) self.conv3 = nn.Conv3d(16, 32, (3, 3, 3), stride=1, padding=0) self.fc1 = nn.Linear(480896, 256) self.dropout1 = nn.Dropout(p=0.4) self.fc2 = nn.Linear(256, 128) self.dropout2 = nn.Dropout(p=0.4) self.fc3 = nn.Linear(128, class_num) def forward(self, x): out = x.reshape(batch, 30, 25, 25) out = self.conv4(out) out = self.bn1(out) out = F.relu(out) out = out.reshape(batch, 1, 64, 23, 23) out = F.relu(self.conv1(out)) out = F.relu(self.conv2(out)) out = F.relu(self.conv3(out)) out = out.view(-1, 32 * 52 * 17 * 17) out = self.fc1(out) out = F.relu(out) out = self.dropout1(out) out = self.fc2(out) out = F.relu(out) out = self.dropout2(out) out = self.fc3(out) return out
-
论文笔记
DnCNN
第一次用深度学习来做图像去噪。
残差学习:拟合H(x),由于网络退化问题难以训练出来,转为训练F(x),F(x)=H(x)-x,F(x)称为残差,然后H(x)=F(x)+x。
根据ResNet中的理论,当残差为0时,堆积层之间等价于恒等映射,而恒等映射是非常容易训练优化的。作者注意到在图像复原领域(尤其是在噪音程度较小的情况下),噪音图片与纯净图片的残差非常小,所以理论上残差学习非常适合运用到图像复原上。
DnCNN是将网络的输出直接改成residual image(残差图片),设纯净图片为x,带噪音图片为y,假设y=x+v,则v是残差图片。即DnCNN的优化目标不是真实图片与网络输出之间的MSE(均方误差),而是真实残差图片与网络输出之间的MSE。
SENet
解决了什么问题:注意力机制
对各个特征图赋予权重,不再是简单的相加,而是加权求和。强调重要的部分,忽略不重要的部分。
还可以用于哪些地方:可以把C抬平,强调在不同位置上的重要性。
SE模块首先对卷积得到的特征图进行Squeeze操作,采用global average pooling来实现,然后对全局特征进行Excitation操作,学习各个channel间的关系,得到不同channel的权重,最后乘以原来的特征图得到最终特征。
深度监督跨模态检索(DSCMR)
跨模态检索是指在不同模态数据之间的检索,比如通过一张图片检索与之相关的文本、音视频等数据,或者通过一段文本检索与之相关的图片等数据。
解决跨模态检索的主要方法有两种,一种是学习不同模态数据的实值表示,通过距离度量(如余弦距离、欧氏距离等)进行相关度排序的方法;另一种是学习不同模态数据的二值哈希码,通过度量汉明距离进行相关度排序的方法,这种方法又称为跨模态哈希,由于汉明距离计算的高效性,跨模态哈希在大规模跨模态检索中运用十分广泛,而利用深度学习进行的跨模态哈希,即为深度跨模态哈希。
-
如何度量不同类型数据之间的内容相似性。
深度监督跨模态检索(DSCMR):目的是找到一个共同的表示空间,在这个空间中可以直接比较来自不同模式的样本。
来源:oschina
链接:https://my.oschina.net/u/4343420/blog/4480666