PyTorch中BN层与CONV层的融合(merge_bn)

本文介绍了如何在PyTorch中实现BN层与CONV层的融合,类似于Caffe中的merge_bn操作。通过安装numpy, torch, torchvision和cv2等库,将PyTorch模型与权重准备就绪,然后运行特定代码实现融合。" 120090710,11027864,C++编程:深入理解数组与指针,"['C++', '数组操作', '指针操作', '编程基础']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

之前发了很久之前写好的一篇关于Caffe中merge_bn的博客,详情可见
Caffe中BN层与CONV层的融合(merge_bn)

今天由于工作需要要对PyTorch模型进行merge_bn,发现网上貌似还没有类似的现成代码,决定自己写个脚本,思路和方法见上面的博客即可,具体的步骤如下:

  1. 要求安装的包有

    numpy
    torch
    torchvision
    cv2

  2. 准备好自己的PyTorch模型,包括模型和权重,放在你能import到的地方即可
  3. 修改代码中的相应路径和import
  4. run and merge!

具体的代码如下

import torch
import os
from collections import OrderedDict
import cv2
import numpy as np
import torchvision.transforms as transforms


"""  Parameters and variables  """
IMAGENET = '/home/zym/ImageNet/ILSVRC2012_img_val_256xN_list.txt'
LABEL = '/home/zym/ImageNet/synset.txt'
TEST_ITER = 10
SAVE = False
TEST_AFTER_MERGE = True


"""  Functions  """
def merge(params, name, layer):
    # global variables
    global weights, bias
    global bn_param

    if layer == 'Convolution':
        # save weights and bias when meet conv layer
        if 'weight' in name:
            weights = params.data
            bias = torch.zeros(weights.size()[0])
        elif 'bias' in name:
            bias = params.data
        bn_param = {
   
   }

    elif layer == 'BatchNorm':
        # save bn params
        bn_param[name.split('.')[-1]] = params.data

        # running_var is the last bn param in pytorch
        if 'running_var' in name:
            # let us merge bn ~
            tmp = bn_param['weight'] /
### UNet在PyTorch中的图像分割运行结果分析 UNet是一种广泛应用于医学影像和其他领域图像分割任务的卷积神经网络架构。其设计基于编码器-解码器结构,能够有效地捕捉全局上下文信息并恢复高分辨率细节[^3]。 #### 1. **UNet模型概述** UNet的核心思想在于通过下采样路径(收缩路径)提取特征,并利用上采样路径(扩展路径)重建空间信息。这种对称的设计使得UNet能够在保持较高精度的同时减少计算资源的需求。具体来说,在PyTorch中实现UNet时,通常会定义双分支结构: - 编码器部分由多个卷积和最大池化操作组成,用于逐步降低输入的空间维度并提取高次特征。 - 解码器部分则通过转置卷积或插值方法进行上采样,逐渐恢复原始尺寸,并融合来自编码器阶段的信息以增强边界预测能力。 以下是UNet的一个简化版本代码示例: ```python import torch.nn as nn import torch class DoubleConv(nn.Module): def __init__(self, in_channels, out_channels): super(DoubleConv, self).__init__() self.conv = nn.Sequential( nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1), nn.BatchNorm2d(out_channels), # 使用BN加速收敛过程 [^2] nn.ReLU(inplace=True), nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1), nn.BatchNorm2d(out_channels), nn.ReLU(inplace=True) ) def forward(self, x): return self.conv(x) class UNet(nn.Module): def __init__(self, input_channel=3, output_channel=1): super(UNet, self).__init__() filters = [64, 128, 256, 512] self.down_conv_1 = DoubleConv(input_channel, filters[0]) self.pool_1 = nn.MaxPool2d(kernel_size=2, stride=2) self.down_conv_2 = DoubleConv(filters[0], filters[1]) self.pool_2 = nn.MaxPool2d(kernel_size=2, stride=2) self.down_conv_3 = DoubleConv(filters[1], filters[2]) self.pool_3 = nn.MaxPool2d(kernel_size=2, stride=2) self.middle_conv = DoubleConv(filters[2], filters[3]) self.up_trans_1 = nn.ConvTranspose2d(filters[3], filters[2], kernel_size=2, stride=2) self.up_conv_1 = DoubleConv(filters[3], filters[2]) self.up_trans_2 = nn.ConvTranspose2d(filters[2], filters[1], kernel_size=2, stride=2) self.up_conv_2 = DoubleConv(filters[2], filters[1]) self.up_trans_3 = nn.ConvTranspose2d(filters[1], filters[0], kernel_size=2, stride=2) self.up_conv_3 = DoubleConv(filters[1], filters[0]) self.out = nn.Conv2d(filters[0], output_channel, kernel_size=1) def forward(self, image): # 下采样 conv1 = self.down_conv_1(image) pool1 = self.pool_1(conv1) conv2 = self.down_conv_2(pool1) pool2 = self.pool_2(conv2) conv3 = self.down_conv_3(pool2) pool3 = self.pool_3(conv3) mid = self.middle_conv(pool3) # 上采样 + 跳跃连接 up_trans_1 = self.up_trans_1(mid) merge1 = torch.cat([up_trans_1, conv3], dim=1) conv_up_1 = self.up_conv_1(merge1) up_trans_2 = self.up_trans_2(conv_up_1) merge2 = torch.cat([up_trans_2, conv2], dim=1) conv_up_2 = self.up_conv_2(merge2) up_trans_3 = self.up_trans_3(conv_up_2) merge3 = torch.cat([up_trans_3, conv1], dim=1) conv_up_3 = self.up_conv_3(merge3) final_output = self.out(conv_up_3) return final_output ``` #### 2. **运行结果展示** 当使用上述UNet模型完成训练后,可以通过测试集评估其性能表现。假设目标是对医疗图像中的肿瘤区域进行分割,则典型的输出可能如下所示: - 输入图像:一张包含正常组织病变部位的MRI扫描图片; - 预测掩模:经过UNet处理得到的概率图,其中每个像素对应属于某一类别的可能性大小; - 叠加显示:将原图二值化的预测结果叠加在一起以便直观对比实际效果如何接近真实标签分布情况。 对于语义级别的划分任务而言,最终呈现形式通常是彩色编码表示各类物体所在位置及其范围轮廓清晰可见的形式[^1]。 #### 3. **结果分析要点** 为了更好地理解UNet PyTorch 实现下的图像分割运行成果,可以从以下几个方面展开讨论: - 准确率指标 (IoU/Dice Coefficient): 衡量重叠程度的有效工具之一; - 边界精确度: 特别是在细小结构或者复杂形状上的描绘准确性至关重要 ; - 泛化能力: 测试样本是否覆盖了足够的多样性场景从而验证算法稳健性. ---
评论 25
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值