«InvalidArgumentError: несовместимые формы: [64,40000] против [64] [Op: Mul]» при выполнении операций между тензорами?

#python #tensorflow #neural-network #layer #tensor

#python #тензорный поток #нейронная сеть #слой #тензор

Вопрос:

Я пытаюсь выполнить эту операцию между двумя тензорами:

 green_mat = sio.loadmat('green.mat')
green = np.array(green_mat['G2'])
green = tf.convert_to_tensor(green)
green = tf.cast(green, dtype='complex64')  # >>>green.shape = TensorShape([64, 40000])



tensor = tf.ones(128,1)        # tensor.shape = TensorShape([128])

def mul_and_sum(tensor):
   real = tensor[0:64]
   imag = tensor[64:128]
   complex_tensor = tf.complex(real, imag)
   return tf.reduce_sum((tf.multiply(green, complex_tensor), 1))

res = mul_and_sum(tensor)
 

по сути, в конце я хочу получить тензор с 40000 элементами для использования в качестве слоя для нейронной сети, но когда я запускаю эту функцию в качестве теста, у меня возникает эта ошибка:

 tensorflow.python.framework.errors_impl.InvalidArgumentError: Incompatible shapes: [64,40000] vs. [64] [Op:Mul]
 

Я впервые работаю над операцией с тензорами, и, возможно, я немного запутался в том, как обрабатывать размеры, какие-либо предложения? Спасибо 🙂

РЕДАКТИРОВАТЬ: хорошо, я понял суть, действительно, для примера, который я привел, все работает, но тогда у меня другая проблема в моей сети:

 def convolution(tensor):
tf.cast(tensor, dtype='float64')
real = tensor[0:64]
imag = tensor[64:128]
complex_tensor = tf.complex(real, imag)
a = tf.math.real(tf.reduce_sum((tf.multiply(green, complex_tensor)), 0))
return a

def get_model3(mask_kind):
epochs = 200
learning_rate = 0.1
decay_rate = learning_rate / epochs
inp_1 = keras.Input(shape=(64, 101, 129), name="RST_inputs")
x = layers.Conv2D(1, kernel_size=(1, 1), strides=(1, 1), padding="valid", trainable=False)(inp_1)
x = layers.Conv2D(256, kernel_size=(3, 3), kernel_regularizer=l2(1e-6), strides=(3, 3), padding="same")(x)
x = layers.LeakyReLU(alpha=0.3)(x)
x = layers.Conv2D(128, kernel_size=(3, 3), kernel_regularizer=l2(1e-6), strides=(3, 3), padding="same")(x)
x = layers.LeakyReLU(alpha=0.3)(x)
x = layers.Conv2D(64, kernel_size=(2, 2), kernel_regularizer=l2(1e-6), strides=(2, 2), padding="same")(x)
x = layers.LeakyReLU(alpha=0.3)(x)
x = layers.Conv2D(32, kernel_size=(2, 2), kernel_regularizer=l2(1e-6), strides=(2, 2), padding="same")(x)
x = layers.LeakyReLU(alpha=0.3)(x)
x = layers.Flatten()(x)
x = layers.Dense(512)(x)
x = layers.LeakyReLU(alpha=0.3)(x)
x = layers.Dense(256)(x)
x = layers.LeakyReLU(alpha=0.3)(x)
out1 = layers.Dense(128, name="ls_weights")(x)

if mask_kind == 1:
    binary_mask = layers.Lambda(mask_layer1, name="lambda_layer", dtype='float64')(out1)
elif mask_kind == 2:
    binary_mask = layers.Lambda(mask_layer2, name="lambda_layer", dtype='float64')(out1)
else:
    binary_mask = out1
#here the binary mask shape is [?,128]
binary_mask = tf.expand_dims(binary_mask, axis=2)  #here the shape is [?,128,1]
binary_mask = tf.squeeze(binary_mask, axis=0) #here the shape is [128,1]

print('binary shape:', binary_mask.shape)

lambda_layer = layers.Lambda(convolution, name="convolutional_layer")(binary_mask)
print(lambda_layer.shape)


model3 = keras.Model(inp_1,  lambda_layer, name="2_out_model")

model3.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=decay_rate),  # in caso
               # rimettere 0.001
               loss="mean_squared_error")

plot_model(model3, to_file='model.png', show_shapes=True, show_layer_names=True)
model3.summary()

return model3
 

и я получаю эту ошибку:

 ValueError: Input 0 of layer sf_vec is incompatible with the layer: : expected min_ndim=2, found ndim=1. Full shape received: [40000]
 

Я знаю, что это потому, что существует несоответствие между размерами, но дело в том, что форма выходного слоя (тензора) должна быть [?,40000], а вместо этого я получаю только тензор [40000], есть какие-либо предложения?

РЕДАКТИРОВАТЬ 2.0 Я не заметил, что мой вывод уже был лямбда-слоем, поэтому при написании модели я не получаю ошибок, но из резюме таким образом я получаю форму лямбды (1, 40000), в то время как обычно должно быть (нет, 40000). Где ошибка?

Ответ №1:

Если вы хотите выполнить умножение между 2 тензорами, они должны иметь совместимую форму, то есть либо одну и ту же форму, либо форму, которая может транслироваться. Цитирую документацию numpy (tensorflow следует тем же правилам трансляции):

При работе с двумя массивами NumPy сравнивает их формы поэлементно. Он начинается с конечных размеров и продвигается вперед. Два измерения совместимы, когда

  • они равны, или
  • один из них равен 1

В вашем случае, если вы хотите использовать tf.multiply , вам нужно добавить измерение к вашему вектору, чтобы оно имело одинаковое количество измерений. Вы можете сделать это, используя tf.expand_dims или используя расширенную индексацию с tf.newaxis помощью .

Пример (с использованием комплексов, как в вашем вопросе):

 >>> a = tf.complex(tf.random.normal((64,128)),tf.random.normal((64,128)))
>>> a.shape
TensorShape([64, 128])
>>> b = tf.complex(tf.ones(64),tf.ones(64))
>>> b.shape
TensorShape([64])
 

Чтобы иметь возможность использовать tf.multiply , вам нужно добавить измерение в b :

 >>> b_exp = tf.exand_dims(b, axis=1)
>>> b_exp.shape
TensorShape([64, 1])
>>> tf.multiply(a,b_exp).shape
TensorShape([64, 128])
 

Примечание: выполнение tf.reduce_sum on tf.multiply может быть сродни просто умножению матрицы

В вашем случае вы, вероятно, можете сделать что-то похожее на

 >>> tf.matmul(b[tf.newaxis,:], a).shape
TensorShape([1, 128])
 

Если вас беспокоит дополнительное измерение, вы можете избавиться от него с tf.squeeze помощью .

Комментарии:

1. Спасибо за ответ!! Действительно, ваше предложение сработало для моего простого примера, но теперь я думаю, что для моего реального случая это сложнее. Я отредактировал сообщение, если вы хотите взглянуть, спасибо 🙂