这几天在看代码,然后看网上关于一维卷积介绍的文档很多,但是对于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]
举例,令被一维卷积的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时介绍。
举例,令被一维卷积的value维度是:(2,3,4)
令卷积核的filter维度是:(2,4,5)
即 [filter_width, in_channels, out_channels] = (2,4,5)
filter_width =2 说明每次对value里的2行进行卷积:
tf.nn.conv1d 一次对一个batch进行卷积处理,batch之间互不影响 ,所以这里以第一个batch中的计算进行说明:
咱们这里设置的filter_width =2, 说明每次对value里的2行进行卷积。
则:
以此类推,完成一个batch的计算后,第二个batch的计算过程也如此。
所以value整体VALID卷积的结果是:
刚才在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为例,整体运算过程是:
以此类推,完成一个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~~