深度学习训练营之J5周DenseNet+SE-Net实战

原文链接

📌第J5周:DenseNet+SE-Net实战📌

语言:Python3、Pytorch
📌本周任务:📌

    1. 在DenseNet系列算法中插入SE-Net通道注意力机制,并完成猴痘病识别
    1. 改进思路是否可以迁移到其他地方呢
  • 3.测试集accuracy达到89%(拔高,可选)

🔊注: 从前几周开始训练营的难度逐渐提升,具体体现在不再直接提供源代码。任务中会给大家提供一些算法改进的思路、方向,希望大家这一块可以积极探索。(这个探索的过程很重要,也将学到更多)
个人感悟:本周由于临近期末考试,本周三进行数学专业课程的考试,然后还加上重感冒,所以这一次的深度学习训练营所准备的时间还是不是很充足,而且在DenseNet的实际应用上可以明显感觉到自身能力的不足,所以本次在代码的实现过程当中还是有点不熟练,所以本次主要以方法介绍为主,给大家带来的不便感到十分抱歉
论文链接:Squeeze-and-Excitation Networks

方法介绍

SE-Net作为ImageNet 2017 的冠军模型,其优点如下:

  • 复杂度低
  • 计算量小

其具体策略为:通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征,这又叫做“特征重标定”策略。具体的SE模块如下图所示
请添加图片描述
给定一个输入 x x x ,其特征通道数为 c 1 c_1 c1,经过一系列卷积等一般变换 F t r F_{tr} Ftr,后得到一个特征通道数为 c 2 c_2 c2的特征。与传统的卷积神经网络不同,我们需要通过下面三个操作来重新标定前面得到的特征。

1.首先是Squeeze操作,我们顺着空间维度来进行特征压缩,将一个通道数和输入的特征通道数相等,例如可以将将形状为(1, 32, 32, 10)的feature map压缩成(1, 1, 1, 10)。此操作通常采用global average pooling来实现。
2.得到了全局描述特征后,我们进行Excitation操作来抓取特征通道之间的关系,它是一个类似于循环神经网络中门的机制:
s = F e x ( z , W ) = σ ( g ( z , W ) ) = σ ( W 2 Re ⁡ L U ( W 1 z ) ) s=F_{e x}(z, W)=\sigma(g(z, W))=\sigma\left(W_{2} \operatorname{Re} L U\left(W_{1} z\right)\right) s=Fex(z,W)=σ(g(z,W))=σ(W2ReLU(W1z))

这里采用包含两个全连接层的bottleneck结构,即中间小两头大的结构:其中第一个全链接层起到即降维的作用,并通过ReLU激活,第二个全链接层用来将其恢复至原始的维度。进行Excitation操作的最终目的是为每个特征通道生成权重,即学习到的各个通道的激活值(sigmoid激活,值在0~1之间)。
最后一个是Scale的操作,我们将Excitation的输出的权重看作是经过特征选择后的每个特征通道的重要性,然后通过乘法逐通道加权到先前的特征上,完成在通道维度上的对原始特征的重标定,从而提高了每一个通道在模型上的特征更有辨别能力,这类似于attention机制。

SE模块应用分析

请添加图片描述
SE模块非常灵活,表现在其可以直接应用在现有的网络结果中,以Inception和ResNet为例,可以直接在这两个模块后面添加SE模块
请添加图片描述
方框旁边的维度信息代表该层的输出, r r r表示Excitation(激发)操作当中的降维系数

SE模块的效果对比

在ImageNet上的效果
请添加图片描述
从上表可以看出,SE-ResNets在各种深度上都远远超过了其对应的没有SE的结构版本的精度,这表示无论网络的深度以及大小,SE模块都能够给网络带来性能上的增益。值得一提的是,SE-ResNet-50可以达到和ResNet-101一样的精度;更甚,SE-ResNet-101远远地超过了更深的ResNet-152

SE模块代码实现

tensorflow

from tensorflow import keras
from keras import layers
from layers import Model, Input, Reshape, Activation, BatchNormalization, GlobalAveragePooling2D, Dense

class SqueezeExcitationLayer(Model):
    def __init__(self, filter_sq):
        # filter_sq是Excitation中第一个卷积过程中卷积核的个数
        super.__init__()
        self.avgpool = GlobalAveragePooling2D()
        self.dense = Dense(filter_sq)
        self.relu = Activation('relu')
        self.sigmoid = Activation('sigmoid')
    
    def call(self, inputs):
        x = self.avgpool(inputs)
        x = self.dense(x)
        x = self.relu(x)
        x = Dense(inputs.shape[-1])(x)
        x = self.sigmoid(x)
        x = Reshape((1,1,inputs.shape[-1]))(x)
        
        scale = inputs * x
        return scale

SE = SqueezeExcitationLayer(16)

SE模块在DenseNet当中的应用

tensorflow

''' Basic unit of DenseBlock (using bottleneck layer) '''
def DenseLayer(x, bn_size, growth_rate, drop_rate, name=None):
    f = BatchNormalization(name=name+'_1_bn')(x)
    f = Activation('relu', name=name+'_1_relu')(f)
    f = Conv2D(bn_size*growth_rate, 1, strides=1, use_bias=False, name=name+'_1_conv')(f)
    
    f = BatchNormalization(name=name+'_2_bn')(f)
    f = Activation('relu', name=name+'_2_relu')(f)
    f = Conv2D(growth_rate, 3, strides=1, padding=1, use_bias=False, name=name+'_2_conv')(f)
    
    if drop_rate>0:
        f = Dropout(drop_rate)(f)
    
    x = layers.Concatenate(axis=-1)([x, f])
    return x


''' DenseBlock '''
def DenseBlock(x, num_layers, bn_size, growth_rate, drop_rate, name=None):
    for i in range(num_layers):
        x = DenseLayer(x, bn_size, growth_rate, drop_rate, name=name+'_denselayer'+str(i+1))
    return x


''' Transition layer between two adjacent DenseBlock '''
def Transition(x, out_channel):
    x = BatchNormalization(name=name+'_bn')(x)
    x = Activation('relu', name=name+'_relu')(x)
    x = Conv2D(out_channel, 1, strides=1, use_bias=False, name=name+'_conv')(x)
    x = AveragePooling2D(2, 2, name='pool')(x)
    return x


''' DenseNet-BC model '''
def DenseNet(input_tensor=None,  # 可选的keras张量,用作模型的图像输入
             input_shape=None,
             init_channel=64,
             growth_rate=32,
             block_config=(6,12,24,16),
             bn_size=4,
             compression_rate=0.5,
             drop_rate=0,
             classes=1000):  # 用于分类图像的可选类数
    img_input = Input(shape=input_shape)
    # first Conv2d
    x = ZeroPadding2D(padding=((3, 3), (3, 3)), name='conv1_pad')(img_input)
    x = Conv2D(64, 7, strides=2, use_bias=False, name='conv1_conv')(x)
    x = BatchNormalization(name='conv1_bn')(x)
    x = Activation('relu', name='conv1_relu')(x)
    x = MaxPooling2D(3, strides=2, padding=1, name='conv1_pool')(x)
    # DenseBlock
    num_features = init_channel
    for i, num_layers in enumerate(block_config):
        x = DenseBlock(x, num_layers, bn_size, growth_rate, drop_rate, name='denseblock'+str(i+1))
        num_features += num_layers*growth_rate
        if i!=len(block_config)-1:
            x = Transition(x, int(num_features*compression_rate))
            num_features = int(num_features*compression_rate)
    # 加SE注意力机制
    x = SqueezeExcitationLayer(16)(x)
    # final bn+ReLU
    x = BatchNormalization(name='final_bn')(x)
    x = Activation('relu', name='final_relu')(x)
    x = GlobalAveragePooling2D(name='final_pool')(x)
    x = Dense(classes, activation='softmax', name='predictions')(x)
    
    model = Model(img_input, x, name='DenseNet')
    return model


''' DenseNet121 '''
def densenet121(n_classes=1000, **kwargs):
    model = DenseNet(init_channel=64, growth_rate=32, block_config=(6,12,24,16),
                     classes=n_classes, **kwargs)
    return model


''' DenseNet169 '''
def DenseNet169(n_classes=1000, **kwargs):
    model = DenseNet(init_channel=64, growth_rate=32, block_config=(6,12,32,32),
                     classes=n_classes, **kwargs)
    return model


''' DenseNet201 '''
def DenseNet201(n_classes=1000, **kwargs):
    model = DenseNet(init_channel=64, growth_rate=32, block_config=(6,12,48,32),
                     classes=n_classes, **kwargs)
    return model

参考内容

经典CNN算法解析实战-第J5周:DenseNet+SE-Net实战

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个基于PyTorch的DenseNet-BiLSTM-Attention模型的五分类训练代码,适用于输入数据集为1行121列的情况。 ```python import torch import torch.nn as nn import torch.optim as optim import numpy as np class DenseNet_BiLSTM_Attention(nn.Module): def __init__(self, num_classes): super(DenseNet_BiLSTM_Attention, self).__init__() self.densenet = torchvision.models.densenet121(pretrained=True) self.densenet_features = self.densenet.features self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) self.dropout = nn.Dropout(p=0.5) self.bilstm = nn.LSTM(input_size=1024, hidden_size=512, num_layers=2, bidirectional=True, batch_first=True) self.attention = nn.Sequential( nn.Linear(1024, 512), nn.Tanh(), nn.Linear(512, 1), nn.Softmax(dim=1) ) self.fc = nn.Linear(1024, num_classes) def forward(self, x): x = x.view(-1, 1, 11, 11) # reshape input to match DenseNet input shape x = self.densenet_features(x) x = self.avgpool(x) x = torch.flatten(x, 1) x = self.dropout(x) x, _ = self.bilstm(x) x = x[:, -1, :] attention_weights = self.attention(x) x = torch.sum(attention_weights * x, dim=1) x = self.fc(x) return x model = DenseNet_BiLSTM_Attention(num_classes=5) criterion = nn.CrossEntropyLoss() optimizer = optim.Adam(model.parameters(), lr=0.001) # Load and preprocess the data # Assume the data is stored in a numpy array X of shape (num_samples, 121) and a numpy array y of shape (num_samples,) X = np.load("data.npy") y = np.load("labels.npy") # Split into training and validation sets num_samples = X.shape[0] num_train = int(num_samples * 0.8) train_indices = np.random.choice(num_samples, num_train, replace=False) val_indices = np.setdiff1d(np.arange(num_samples), train_indices) X_train, y_train = X[train_indices], y[train_indices] X_val, y_val = X[val_indices], y[val_indices] # Convert to PyTorch tensors X_train = torch.from_numpy(X_train).float() y_train = torch.from_numpy(y_train).long() X_val = torch.from_numpy(X_val).float() y_val = torch.from_numpy(y_val).long() # Train the model num_epochs = 10 batch_size = 32 for epoch in range(num_epochs): model.train() running_loss = 0.0 for i in range(0, num_train, batch_size): optimizer.zero_grad() batch_X = X_train[i:i+batch_size] batch_y = y_train[i:i+batch_size] outputs = model(batch_X) loss = criterion(outputs, batch_y) loss.backward() optimizer.step() running_loss += loss.item() * batch_X.size(0) epoch_loss = running_loss / num_train print("Epoch {} training loss: {:.4f}".format(epoch+1, epoch_loss)) model.eval() with torch.no_grad(): val_outputs = model(X_val) val_loss = criterion(val_outputs, y_val) val_predictions = torch.argmax(val_outputs, dim=1) val_accuracy = torch.sum(val_predictions == y_val) / len(y_val) print("Epoch {} validation loss: {:.4f} accuracy: {:.4f}".format(epoch+1, val_loss.item(), val_accuracy.item())) ``` 在此代码中,我们首先定义了一个名为`DenseNet_BiLSTM_Attention`的神经网络模型,它由DenseNet、BiLSTM和Attention层组成。其中,DenseNet用于提取输入数据的特征,BiLSTM用于学习时序特征,Attention层用于加强模型对关键信息的关注。然后,我们使用PyTorch内置的交叉熵损失函数和Adam优化器来训练模型。在训练过程中,我们将数据集分成80%的训练集和20%的验证集,并使用随机梯度下降法进行优化。最后,我们在每个epoch结束时输出训练和验证的损失和精度。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值