我正在尝试使用功能 API中描述的每个输出中的不同损失函数来实现多输出回归问题。对于每个输出,我尝试使用与每个输出对应的自定义损失函数(分位数)。但是,该模型似乎没有适当地应用不同的损失函数,并且仅针对其中一个评估每个输出(它恰好是列表中的最后一个)。
quantiles = [0.05,0.5,0.95]
input_layer = keras.Input(shape=(inputs_norm.shape[1]), name="input")
hidden_layer_1 = layers.Dense(units=100,name='hidden_1',activation='tanh',kernel_regularizer=regularizers.l2(0.05))(input_layer)
output_layers = []
losses = {}
def quantile_loss(q,y,f): #Custom quantile loss function with parameter q
e = (y-f)
return K.mean(K.maximum(q*e, (q-1)*e), axis=-1)
for q in quantiles:
name = 'q{:0.2f}'.format(q) #Name to give each layer/loss function
output_layers.append(layers.Dense(1,name=name)(hidden_layer_1)) #Add output layers for each quantile
losses[name] = lambda y,f:quantile_loss(q,y,f) #Specify loss function for each output layer
model = keras.Model(inputs=input_layer,outputs=output_layers)
model.compile(optimizer='Adam',loss=losses)
model.fit(x=X_train,y=y_train,verbose=1,epochs=20,batch_size=8)
在训练期间,模型快速收敛到每个输出的值。在测试样本上评估模型会为每个输出层产生相同的损失:
sample_x = X_test[0:24,:]
sample_y = y_test[0:24] * targets.std() + targets.mean()
print(model.evaluate(sample_x,sample_y))
1/1 [==============================] - 0s 12ms/step - loss: 42.3914 - q0.05_loss: 14.1223 - q0.50_loss: 14.1212 - q0.95_loss: 14.1231
[42.39143753051758, 14.122288703918457, 14.121197700500488, 14.123051643371582]
但正如我所料,单独循环遍历每个损失函数会产生不同的损失值。
preds = model.predict(sample_x)
test_losses = []
for i in range(0,len(quantiles)):
q = quantiles[i]
print(K.mean(model.loss['q{:0.2f}'.format(q)](sample_y,preds[i])))
tf.Tensor(0.8576285001198866, shape=(), dtype=float64)
tf.Tensor(7.439945051634891, shape=(), dtype=float64)
tf.Tensor(14.023351473256945, shape=(), dtype=float64)
这个真的让我摸不着头脑。我的直觉告诉我,我指定输出层或损失函数的方式存在问题。