簡體   English   中英

如何在 tensorflow 自定義訓練循環中考慮 l1 和 l2 正則化器?

[英]How do I take l1 and l2 regularizers into account in tensorflow custom training loops?

在使用 model.fit_on_batch 方法和自定義訓練循環時,我意識到在自定義訓練循環代碼中,損失和梯度沒有考慮任何 l1-l2 正則化器,因此 optimizer.apply_gradients 方法沒有考慮正則化器。 您可以在下面找到顯示這一點的代碼,但這個想法非常簡單。 所以我的問題是,是否有一種方法可以以與優化器細節無關的方式使用所有這些優化器來考慮正則化器。 它是如何在 Keras 中實現的? 在相關說明中, model.fit_on_batch 返回一個值,它不是損失(如文檔字符串中所述)而是其他值。 我想知道這里是否有人知道它會返回什么。

代碼

要查看此效果,請先創建一些數據

x=tf.constant([[1]])
y=tf.constant([[1]])

並創建 function 以制作可重現的 model

def make_model(l1=.01,l2=.01):
    tf.random.set_seed(42)
    np.random.seed(42)
    model=tf.keras.models.Sequential([
        tf.keras.layers.Dense(2,'softmax',
                              use_bias=False,
                              kernel_regularizer=tf.keras.regularizers.l1_l2(l1=l1,l2=l2),
                              input_shape=(1,))
    ])
    return model

現在運行 Keras train_on_batch

model=make_model()
loss_object=tf.keras.losses.SparseCategoricalCrossentropy()
optimizer=tf.keras.optimizers.RMSprop()
model.compile(loss=loss_object,optimizer=optimizer)
model.train_on_batch(x,y)

並將輸出與自定義訓練循環進行比較,如上述鏈接和此處所述

model=make_model()
loss_object=tf.keras.losses.SparseCategoricalCrossentropy()
optimizer=tf.keras.optimizers.RMSprop()

@tf.function
def train_step(x,y):

    with tf.GradientTape() as tape:
        predictions  = model(x)
        loss = loss_object(y, predictions)

    gradients = tape.gradient(loss, model.trainable_variables)    
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    return loss

train_step(x,y).numpy()

你會看到這兩個結果是不同的,除非 l1==0 和 l2==0。

其實我在 Aurelien Geron 的書中找到了答案在此處輸入圖像描述

事實上,在我實現了下面的代碼之后,我發現tensorflow 自定義培訓指南中涵蓋了這一點(我不知道為什么它不在問題中提到的教程中,因為它很重要)。 那里的解決方案比這里提到的解決方案更通用,但我保留了這一點,因為它對正在發生的事情有更多的了解。

所以就像修改自定義訓練循環一樣簡單

def add_model_regularizer_loss(model):
    loss=0
    for l in model.layers:
        if hasattr(l,'layers') and l.layers: # the layer itself is a model
            loss+=add_model_loss(l)
        if hasattr(l,'kernel_regularizer') and l.kernel_regularizer:
            loss+=l.kernel_regularizer(l.kernel)
        if hasattr(l,'bias_regularizer') and l.bias_regularizer:
            loss+=l.bias_regularizer(l.bias)
    return loss

def train_step(x,y):

    with tf.GradientTape() as tape:
        predictions  = model(x)
        loss = loss_object(y, predictions)
        loss += add_model_regularizer_loss(model)

    gradients = tape.gradient(loss, model.trainable_variables)    
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    return loss

要回答我問題的第二部分,keras 的 model 擬合方法返回的正是這個損失值。

TF 網站所述,推薦的做法是使用model.losses 例如:

def train_step(x,y):

    with tf.GradientTape() as tape:
        predictions  = model(x)
        loss = loss_object(y, predictions)
        loss += tf.add_n(model.losses)   # <--- SEE HERE

    gradients = tape.gradient(loss, model.trainable_variables)    
    optimizer.apply_gradients(zip(gradients, model.trainable_variables))
    return loss

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM