Хорошо, я хотел бы сделать одномерную свертку данных временных рядов в Tensorflow. Это, по-видимому, поддерживается с использованием tf.nn.conv2d
, в соответствии с этими билетами и руководством. единственное требование - установить strides=[1,1,1,1]
. Звучит просто!
Однако я не могу понять, как это сделать даже в очень минимальном тестовом случае. Что я делаю не так?
Позвольте установить это.
import tensorflow as tf
import numpy as np
print(tf.__version__)
>>> 0.9.0
OK, теперь создайте базовый тест свертки на двух небольших массивах. Я сделаю это легко, используя размер партии 1, а так как временные ряды 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
OK. Для начала я не понимаю, как это должно происходить с любым измерением, поскольку я указал, что я заполняю аргументы в свертке 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',)
Хм. Хорошо, похоже, что есть две проблемы. Во-первых, ValueError
- это применение фильтра вдоль неправильной оси, я думаю, хотя есть две формы.
Но тогда оси, вдоль которых я могу применить фильтр, тоже сбивают с толку - обратите внимание, что он фактически создает граф с формой ввода (5, 1, 1, 1) и формой фильтра (1, 1, 1, 3). AFAICT из документации, это должен быть фильтр, который выглядит, например, из пакета, один "пиксель" и один "канал" и выводит 3 "канала". Почему же это работает, когда другие не делают этого?
Во всяком случае, иногда это не сбой при построении графика. Когда-то он строит график; то мы получаем tensorflow.python.framework.errors.InvalidArgumentError
. Из некоторых запутанных билетов на github я понимаю, что это, вероятно, связано с тот факт, что я запускаю CPU вместо графического процессора или наоборот тот факт, что свертка Op определена только для 32-битных поплавков, а не для 64-битных поплавков. Если бы кто-нибудь мог пролить свет на то, какие оси я должен выровнять, для того, чтобы сверлить временные ряды с ядром, я был бы очень благодарен.