Как исправить "ValueError: Операнды не могут передаваться вместе с фигурами (2592,) (4,)" в Tensorflow?
В настоящее время я проектирую слой NoisyNet, как предлагается здесь: "Шумные сети для исследования", в Tensorflow и получаю ошибку размерности, как указано в заголовке, в то время как размеры двух тензоров должны быть умножены поэлементно в линию filtered_output = keras.layers.merge.Multiply()([output, actions_input])
должны (в принципе) быть совместимыми друг с другом в соответствии с выводом на печать при печати размеров обоих задействованных тензоров, filtered_output
а также actions_input
где оба тензора кажутся размерными shape=(1, 4)
,
Я использую Tensorflow 1.12.0 в Python3.
Соответствующий код выглядит следующим образом:
import numpy as np
import tensorflow as tf
import keras
class NoisyLayer(keras.layers.Layer):
def __init__(self, in_shape=(1,2592), out_units=256, activation=tf.identity):
super(NoisyLayer, self).__init__()
self.in_shape = in_shape
self.out_units = out_units
self.mu_interval = 1.0/np.sqrt(float(self.out_units))
self.sig_0 = 0.5
self.activation = activation
self.assign_resampling()
def build(self, input_shape):
# Initializer
self.mu_initializer = tf.initializers.random_uniform(minval=-self.mu_interval, maxval=self.mu_interval) # Mu-initializer
self.si_initializer = tf.initializers.constant(self.sig_0/np.sqrt(float(self.out_units))) # Sigma-initializer
# Weights
self.w_mu = tf.Variable(initial_value=self.mu_initializer(shape=(self.in_shape[-1], self.out_units), dtype='float32'), trainable=True) # (1,2592)x(2592,4) = (1,4)
self.w_si = tf.Variable(initial_value=self.si_initializer(shape=(self.in_shape[-1], self.out_units), dtype='float32'), trainable=True)
# Biases
self.b_mu = tf.Variable(initial_value=self.mu_initializer(shape=(self.in_shape[0], self.out_units), dtype='float32'), trainable=True)
self.b_si = tf.Variable(initial_value=self.si_initializer(shape=(self.in_shape[0], self.out_units), dtype='float32'), trainable=True)
def call(self, inputs, resample_noise_flag):
if resample_noise_flag:
self.assign_resampling()
# Putting it all together
self.w = tf.math.add(self.w_mu, tf.math.multiply(self.w_si, self.w_eps))
self.b = tf.math.add(self.b_mu, tf.math.multiply(self.b_si, self.q_eps))
return self.activation(tf.linalg.matmul(inputs, self.w) + self.b)
def assign_resampling(self):
self.p_eps = self.f(self.resample_noise([self.in_shape[-1], 1]))
self.q_eps = self.f(self.resample_noise([1, self.out_units]))
self.w_eps = self.p_eps * self.q_eps # Cartesian product of input_noise x output_noise
def resample_noise(self, shape):
return tf.random.normal(shape, mean=0.0, stddev=1.0, seed=None, name=None)
def f(self, x):
return tf.math.multiply(tf.math.sign(x), tf.math.sqrt(tf.math.abs(x)))
frames_input = tf.ones((1, 84, 84, 4)) # Toy input
conv1 = keras.layers.Conv2D(16, (8, 8), strides=(4, 4), activation="relu")(frames_input)
conv2 = keras.layers.Conv2D(32, (4, 4), strides=(2, 2), activation="relu")(conv1)
flattened = keras.layers.Flatten()(conv2)
actionspace_size = 4
# NoisyNet
hidden = NoisyLayer(activation=tf.nn.relu)(inputs=flattened, resample_noise_flag=True)
output = NoisyLayer(in_shape=(1,256), out_units=actionspace_size)(inputs=hidden, resample_noise_flag=True)
actions_input = tf.ones((1,actionspace_size))
print('hidden:\n', hidden)
print('output:\n', output)
print('actions_input:\n', actions_input)
filtered_output = keras.layers.merge.Multiply()([output, actions_input])
Вывод, когда я запускаю код, выглядит следующим образом:
hidden:
Tensor("noisy_layer_5/Relu:0", shape=(1, 256), dtype=float32)
output:
Tensor("noisy_layer_6/Identity:0", shape=(1, 4), dtype=float32)
actions_input:
Tensor("ones_5:0", shape=(1, 4), dtype=float32)
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-f6df621eacab> in <module>()
68 print('actions_input:\n', actions_input)
69
---> 70 filtered_output = keras.layers.merge.Multiply()([output, actions_input])
2 frames
/usr/local/lib/python3.6/dist-packages/keras/layers/merge.py in _compute_elemwise_op_output_shape(self, shape1, shape2)
59 raise ValueError('Operands could not be broadcast '
60 'together with shapes ' +
---> 61 str(shape1) + ' ' + str(shape2))
62 output_shape.append(i)
63 return tuple(output_shape)
ValueError: Operands could not be broadcast together with shapes (2592,) (4,)
В частности, мне интересно, где число 2592
в Operands could not be broadcast together with shapes (2592,) (4,)
происходит, так как число совпадает с длиной сплющенного входного тензора flattened
к первому шумному слою, но, как мне кажется, не является частью выходного измерения второго шумного слоя output
больше, что, в свою очередь, служит вводом в ошибочную строку, указанную выше.
Кто-нибудь знает, что идет не так?
Заранее спасибо, Даниэль
1 ответ
Как указано в документе пользовательского уровня, вам необходимо реализовать compute_output_shape(input_shape)
метод:
compute_output_shape(input_shape)
: в случае, если ваш слой изменяет форму своего входа, вы должны указать здесь логику преобразования формы. Это позволяет Keras делать автоматический вывод формы.
Keras не может сделать вывод формы без фактического выполнения вычисления, когда вы не применяете этот метод.
print(keras.backend.int_shape(hidden))
print(keras.backend.int_shape(output))
(1, 2592)
(1, 2592)
Так что вам нужно добавить его следующим образом:
def compute_output_shape(self, input_shape):
return (input_shape[0], self.out_units)
К тому же, build()
метод должен установить self.built = True
в конце, что можно сделать, позвонив super(NoisyLayer, self).build(input_shape)
согласно документу.