HybridSN修改

原代码链接

结果为:

经过一周的学习与参考其他同学的代码,我对自己的代码进行了一定的修改。

添加bn层

class HybridSN(nn.Module):
  def __init__(self, num_classes=16):
    super(HybridSN, self).__init__()
    self.conv1 = nn.Sequential(nn.Conv3d(1, 8, (7, 3, 3)), nn.BatchNorm3d(8), nn.ReLU())
    self.conv2 = nn.Sequential(nn.Conv3d(8, 16, (5, 3, 3)), nn.BatchNorm3d(16), nn.ReLU())
    self.conv3 = nn.Sequential(nn.Conv3d(16, 32, (3, 3, 3)), nn.BatchNorm3d(32), nn.ReLU())
    self.conv3_2d = nn.Sequential(nn.Conv2d(576, 64, (3,3)), nn.BatchNorm2d(64), nn.ReLU())
    self.dense1 =  nn.Linear(18496,256)
    self.dense2 =  nn.Linear(256,128)
    self.out = nn.Linear(128, num_classes)
    self.drop = nn.Dropout(p=0.4)
    self.soft = nn.LogSoftmax(dim=1)
    self.relu = nn.ReLU()

最终结果为:

添加学习率衰减

在参考了解志杰同学的代码后,我发现他使用了一个我没有见过的函数,遂百度之

scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min',verbose=True,factor=0.9,min_lr=1e-6)
'''
'''
scheduler.step(loss)

这是一个学习率衰减函数

当网络的评价指标不在提升的时候,可以通过降低网络的学习率来提高网络性能。

class torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, mode='min', factor=0.1, patience=10,
 verbose=False, threshold=0.0001, threshold_mode='rel', cooldown=0, min_lr=0, eps=1e-08)

其中:

  • optimer指的是网络的优化器
  • mode (str) ,可选择‘min’或者‘max’,min表示当监控量停止下降的时候,学习率将减小,max表示当监控量停止上升的时候,学习率将减小。默认值为‘min’
  • factor 学习率每次降低多少,new_lr = old_lr * factor
  • patience=10,容忍网路的性能不提升的次数,高于这个次数就降低学习率
  • verbose(bool) - 如果为True,则为每次更新向stdout输出一条消息。 默认值:False
  • threshold(float) - 测量新最佳值的阈值,仅关注重大变化。 默认值:1e-4
  • cooldown: 减少lr后恢复正常操作之前要等待的时期数。 默认值:0。
  • min_lr,学习率的下限
  • eps ,适用于lr的最小衰减。 如果新旧lr之间的差异小于eps,则忽略更新。 默认值:1e-8。

注意:

使用的时候需要选择网络的度量指标,使用如下类的step方法实现,例子如下:

optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = ReduceLROnPlateau(optimizer, 'min',factor=0.5, patience=4, verbose=True)
.....
scheduler.step(train_loss)

使用后可以发现,学习率确实是在衰减

最终的结果:

采用不同的衰减算法的结果:

scheduler = torch.optim.lr_scheduler.StepLR(optimizer,step_size=5,gamma = 0.8)
scheduler = torch.optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.98)

train与eval

但是有一个问题始终没有解决,就是每次测试的时候,正确率都在小幅度的变化

为了探究这个问题,我上网查询了相关资料

在pytorch中,网络有train和eval两种模式

在train模式下,dropout和batch normalization会生效

而eval模式下,dropout不生效,bn固定参数。

这就说明了为什么每次的正确率都会浮动而不是一个固定的值,因为如果没有在没有在测试时添加net.eval,则BN和DropOut没有被固定住使用训练好的值,就会导致每次的结果有变化。

SENet网络

万事俱备,只欠东风。

在设计好的HybridSN模块中加入SENet网络试试吧。

class SELayer(nn.Module):
    def __init__(self, channel, r=16):
        super(SELayer, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d((1,1))
        self.fc = nn.Sequential(
            nn.Linear(channel, channel // r),
            nn.ReLU(),
            nn.Linear(channel // r, channel),
            nn.Sigmoid()
        )

    def forward(self, x):
        a, b, _, _ = x.size()
        y = self.avg_pool(x).view(a, b)
        y = self.fc(y).view(a, b, 1, 1)
        return x * y.expand_as(x)
class HybridSN(nn.Module):
  	def __init__(self, num_classes=16):
	'''
		self.senet = SELayer(64)
	'''
 	 def forward(self, x):
	'''
	    out = self.conv3_2d(out)
    	out = self.senet(out)
	'''

最终结果为:

通过表格整理一下(以下结果均为三次测试中的最大值)

方法 结果
HybridSN 94.99
添加bn层 98.41
添加学习率衰减函数 98.93
添加SENet 99.06
posted @ 2020-08-15 11:22  码我疯狂的码  阅读(383)  评论(0编辑  收藏  举报