Keras - 自定义丢失函数 - 计算来自真值标签的softmax输出的平方距离

时间:2018-03-12 00:04:33

标签: python tensorflow machine-learning neural-network keras

我正在训练一个以softmax层结尾的分类问题。我想将损失计算为预测概率和每个示例的softmax输出与真值标签的平方距离乘积的平均值。

在伪代码中:平均值(概率* distance_from_label ** 2)

现在我正在使用以下代码运行,但会收敛到输出' 0'对于每个实例。它的实施存在一些问题:

bs = batch_size
l = labels
X = K.constant([[0,1,...,l-1] for y in range(bs)], shape=((bs,l))
X = tf.add(-y_true, X)
X = tf.abs(X)
X = tf.multiply(y_pred, X)
X = tf.multiply(X, X)
return K.mean(X)

有没有办法实现这个方差损失功能并保持softmax层?还是要测量预测标签和真实标签之间的实际欧几里德距离,而不仅仅是单热矢量中的元素差异吗?

为清楚起见,我提供了以下示例:

示例1:

label1 = [0,0,1,0],prediction1 = [1,0,0,0]

loss1 = 4 =(4 + 0 + 0 + 0)=(1 * 2 ^ 2 + 0 * 1 ^ 2 + 0 * 0 ^ 2 + 0 * 1 ^ 2)

示例2:

label2 = [0,1,0,0],prediction2 = [0.3,0.1,0.3,0.3]

损失2 = 1.8 =(0.3 + 0 + 0.3 + 1.2)=(0.3 * 1 ^ 2 + 0.1 * 0 ^ 2 + 0.3 * 1 ^ 2 + 0.3 * 2 ^ 2)

2 个答案:

答案 0 :(得分:0)

在设计自定义丢失功能时,您可以使用Tensorflow(或Theano)以及Keras后端。请注意Tensorflow中的tf.multiply和其他函数。

以下代码在Keras(测试和工作)中实现此自定义丢失功能:

bs = batch_size
l = labels
c = K.constant([[x for x in range(l)] for y in range(bs)], 
               shape=((bs,l))

truths = tf.multiply(y_true, c)
truths = K.sum(truths, axis=1)
truths = K.concatenate(list(truths for i in range(l)))
truths = K.reshape(truths, ((sb,l)))

distances = tf.add(truths, -c)
sqdist = tf.multiply(distances, distances)

out = tf.multiply(y_pred, sqdist)
out = K.sum(out, axis=1)

return K.mean(out)

答案 1 :(得分:0)

这里是另一种实现方式,它以略微不同的权重实现相同的目标。注意:一次性标签必须为dtype = float32。所有学分归我的主管所有。

import numpy as np
import tensorflow as tf
import tensorflow.keras as keras
 
model = keras.models.Sequential()
model.add(keras.layers.Dense(5, activation="relu"))
model.add(keras.layers.Dense(4, activation="softmax"))
opt = keras.optimizers.Adam(lr=1e-3, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
 
def custom_loss(y_true, y_pred):

    a = tf.reshape(tf.range(tf.cast(tf.shape(y_pred)[1],dtype=tf.float32)),(1,-1))
    c = tf.tile(a,(tf.shape(y_pred)[0],1))
    x = tf.math.multiply(y_true,c)
    x = tf.reshape(tf.reduce_sum(x, axis=1),(-1,1))
    x = tf.tile(x,(1,tf.shape(y_pred)[1]))
    x = tf.math.pow(tf.math.subtract(x,c),2)
    x = tf.math.multiply(x,y_pred)
    x = tf.reduce_sum(x, axis=1)
    return tf.reduce_mean(x)
     

 
yTrue= np.array([[0,0,1,0],[0,0,1,0],[0, 1, 0, 0]]).astype(np.float32)
y_true = tf.constant(yTrue)
y_pred = tf.constant([[1,0,0,0],[0,0,1,0],[0.3, 0.1, 0.3, 0.3]])
custom_loss(y_true,y_pred)
 
model.compile(optimizer=opt, loss=custom_loss)
model.fit(np.random.random((3,10)),yTrue, epochs=100)