假设我们希望使用梯度下降最小化以下方程:
min f(alpha * v + (1-alpha)*w)与v和w一起表示模型的权重,而alpha的权重在0到1之间,用于导致组合模型v_bar或ū (此处称为m)的总和。
alpha = tf.Variable(0.01, name='Alpha', constraint=lambda t: tf.clip_by_value(t, 0, 1))
w_weights = tff.learning.ModelWeights.from_model(w)
v_weights = tff.learning.ModelWeights.from_model(v)
m_weights = tff.learning.ModelWeights.from_model(m)
m_weights_trainable = tf.nest.map_structure(lambda v, w: alpha*v + (tf.constant(1.0) - alpha)*w, v_weights.trainable, w_weights.trainable)
tf.nest.map_structure(lambda v, t: v.assign(t), m_weights.trainable, m_weights_trainable)在自适应个性化联合学习论文中,带更新步骤的alpha公式建议根据应用于小型批处理的模型m的梯度更新alpha。不管有没有手表,我都试过了,但它总是通向No gradients provided for any variable
with tf.GradientTape(watch_accessed_variables=False) as tape:
tape.watch([alpha])
outputs_m = m.forward_pass(batch)
grad = tape.gradient(outputs_m.loss, alpha)
optimizer.apply_gradients(zip([grad], [alpha]))关于模型初始化的更多信息:
m.forward_pass(batch)是来自tff.learning.Model (发现的这里)的默认实现,通过使用tff.learning.from_keras_model和tf.keras.Sequential模型创建模型。
def model_fn():
keras_model = create_keras_model()
return tff.learning.from_keras_model(
keras_model,
input_spec = element_spec,
loss = tf.keras.losses.MeanSquaredError(),
metrics = [tf.keras.metrics.MeanSquaredError(),
tf.keras.metrics.MeanAbsoluteError()],
)
w = model_fn()
v = model_fn()
m = model_fn()以下是Zachary Garrett提出的更多实验:
似乎只要计算出这个加权和,并为模型分配新的权重,它就失去了两个求和模型先前可训练变量的跟踪。同样,每当调用No gradients provided for any variable时,它都会导致optimizer.apply_gradients(zip([grad], [alpha]))。所有的梯度似乎都是None。
with tf.GradientTape() as tape:
alpha = tf.Variable(0.01, name='Alpha', constraint=lambda t: tf.clip_by_value(t, 0, 1))
m_weights_t = tf.nest.map_structure(lambda w, v: tf.math.scalar_mul(alpha, v, name=None) + tf.math.scalar_mul(tf.constant(1.0) - alpha, w, name=None),
w.trainable,
v.trainable)
m_weights = tff.learning.ModelWeights.from_model(m)
tf.nest.map_structure(lambda v, t: v.assign(t), m_weights.trainable,
m_weights_trainable)
outputs_m = m.forward_pass(batch)
grad = tape.gradient(outputs_m.loss, alpha)
optimizer.apply_gradients(zip([grad], [alpha]))另一个编辑:我认为我有一个让它工作的策略,但是手动设置trainable_weights或_trainable_weights不起作用,这是错误的做法。有什么改进的建议吗?
def do_weighted_combination():
def _mapper(target_layer, v_layer, w_layer):
target_layer.kernel = v_layer.kernel * alpha + w_layer.kernel * (1-alpha)
target_layer.bias = v_layer.bias * alpha + w_layer.bias * (1-alpha)
tf.nest.map_structure(_mapper, m.layers, v.layers, w.layers)
with tf.GradientTape(persistent=True) as tape:
do_weighted_combination()
predictions = m(x_data)
loss = m.compiled_loss(y_data, predictions)
g1 = tape.gradient(loss, v.trainable_weights) # Not None
g2 = tape.gradient(loss, alpha) # Not None发布于 2022-06-03 18:37:30
对于使用TensorFlow的tf.GradientTape自动区分,必须在tf.GradientTape Python上下文管理器中进行操作,以便TensorFlow能够“看到”它们。
这里可能发生的情况是,在设置模型变量时,在磁带上下文之外/之前使用了alpha。然后,当m.forwad_pass被调用时,TensorFlow看不到对alpha的任何访问,因此无法计算它的梯度(相反,返回None)。
移动
alpha*v + (tf.constant(1.0) - alpha)*w, v_weights.trainable, w_weights.trainabletf.GradientTape上下文管理器中的逻辑(可能在m.forward_pass中)可能是一个解决方案。
https://stackoverflow.com/questions/72384343
复制相似问题