tensorflow 中的深度可分离卷积接口 slim.separable_conv2d()

    我在前面的一篇博客 深入浅出谈谈深度可分离卷积 中介绍了深度可分离卷积的原理,然后用 tensorflow 实现了下。

    在 tensorflow 中的接口是 slim.separable_conv2d(),接口说明:

def separable_convolution2d(
    inputs,
    num_outputs,
    kernel_size,
    depth_multiplier=1,
    stride=1,
    padding='SAME',
    data_format=DATA_FORMAT_NHWC,
    rate=1,
    activation_fn=nn.relu,
    normalizer_fn=None,
    normalizer_params=None,
    weights_initializer=initializers.xavier_initializer(),
    pointwise_initializer=None,
    weights_regularizer=None,
    biases_initializer=init_ops.zeros_initializer(),
    biases_regularizer=None,
    reuse=None,
    variables_collections=None,
    outputs_collections=None,
    trainable=True,
    scope=None):
  """一个2维的可分离卷积,可以选择是否增加BN层。
  这个操作首先执行逐通道的卷积(每个通道分别执行卷积),创建一个称为depthwise_weights的变量。如果num_outputs
不为空,它将增加一个pointwise的卷积(混合通道间的信息),创建一个称为pointwise_weights的变量。如果
normalizer_fn为空,它将给结果加上一个偏置,并且创建一个为biases的变量,如果不为空,那么归一化函数将被调用。
最后再调用一个激活函数然后得到最终的结果。
  Args:
    inputs: 一个形状为[batch_size, height, width, channels]的tensor
    num_outputs: pointwise 卷积的卷积核个数,如果为空,将跳过pointwise卷积的步骤.
    kernel_size: 卷积核的尺寸:[kernel_height, kernel_width],如果两个的值相同,则可以为一个整数。
    depth_multiplier: 卷积乘子,即每个输入通道经过卷积后的输出通道数。总共的输出通道数将为:
num_filters_in * depth_multiplier。
    stride:卷积步长,[stride_height, stride_width],如果两个值相同的话,为一个整数值。
    padding:  填充方式,'VALID' 或者 'SAME'.
    data_format:数据格式, `NHWC` (默认) 和 `NCHW` 
    rate: 空洞卷积的膨胀率:[rate_height, rate_width],如果两个值相同的话,可以为整数值。如果这两个值
任意一个大于1,那么stride的值必须为1.     
    activation_fn: 激活函数,默认为ReLU。如果设置为None,将跳过。
    normalizer_fn: 归一化函数,用来替代biase。如果归一化函数不为空,那么biases_initializer
和biases_regularizer将被忽略。 biases将不会被创建。如果设为None,将不会有归一化。
    normalizer_params: 归一化函数的参数。
    weights_initializer: depthwise卷积的权重初始化器
    pointwise_initializer: pointwise卷积的权重初始化器。如果设为None,将使用weights_initializer。
    weights_regularizer: (可选)权重正则化器。
    biases_initializer: 偏置初始化器,如果为None,将跳过偏置。
    biases_regularizer: (可选)偏置正则化器。
    reuse: 网络层和它的变量是否可以被重用,为了重用,网络层的scope必须被提供。
    variables_collections: (可选)所有变量的collection列表,或者是一个关键字为变量值为collection的字典。
    outputs_collections: 输出被添加的collection.
    trainable: 变量是否可以被训练
    scope: (可选)变量的命名空间。
  Returns:
    代表这个操作的输出的一个tensor

    但是这个接口根据原理来看,我觉得有个缺点,如果设置 depth_multiplier 为1,则变成了单通道的点乘,那这样是否缺乏了通道间的信息融合?

    这样显然能极大程度减少参数,但是网络性能也会受到影响,至少对于low-levle 的 cv 任务来说,性能下降很大。

    如有不对请指正。

 

### YOLOv7 Slim Neck 轻量化改进实现与优化技术 YOLOv7作为一种高效的实时目标检测模型,在实际应用中往往需要进一步的轻量化处理来适应资源受限环境。对于Slim Neck部分,主要通过减少计算量、降低内存占用以及加速推理速度来进行优化。 #### 1. 参数剪枝与稀疏化 参数剪枝是一种有效的方法,可以去除网络中的冗余连接或不重要的权重,从而减小模型大小并加快推断过程。具体到Slim Neck模块,可以通过分析各层的重要性得分,移除那些贡献较小的通道或滤波器[^1]。 ```python import torch.nn.utils.prune as prune def apply_pruning(model): for name, module in model.named_modules(): if isinstance(module, torch.nn.Conv2d): prune.ln_structured( module, name='weight', amount=0.2, # 剪枝比例 n=2, # L2范数 dim=0 # 对输入维度进行操作 ) ``` #### 2. 低秩分解 利用矩阵低秩特性对卷积核实施近似表示,能够显著减少乘法次数。例如采用CP分解或者Tucker分解等方式重构原始张量结构,进而达到压缩效果的同时保持较高精度[^2]。 #### 3. 权重量化 将浮点型权值转换成低位整数形式存储和运算,不仅节省空间还能提高硬件执行效率。通常情况下会选择INT8作为替代方案,并配合相应校准流程确保性能损失最小化[^3]。 ```python from torchvision import models model = models.resnet18(pretrained=True) # Quantization Aware Training setup model.qconfig = torch.quantization.get_default_qat_qconfig('fbgemm') torch.quantization.prepare_qat(model, inplace=True) ``` #### 4. 动态调整特征图分辨率 适当缩小中间层输出尺寸有助于减轻后续阶段负担,特别是在设计Slim Neck时可考虑引入渐进式下采样策略,即随着深度增加逐步降低空间维数而不影响整体表现力[^4]。 #### 5. 使用更高效的基础组件 替换传统卷积操作为Depthwise Separable Convolution等更加紧凑的设计模式;同时探索MobileNet V3提出的EfficientNet架构下的复合缩放法则应用于Neck构建之中[^5]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值