Keras中的自定义丢失功能

Eri*_*ric 39 computer-vision deep-learning conv-neural-network keras loss-function

我正在研究一种图像类增量分类器方法,使用CNN作为特征提取器和一个完全连接的块进行分类.

首先,我对每个训练有素的VGG网络进行了微调,以完成一项新任务.一旦网络被训练用于新任务,我就为每个班级存储一些示例,以避免在新班级可用时忘记.

当某些类可用时,我必须计算样本的每个输出,包括新类的示例.现在为旧类的输出添加零,并在新类输出上添加与每个新类对应的标签,我有新标签,即:如果有3个新类输入....

旧班类型输出: [0.1, 0.05, 0.79, ..., 0 0 0]

新类类型输出:[0.1, 0.09, 0.3, 0.4, ..., 1 0 0]**最后的输出对应于类.

我的问题是,我如何改变自定义的损失函数来训练新的类?我想要实现的损失函数定义为:

损失功能

蒸馏损失对应于旧类别的输出以避免遗忘,而分类损失对应于新类别.

如果你能给我一些代码样本来改变keras中的损失函数会很好.

谢谢!!!!!

Dan*_*ler 66

您所要做的就是使用keras后端函数进行计算,为此定义一个函数.该函数必须采用真值和模型预测值.

现在,因为我不确定函数中的g,q,x和y是什么,所以我只是在这里创建一个基本的例子而不关心它的含义或它是否是一个实际有用的函数:

import keras.backend as K

def customLoss(yTrue,yPred):
    return K.sum(K.log(yTrue) - K.log(yPred))
Run Code Online (Sandbox Code Playgroud)

所有后端功能都可以在这里看到:https://keras.io/backend/

之后,使用该函数而不是常规函数编译模型:

model.compile(loss=customLoss, optimizer = .....)
Run Code Online (Sandbox Code Playgroud)

  • @Daniel那么,keras如何映射自定义损失函数参数?是否接受模型输出并将其隐式应用于customLoss?像CustomLoss(* model_outputs)吗? (2认同)

Nic*_*ais 5

由于 Keras 不再是多后端(),因此自定义损失的操作应直接在 Tensorflow 中进行,而不是使用后端。

您可以通过创建一个以y_truey_pred作为参数的函数来使用 Tensorflow 进行自定义损失,如文档中所建议的:

import tensorflow as tf

x = tf.random.uniform(minval=0, maxval=1, shape=(10, 1), dtype=tf.float32)
y = tf.random.uniform(minval=0, maxval=1, shape=(10, 1), dtype=tf.float32)

def custom_mse(y_true, y_pred):
    squared_difference = tf.square(y_true - y_pred)
    return tf.reduce_mean(squared_difference, axis=-1)

custom_mse(x, y)
Run Code Online (Sandbox Code Playgroud)
<tf.Tensor: shape=(10,), dtype=float32, numpy=
array([0.30084264, 0.03535452, 0.10345092, 0.28552982, 0.02426687,
       0.04410492, 0.01701574, 0.55496216, 0.74927425, 0.05747304],
      dtype=float32)>
Run Code Online (Sandbox Code Playgroud)

然后您可以在 中设置您的自定义损失model.compile()。这是一个完整的示例:

x = tf.random.uniform(minval=0, maxval=1, shape=(1000, 4), dtype=tf.float32)
y = tf.multiply(tf.reduce_sum(x, axis=-1), 5) # y is a function of x

model = tf.keras.Sequential([
    tf.keras.layers.Dense(16, input_shape=[4], activation='relu'),
    tf.keras.layers.Dense(32, activation='relu'),
    tf.keras.layers.Dense(1)
])

model.compile(loss=custom_mse, optimizer='adam')

history = model.fit(x, y, epochs=10)
Run Code Online (Sandbox Code Playgroud)
Train on 1000 samples
Epoch 1/5
  32/1000 [..............................] - ETA: 10s - loss: 99.5402
1000/1000 [==============================] - 0s 371us/sample - loss: 105.6800
Epoch 2/5
  32/1000 [..............................] - ETA: 0s - loss: 89.2909
1000/1000 [==============================] - 0s 35us/sample - loss: 98.8208
Epoch 3/5
  32/1000 [..............................] - ETA: 0s - loss: 86.4339
1000/1000 [==============================] - 0s 34us/sample - loss: 82.7988
Epoch 4/5
  32/1000 [..............................] - ETA: 0s - loss: 75.2580
1000/1000 [==============================] - 0s 33us/sample - loss: 52.4585
Epoch 5/5
  32/1000 [..............................] - ETA: 0s - loss: 28.1625
1000/1000 [==============================] - 0s 34us/sample - loss: 17.8190
Run Code Online (Sandbox Code Playgroud)

  • 因此,接受的答案从自定义损失函数返回一个标量,但您的答案返回一个 (10,) 张量(这显然似乎有效)。我们真的可以自由地这样做吗?或者接受的答案是否不正确,或者是自定义损失函数的有效返回? (2认同)