假设我们有x = K.zeros((4, 6))
,我们希望将 1 添加到第 0 行:x[0] += 1
。该变量是通过 Layer
创建的的 add_weight()
带training=False
,因此它不会通过反向传播更新。最速度效率的方法是什么?
上下文:我正在实现循环批量标准化,使用 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)
。检查 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 .
关于python - 如何高效更新 Keras 变量切片?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60102503/