如何有效地更新 Keras 变量切片?
How to efficiently update a Keras variable slice?
假设我们有 x = K.zeros((4, 6))
,我们希望将 1 添加到第 0 行:x[0] += 1
。该变量是通过 Layer
的 add_weight()
w/ training=False
创建的,因此它不会通过反向传播更新。最 最高效 的方法是什么?
Context:我正在实施循环批量归一化,moving_mean
和 moving_variance
变量对于 RNN 中的每个时间步长都是不同的 - 因此每个都有一个(units, timesteps)
的形状。目标是通过 K.moving_average_update()
每一步更新一个 timesteps
切片。一种方法如下:
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 中?
注意:我知道 "append to list* then assign via array at last step" 替代方案, 效率更高,但我们可以做得更好——至少就 'traditional' 数组而言(* 或 填充零数组)。虽然不可否认,还有 GPU 因素,它在批处理分配中比迭代更有效 - 但我无法根据我的描述有效地对后者进行基准测试。
想出直接切片更新:
x_slice = x[4:5]
x_slice.assign(math_ops.sub(x_slice, some_tensor))
x_slice
似乎很好地引用了原始张量数组;由于某种原因,assign_sub
失败了;参见 clarifying comment。
假设我们有 x = K.zeros((4, 6))
,我们希望将 1 添加到第 0 行:x[0] += 1
。该变量是通过 Layer
的 add_weight()
w/ training=False
创建的,因此它不会通过反向传播更新。最 最高效 的方法是什么?
Context:我正在实施循环批量归一化,moving_mean
和 moving_variance
变量对于 RNN 中的每个时间步长都是不同的 - 因此每个都有一个(units, timesteps)
的形状。目标是通过 K.moving_average_update()
每一步更新一个 timesteps
切片。一种方法如下:
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 中?
注意:我知道 "append to list* then assign via array at last step" 替代方案, 效率更高,但我们可以做得更好——至少就 'traditional' 数组而言(* 或 填充零数组)。虽然不可否认,还有 GPU 因素,它在批处理分配中比迭代更有效 - 但我无法根据我的描述有效地对后者进行基准测试。
想出直接切片更新:
x_slice = x[4:5]
x_slice.assign(math_ops.sub(x_slice, some_tensor))
x_slice
似乎很好地引用了原始张量数组;由于某种原因,assign_sub
失败了;参见 clarifying comment。