我正在尝试使用负似然函数来训练简单的前馈神经网络来估计回归任务的不确定性。我的神经网络将均值和方差作为两个标签输出,我将自定义损失函数写成如下:
def nll_loss(y_true, y_pred):
epsilon = 1e-6
mean = y_pred[:,0] # mean
sigma_sq = y_pred[:,1] # variance
sigma_sq_sp = K.log(1 + K.exp(sigma_sq)) + 1e-06 # softplus on the variance
nll_loss = 0.5 * K.mean(K.log(sigma_sq_sp + epsilon) + K.square(y_true - mean) / (sigma_sq_sp + epsilon))
return nll_loss
inp = Input(shape=(1,))
x = Dense(10, activation="relu")(inp)
x = Dense(20, activation="relu")(x)
x = Dense(30, activation="relu")(x)
output = Dense(2, activation="linear")(x)
model = Model(inp, output)
model.compile(loss=nll_loss, optimizer='adam')
model.fit(x_train, y_train, epochs=50)
我的x_train
和y_train
具有(200,)形状,这意味着标量特征和标签(和200个示例)。使用切片y_pred[:,0]
和y_pred[:,1]
从输出层提取第一和第二标签是否正确?
我的模型被训练了几个时代,然后损失是nan
。我在计算损失函数时做错了什么吗?y_true
和y_pred
有不同的形状是可以的吗?
谢谢。
问题似乎出在Softplus激活函数的计算上:
sigma_sq_sp = K.log(1 + K.exp(sigma_sq)) + 1e-06
当我用下面的代码替换上面的行时,它工作正常:
sigma_sq_sp = tf.keras.activations.softplus(sigma_sq)
也许,为softplus内置的Keras激活确保了稳定性。谢谢你。