tensorflow实现空洞卷积(dilated connvolution也叫扩张卷积)

wavenet在做语音合成的时候,用到了dilated connvolution(空洞卷积).关于空洞卷积的介绍,知乎的这篇文章写的不错:

https://www.zhihu.com/question/54149221/answer/192025860

关于在tensorflow中实现一般的卷积,可以参考:

https://blog.csdn.net/u010866505/article/details/80917180

https://blog.csdn.net/mao_xiao_feng/article/details/78004522

由于一般cnn在昨晚卷积之后会对feature map进行downSampling,这样会造成一定的信息丢失.那么空洞卷积就是没有pooling层,同时可以扩大感受野(如上知乎的讲解)

接下来,我用tensorflow的api来介绍一下空洞卷积的发生过程。

tf.nn.atrous_conv2d(value,filters,rate,padding,name=None

这是tensorflow的空洞卷积的api,value和filter是输入和卷积核.详细可参考:

https://blog.csdn.net/u010866505/article/details/80917180

rate:在一般的cnn的api中,会有stride这个参数,但是在空洞卷积里面是没有的.这个参数是扩大采样间隔,即在卷积核中插入rate-1个'0'得到新的卷积核,当rate=1时,新的卷积核和旧的相同,卷积过程等同于安普通的卷积过程.

padding:这个和是之前的一样.

接下来用一个例子来说明空洞卷积的过程:

如下三张通道图(5*5):

 即input:

0

1

1

2

2

0

1

1

0

0

1

1

0

1

0

1

0

1

1

1

0

2

0

1

0

 

1

1

1

2

0

0

2

1

1

2

1

2

0

0

2

0

2

1

2

1

2

0

1

2

0

 

2

0

2

0

2

0

0

1

2

1

1

0

2

2

1

2

0

2

0

0

0

0

1

1

2


三个滤波器(3*3):

-1

-1

0

-1

1

0

-1

1

0


1

-1

0

-1

0

-1

-1

0

0


-1

0

1

1

0

1

0

-1

0


接下来,我们看取rate=1和rate=2两种情况来说明,这里padding选取'SAME',取'VALID'原理一样。

当rate=1,此时的卷积过程和普通卷积过程是一样的.

最终输出的结果是:


接下来着重讲rate=2:

当rate=2时,之前的卷积核,需要在每个点中间插入1个'0',于是乎,之前的卷积核就是如下图所示:


以上就是新的卷积核。根据公式计算出新的输入需要pad的像素点:

padding='SAME':

new_width = 5:

需要pad的像素点是(new_width-1)*S + F - W

S=1(在后面的卷积过程中,滤波器每次只移动一步)

F = 5(新卷积核的size=5*5)

W = 5(输入的size=5*5)

因此需要pad的像素点是4,上下各一半都为2,因此输入的矩阵就变成了如下所示的:







然后用新的卷积核和新的输入,进行卷积,求和,最后得到的结果是:


上述结果经过笔验算成功.

如下是上述的简易代码:

import tensorflow as tf
import numpy as np
input_data=[
              [[0,1,1,2,2],
               [0,1,1,0,0],
               [1,1,0,1,0],
               [1,0,1,1,1],
               [0,2,0,1,0]],

               [[1,1,1,2,0],
                [0,2,1,1,2],
                [1,2,0,0,2],
                [0,2,1,2,1],
                [2,0,1,2,0]],

               [[2,0,2,0,2],
                [0,0,1,2,1],
                [1,0,2,2,1],
                [2,0,2,0,0],
                [0,0,1,1,2]]

            ]
weights_data=[ 
               [[ -1, -1, 0],
                [-1, 1, 0],
                [ -1,1, 0]],
               [[1, -1, 0],
                [ -1, 0, -1],
                [ -1, 0, 0]],
                [[-1, 0, 1],
                [ 1, 0, 1],
                [ 0, -1, 0]]  
           ]
def get_shape(tensor):
    [s1,s2,s3]= tensor.get_shape() 
    s1=int(s1)
    s2=int(s2)
    s3=int(s3)
    return s1,s2,s3

def chw2hwc(chw_tensor): 
    [c,h,w]=get_shape(chw_tensor) 
    cols=[]

    for i in range(c):
        #每个通道里面的二维数组转为[w*h,1]即1列 
        line = tf.reshape(chw_tensor[i],[h*w,1])
        cols.append(line)

    #横向连接,即将所有竖直数组横向排列连接
    input = tf.concat(cols,1)#[w*h,c]
    #[w*h,c]-->[h,w,c]
    input = tf.reshape(input,[h,w,c])
    return input

def hwc2chw(hwc_tensor):
    [h,w,c]=get_shape(hwc_tensor) 
    cs=[] 
    for i in range(c): 
        #[h,w]-->[1,h,w] 
        channel=tf.expand_dims(hwc_tensor[:,:,i],0)
        cs.append(channel)
    #[1,h,w]...[1,h,w]---->[c,h,w]
    input = tf.concat(cs,0)#[c,h,w]
    return input

def tf_dilatedConv2d(input,weights,rate,pad):
    conv = tf.nn.atrous_conv2d(input, weights, rate, pad)
    return conv

def main(): 
    const_input = tf.constant(input_data , tf.float32)
    const_weights = tf.constant(weights_data , tf.float32 )


    input = tf.Variable(const_input,name="input")
    #[3,5,5]------>[5,5,3]
    input=chw2hwc(input)
    #[5,5,3]------>[1,5,5,32]
    input=tf.expand_dims(input,0)


    weights = tf.Variable(const_weights,name="weights")
    #[3,3,3]-->[3,3,3]
    weights=chw2hwc(weights)
    #[3,3,3]-->[3,3,3,1]
    weights=tf.expand_dims(weights,3) 

    #[b,h,w,c]
    conv=tf_dilatedConv2d(input,weights,1,'SAME')
    rs=hwc2chw(conv[0]) 

    init=tf.global_variables_initializer()
    sess=tf.Session()
    sess.run(init)
    conv_val = sess.run(rs)
    print('rate=1:')
    print(conv_val[0]) 

    conv=tf_dilatedConv2d(input,weights,2,'SAME')
    rs=hwc2chw(conv[0]) 

    init=tf.global_variables_initializer()
    sess=tf.Session()
    sess.run(init)
    conv_val = sess.run(rs)
    print('rate=2:')
    print(conv_val[0]) 

if __name__=='__main__':
    main()

如果OK,点个赞呗.哈哈!




  • 29
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
### 回答1: 残差空洞卷积(Residual Dilated Convolution)是一种深度学习中常用的卷积操作,用于增加神经网络的感受野。这种卷积是在原始的卷积操作上引入了残差连接和空洞卷积的思想。 Tensorflow代码实现残差空洞卷积如下: 首先,我们导入需要使用的tensorflow库和函数: ```python import tensorflow as tf from tensorflow.keras.layers import Conv2D, BatchNormalization, Activation ``` 然后,定义残差空洞卷积的函数: ```python def residual_dilated_conv(x, filters, kernel_size, dilations): # 1x1卷积降维 shortcut = Conv2D(filters, (1, 1), padding='same')(x) # 空洞卷积 out = Conv2D(filters, kernel_size, padding='same', dilation_rate=dilations[0])(x) out = BatchNormalization()(out) out = Activation('relu')(out) # 多次空洞卷积 for dilation in dilations[1:]: out = Conv2D(filters, kernel_size, padding='same', dilation_rate=dilation)(out) out = BatchNormalization()(out) out = Activation('relu')(out) # 残差连接 out = tf.keras.layers.add([shortcut, out]) out = Activation('relu')(out) return out ``` 使用这个函数来构建残差空洞卷积网络: ```python input = tf.keras.layers.Input(shape=(None, None, 3)) x = input # 构建残差空洞卷积网络 num_filters = 64 kernel_size = (3, 3) dilations = [1, 2, 4, 8] for dilation in dilations: x = residual_dilated_conv(x, num_filters, kernel_size, [dilation]) model = tf.keras.models.Model(inputs=input, outputs=x) ``` 以上就是使用Tensorflow实现残差空洞卷积的代码。在使用时,可以根据需要调整卷积的层数、输出通道数和卷积核的大小等参数。这个残差空洞卷积网络可以用于图像处理、语义分割等任务中,能够有效提取图像的空间特征。 ### 回答2: 残差空洞卷积(Residual Dilated Convolution)是一种卷积神经网络中常用的操作。下面我会用300字的中文解释如何在TensorFlow实现这个操作。 首先,残差空洞卷积是由空洞卷积Dilated Convolution)和残差连接(Residual Connection)两部分组成的。空洞卷积是通过在卷积核中引入“孔洞”,使得卷积核可以在更大的感受野内获取特征信息。残差连接是将输入特征图直接与卷积操作的输出特征图相加,从而提高网络的表示能力。 在TensorFlow中,可以使用tf.nn.conv2d函数来进行标准的卷积操作。要实现残差空洞卷积,可以按照以下步骤进行: 1. 定义卷积核的权重变量:可以使用tf.Variable函数来定义一个卷积核的权重变量,例如W1。需要注意的是,卷积核的维度应该根据输入特征图和输出特征图的通道数量来决定。 2. 进行卷积操作:使用tf.nn.conv2d函数来实现卷积操作,并传入输入特征图、卷积核、步长、填充等参数。得到的输出特征图可以表示为conv1。 3. 添加残差连接:将输入特征图与输出特征图相加,可以使用tf.add函数来实现。最终的输出特征图可以表示为residual1 = input + conv1。 4. 对输出特征图进行激活函数处理:可以使用tf.nn.relu函数来对输出特征图进行ReLU激活。 以上就是在TensorFlow实现残差空洞卷积的基本步骤。通过适当调整卷积核的参数和其他超参数,可以进一步优化这个操作。不过,由于字数限制,无法展开更多细节,希望以上回答对您有所帮助。 ### 回答3: 残差空洞卷积(Residual Dilated Convolution)是一种用于深度学习模型中的卷积操作技术。在TensorFlow中,可以使用以下代码实现残差空洞卷积: ```python import tensorflow as tf def residual_dilated_convolution(input, filters, dilations): # 定义残差空洞卷积的输入层 input_layer = tf.keras.layers.Input(shape=input) # 定义残差空洞卷积的主要网络结构 x = input_layer for i, dilation in enumerate(dilations): # 定义残差空洞卷积的一个卷积conv1 = tf.keras.layers.Conv1D(filters=filters, kernel_size=3, padding='same', dilation_rate=dilation)(x) # 定义残差空洞卷积的激活层 act1 = tf.keras.layers.Activation('relu')(conv1) # 定义残差空洞卷积的另一个卷积conv2 = tf.keras.layers.Conv1D(filters=filters, kernel_size=3, padding='same', dilation_rate=dilation)(act1) # 使用跳跃连接将残差层与卷积层相加 x = tf.keras.layers.add([x, conv2]) # 定义残差空洞卷积的输出层 output_layer = tf.keras.layers.Activation('relu')(x) # 构建并返回残差空洞卷积模型 model = tf.keras.models.Model(inputs=input_layer, outputs=output_layer) return model ``` 以上代码中,`input`参数表示输入张量的形状,`filters`参数表示输出张量的通道数,`dilations`参数表示空洞卷积的膨胀率。在函数中,通过使用循环来构建多个残差空洞卷积层,其中每层都包括两个卷积层和一个跳跃连接。最后,通过将输入和输出张量传递给`tf.keras.models.Model`函数,构建并返回残差空洞卷积模型。 残差空洞卷积可以增加模型的感受野( receptive field),有效地提取输入数据的空间特征。在深度学习中,这种技术通常应用于语音识别、图像分割和自然语言处理等领域。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值