#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. Спасибо за ответ!! Действительно, ваше предложение сработало для моего простого примера, но теперь я думаю, что для моего реального случая это сложнее. Я отредактировал сообщение, если вы хотите взглянуть, спасибо 🙂