【问题标题】:Nested Gradient Tape in function (TF2.0)函数中的嵌套渐变带 (TF2.0)
【发布时间】:2020-03-10 09:53:26
【问题描述】:

我尝试实现 MAML。因此,我需要我的模型(model_copy)的副本进行一步训练, 那么我需要在丢失 model_copy 的情况下训练我的 meta_model。

我想在一个函数中训练 model_copy。 如果我将我的代码复制到函数中,我不会得到正确的 gradients_meta(它们都不会)。

图似乎没有连接 - 我如何连接图?

知道我做错了什么吗?我观察了很多变量,但这似乎并没有什么不同..

这是重现此问题的代码:

import tensorflow as tf
import tensorflow.keras as keras
import tensorflow.keras.backend as keras_backend


def copy_model(model):
    copied_model = keras.Sequential()
    copied_model.add(keras.layers.Dense(5, input_shape=(1,)))
    copied_model.add(keras.layers.Dense(1))
    copied_model.set_weights(model.get_weights())
    return copied_model


def compute_loss(model, x, y):
    logits = model(x)  # prediction of my model
    mse = keras_backend.mean(keras.losses.mean_squared_error(y, logits))  # compute loss between prediciton and label/truth
    return mse, logits


# meta_model to learn in outer gradient tape
meta_model = keras.Sequential()
meta_model.add(keras.layers.Dense(5, input_shape=(1,)))
meta_model.add(keras.layers.Dense(1))

# optimizer for training
optimizer = keras.optimizers.Adam()


# function to calculate model_copys params
def do_calc(x, y, meta_model):
    with tf.GradientTape() as gg:
        model_copy = copy_model(meta_model)
        gg.watch(x)
        gg.watch(meta_model.trainable_variables)
        gg.watch(model_copy.trainable_variables)
        loss, _ = compute_loss(model_copy, x, y)
        gradient = gg.gradient(loss, model_copy.trainable_variables)
        optimizer.apply_gradients(zip(gradient, model_copy.trainable_variables))
        return model_copy


# inputs for training
x = tf.constant(3.0, shape=(1, 1, 1))
y = tf.constant(3.0, shape=(1, 1, 1))

with tf.GradientTape() as g:

    g.watch(x)
    g.watch(y)

    model_copy = do_calc(x, y, meta_model)
    g.watch(model_copy.trainable_variables)
    # calculate loss of model_copy
    test_loss, _ = compute_loss(model_copy, x, y)
    # build gradients for meta_model update
    gradients_meta = g.gradient(test_loss, meta_model.trainable_variables)
    # gradients always None !?!!11 elf
    optimizer.apply_gradients(zip(gradients_meta, meta_model.trainable_variables))

提前感谢您的帮助。

【问题讨论】:

    标签: python tensorflow machine-learning deep-learning tensorflow2.0


    【解决方案1】:

    我找到了解决方案: 我需要以某种方式“连接”元模型和模型副本。

    谁能解释一下为什么会这样以及我如何使用“适当的”优化器来实现这一点?

    import tensorflow as tf
    import tensorflow.keras as keras
    import tensorflow.keras.backend as keras_backend
    
    
    def copy_model(model):
        copied_model = keras.Sequential()
        copied_model.add(keras.layers.Dense(5, input_shape=(1,)))
        copied_model.add(keras.layers.Dense(1))
        copied_model.set_weights(model.get_weights())
        return copied_model
    
    
    def compute_loss(model, x, y):
        logits = model(x)  # prediction of my model
        mse = keras_backend.mean(keras.losses.mean_squared_error(y, logits))  # compute loss between prediciton and label/truth
        return mse, logits
    
    
    # meta_model to learn in outer gradient tape
    meta_model = keras.Sequential()
    meta_model.add(keras.layers.Dense(5, input_shape=(1,)))
    meta_model.add(keras.layers.Dense(1))
    
    # optimizer for training
    optimizer = keras.optimizers.Adam()
    
    
    # function to calculate model_copys params
    def do_calc(meta_model, x, y, gg, alpha=0.01):
        model_copy = copy_model(meta_model)
        loss, _ = compute_loss(model_copy, x, y)
        gradients = gg.gradient(loss, model_copy.trainable_variables)
        k = 0
        for layer in range(len(model_copy.layers)):
            # calculate adapted parameters w/ gradient descent
            # \theta_i' = \theta - \alpha * gradients
            model_copy.layers[layer].kernel = tf.subtract(meta_model.layers[layer].kernel,
                                                          tf.multiply(alpha, gradients[k]))
            model_copy.layers[layer].bias = tf.subtract(meta_model.layers[layer].bias,
                                                        tf.multiply(alpha, gradients[k + 1]))
            k += 2
        return model_copy
    
    
    with tf.GradientTape() as g:
        # inputs for training
        x = tf.constant(3.0, shape=(1, 1, 1))
        y = tf.constant(3.0, shape=(1, 1, 1))
        adapted_models = []
    
        # model_copy = meta_model
        with tf.GradientTape() as gg:
            model_copy = do_calc(meta_model, x, y, gg)
    
        # calculate loss of model_copy
        test_loss, _ = compute_loss(model_copy, x, y)
        # build gradients for meta_model update
        gradients_meta = g.gradient(test_loss, meta_model.trainable_variables)
        # gradients work. Why???
        optimizer.apply_gradients(zip(gradients_meta, meta_model.trainable_variables))
    

    【讨论】:

      【解决方案2】:

      将Tensor转换为numpy并使用set_weights()只会复制梯度更新后的参数值,但是tf2图中的节点名称发生了变化,所以无法直接使用复制模型的loss来查找元模型的梯度

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-06
        • 2018-10-17
        • 2013-05-03
        • 2020-07-01
        • 1970-01-01
        • 2019-11-01
        相关资源
        最近更新 更多