Ta strona została przetłumaczona przez Cloud Translation API.
Switch to English

tf.while_loop

TensorFlow 1 wersja Zobacz źródło na GitHub

Powtórz body natomiast warunek cond jest prawdą. (Przestarzałe wartości argumentu)

Stosowany w notebookach

Używany w samouczków

cond jest wymagalne powrocie logiczną skalarnego tensor. body jest wywoływalnym powrotu (ewentualnie zagnieżdżonych) krotny, namedtuple lub listę tensorów o tej samej budowie (długości i kształtu) oraz Wykonania loop_vars . loop_vars to (być zagnieżdżone) krotka, namedtuple lub listy tensorów, który jest przekazywany zarówno cond i body . cond i body zarówno odbioru jak wiele argumentów, ponieważ istnieją loop_vars .

Oprócz regularnych tensory lub IndexedSlices, organizm może zaakceptować i powrócić obiekty TensorArray. Przepływy obiektów TensorArray będą odpowiednio przekazywane między pętlami i podczas obliczania gradientu.

Zauważ, że while_loop wzywa cond i body dokładnie jeden raz (w środku wywołanie while_loop , a nie w ogóle podczas Session.run() ). while_loop szwy razem fragmenty wykresu utworzone podczas cond i body połączeń z dodatkowymi węzłami wykres, aby utworzyć przepływ wykres, który powtarza bodycond zwraca false.

Poprawności, tf.while_loop() ściśle wymusza niezmienników kształt zmiennych pętli. Kształt jest niezmienna (ewentualnie częściowo) kształt, który nie zmienił się po drugiej iteracji pętli. Błąd zostanie zwiększona, jeżeli kształt zmiennej sterującej po iteracji określa się jako szersze niż lub niezgodny z kształtem niezmienne. Na przykład, kształt, [11] Brak jest szersze niż kształcie [11, 17] i [11, 21], nie jest zgodna z [11, 17]. Domyślnie (jeśli argument shape_invariants nie jest określony), zakłada się, że początkowy kształt każdego tensora w loop_vars jest taka sama w każdej iteracji. shape_invariants argument umożliwia dzwoniącemu określić mniej określony kształt niezmiennik dla każdej zmiennej sterującej, która jest potrzebna, jeżeli kształt różni się od iteracji. tf.Tensor.set_shape funkcja ta może być również stosowana w body funkcji celu wskazania, że zmienną wyjściowego obwodu ma szczególny kształt. Niezmienna kształt SparseTensor i IndexedSlices są traktowane w sposób następujący:

a) W przypadku zmienna pętli jest SparseTensor kształt musi być niezmienna TensorShape ([R]), gdzie r jest stopień gęstego tensora reprezentowane przez rzadki tensora. Oznacza to, że kształty trzech tensorów z SparseTensor są ([Brak] [Brak, R], [R]). UWAGA: Kształt niezmienna tutaj jest kształt nieruchomości SparseTensor.dense_shape. Musi to być kształt wektora.

b) Jeżeli zmienna pętli stanowi IndexedSlices kształt niezmienna musi być niezmienny kształt wartości tensora z IndexedSlices. Oznacza to, że kształty trzech tensorów tych IndexedSlices są (kształt, [kształtu [0]] [shape.ndims)].

while_loop przyrządy nie ściśle semantyka, umożliwiające wiele iteracji równolegle. Maksymalna liczba równoległych iteracji może być kontrolowany przez parallel_iterations , który daje użytkownikom kontrolę nad zużyciem pamięci i kolejności wykonywania. Dla poprawnych programów while_loop powinien zwrócić ten sam rezultat za parallel_iterations> 0.

Na szkolenia, TensorFlow przechowuje tensorów, które są produkowane w wnioskowania do przodu i są potrzebne w propagacji powrotem. Te tensory są głównym źródłem zużycia pamięci i często przyczyną błędów OOM podczas treningu na GPU. Gdy flaga swap_memory jest prawda, zamienić te tensory z GPU do CPU. To pozwala nam na przykład trenować modele RNN z bardzo długich sekwencji i dużych partiach.

cond Wywoływalnym który reprezentuje warunek zakończenia pętli.
body Wywoływalnym reprezentującą ciała pętli.
loop_vars (Ewentualnie zagnieżdżonych) krotka, namedtuple lub listy numpy tablicy Tensor i TensorArray obiektów.
shape_invariants Niezmienniki kształt zmiennych pętli.
parallel_iterations Liczba powtórzeń mogą być uruchamiane równolegle. To musi być dodatnia.
back_prop (Opcjonalnie) przestarzała. Fałszywe wyłącza obsługę propagacji powrotem. Wolą używać tf.stop_gradient zamiast.
swap_memory Czy pamięć CPU GPU-Swap jest włączona dla tej pętli.
maximum_iterations Opcjonalnie maksymalna ilość iteracji pętli while uruchomić. Jeśli stosuje się, cond wyjście jest I-ed z dodatkowym warunkiem zapewniającym liczbę iteracji wykonywanych jest nie większa niż maximum_iterations .
name Nazwa opcjonalny przedrostek dla zwróconych tensorów.

W tensory wyjściowe zmiennych pętli po pętli. Wartość powrotna ma taką samą strukturę jak loop_vars .

TypeError jeśli cond lub body nie jest wymagalne.
ValueError jeśli loop_vars jest pusty.

Przykład:

 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])
 

Przykład z zagnieżdżenia i 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)
 

Przykład zastosowania 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])])
 

Przykładem tego, nie ściśle semantykę: W tym przykładzie, końcowa wartość licznika i nie zależy od x . Więc while_loop może zwiększyć się równolegle w kierunku przeciwnym do aktualizacji x . Jednakże, ponieważ licznik pętli w jednej iteracji pętli w zależności od wartości w poprzedniej iteracji, i jest licznikiem pętli sama nie może być zwiększana równolegle. Dlatego jeśli chcemy tylko ostateczną wartość licznika (który drukujemy na linii print(sess.run(i)) ), a następnie x nigdy nie będzie zwiększany, ale licznik zostanie zaktualizowany na jednym wątku. I odwrotnie, jeśli chcemy wartość wyjścia (który drukujemy na linii print(sess.run(out).shape) ), to licznik może być zwiększana o własnym wątku, podczas gdy x może być zwiększana równolegle na oddzielne nici. W skrajnym przypadku, nie jest wykluczone, że wątek zwiększając sprzeczne aż do zakończenia przed x jest zwiększany nawet jeden raz. Jedyną rzeczą, która nigdy nie może się zdarzyć, że uaktualnienie gwint x nigdy nie może iść do przodu gwintu licznika ponieważ wątek zwiększając x zależy od wartości licznika.

 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)