第五周作业:卷积神经网络(Part3)

一、MobileNetV1 网络

  • 这篇论文是 Google 针对手机等嵌入式设备提出的一个小网络模型,主要侧重于简单有效,描述了一个有效的网络架构和两个超参数来建立非常小的、低延迟的模型,以便轻松匹配移动和嵌入式视觉应用的设计要求。

 Mobilenet v1核心是把卷积拆分为Depthwise+Pointwise两部分。

  • 深度卷积在每个通道上应用一个卷积核。逐点卷积接着应用1*1卷积把输出和深度卷积结合起来。标准卷积在一个步骤把卷积核和输入结合为新的输出。深度可分离卷积将其分为两层,一层用于滤波,一层用于结合。这个分解过程极大地减少了计算量和模型的大小。具体如下:

  •  其中分母为原来标准卷积的模型参数,分子为将标准卷积分为Depthwise+Pointwise两部分后的参数量,可以看到明显模型参数降低。
  • 代码部分:

 

 二、MobileNetV2 网络

  • MobileNetV2 主要提出两方面的改进:
    • Linear Bottlenecks:在维度较小的 1x1 卷积之后不再采用ReLU操作,避免对特征的破坏。作者去掉了第二个pointwise convolution的激活函数ReLU,作者认为激活函数在高维空间能够有效增加非线性,但在低维空间则会破坏特征。
    • Inverted Residuals:与传统resnet结构中先对bottlenecks降维再复原不同,这里先用一个expand layer进行升维,然后再depthwise convolution最后再1x1降维复原。

 

 

 

 三、HybridSN 高光谱分类网络

补充代码段

class_num = 16

class HybridSN(nn.Module):
  def __init__(self):
    super(HybridSN, self).__init__()
    self.conv1=nn.Conv3d(in_channels=1,out_channels=8,kernel_size=(7,3,3))
    self.conv2=nn.Conv3d(in_channels=8,out_channels=16,kernel_size=(5,3,3))
    self.conv3=nn.Conv3d(in_channels=16,out_channels=32,kernel_size=(3,3,3))
    self.conv4=nn.Conv2d(576, 64, 3)
    self.fc1=nn.Linear(18496,256)
    self.fc2=nn.Linear(256,128)
    self.fc3=nn.Linear(128,class_num)
    self.dropout=nn.Dropout(p=0.4)
    
  def forward(self, x):
    x=F.relu(self.conv1(x))
    x=F.relu(self.conv2(x))
    x=F.relu(self.conv3(x))
    x=torch.reshape(x,[x.shape[0],576,19,19])
    x=F.relu(self.conv4(x))
    x=torch.flatten(x,start_dim=1)
    x=F.relu(self.fc1(x))
    x=F.dropout(x,p=0.4,training=self.training)
    x=F.relu(self.fc2(x))
    x=F.dropout(x,p=0.4,training=self.training)
    x=self.fc3(x)
    return x

1、3D卷积和2D卷积的区别

 2D卷积操作如图1所示,为了解释的更清楚,分别展示了单通道和多通道的操作。且为了画图方便,假定只有1个filter,即输出图像只有一个chanel。

其中,针对单通道,输入图像的channel为1,即输入大小为(1, height, weight),卷积核尺寸为 (1, k_h, k_w),卷积核在输入图像上的的空间维度(即(height, width)两维)上进行进行滑窗操作,每次滑窗和 (k_h, k_w) 窗口内的values进行卷积操作(现在都用相关操作取代),得到输出图像中的一个value。

针对多通道,假定输入图像的channel为3,即输入大小为(3, height, weight),卷积核尺寸为 (3, k_h, k_w), 卷积核在输入图像上的的空间维度(即(height, width)两维)上进行进行滑窗操作,每次滑窗与3个channels上的 (k_h, k_w) 窗口内的所有的values进行相关操作,得到输出图像中的一个value。

preview

 

3D卷积操作如图2所示,同样分为单通道和多通道,且只使用一个filter,输出一个channel。

其中,针对单通道,与2D卷积不同之处在于,输入图像多了一个 depth 维度,故输入大小为(1, depth, height, width),卷积核也多了一个k_d维度,因此卷积核在输入3D图像的空间维度(height和width维)和depth维度上均进行滑窗操作,每次滑窗与 (k_d, k_h, k_w) 窗口内的values进行相关操作,得到输出3D图像中的一个value.

针对多通道,输入大小为(3, depth, height, width),则与2D卷积的操作一样,每次滑窗与3个channels上的 (k_d, k_h, k_w) 窗口内的所有values进行相关操作,得到输出3D图像中的一个value。

preview

 

 参考文章:

【模型解读】从2D卷积到3D卷积,都有什么不一样 - 知乎

2、每次分类的结果为何不同

在神经网络中,采用了Dropout防止过拟合,本网络中以概率p=0.4进行了Dropout,导致有些神经元被丢弃,所以每次的结果会显得不同。

3、进一步提升高光谱图像的分类性能,可以如何改进

通过注意力机制改善网络性能

参考文章:

高光谱图像分类--HybridSN: Exploring 3-D–2-DCNN Feature Hierarchy for Hyperspectral Image Classification_AshesOfTimeeee的博客-CSDN博客

class_num = 16
# 通道注意力机制
class ChannelAttention(nn.Module):
    def __init__(self, in_planes, ratio=16):
        super(ChannelAttention, self).__init__()
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        self.max_pool = nn.AdaptiveMaxPool2d(1)
 
        self.fc1   = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)
        self.relu1 = nn.ReLU()
        self.fc2   = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)
 
        self.sigmoid = nn.Sigmoid()
 
    def forward(self, x):
        avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))
        max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))
        out = avg_out + max_out
        return self.sigmoid(out)
        
# 空间注意力机制
class SpatialAttention(nn.Module):
    def __init__(self, kernel_size=7):
        super(SpatialAttention, self).__init__()
 
        assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
        padding = 3 if kernel_size == 7 else 1
 
        self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
        self.sigmoid = nn.Sigmoid()
 
    def forward(self, x):
        avg_out = torch.mean(x, dim=1, keepdim=True)
        max_out, _ = torch.max(x, dim=1, keepdim=True)
        x = torch.cat([avg_out, max_out], dim=1)
        x = self.conv1(x)
        return self.sigmoid(x)

class HybridSN(nn.Module):
  def __init__(self, num_classes, self_attention=False):
    super(HybridSN, self).__init__()
    self.conv3d_1 = nn.Sequential(
        nn.Conv3d(1, 8, kernel_size=(7, 3, 3), stride=1, padding=0),
        nn.BatchNorm3d(8),
        nn.ReLU(inplace = True),
    )
    
    self.self_attention = self_attention   #默认
    
    self.conv3d_2 = nn.Sequential(
        nn.Conv3d(8, 16, kernel_size=(5, 3, 3), stride=1, padding=0),
        nn.BatchNorm3d(16),
        nn.ReLU(inplace = True),
    ) 
    self.conv3d_3 = nn.Sequential(
        nn.Conv3d(16, 32, kernel_size=(3, 3, 3), stride=1, padding=0),
        nn.BatchNorm3d(32),
        nn.ReLU(inplace = True)
    )

    if self_attention:
            self.channel_attention_1 = ChannelAttention(576)
            self.spatial_attention_1 = SpatialAttention(kernel_size=7)

    self.conv2d_4 = nn.Sequential(
        nn.Conv2d(576, 64, kernel_size=(3, 3), stride=1, padding=0),
        nn.BatchNorm2d(64),
        nn.ReLU(inplace = True),
    )

    if self_attention:
            self.channel_attention_1 = ChannelAttention(576)
            self.spatial_attention_1 = SpatialAttention(kernel_size=7)
    
    self.fc1 = nn.Linear(18496,256)
    self.fc2 = nn.Linear(256,128)
    self.fc3 = nn.Linear(128,16)
    self.dropout = nn.Dropout(p = 0.4)

  def forward(self,x):
    out = self.conv3d_1(x)
    out = self.conv3d_2(out)
    out = self.conv3d_3(out)
    out = self.conv2d_4(out.reshape(out.shape[0],-1,19,19))
    out = out.reshape(out.shape[0],-1)
    out = F.relu(self.dropout(self.fc1(out)))
    out = F.relu(self.dropout(self.fc2(out)))
    out = self.fc3(out)
    return out 

# 随机输入,测试网络结构是否通
# x = torch.randn(1, 1, 30, 25, 25)
# net = HybridSN()
# y = net(x)
# print(y.shape)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值