ResNet,BN实现

1.ResNet

# bottleneck残差单元模块
def _bottleneck_residual(self, x, in_filter, out_filter, stride,
                         activate_before_residual=False):
    # 是否前置激活(取残差直连之前进行BN和ReLU)
    if activate_before_residual:
        with tf.variable_scope('common_bn_relu'):
            # 先做BN和ReLU激活
            x = self._batch_norm('init_bn', x)
            x = self._relu(x, self.hps.relu_leakiness)
            # 获取残差直连
            orig_x = x
    else:
        with tf.variable_scope('residual_bn_relu'):
            # 获取残差直连
            orig_x = x
            # 后做BN和ReLU激活
            x = self._batch_norm('init_bn', x)
            x = self._relu(x, self.hps.relu_leakiness)

    # 第1子层
    with tf.variable_scope('sub1'):
        # 1x1卷积,使用输入步长,通道数(in_filter -> out_filter/4)
        x = self._conv('conv1', x, 1, in_filter, out_filter / 4, stride)

    # 第2子层
    with tf.variable_scope('sub2'):
        # BN和ReLU激活
        x = self._batch_norm('bn2', x)
        x = self._relu(x, self.hps.relu_leakiness)
        # 3x3卷积,步长为1,通道数不变(out_filter/4)
        x = self._conv('conv2', x, 3, out_filter / 4, out_filter / 4,
                       [1, 1, 1, 1])

    # 第3子层
    with tf.variable_scope('sub3'):
        # BN和ReLU激活
        x = self._batch_norm('bn3', x)
        x = self._relu(x, self.hps.relu_leakiness)
        # 1x1卷积,步长为1,通道数不变(out_filter/4 -> out_filter)
        x = self._conv('conv3', x, 1, out_filter / 4, out_filter,
                       [1, 1, 1, 1])

    # 合并残差层
    with tf.variable_scope('sub_add'):
        # 当通道数有变化时
        if in_filter != out_filter:
            # 1x1卷积,使用输入步长,通道数(in_filter -> out_filter)
            orig_x = self._conv('project', orig_x, 1, in_filter, out_filter,
                                stride)

        # 合并残差
        x += orig_x
    tf.logging.info('image after unit %s', x.get_shape())
    return x

2.BN

# Batch Normalization批归一化
    # ((x-mean)/var)*gamma+beta
def _batch_norm(self, name, x):
    with tf.variable_scope(name):
        # 输入通道维数
        params_shape = [x.get_shape()[-1]]
        # offset
        beta = tf.get_variable('beta',
                               params_shape,
                               tf.float32,
                               initializer=tf.constant_initializer(0.0,
                                                                   tf.float32))
        # scale
        gamma = tf.get_variable('gamma',
                                params_shape,
                                tf.float32,
                                initializer=tf.constant_initializer(1.0,
                                                                    tf.float32))

        if self.mode == 'train':
            # 为每个通道计算均值、标准差
            mean, variance = tf.nn.moments(x, [0, 1, 2], name='moments')
            # 新建或建立测试阶段使用的batch均值、标准差
            moving_mean = tf.get_variable('moving_mean',
                                          params_shape, tf.float32,
                                          initializer=tf.constant_initializer(
                                              0.0, tf.float32),
                                          trainable=False)
            moving_variance = tf.get_variable('moving_variance',
                                              params_shape, tf.float32,
                                              initializer=tf.constant_initializer(
                                                  1.0, tf.float32),
                                              trainable=False)
            # 添加batch均值和标准差的更新操作(滑动平均)
            # moving_mean = moving_mean * decay + mean * (1 - decay)
            # moving_variance = moving_variance * decay + variance * (1 - decay)
            # _extra_train_ops = []使用来存储值的
            self._extra_train_ops.append(
                moving_averages.assign_moving_average(
                    moving_mean, mean, 0.9))
            self._extra_train_ops.append(
                moving_averages.assign_moving_average(
                    moving_variance, variance, 0.9))
        else:
            # 获取训练中积累的batch均值、标准差
            mean = tf.get_variable('moving_mean',
                                   params_shape, tf.float32,
                                   initializer=tf.constant_initializer(0.0,
                                                                       tf.float32),
                                   trainable=False)
            variance = tf.get_variable('moving_variance',
                                       params_shape, tf.float32,
                                       initializer=tf.constant_initializer(
                                           1.0, tf.float32),
                                       trainable=False)
            # 添加到直方图总结
            tf.summary.histogram(mean.op.name, mean)
            tf.summary.histogram(variance.op.name, variance)

        # BN层:((x-mean)/var)*gamma+beta
        y = tf.nn.batch_normalization(x, mean, variance, beta, gamma, 0.001)
        y.set_shape(x.get_shape())
        return y

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ResNet(Residual Network)是一种非常流行的深度卷积神经网络模型,它在解决深层网络训练过程中的梯度消失和梯度爆炸问题上具有很好的效果。下面是ResNet在PyTorch中的实现方式: 1. 导入所需的库和模块: ```python import torch import torch.nn as nn import torch.nn.functional as F ``` 2. 定义基本的残差块(Residual Block): ```python class ResidualBlock(nn.Module): def __init__(self, in_channels, out_channels, stride=1): super(ResidualBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(out_channels) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channels) self.shortcut = nn.Sequential() if stride != 1 or in_channels != out_channels: self.shortcut = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False), nn.BatchNorm2d(out_channels) ) def forward(self, x): residual = x out = F.relu(self.bn1(self.conv1(x))) out = self.bn2(self.conv2(out)) out += self.shortcut(residual) out = F.relu(out) return out ``` 3. 定义ResNet模型: ```python class ResNet(nn.Module): def __init__(self, block, num_blocks, num_classes=10): super(ResNet, self).__init__() self.in_channels = 64 self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(64) self.layer1 = self.make_layer(block, 64, num_blocks[0], stride=1) self.layer2 = self.make_layer(block, 128, num_blocks[1], stride=2) self.layer3 = self.make_layer(block, 256, num_blocks[2], stride=2) self.layer4 = self.make_layer(block, 512, num_blocks[3], stride=2) self.avg_pool = nn.AdaptiveAvgPool2d((1, 1)) self.fc = nn.Linear(512, num_classes) def make_layer(self, block, out_channels, num_blocks, stride): layers = [] layers.append(block(self.in_channels, out_channels, stride)) self.in_channels = out_channels for _ in range(1, num_blocks): layers.append(block(out_channels, out_channels)) return nn.Sequential(*layers) def forward(self, x): out = F.relu(self.bn1(self.conv1(x))) out = self.layer1(out) out = self.layer2(out) out = self.layer3(out) out = self.layer4(out) out = self.avg_pool(out) out = out.view(out.size(0), -1) out = self.fc(out) return out ``` 4. 创建ResNet模型实例: ```python def ResNet18(): return ResNet(ResidualBlock, [2, 2, 2, 2]) ``` 这样就完成了ResNet在PyTorch中的实现。你可以根据自己的需求进行修改和扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值