Предположим, у нас есть x = K.zeros((4, 6))
, и мы будем sh, чтобы добавить 1 к строке 0: x[0] += 1
. Переменная создается с помощью Layer
add_weight()
w / training=False
, поэтому она не обновляется с помощью backprop. Какой самый эффективный быстрый способ сделать это?
Релевантно Git
Контекст : я реализую периодическую нормализацию партии с переменными moving_mean
и moving_variance
отличается для каждого временного шага в RNN - каждый, таким образом, имеет форму (units, timesteps)
. Цель состоит в том, чтобы обновить один timesteps
срез за шаг с помощью K.moving_average_update()
. Один из подходов заключается в следующем:
import keras.backend as K
units, timesteps = 4, 6
x = K.zeros((units, timesteps), dtype='float32', name='x')
x_new = x[:units, 0].assign(K.ones((units,), dtype='float32')) # dummy example
K.set_value(x, K.get_value(x_new))
print(K.get_value(x))
[[1. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0.]]
Выглядит хорошо - за исключением того, что новая копия из x
была создана. На практике у нас может быть timesteps > 100
(например, 120), поэтому мы создаем массив в 120 раз больше, чем нужно, в 120 раз (1 / шаг), что делает его операцией O(timesteps**2)
- в отличие от обычного среза, O(timesteps)
. При проверке Backend Keras все его методы update_
включают копирование исходного массива.
Есть ли что-нибудь более эффективное в Keras? Если нет, то в TensorFlow?
Примечание : мне известно об альтернативе «добавить в список *, затем назначить с помощью массива на последнем шаге», которая равна намного эффективнее, но мы можем добиться большего успеха - по крайней мере, с точки зрения «традиционных» массивов (* или заполнение нулевого массива). Правда, есть и фактор GPU, который лучше работает в пакетных назначениях, чем итеративный, но я не могу сравнительно эффективно сравнить его с тем, что я описал.