Keras 训练期间损失的移动平均

Moving averaging of Loss during Training in Keras

我正在使用 Keras 和 TensorFlow 来实现深度神经网络。当我 plot 损失和迭代次数时,每个时期后损失都会显着增加。实际上,每个 mini-batch 的损失应该互不相同,但是 Keras 计算了 mini-batch 损失的移动平均值,这就是为什么我们得到一条平滑曲线而不是任意曲线的原因。移动平均线的数组在每个时期后重置,因此我们可以观察到损失的跳跃。

我想删除移动平均线的功能,而不是我想要原始损失值,每个小批量都会有所不同。现在,我尝试减少损失函数,但它仅适用于小批量中的示例。以下代码总结了小批量中所有训练示例的损失。

tf.keras.losses.BinaryCrossentropy(reduction = 'sum')

我也尝试编写自定义损失函数,但这也无济于事。

( 1 ): 我想删除移动平均线的功能,而不是我希望每个 mini-batch.

的原始损失值都会有所不同

这可以通过使用回调函数来实现,但我再次查看了问题,您也尝试将实际损失值优化回计算中。

也就是说,当然,您可以在回调函数中应用,也可以直接执行,因为这个示例告诉您基本的自定义优化器是如何工作的。

[样本]:

import os
from os.path import exists

import tensorflow as tf

import matplotlib.pyplot as plt
from skimage.transform import resize

import numpy as np

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
Variables
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
learning_rate = 0.001
global_step = 0
tf.compat.v1.disable_eager_execution()

BATCH_SIZE = 1
IMG_SIZE = (32, 32)

history = [ ] 
history_Y = [ ]
list_file = [ ]
list_label = [ ]

for file in os.listdir("F:\datasets\downloads\dark\train") :
    image = plt.imread( "F:\datasets\downloads\dark\train\" + file )
    image = resize(image, (32, 32))
    image = np.reshape( image, (1, 32, 32, 3) )
    list_file.append( image )
    list_label.append(1)

optimizer = tf.compat.v1.train.ProximalAdagradOptimizer(
    learning_rate,
    initial_accumulator_value=0.1,
    l1_regularization_strength=0.2,
    l2_regularization_strength=0.1,
    use_locking=False,
    name='ProximalAdagrad'
)

var1 = tf.Variable(255.0)
var2 = tf.Variable(10.0)
X_var = tf.compat.v1.get_variable('X', dtype = tf.float32, initializer = tf.random.normal((1, 32, 32, 3)))
y_var = tf.compat.v1.get_variable('Y', dtype = tf.float32, initializer = tf.random.normal((1, 32, 32, 3)))
Z = tf.nn.l2_loss((var1 - X_var) ** 2 + (var2 - y_var) ** 2, name="loss")

cosine_loss = tf.keras.losses.CosineSimilarity(axis=1)
loss = tf.reduce_mean(input_tensor=tf.square(Z))
training_op = optimizer.minimize(cosine_loss(X_var, y_var))

previous_train_loss = 0
with tf.compat.v1.Session() as sess:
    sess.run(tf.compat.v1.global_variables_initializer())

    image = list_file[0]
    X = image
    Y = image

    for i in range(1000):
        global_step = global_step + 1
        train_loss, temp = sess.run([loss, training_op], feed_dict={X_var:X, y_var:Y})
        
        history.append( train_loss )
        
        if global_step % 2 == 0 :
            var2 = var2 - 0.001
        if global_step % 4 == 0 and train_loss <=  previous_train_loss :
            var1 = var1 - var2 + 0.5
        print( 'steps: ' + str(i) )
        print( 'train_loss: ' + str(train_loss) )
        
        previous_train_loss = train_loss
        
sess.close()

"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
: Graph
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""
history = history[:-1]

plt.plot(np.asarray(history))
plt.xlabel('Epoch')
plt.ylabel('loss')
plt.legend(loc='lower right')
plt.show()

[输出]: ...

Keras 实际上显示的是移动平均线而不是“原始”损失值。为了获取原始损失值,应该实现如下所示的回调:

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        #initialize a list at the begining of training
        self.losses = []

    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))

mycallback = LossHistory()

然后在model.fit

中调用
model.fit(X, Y, epochs=epochs, batch_size=batch, shuffle=True, verbose = 0, callbacks=[mycallback])
print(mycallback.losses)

我使用以下配置进行测试

Keras 2.3.1
Tensorflow 2.1.0
Python 3.7.9