假设我们有x = K.zeros((4, 6))
,我们希望在第0行:x[0] += 1
上加1。该变量是通过Layer
的add_weight()
w / training=False
创建的,因此不会通过反向传播进行更新。最快的速度方式是什么?
Relevant Git
上下文:我正在实现循环批处理归一化,对于RNN中的每个时间步,moving_mean
和moving_variance
变量是不同的-因此,每个变量的形状均为(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)
。检查Keras的Backend,其update_
方法都涉及复制原始数组。Keras有什么更有效的方法吗?如果没有,在TensorFlow中?
注意:我知道“追加到列表*,然后在最后一步通过数组分配”替代方案,它效率更高,但我们可以做得更好-至少就“传统”数组而言(*或填充)零数组)。尽管可以承认,还有GPU因素,它在批处理分配中比迭代更有效-但是我无法按照我的描述有效地对后者进行基准测试。
最佳答案
找出直接切片更新:
x_slice = x[4:5]
x_slice.assign(math_ops.sub(x_slice, some_tensor))
x_slice
似乎很好地引用了原始张量数组;由于某些原因,assign_sub
失败了;参见clarifying comment。