Python theano.scan использует аргумент

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

Я просто не понимаю механизма "кранов". Ну я ок. Я знаю, в каком порядке последовательности передаются в функцию, но не знаю смысла. Например (я позаимствовал этот код из другого вопроса Python - Theano scan() function):

import numpy as np
import theano
import theano.tensor as T


def addf(a1,a2):
    print(a1)
    print(a2)
    return a1+a2

i = T.iscalar('i')
x0 = T.ivector('x0') 
step= T.iscalar('step')

results, updates = theano.scan(fn=addf,
                   outputs_info=[dict(initial=x0, taps=[-3])],
                   non_sequences=step,
                   n_steps=i)

f=theano.function([x0, step,i],results)

input = [2, 3]

print(f(input, 2, 20))

Установка taps на -1 имеет смысл для меня. Насколько я понимаю, это то же самое, что не устанавливать значение taps, и весь вектор 'x0' передается в функцию addf. Затем x0 будет добавлен с параметром «шаг» (int 2, который будет транслироваться с тем же размером). На следующей итерации результат [4, 5] будет входом и так далее, что даст следующий результат:

[[ 4  5]
 [ 6  7]
 [ 8  9]
 [10 11]
 [12 13]
 [14 15]
 [16 17]
 [18 19]
 [20 21]
 [22 23]
 [24 25]
 [26 27]
 [28 29]
 [30 31]
 [32 33]
 [34 35]
 [36 37]
 [38 39]
 [40 41]
 [42 43]]

Однако установка taps на -3 дает следующий результат:

[ 5  2  6  7  4  8  9  6 10 11  8 12 13 10 14 15 12 16 17]

У меня нет никакого объяснения, как функция сканирования создает этот вывод. Почему сейчас только список? «Печать (a1)» оказывается такой, как ожидалось.

x0[t-3]

Хотя я знаю, что это значение, которое должно иметь a1, я не знаю, как его интерпретировать. Каково t-3-е значение x0? Документация theano, кажется, не очень подробно описывает аргумент taps... так что, надеюсь, кто-то из вас, ребята, будет.

Спасибо


person Nima Mousavi    schedule 01.05.2015    source источник
comment
Если вы посмотрите на ответ на вопрос, который вы связали, вы увидите, что @nouiz объяснил, что передача чего-либо, кроме -1 в taps в outputs_info, приведет к тому, что переданное значение будет иметь на одно измерение меньше, чем начальное значение. Я считаю, что значение tm3 для x0 в t0 по умолчанию будет равно начальному значению, указанному в переданном вами аргументе dict(), поэтому начальное значение x0, хотя я не совсем уверен в этом соглашении.   -  person user2805751    schedule 03.05.2015


Ответы (1)


Чтобы лучше понять использование taps, вы должны сначала понять, как scan использует аргумент outputs_info в целом и как предоставленные для него значения (точнее, initial) меняют характер результата.

scan ожидает, что вы предоставите тип вывода, который вы ожидаете от этой операции (если, конечно, у вас нет начальных значений для предоставления и вы просто упомяните None, и в этом случае он начнет первый раунд {step}, а вывод не будет передан как параметр для fn в последующих раундах).

Таким образом, scan используется для итеративного сокращения предоставленного sequences. Это означает, что в step n (и если taps не указано ни для sequences, ни для outputs_info), данное fn будет применено к n-ым элементам каждого из sequences вдоль с выходными данными, сгенерированными предыдущим (n-1 th) step. Следовательно, значение по умолчанию taps для sequences равно 0, а для outputs_info равно -1.

Другой способ взглянуть на это — рассмотреть, что все последовательности состоят из срезов по их соответствующему первому измерению. Таким образом, для определенного шага текущий срез (срезы) sequence(s) и выходной срез предыдущего шага передаются в fn, а вычисленный вывод добавляется к результатам в виде нового среза, который затем будет использоваться для следующего step. Очевидно, что каждый из выходных срезов будет иметь одинаковую форму. И если вы предоставляете начальный срез как часть outputs_info, он также должен иметь ту же форму, что и созданный приложением fn. В вашем примере, если output_info=[dict(initial=x0)], он возьмет [2, 3] в качестве первого фрагмента и будет использовать его для первого step в качестве аргумента от a1 до addf.

Но довольно часто при обработке сигналов (и где-либо еще) в качестве причинно-следственной информации требуется нечто большее, чем просто последние данные во времени. Здесь я использовал время просто как способ представить steps. Во всяком случае, именно здесь taps полезен и помогает указать, какие именно точки данных из sequences и results должны использоваться для текущего step. В вашем примере это означает, что для текущего step 3-й последний вывод должен быть передан в fn.

И здесь вам нужно быть осторожным, описывая initial для outputs_info. Поскольку сканирование сначала разделит значение initial на срезы по первому измерению. Тогда первый фрагмент среди этого набора фрагментов будет считаться самым ранним фрагментом (3-й последний в вашем примере), необходимым для вычисления выходных данных первого step.

Предположим, в вашем примере taps=[-2] и input = [2, 3]. В этом случае сканирование разделит ввод на слайсы и будет использовать первый слайс (здесь значение 2) в качестве аргумента от a1 до addf. Результирующее значение 4 будет добавлено к выходным данным, и для следующего шага срезы будут включать [2, 3, 4], из которых значение 3 находится на предпоследнем (-2) касании. И так далее. Однако с taps=[-3] и тем же input отсутствует одно значение, что равносильно утверждению, что вы собрали значения в моменты времени (t-3) и (t-2), но не собрали значение в (t-1).

Поэтому, если вы считаете, что ваш вывод имеет определенную форму, и вам требуется несколько касаний вывода за пределами -1, тогда значение initial должно быть списком элементов требуемой формы вывода и иметь ровно столько таких элементов, сколько потребуется для извлечения самого раннего фрагмента.

TLDR: в вашем примере, если вы хотите получить 2d-векторы в результате каждого step и используете taps=[-3], то input должен быть списком из 3 таких 2d-векторов. Если вы хотите получить однозначные результаты, то input должен быть списком из 3 целых чисел. Список с двумя целыми числами вообще не имеет смысла в этом контексте. Это имело бы смысл только в том случае, если taps равно либо -2, либо -1, либо [-2, -1].

person JunkMechanic    schedule 13.10.2015