一维卷积 以例子说明 tf.nn.conv1d 矩阵运算过程

这几天在看代码,然后看网上关于一维卷积介绍的文档很多,但是对于tf.nn.conv1d 矩阵运算过程几乎没有介绍,这里我就将刚弄懂的写出来,希望能帮到大家理解这个函数,也为了让自己以后能更好的查阅~~


conv1d(value,  filters, stride, padding, use_cudnn_on_gpu=None, data_format=None, name=None)

value: A 3D Tensor. Must be of type float16 or float32.
被卷积的矩阵:可以当成是[batch, sample, feature]

filters: A 3D Tensor. Must have the same type as input.
卷积核:形状 [filter_width, in_channels, out_channels]

stride: An integer. The number of entries by which the filter is moved right at each step.
步长:卷积核滑动步长

padding: ‘SAME’ or ‘VALID’
same和valid可以参考这篇文档:深度学习面试题09:一维卷积(Full卷积、Same卷积、Valid卷积、带深度的一维卷积)

废话不多说,咱们今天不讲原理,只讲其中矩阵运算过程~ 帮助大家理解~


卷积核filter 的形状:[filter_width, in_channels, out_channels]

  • in_channels 必须等于被卷积的矩阵的第3维数,即列数
  • out_channels 表示卷积核数目,类似于图像里,一个卷积核得到一个输出,这里有|out_channels |个卷积核,则输出必定有|out_channels|
  • filter_width 表示与 value 进行卷积的 个数/每次 (这里不懂可以以往后看例子)

例一:filter_width=1时:

举例,令被一维卷积的value维度是:(2,3,4)
在这里插入图片描述
令卷积核的filter维度是:(1,4,5)
即 [filter_width, in_channels, out_channels] = (1,4,5)
在这里插入图片描述
filter_width =1 说明每次对value里的一行进行卷积:

以value第一个batch里为例:

第一个batch中第1行的计算过程是:
在这里插入图片描述
第一个batch中第2行的计算过程是:
在这里插入图片描述
tf.nn.conv1d 一次对一个batch进行卷积处理,batch之间互不影响。
以此类推,完成一个batch的计算后,第二个batch的计算过程也如此。
所以value整体卷积的结果是:
在这里插入图片描述
以上filter_width=1时的代码如下:

sess= tf.Session()
    a = tf.Variable(np.random.randint(1,3,(2,3,4)))
    filt = tf.get_variable("weights", initializer=np.random.randint(1,3,(1,4,5)))

    sess.run(tf.global_variables_initializer())
    print(sess.run(a))
    print('\n')
    print(sess.run(filt))
    filt_input = tf.nn.conv1d(tf.to_float(a), tf.to_float(filt), 1, "VALID", name="embedded_input")
    print(sess.run(filt_input))

由于filter_width=1时,valid和same的计算没啥区别,这里不讲,在filter_width>1时介绍。


例二:filter_width>1时:

举例,令被一维卷积的value维度是:(2,3,4)
在这里插入图片描述
令卷积核的filter维度是:(2,4,5)
即 [filter_width, in_channels, out_channels] = (2,4,5)
在这里插入图片描述
filter_width =2 说明每次对value里的2行进行卷积:

1. VALID 时:

tf.nn.conv1d 一次对一个batch进行卷积处理,batch之间互不影响 ,所以这里以第一个batch中的计算进行说明:
咱们这里设置的filter_width =2, 说明每次对value里的2行进行卷积。
则:

  • 第一次计算取1,2行进行卷积,第1行和卷积核的第一大块,也就是(0,:,:)进行矩阵乘法,第2行和卷积核的第二大块,也就是(1,:,:)进行矩阵乘法,结果相加得到第一次卷积结果:

在这里插入图片描述

  • 第二次计算取2,3行进行卷积,第2行和卷积核的第一大块,也就是(0,:,:)进行矩阵乘法,第3行和卷积核的第二大块,也就是(1,:,:)进行矩阵乘法,结果相加得到第二次卷积结果:
    在这里插入图片描述

以此类推,完成一个batch的计算后,第二个batch的计算过程也如此。

所以value整体VALID卷积的结果是:
在这里插入图片描述


2. SAME 时:

刚才在VALID中,第一次计算取value的1,2行进行卷积,第二次取value的2,3行进行卷积。
也就是说VALID中,filter_width =2时每次取两行来卷积,然后只要value的1,2,3行全部都处理完了就OK。也就是一共进行了两次卷积,得到的卷积的结果,每个batch的行数为两行
而这里的 “SAME”,为了保证卷积后的结果每个batch的行数和原先VALUE行数相等(原先Value中每个batch有3行),所以还需要再在VALID基础上做一次卷积!

以第一个batch为例,整体运算过程是:

  • 第一次计算取1,2行进行卷积,第1行和卷积核的第一大块,也就是(0,:,:)进行矩阵乘法,第2行和卷积核的第二大块,也就是(1,:,:)进行矩阵乘法,相加得到第一次卷积结果:
    在这里插入图片描述
  • 第二次计算取2,3行进行卷积,第2行和卷积核的第一大块,也就是(0,:,:)进行矩阵乘法,第3行和卷积核的第二大块,也就是(1,:,:)进行矩阵乘法,相加得到第二次卷积结果:
    在这里插入图片描述
  • 第三次计算按理来说,每次取两行来卷积,这里就要取3,4行进行卷积,但是这里VALUE中没有第4行,所以只需要第3行和卷积核的第一大块,也就是(0,:,:)进行矩阵乘法,得到第三次卷积结果:
    在这里插入图片描述
    这样就保证了计算结果是3行。

以此类推,完成一个batch的计算后,第二个batch的计算过程也如此。

所以value整体SAME卷积的结果是:
在这里插入图片描述

这里VALID和SAME代码如下:

sess= tf.Session()
    a = tf.Variable(np.random.randint(1,3,(2,3,4)))
    filt = tf.get_variable("weights", initializer=np.random.randint(1,3,(2,4,5)))

    sess.run(tf.global_variables_initializer())
    print(sess.run(a))
    print('\n')
    print(sess.run(filt))
    filt_input = tf.nn.conv1d(tf.to_float(a), tf.to_float(filt), 1, "VALID", name="embedded_input")
    filt_input2 = tf.nn.conv1d(tf.to_float(a), tf.to_float(filt), 1, "SAME", name="embedded_input")
    print(sess.run(filt_input))
    print(sess.run(filt_input2))

个人觉得filter_width=1的时候更适合做embedding~~

你可能感兴趣的:(Tensorflow笔记)