我在使用Keras训练神经网络,并且使用自定义的度量函数作为损失函数。这样做的原因是测试集中的实际值包含大量NaN值。让我举个测试集中实际值的例子:
12NaNNaNNaN8NaNNaN3
在数据预处理过程中,我将所有NaN值替换为零,因此上面的例子在每个NaN位置都包含零。
神经网络产生的输出如下:
1412998763
我只想计算非零值之间的均方根误差。因此,对于上面的例子,它应该只计算第1、5和8行的RMSE。为此,我创建了以下函数:
from sklearn.metrics import mean_squared_errorfrom math import sqrt[...]def evaluation_metric(y_true, y_pred):y_true = y_true[np.nonzero(y_true)]y_pred = y_pred[np.nonzero(y_true)]error = sqrt(mean_squared_error(y_true, y_pred))return error
当你手动测试这个函数,通过输入测试集的实际值和初始化为随机权重的神经网络输出时,它工作得很好并产生了一个误差值。我能够使用进化方法优化权重,并且通过调整网络的权重来优化这个误差度量。
现在,我想使用evaluation_metric
作为损失函数来训练网络,使用Keras的model.compile
函数。当我运行以下代码时:
model.compile(loss=evaluation_metric, optimizer='rmsprop', metrics=[evaluation_metric])
我得到了以下错误:
TypeError: 不允许将
tf.Tensor
用作Python的bool
。使用if t is not None:
代替if t:
来测试一个张量是否已定义,并使用TensorFlow操作如tf.cond来执行基于张量值的子图。
我认为这与使用np.nonzero
有关。由于我在使用Keras,可能应该使用Keras后端的函数,或者使用类似tf.cond的东西来检查y_true的非零值。
有人能帮我解决这个问题吗?
编辑
应用以下修复后,代码可以工作:
def evaluation_metric(y_true, y_pred): y_true = y_true * (y_true != 0) y_pred = y_pred * (y_true != 0) error = root_mean_squared_error(y_true, y_pred) return error
连同以下用于计算tf对象的RMSE的函数:
def root_mean_squared_error(y_true, y_pred): return K.sqrt(K.mean(K.square(y_pred - y_true), axis=-1))
回答:
是的,问题确实出在使用numpy
函数上。这里有一个快速修复方法:
def evaluation_metric(y_true, y_pred): y_true = y_true * (y_true != 0) y_pred = y_pred * (y_true != 0) error = sqrt(mean_squared_error(y_true, y_pred)) return error