【问题标题】:How to efficiently update a Keras variable slice?如何有效地更新 Keras 变量切片?
【发布时间】:2020-05-22 22:39:33
【问题描述】:

假设我们有x = K.zeros((4, 6)),并且我们希望将 1 添加到第 0 行:x[0] += 1。该变量是通过Layeradd_weight() w/training=False 创建的,因此它不会通过反向传播进行更新。这样做的最速度效率方法是什么?

Relevant Git


上下文:我正在实施循环批标准化,moving_meanmoving_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 中?


注意:我知道“追加到列表*,然后在最后一步通过数组分配”替代方案, 效率更高,但我们可以做得更好 - 至少在“传统”数组方面(* 填充零数组)。虽然不可否认,还有 GPU 因素,它在批量分配中比迭代更有效 - 但我无法根据我描述的内容有效地对后者进行基准测试。

【问题讨论】:

  • 当您执行assign 时,x 不是已经更新了吗?如果x_new 具有完整的形状,那么系统很可能正在解释它,对吗?
  • @DanielMöller 不是; print(K.get_value(x))x.assign() 之后返回原来的x
  • 嗯...您可以尝试将新片段与旧的大片段连接起来,不确定是否更好,但这是一种选择。

标签: python tensorflow keras tf.keras


【解决方案1】:

想出直接切片更新:

x_slice = x[4:5]
x_slice.assign(math_ops.sub(x_slice, some_tensor))

x_slice 似乎很好地引用了原始张量数组;出于某种原因,assign_sub 失败了;见clarifying comment

【讨论】:

    猜你喜欢
    • 2018-05-07
    • 2019-11-11
    • 2020-09-17
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 2018-05-30
    • 1970-01-01
    相关资源
    最近更新 更多