Используйте tf.shape(tensor) в качестве границы цикла

Используя Tensorflow в Python, я хочу использовать форму заполнителя для границы цикла for. Однако, когда я пытаюсь это сделать, я получаю сообщение об ошибке: объект «Тензор» не может быть интерпретирован как целое число. Эта форма не является постоянным значением для данных, поэтому мы не можем использовать tf.constant. Как мы можем решить эту проблему?

Вот часть нашего кода:

def Model(M, v_a, weights, biases, d, N):

c = multilayer_perceptron((tf.slice(M, [0, 0], ([d, 1]))), v_a, weights, 
    biases)

for i in range(1, N):

    c = tf.concat([c, multilayer_perceptron((tf.slice(M, [0, i], [d, 1])), 
    v_a, weights, biases)], axis=0)

alpha = tf.nn.softmax(tf.reshape(c, [-1]))

v_ns = tf.matmul(M, tf.reshape(alpha, [N, 1]))

layer_3 = tf.add(tf.matmul(weights['W4'], v_ns), biases['b2'])
v_ms = tf.nn.tanh(layer_3)

layer_4 = tf.add(tf.matmul(weights['W5'], v_ms), biases['b3'])
pred = tf.nn.softmax(tf.reshape(layer_4, [-1]))

return pred

M = tf.placeholder(tf.float32)

Мне нужно, чтобы N было целым числом, но оно должно быть равно количеству столбцов заполнителя M, которое не является постоянным для обучающих примеров.


person K. Project    schedule 22.03.2018    source источник


Ответы (1)


ИЗМЕНИТЬ:

Кажется, я не правильно понял вопрос в первую очередь. Я оставлю исходный ответ, потому что он связан и на всякий случай, если кто-то найдет его полезным.

В любом случае, если вы хотите использовать размерность тензора как количество итераций в цикле, то значение размерности должно быть известно статически (не может быть None). Вы бы просто сделали что-то вроде этого:

for i in range(my_tensor.shape[i_dim].value):
    # loop body...

Где i_dim — это размер, который вы хотите повторить. Опять же, если вы не знаете размер тензорного измерения, вам нужно будет прибегнуть к tf.while_loop:

def body(dim, i):
    # loop body...
    return dim, i + 1

cond = lambda dim, i: dim > i

tf.while_loop(cond, body, [tf.shape(my_tensor)[i_dim], 0])

Как и сможете ли вы это сделать вообще, зависит от того, как много вы знаете о тензоре во время цикла. Если форма полностью известна, вы можете просто сделать:

for dim in my_tensor.shape.as_list():
    # loop body...

Здесь dim будут обычными целыми числами Python для известных размеров. Однако, если есть неизвестные размеры, они будут прочитаны как None. Если вы не знаете точных размеров, но знаете ранг (т.е. количество измерений) тензора, вы можете сделать что-то вроде этого:

shape = tf.shape(my_tensor)
for i in range(my_tensor.shape.ndims):
    dim = shape[i]
    # loop body...

В этом случае dim будут значениями TensorFlow, содержащими размеры тензора, поэтому вы сможете использовать его только для вычисления других тензоров, но все измерения гарантированно будут определены.

Наконец, если вы даже не знаете количество измерений в тензоре, вы не сможете сделать обычный цикл с фигурами. Во всяком случае, вы можете использовать tf.while_loop, чтобы сделать что-то вроде того, что вам нужно:

def body(shape, i):
    dim = shape[i]
    # loop body...
    return shape, i + 1

cond = lambda shape, i: tf.shape(shape)[0] > i

tf.while_loop(cond, body, [tf.shape(my_tensor), 0])
person jdehesa    schedule 22.03.2018
comment
Спасибо за Ваш ответ. Я отредактировал вопрос, чтобы сделать его более понятным. Я попробую ваш код позже, когда вернусь домой. - person K. Project; 22.03.2018
comment
Я надеялся использовать это, чтобы получить размер партии в пользовательской функции потерь, используемой в Keras. Однако в конечном итоге это стало довольно сложным, поскольку у меня были нижестоящие функции, основанные на построении списков, равных размеру пакета. - person CMCDragonkai; 05.06.2020