与此问题类似,我在使用来自google-research的鲁棒损失(提交c24a2d8)的自适应损失函数时遇到了一些麻烦:AdaptiveLossFunction
类作为损失函数工作,但不是"自适应"(潜在参数不更新)。
作者给出的例子是tf1时尚,我不知道如何制作一个损失类,我可以用Keras模型编译并监控alpha &比例尺:
在adaptive.py中,提供了class AdaptiveLossFunction
。但是,由于它不能直接用作损失,所以我做了一个朴素的包装器:
class adaLoss(AdaptiveLossFunction):
def __init__(self, num_channels, float_dtype, name='adaLoss'):
super().__init__(num_channels, float_dtype)
self.__name__=name
def __call__(self,t,p):
return super().__call__(t-p)
def alpha(self,t=0,p=0):
return super().alpha()
def scale(self,t=0,p=0):
return super().scale()
这是一些神经网络只有一个输出的结果:
opt=Adam(lr=lr_max)
loss=adaLoss(1,np.float32)
model.compile(loss=loss, optimizer=opt, metrics=[loss.alpha,loss.scale])
model.fit(x=X_train, y=Y_train, verbose=2, validation_data=(X_val,Y_val), epochs=epochs, batch_size=batch_size, callbacks=callbacks)
Epoch 1/1454
140/140 - 4s - loss: 55.1648 - alpha: 1.0000 - scale: 1.0000 - val_loss: 12.5521 - val_alpha: 1.0000 - val_scale: 1.0000
Epoch 2/1454
140/140 - 2s - loss: 17.4579 - alpha: 1.0000 - scale: 1.0000 - val_loss: 12.1275 - val_alpha: 1.0000 - val_scale: 1.0000
Epoch 3/1454
140/140 - 2s - loss: 16.3631 - alpha: 1.0000 - scale: 1.0000 - val_loss: 10.9933 - val_alpha: 1.0000 - val_scale: 1.0000
Epoch 4/1454
140/140 - 2s - loss: 15.4100 - alpha: 1.0000 - scale: 1.0000 - val_loss: 9.2542 - val_alpha: 1.0000 - val_scale: 1.0000
Epoch 5/1454
140/140 - 2s - loss: 14.3685 - alpha: 1.0000 - scale: 1.0000 - val_loss: 7.9095 - val_alpha: 1.0000 - val_scale: 1.0000
模型确实在用这个损失函数进行训练,但是alpha和scale参数没有更新。检查内部调用loss.trainable_variables
给我,这证实了潜在变量没有更新。
(<tf.Variable 'LatentAlpha:0' shape=(1, 1) dtype=float32, numpy=array([[-0.]], dtype=float32)>,
<tf.Variable 'LatentScale:0' shape=(1, 1) dtype=float32, numpy=array([[0.]], dtype=float32)>)
任何帮助都是感激的。谢谢。
损失函数的tf.Variable
由于不属于模型的training_variables
集合而没有被fit
调用优化。
一种快速而肮脏的方法是使用隐藏属性tf._trainable_weights
将潜在alpha和潜在尺度tf.Variable
添加到keras模型中。
类似这样:
opt=tf.keras.optimizers.Adam(lr=1e-3)
loss = adaLoss(1, tf.float32)
X_train = tf.random.normal((1000,1))
Y_train = X_train*3 + 4
model = tf.keras.Sequential([tf.keras.layers.Dense(1,input_shape=(1,))])
# adding the variable from the loss function to the model variables
model._trainable_weights += [loss._latent_alpha, loss._latent_scale]
model.compile(loss=loss, optimizer=opt, metrics=[loss.alpha,loss.scale])
然后,运行几个epoch:
>>> model.fit(x=X_train, y=Y_train, verbose=2, epochs=3)
Epoch 1/3
32/32 - 2s - loss: 4.6627 - alpha: 0.9919 - scale: 1.0104
Epoch 2/3
32/32 - 0s - loss: 4.5371 - alpha: 0.9765 - scale: 1.0305
Epoch 3/3
32/32 - 0s - loss: 4.4217 - alpha: 0.9620 - scale: 1.0497
更明确的方法是编写自定义训练循环,并将损失的两个变量添加到梯度计算和优化器中。(参见指南:从头开始编写训练循环)