Вложенный цикл while в тензорном потоке - PullRequest
0 голосов
/ 08 мая 2018

Я пытаюсь реализовать функцию потерь в кератах, например, в следующем псевдокоде

for i in range(N):
    for j in range(N):
        sum += some_calculations

но я читал, что тензорный поток не поддерживает такие циклы, поэтому я узнал о функции while_loop (cond, body, loop_vars) из здесь

Я понял основную работу цикла while, поэтому реализовал следующий код:

def body1(i):
    global data
    N = len(data)*positive_samples     //Some length
    j = tf.constant(0)    //iterators
    condition2 = lambda j, i :tf.less(j, N)   //one condition only j should be less than N
    tf.add(i, 1)   //increment previous index i
    result = 0

    def body2(j, i):
        global similarity_matrix, U, V
        result = (tf.transpose(U[:, i])*V[:, j])   //U and V are 2-d tensor Variables and here only a column is extracted and their final product is a single value
        return result

    tf.while_loop(condition2, body2, loop_vars=[j, i])
    return result


def loss_function(x):
    global data
    N = len(data)*positive_samples
    i = tf.constant(0)
    condition1 =  lambda i : tf.less(i, N)
    return tf.while_loop(condition1, body1, [i])

Но когда я запускаю этот код, я получаю сообщение об ошибке

ValueError: The two structures don't have the same number of elements. First structure: [<tf.Tensor 'lambda_1/while/while/Identity:0' shape=() dtype=int32>, <tf.Tensor 'lambda_1/while/while/Identity_1:0' shape=() dtype=int32>], second structure: [0]

1 Ответ

0 голосов
/ 08 мая 2018

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

def body1(i, result):
    global data
    N = len(data) * positive_samples
    j = tf.constant(0)
    condition2 = lambda j, i, result: tf.less(j, N)
    result = 0

    def body2(j, i, result):
        global similarity_matrix, U, V
        result_j = (tf.transpose(U[:, i]) * V[:, j])
        return j + 1, i, result + result_j

    j, i, result = tf.while_loop(condition2, body2, loop_vars=[j, i, result])
    return i + 1, result

def loss_function(x):
    global data
    N = len(data)*positive_samples
    i = tf.constant(0)
    result = tf.constant(0, dtype=tf.float32)
    condition1 = lambda i, result: tf.less(i, N)
    i, result = tf.while_loop(condition1, body1, [i, result])
    return result

Из вашего кода неясно, где будет использоваться x.В этом случае, однако, результат операции должен быть равен просто:

result = tf.reduce_sum(tf.transpose(U) @ V)
# Equivalent
result = tf.reduce_sum(tf.matmul(tf.transpose(U), V))

, что также будет намного быстрее.

...