深度可分离卷积的Depth,Stack,Channel Multiplier

本文深入探讨深度可分离卷积的不同方面,包括单通道和双通道卷积的差异,堆叠与非堆叠滤波器的实现,以及Channel Multiplier参数的影响。通过实例展示了输入数据、滤波器的结构以及输出计算过程,帮助理解这种轻量级卷积操作的工作原理。

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

通道数目的不同

单通道的卷积

下面的代码测试了仅仅一个属性(depth是1)的深度卷积,其结果和普通卷积是一样的:

async function depthwiseConv2dTestSingleDepth() {
  const fSize = 2;
  const pad = 'valid';
  const stride = 1;
  const chMul = 1;
  const inDepth = 1;
  const x = tf.tensor4d(
      [
        0, 1, 2, 5, 0, 5,
        0, 1, 5
      ],
      [1, 3, 3, inDepth]);
  const w = tf.tensor4d(
      [1.0, 2.0, 2.0, 2.0],
      [fSize, fSize, inDepth, chMul],
  );   
  const result = tf.depthwiseConv2d(x, w, stride, pad);
  result.print();
}

输出是:

Tensor
    [[[[12],
       [15]],
       [[7 ],
       [22]]]]​

如下图(依次是:输入数据,滤波器,输出)演示了输出12的参与卷积的数据:
在这里插入图片描述

双通道的卷积

下面是深度是2的情况(NHWC)。输入数据是两个通道(假设是红色,黄色),每个通道大小是2x2。因此输入数据的形状是:1x2x2x2。卷积提供了两个窗口(假设是红色,黄色),每个窗口提取一个通道的属性。滤波器的形状是2x2x2x1。因此输出数据是两个通道。同时pading模式是valid,因此每个通道输出数据的大小是1x1。输出数据的形状是:1x1x2。

/*
[ [ [[6, 2],]]]
*/
async function depthwiseConv2dTestMultipleDepth3() {
  const fSize = 2;
  const pad = 'valid';
  const stride = 1;
  //const dilation = 2;
  const inDepth = 2;

  const x = tf.tensor4d(
      [
        0, 1, 3, 1,
        0, 2, 2, 1,
      ],
      [1, fSize, fSize, inDepth]);

  const w =
      tf.stack(
            [
              tf.tensor2d(
                [2,0,1,3], [fSize, fSize]),
              tf.tensor2d(
                [1,0,0,1], [fSize, fSize])
            ],
            2).expandDims(3);// as tf.Tensor4D;

  const result = tf.depthwiseConv2d(x, w, stride, pad);
  result.print();
}

输入数据是下面的:

  [
    0, 1, 3, 1,
    0, 2, 2, 1,
  ],
Winograd算法是一种加速卷积计算的方法,它通过将输入数据和卷积核转换为小块的矩阵乘法来实现加速。在深度可分离卷积中,每个卷积层都由一个深度可分离卷积和一个点卷积组成。因此,我们可以使用Winograd算法来加速深度可分离卷积中的深度可分离卷积。 具体来说,我们可以将深度可分离卷积的深度可分离部分转换为Winograd算法中的小块矩阵乘法。假设输入数据为$X\in R^{H\times W\times C_{in}}$,卷积核为$K\in R^{K_h\times K_w\times C_{in}\times C_{out}}$,其中$C_{in}$和$C_{out}$分别表示输入数据和输出数据的通道数。我们可以将输入数据和卷积核都转换为$G\times G$的小块矩阵,其中$G$是Winograd算法中的常数。 具体来说,我们可以将输入数据转换为$B\in R^{G\times G\times C_{in}\times N}$,其中$N=\frac{(H-K_h+1)\times (W-K_w+1)}{G^2}$是输入数据的块数。然后,我们可以将卷积核转换为$A\in R^{G\times G\times C_{in}\times C_{out}}$。接下来,我们可以计算$B$和$A$之间的矩阵乘积$BA$,得到输出数据$Y\in R^{H\times W\times C_{out}}$。最后,我们可以通过点卷积来计算深度可分离卷积的点卷积部分。 由于Winograd算法的复杂度较低,因此可以有效地加速深度可分离卷积的计算。同时,使用Winograd算法也可以减少内存占用和计算量,提高模型的效率和性能。 下面是使用tensorflow实现基于Winograd算法的深度可分离卷积的示例代码: ```python import tensorflow as tf def winograd_depthwise_separable_conv(input, filter, strides, padding='SAME', name=None): with tf.variable_scope(name, default_name='winograd_depthwise_separable_conv'): # Depthwise convolution in_channels = input.get_shape().as_list()[-1] filter_shape = filter.get_shape().as_list() filter = tf.reshape(filter, [filter_shape[0], filter_shape[1], in_channels, 1]) input = tf.expand_dims(input, axis=-2) depthwise_out = tf.nn.depthwise_conv2d(input, filter, strides=[1, 1, 1, 1], padding='VALID') depthwise_out = tf.squeeze(depthwise_out, axis=-2) # Winograd convolution G = 3 B = tf.constant([ [1, 0, 0], [-1/6, -1/6, -1/6], [-1/6, 1/6, -1/6], [1/24, 1/12, 1/6], [1/24, -1/12, 1/6], [0, 0, 1] ], dtype=tf.float32) B = tf.reshape(B, [1, 1, G, G, 1, 6]) B = tf.tile(B, [1, 1, 1, 1, in_channels, 1]) A = tf.transpose(filter, [0, 1, 3, 2]) A = tf.reshape(A, [filter_shape[0], filter_shape[1], 1, in_channels, filter_shape[2]]) A = tf.tile(A, [1, 1, G, 1, 1]) A = tf.reshape(A, [1, 1, G, G, in_channels, filter_shape[2]]) out_shape = tf.stack([tf.shape(input)[0], tf.shape(input)[1], tf.shape(input)[2], filter_shape[2]]) input = tf.pad(input, [[0, 0], [1, 1], [1, 1], [0, 0]], mode='CONSTANT') input = tf.expand_dims(input, axis=-2) winograd_out = tf.nn.conv2d(input, B, strides=[1, strides, strides, 1], padding='VALID') winograd_out = tf.squeeze(winograd_out, axis=-2) winograd_out = tf.transpose(winograd_out, [0, 1, 2, 4, 3]) winograd_out = tf.reshape(winograd_out, [-1, G, G, in_channels]) winograd_out = tf.matmul(winograd_out, A) winograd_out = tf.reshape(winograd_out, out_shape) # Pointwise convolution pointwise_out = tf.layers.conv2d(winograd_out, filter_shape[3], [1, 1], strides=[1, 1], padding='SAME') return pointwise_out ``` 在这个实现中,我们首先使用tensorflow的`depthwise_conv2d`函数来实现深度可分离卷积的深度可分离部分。然后,我们使用Winograd算法来实现深度可分离卷积的深度可分离部分。具体来说,我们将输入数据和卷积核都转换为$G\times G$的小块矩阵,并计算它们之间的矩阵乘积。最后,我们使用点卷积来实现深度可分离卷积的点卷积部分。 总之,基于tensorflow,使用Winograd算法改进深度可分离卷积是一种有效的加速深度学习模型的方法。通过使用Winograd算法,我们可以大大减少深度可分离卷积的计算复杂度,提高模型的效率和性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值