张量流中的基本一维卷积

新手上路,请多包涵

好的,我想在 Tensorflow 中对时间序列数据进行一维卷积。根据 这些 票据手册,这显然支持使用 tf.nn.conv2d 。唯一的要求是设置 strides=[1,1,1,1] 。听起来很简单!

但是,即使是非常小的测试用例,我也无法弄清楚如何做到这一点。我究竟做错了什么?

让我们设置一下。

 import tensorflow as tf
import numpy as np
print(tf.__version__)
>>> 0.9.0

好的,现在在两个小数组上生成一个基本的卷积测试。我会通过使用 1 的批量大小来简化它,并且由于时间序列是一维的,我将有一个 1 的“图像高度”。而且由于它是一个单变量时间序列,显然“通道”的数量也是1,所以这很简单,对吧?

 g = tf.Graph()
with g.as_default():
    # data shape is "[batch, in_height, in_width, in_channels]",
    x = tf.Variable(np.array([0.0, 0.0, 0.0, 0.0, 1.0]).reshape(1,1,-1,1), name="x")
    # filter shape is "[filter_height, filter_width, in_channels, out_channels]"
    phi = tf.Variable(np.array([0.0, 0.5, 1.0]).reshape(1,-1,1,1), name="phi")
    conv = tf.nn.conv2d(
        phi,
        x,
        strides=[1, 1, 1, 1],
        padding="SAME",
        name="conv")

繁荣。错误。

 ValueError: Dimensions 1 and 5 are not compatible

好的,首先,我不明白这应该如何在 任何 维度上发生,因为我已经指定我正在填充卷积 OP 中的参数。

但是很好,也许这有限制。我一定是把文档弄糊涂了,并在错误的张量轴上设置了这个卷积。我会尝试所有可能的排列:

 for i in range(4):
    for j in range(4):
        shape1 = [1,1,1,1]
        shape1[i] = -1
        shape2 = [1,1,1,1]
        shape2[j] = -1
        x_array = np.array([0.0, 0.0, 0.0, 0.0, 1.0]).reshape(*shape1)
        phi_array = np.array([0.0, 0.5, 1.0]).reshape(*shape2)
        try:
            g = tf.Graph()
            with g.as_default():
                x = tf.Variable(x_array, name="x")
                phi = tf.Variable(phi_array, name="phi")
                conv = tf.nn.conv2d(
                    x,
                    phi,
                    strides=[1, 1, 1, 1],
                    padding="SAME",
                    name="conv")
                init_op = tf.initialize_all_variables()
            sess = tf.Session(graph=g)
            sess.run(init_op)
            print("SUCCEEDED!", x_array.shape, phi_array.shape, conv.eval(session=sess))
            sess.close()
        except Exception as e:
            print("FAILED!", x_array.shape, phi_array.shape, type(e), e.args or e._message)

结果:

 FAILED! (5, 1, 1, 1) (3, 1, 1, 1) <class 'ValueError'> ('Filter must not be larger than the input: Filter: (3, 1) Input: (1, 1)',)
FAILED! (5, 1, 1, 1) (1, 3, 1, 1) <class 'ValueError'> ('Filter must not be larger than the input: Filter: (1, 3) Input: (1, 1)',)
FAILED! (5, 1, 1, 1) (1, 1, 3, 1) <class 'ValueError'> ('Dimensions 1 and 3 are not compatible',)
FAILED! (5, 1, 1, 1) (1, 1, 1, 3) <class 'tensorflow.python.framework.errors.InvalidArgumentError'> No OpKernel was registered to support Op 'Conv2D' with these attrs
     [[Node: conv = Conv2D[T=DT_DOUBLE, data_format="NHWC", padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](x/read, phi/read)]]
FAILED! (1, 5, 1, 1) (3, 1, 1, 1) <class 'tensorflow.python.framework.errors.InvalidArgumentError'> No OpKernel was registered to support Op 'Conv2D' with these attrs
     [[Node: conv = Conv2D[T=DT_DOUBLE, data_format="NHWC", padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](x/read, phi/read)]]
FAILED! (1, 5, 1, 1) (1, 3, 1, 1) <class 'ValueError'> ('Filter must not be larger than the input: Filter: (1, 3) Input: (5, 1)',)
FAILED! (1, 5, 1, 1) (1, 1, 3, 1) <class 'ValueError'> ('Dimensions 1 and 3 are not compatible',)
FAILED! (1, 5, 1, 1) (1, 1, 1, 3) <class 'tensorflow.python.framework.errors.InvalidArgumentError'> No OpKernel was registered to support Op 'Conv2D' with these attrs
     [[Node: conv = Conv2D[T=DT_DOUBLE, data_format="NHWC", padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](x/read, phi/read)]]
FAILED! (1, 1, 5, 1) (3, 1, 1, 1) <class 'ValueError'> ('Filter must not be larger than the input: Filter: (3, 1) Input: (1, 5)',)
FAILED! (1, 1, 5, 1) (1, 3, 1, 1) <class 'tensorflow.python.framework.errors.InvalidArgumentError'> No OpKernel was registered to support Op 'Conv2D' with these attrs
     [[Node: conv = Conv2D[T=DT_DOUBLE, data_format="NHWC", padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](x/read, phi/read)]]
FAILED! (1, 1, 5, 1) (1, 1, 3, 1) <class 'ValueError'> ('Dimensions 1 and 3 are not compatible',)
FAILED! (1, 1, 5, 1) (1, 1, 1, 3) <class 'tensorflow.python.framework.errors.InvalidArgumentError'> No OpKernel was registered to support Op 'Conv2D' with these attrs
     [[Node: conv = Conv2D[T=DT_DOUBLE, data_format="NHWC", padding="SAME", strides=[1, 1, 1, 1], use_cudnn_on_gpu=true](x/read, phi/read)]]
FAILED! (1, 1, 1, 5) (3, 1, 1, 1) <class 'ValueError'> ('Dimensions 5 and 1 are not compatible',)
FAILED! (1, 1, 1, 5) (1, 3, 1, 1) <class 'ValueError'> ('Dimensions 5 and 1 are not compatible',)
FAILED! (1, 1, 1, 5) (1, 1, 3, 1) <class 'ValueError'> ('Dimensions 5 and 3 are not compatible',)
FAILED! (1, 1, 1, 5) (1, 1, 1, 3) <class 'ValueError'> ('Dimensions 5 and 1 are not compatible',)

唔。 OK,现在看起来有两个问题。首先,我猜 ValueError 是关于沿错误的轴应用过滤器,尽管有两种形式。

但是我可以应用过滤器的轴也很混乱 - 请注意,它实际上构建了具有输入形状 (5, 1, 1, 1) 和过滤器形状 (1, 1, 1, 3) 的图形。根据文档的 AFAICT,这应该是一个过滤器,它查看批处理中的示例,一个“像素”和一个“通道”并输出 3 个“通道”。那么,为什么那个有效,而其他无效呢?

无论如何,有时在构建图形时它不会失败。有时它构建图形;然后我们得到 tensorflow.python.framework.errors.InvalidArgumentError 。从一些 令人困惑的 github 门票 中我收集到这可能是由于我在 CPU 而不是 GPU 上运行的事实,反之亦然事实上,卷积 Op 仅针对 32 位浮点数定义,而不是 64 位浮点数。如果有人可以阐明我应该对齐 哪些 以便将时间序列与内核进行卷积,我将不胜感激。

原文由 dan mackinlay 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 307
2 个回答

很抱歉这么说,但你的第一个代码几乎是正确的。您刚刚 xphi 反转为 tf.nn.conv2d

 g = tf.Graph()
with g.as_default():
    # data shape is "[batch, in_height, in_width, in_channels]",
    x = tf.Variable(np.array([0.0, 0.0, 0.0, 0.0, 1.0]).reshape(1, 1, 5, 1), name="x")
    # filter shape is "[filter_height, filter_width, in_channels, out_channels]"
    phi = tf.Variable(np.array([0.0, 0.5, 1.0]).reshape(1, 3, 1, 1), name="phi")
    conv = tf.nn.conv2d(
        x,
        phi,
        strides=[1, 1, 1, 1],
        padding="SAME",
        name="conv")


更新: TensorFlow 从 r0.11 版本开始支持一维卷积,使用 tf.nn.conv1d 。我之前在我粘贴在这里的 stackoverflow 文档(现已绝迹)中制作了一个使用它们的指南:


一维卷积指南

考虑一个输入长度为 10 和维度为 16 的基本示例。批量大小为 32 。因此,我们有一个输入形状为 [batch_size, 10, 16] 的占位符。

 batch_size = 32
x = tf.placeholder(tf.float32, [batch_size, 10, 16])

然后我们创建一个宽度为 3 的过滤器,我们将 16 通道作为输入,并输出 16 通道。

 filter = tf.zeros([3, 16, 16])  # these should be real values, not 0


最后我们应用 tf.nn.conv1d 带一个步幅和一个填充: - 步幅:整数 s - 填充:这就像在 2D 中一样,你可以在 SAMEVALID 之间进行选择 ---SAME 将输出相同的输入长度,而 VALID 将不添加零填充。

对于我们的示例,我们采用 2 的步幅和有效的填充。

 output = tf.nn.conv1d(x, filter, stride=2, padding="VALID")

输出形状应为 [batch_size, 4, 16]

使用 padding="SAME" ,我们的输出形状为 [batch_size, 5, 16]

原文由 Olivier Moindrot 发布,翻译遵循 CC BY-SA 3.0 许可协议

在新版本的 TF 中(从 0.11 开始)你有 conv1d ,所以不需要使用 2d 卷积来做 1d 卷积。这是一个如何使用 conv1d 的简单示例:

 import tensorflow as tf
i = tf.constant([1, 0, 2, 3, 0, 1, 1], dtype=tf.float32, name='i')
k = tf.constant([2, 1, 3], dtype=tf.float32, name='k')

data   = tf.reshape(i, [1, int(i.shape[0]), 1], name='data')
kernel = tf.reshape(k, [int(k.shape[0]), 1, 1], name='kernel')

res = tf.squeeze(tf.nn.conv1d(data, kernel, stride=1, padding='VALID'))
with tf.Session() as sess:
    print sess.run(res)

要了解 conv1d 是如何计算的,请查看 各种示例

原文由 Salvador Dali 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题