Расширенное индексирование Theano для тензора, общий индекс

У меня есть тензор probs с probs.shape = (max_time, num_batches, num_labels).

И у меня есть тензор targets с targets.shape = (max_seq_len, num_batches), где значения являются индексами меток, т.е. для третьего измерения в probs.

Теперь я хочу получить тензор probs_y с probs.shape = (max_time, num_batches, max_seq_len), где третье измерение является индексом в targets. В основном

probs_y[:,i,:] = probs[:,i,targets[:,i]]

для всех 0 <= i < num_batches.

Как я могу этого добиться?

Аналогичная проблема с решением была опубликована здесь.

Решение там, если я правильно понял, будет таким:

probs_y = probs[:,T.arange(targets.shape[1])[None,:],targets]

Но это, кажется, не работает. Я получаю: IndexError: only integers, slices (`:`), ellipsis (`...`), numpy.newaxis (`None`) and integer or boolean arrays are valid indices.

Кроме того, не слишком ли затратно создание временного T.arange? Особенно, когда я пытаюсь обойти это, действительно делая его полным плотным целочисленным массивом. Должен быть лучший способ.

Может theano.map? Но насколько я понимаю, это не распараллеливает код, так что это тоже не решение.


person Albert    schedule 09.07.2015    source источник
comment
Только что понял, что все, что я сделал иначе, чем ваша линия, это то, что я переставил оси как в T.arange, так и в targets. Это странно. В таком случае ваш тоже должен был сработать.   -  person eickenberg    schedule 09.07.2015
comment
Хорошо, то, как вы это делаете, тоже работает, я обновил свой ответ. Значит проблема в другом. Либо версия theano, либо что-то, не относящееся к этой конкретной операции, хотя, учитывая сообщение об ошибке, последнее кажется маловероятным.   -  person eickenberg    schedule 09.07.2015


Ответы (1)


Это работает для меня:

import theano
import theano.tensor as T

max_time, num_batches, num_labels = 3, 4, 6
max_seq_len = 5

probs_ = np.arange(max_time * num_batches * num_labels).reshape(
    max_time, num_batches, num_labels)

targets_ = np.arange(num_batches * max_seq_len).reshape(max_seq_len, 
    num_batches) % (num_batches - 1)  # mix stuff up

probs, targets = map(theano.shared, (probs_, targets_))

print probs_
print targets_

probs_y = probs[:, T.arange(targets.shape[1])[:, np.newaxis], targets.T]

print probs_y.eval()

Выше использовалась транспонированная версия ваших индексов. Ваше точное предложение также работает

probs_y2 = probs[:, T.arange(targets.shape[1])[np.newaxis, :], targets]

print probs_y2.eval()
print (probs_y2.dimshuffle(0, 2, 1) - probs_y).eval()

Так что, возможно, ваша проблема в другом.

Что касается скорости, я в недоумении, что может быть быстрее этого. map, который является специализацией scan, почти наверняка таковым не является. Я не знаю, в какой степени arange действительно создается, а не просто повторяется.

person eickenberg    schedule 09.07.2015
comment
Спасибо, мой пример на самом деле тоже сработал. В моем тестовом коде probs по ошибке все еще был numpy.ndarray. :П - person Albert; 09.07.2015
comment
Аааа, ОК, должно быть, я уже делал это раньше, потому что сообщение об ошибке показалось очень знакомым. - person eickenberg; 09.07.2015