基于Keras中Conv1D和Conv2D的区别说明
如有错误,欢迎斧正。
我的答案是,在Conv2D输入通道为1的情况下,二者是没有区别或者说是可以相互转化的。首先,二者调用的最后的代码都是后端代码(以TensorFlow为例,在tensorflow_backend.py里面可以找到):
x = tf.nn.convolution( input=x, filter=kernel, dilation_rate=(dilation_rate,), strides=(strides,), padding=padding, data_format=tf_data_format)
区别在于input和filter传递的参数不同,input不必说,filter=kernel是什么呢?
我们进入Conv1D和Conv2D的源代码看一下。他们的代码位于layers/convolutional.py里面,二者继承的都是基类_Conv(Layer)。
进入_Conv类查看代码可以发觉以下代码:
self.kernel_size = conv_utils.normalize_tuple(kernel_size, rank, 'kernel_size') ……#中间代码省略 input_dim = input_shape[channel_axis] kernel_shape = self.kernel_size + (input_dim, self.filters)
我们假设,Conv1D的input的大小是(600,300),而Conv2D的input大小是(m,n,1),二者kernel_size为3。
进入conv_utils.normalize_tuple函数可以看到:
def normalize_tuple(value, n, name): """Transforms a single int or iterable of ints into an int tuple. # Arguments value: The value to validate and convert. Could an int, or any iterable of ints. n: The size of the tuple to be returned. name: The name of the argument being validated, e.g. "strides" or "kernel_size". This is only used to format error messages. # Returns A tuple of n integers. # Raises ValueError: If something else than an int/long or iterable thereof was passed. """ if isinstance(value, int): return (value,) * n else: try: value_tuple = tuple(value) except TypeError: raise ValueError('The `' + name + '` argument must be a tuple of ' + str(n) + ' integers. Received: ' + str(value)) if len(value_tuple) != n: raise ValueError('The `' + name + '` argument must be a tuple of ' + str(n) + ' integers. Received: ' + str(value)) for single_value in value_tuple: try: int(single_value) except ValueError: raise ValueError('The `' + name + '` argument must be a tuple of ' + str(n) + ' integers. Received: ' + str(value) + ' ' 'including element ' + str(single_value) + ' of type' + ' ' + str(type(single_value))) return value_tuple
所以上述代码得到的kernel_size是kernel的实际大小,根据rank进行计算,Conv1D的rank为1,Conv2D的rank为2,如果是Conv1D,那么得到的kernel_size就是(3,)如果是Conv2D,那么得到的是(3,3)
input_dim = input_shape[channel_axis] kernel_shape = self.kernel_size + (input_dim, self.filters)
又因为以上的inputdim是最后一维大小(Conv1D中为300,Conv2D中为1),filter数目我们假设二者都是64个卷积核。
因此,Conv1D的kernel的shape实际为:
(3,300,64)
而Conv2D的kernel的shape实际为:
(3,3,1,64)
刚才我们假设的是传参的时候kernel_size=3,如果,我们将传参Conv2D时使用的的kernel_size设置为自己的元组例如(3,300),那么传根据conv_utils.normalize_tuple函数,最后的kernel_size会返回我们自己设置的元组,也即(3,300)那么Conv2D的实际shape是:
(3,300,1,64),也即这个时候的Conv1D的大小reshape一下得到,二者等价。
换句话说,Conv1D(kernel_size=3)实际就是Conv2D(kernel_size=(3,300)),当然必须把输入也reshape成(600,300,1),即可在多行上进行Conv2D卷积。
这也可以解释,为什么在Keras中使用Conv1D可以进行自然语言处理,因为在自然语言处理中,我们假设一个序列是600个单词,每个单词的词向量是300维,那么一个序列输入到网络中就是(600,300),当我使用Conv1D进行卷积的时候,实际上就完成了直接在序列上的卷积,卷积的时候实际是以(3,300)进行卷积,又因为每一行都是一个词向量,因此使用Conv1D(kernel_size=3)也就相当于使用神经网络进行了n_gram=3的特征提取了。
这也是为什么使用卷积神经网络处理文本会非常快速有效的内涵。
补充知识:tf.layer.conv1d、conv2d、conv3d
下面我都是抄的,如果说是正确,那么conv3d就是2d+时间域的吧?
网上搜的一篇资料,还没看:tensorflow中一维卷积conv1d处理语言序列的一点记录
tensorflow中的conv1d和conv2d的区别:conv1d是单通道的,conv2d是多通道,所以conv1d适合处理文本序列,conv2d适合处理图像。
conv1d
import tensorflow as tf input = tf.Variable(tf.random_normal([1, 5, 20])) params1 = {"inputs": input, "filters": 2048, "kernel_size": 2,"strides":1,"activation": tf.nn.relu, "use_bias": True,"padding":'SAME'} op01 = tf.layers.conv1d(**params1) init = tf.initialize_all_variables() with tf.Session() as sess: sess.run(init) print(sess.run(tf.shape(op01))) >>>[1,5,2048]
输入input第一维为batch_size,此处为1,即只有一个样本,第二维和第三维分别表示输入的长和宽,在文本中就是word_embedding矩阵,句子长度为5,embedding维度为20。
在文本中,卷积的某一维大小往往为embedding长度,即在宽度上不需要窗口移动,宽度就是整个窗口。所以conv1d默认卷积的宽度就为embedding维度,长度是通过kernel_size来指定的,此处为2,即卷积核的大小为2*embedding_size。strides为步长,此处为1,即卷积核每隔一个单词移动一次。filters是卷积核的个数,即输出的维度。padding有valid和same两种选择,valid在长度方向(宽度方向不padding)不进行padding,而same则在长度方向进行padding,保证输入句子长度和卷积后输出的句子长度一致,此处为5。
conv2d
#case 1 #input输入是1张 3*3 大小的图片,图像通道数是5(batch,长,宽,输入通道数) #filter卷积核是 1*1 大小,数量是1(长,宽,输入通道数,输出通道数(卷积核个数)) #strides步长是[1,1,1,1],第一维和最后一维保持1不变,第二维和第三维分别为长度方向和宽度方向的步长。 #1张图最后输出的op1就是一个 shape为[1,3,3,1] 的张量,即得到一个3*3的feature map(batch,长,宽,输出通道数) input = tf.Variable(tf.random_normal([1, 3, 3, 5])) filter = tf.Variable(tf.random_normal([1, 1, 5, 1])) op1 = tf.nn.conv2d(input, filter, strides=[1, 1, 1, 1], padding='SAME')
这是另一个内容
class AveragePooling1D:1D输入的平均池层.
class AveragePooling2D:2D输入的平均池层(例如图像).
class AveragePooling3D:3D输入的平均池层(例如,体积).
class Conv1D:一维卷积层(例如时间卷积).
class Conv2D:二维卷积层(例如图像上的空间卷积).
class Conv3D:3D卷积层(例如卷上的空间卷积).
class MaxPooling1D:1D输入的最大池层.
class MaxPooling2D:2D输入的最大池层(例如图像).
class MaxPooling3D:3D输入的最大池层(例如卷).
以上这篇基于Keras中Conv1D和Conv2D的区别说明就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。