Esta página foi traduzida pela API Cloud Translation.
Switch to English

tf.while_loop

TensorFlow 1 versão Ver fonte no GitHub

Repita body enquanto a condição cond é verdadeira. (Preterido valores de argumento)

Usado nos cadernos

Usado nos tutoriais

cond é uma exigível retornando um tensor escalar boolean. body é um que pode ser chamado de retornar um (possivelmente aninhados) tuplo, namedtuple ou lista dos tensores da mesma aridade (comprimento e estrutura) e tipos como loop_vars . loop_vars é um (possivelmente aninhados) tuplo, namedtuple ou lista dos tensores que são passados para ambos cond e body . cond e body tanto tomar tantos argumentos como existem loop_vars .

Além tensores regulares ou IndexedSlices, o corpo pode aceitar e retornar objetos TensorArray. Os fluxos dos objectos TensorArray serão transmitidos de forma adequada entre as voltas e durante os cálculos de gradiente.

Note-se que while_loop chama cond e body exatamente uma vez (dentro da chamada para while_loop , e não durante todo Session.run() ). while_loop pontos junto os fragmentos gráfico criadas durante as cond e body chamadas com alguns nós gráfico adicionais para criar o fluxo gráfico que repete body até cond retornos falso.

Para exactidão, tf.while_loop() reforça estritamente forma invariantes para as variáveis de laço. Uma forma invariante é uma forma (eventualmente parcial) que é inalterado através das iterações do ciclo. Um erro será gerado se a forma de uma variável de contagem após uma iteração é determinada para ser mais geral do que ou incompatíveis com a sua forma invariável. Por exemplo, uma forma de [11, Nenhum] é mais geral do que uma forma de [11, 17], e [11, 21] não é compatível com [11, 17]. Por padrão (se o argumento shape_invariants não é especificado), presume-se que a forma inicial de cada tensor em loop_vars é a mesma em cada iteração. O shape_invariants argumento permite que o chamador para especificar uma forma menos invariante específico para cada variável de contagem, o que é necessário, se a forma varia entre iterações. O tf.Tensor.set_shape função também pode ser usado no body função para indicar que a variável de contagem de saída tem uma forma particular. A invariante forma para SparseTensor e IndexedSlices são tratados de maneira especial como se segue:

a) Caso a variável de contagem é um SparseTensor, o invariante forma deve ser TensorShape ([r]) em que r é a classificação do tensor densa representado pelo tensor escasso. Isso significa que as formas das três tensores do SparseTensor são ([Nenhum], [Nenhum, R], [r]). NOTA: A invariante forma aqui é a forma da propriedade SparseTensor.dense_shape. Deve ser a forma de um vector.

b) Se uma variável de contagem é um IndexedSlices, o invariante forma deve ser invariante uma forma do tensor de valores dos IndexedSlices. Isso significa que as formas das três tensores dos IndexedSlices são (forma, [forma [0]], [shape.ndims]).

while_loop implementa semântica não rigorosas, permitindo múltiplas iterações para ser executado em paralelo. O número máximo de iterações paralelas pode ser controlado por parallel_iterations , que dá aos usuários algum controle sobre o consumo de memória e ordem de execução. Para os programas corretos, while_loop deve retornar o mesmo resultado para qualquer parallel_iterations> 0.

Para o treinamento, TensorFlow armazena os tensores que são produzidos na inferência para a frente e são necessários na propagação de volta. Estes tensores são a principal fonte de consumo de memória e muitas vezes causa erros OOM ao treinar em GPUs. Quando o swap_memory bandeira é verdade, nós trocar esses tensores de GPU para CPU. Este, por exemplo, nos permite treinar modelos RNN com sequências muito longas e grandes lotes.

cond Um exigível que representa a condição de terminação do ciclo.
body Um exigível que representa o corpo do ciclo.
loop_vars Um (possivelmente aninhados) tuplo, namedtuple ou lista de matriz numpy, Tensor , e TensorArray objetos.
shape_invariants Os invariantes de forma para as variáveis ​​de laço.
parallel_iterations O número de iterações pode ser executado em paralelo. Deve ser um número inteiro positivo.
back_prop (Opcional) Reprovado. desativa falsos apoiar para a propagação de volta. Preferem usar tf.stop_gradient vez.
swap_memory Se swap de memória GPU-CPU está habilitado para este loop.
maximum_iterations número máximo opcional de iterações do loop while para executar. Se fornecidos, o cond saída é E-ed com uma condição adicional de garantir o número de iterações executadas não é maior do que maximum_iterations .
name prefixo nome opcional para os tensores devolvidos.

Os tensores de saída para as variáveis ​​de loop após o ciclo. O valor de retorno tem a mesma estrutura que loop_vars .

TypeError Se cond ou body não é exigível.
ValueError se loop_vars está vazia.

Exemplo:

 i = tf.constant(0)
c = lambda i: tf.less(i, 10)
b = lambda i: (tf.add(i, 1), )
r = tf.while_loop(c, b, [i])
 

Exemplo de assentamento e com uma namedtuple:

 import collections
Pair = collections.namedtuple('Pair', 'j, k')
ijk_0 = (tf.constant(0), Pair(tf.constant(1), tf.constant(2)))
c = lambda i, p: i < 10
b = lambda i, p: (i + 1, Pair((p.j + p.k), (p.j - p.k)))
ijk_final = tf.while_loop(c, b, ijk_0)
 

Exemplo usando shape_invariants:

 i0 = tf.constant(0)
m0 = tf.ones([2, 2])
c = lambda i, m: i < 10
b = lambda i, m: [i+1, tf.concat([m, m], axis=0)]
tf.while_loop(
    c, b, loop_vars=[i0, m0],
    shape_invariants=[i0.get_shape(), tf.TensorShape([None, 2])])
 

Exemplo demonstra que semântica não rigorosos: No exemplo a seguir, o valor final do contador i não depende de x . Assim, o while_loop pode incrementar o contador paralelo com atualizações de x . No entanto, porque o contador de ciclo a uma iteração depende do valor na iteração anterior, o próprio contador de ciclo não pode ser incrementado em paralelo. Portanto, se nós só queremos o valor final do contador (que imprimir na linha print(sess.run(i)) ), então x nunca será incrementado, mas o contador será atualizado em um único segmento. Por outro lado, se queremos que o valor da produção (que imprimir na linha print(sess.run(out).shape) ), em seguida, o contador pode ser incrementado em seu próprio segmento, enquanto que x pode ser incrementado em paralelo em um segmento separado. No caso extremo, é possível que o fio de incrementar o contador é executado até a conclusão antes x é incrementado até mesmo um único tempo. A única coisa que nunca pode acontecer é que o segmento atualizar x pode nunca chegar à frente da linha contra porque o segmento incrementar x depende do valor do contador.

 import tensorflow as tf

n = 10000
x = tf.constant(list(range(n)))
c = lambda i, x: i < n
b = lambda i, x: (tf.compat.v1.Print(i + 1, [i]), tf.compat.v1.Print(x + 1,
[i], "x:"))
i, out = tf.while_loop(c, b, (0, x))
with tf.compat.v1.Session() as sess:
    print(sess.run(i))  # prints [0] ... [9999]

    # The following line may increment the counter and x in parallel.
    # The counter thread may get ahead of the other thread, but not the
    # other way around. So you may see things like
    # [9996] x:[9987]
    # meaning that the counter thread is on iteration 9996,
    # while the other thread is on iteration 9987
    print(sess.run(out).shape)