好的,我想在 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 许可协议
很抱歉这么说,但你的第一个代码几乎是正确的。您刚刚
x
和phi
反转为tf.nn.conv2d
:更新: TensorFlow 从 r0.11 版本开始支持一维卷积,使用
tf.nn.conv1d
。我之前在我粘贴在这里的 stackoverflow 文档(现已绝迹)中制作了一个使用它们的指南:一维卷积指南
考虑一个输入长度为
10
和维度为16
的基本示例。批量大小为32
。因此,我们有一个输入形状为[batch_size, 10, 16]
的占位符。然后我们创建一个宽度为 3 的过滤器,我们将
16
通道作为输入,并输出16
通道。最后我们应用
tf.nn.conv1d
带一个步幅和一个填充: - 步幅:整数s
- 填充:这就像在 2D 中一样,你可以在SAME
和VALID
之间进行选择---
。SAME
将输出相同的输入长度,而VALID
将不添加零填充。对于我们的示例,我们采用 2 的步幅和有效的填充。
输出形状应为
[batch_size, 4, 16]
。使用
padding="SAME"
,我们的输出形状为[batch_size, 5, 16]
。