【发布时间】:2018-07-04 00:25:46
【问题描述】:
我正在训练使用 Keras 训练神经网络,并且我使用自己的度量函数作为损失函数。原因是测试集中的实际值有很多 NaN 值。让我举一个测试集中实际值的例子:
12
NaN
NaN
NaN
8
NaN
NaN
3
在我的数据预处理中,我用零替换了所有的 NaN 值,因此上面的示例在每个 NaN 行上都包含零。
神经网络产生如下输出:
14
12
9
9
8
7
6
3
我只想计算非零值之间的均方根误差。所以对于上面的例子,它应该只计算第 1、5 和 8 行的 RMSE。为此,我创建了以下函数:
from sklearn.metrics import mean_squared_error
from 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
当您手动测试函数时,通过输入测试集中的实际值和使用随机权重初始化的神经网络的输出,它运行良好并产生错误值。我能够使用进化方法来优化权重,并且我能够通过调整网络的权重来优化这个误差度量。
现在,我想使用 Keras 的 model.compile 函数以 evaluation_metric 作为损失函数来训练网络。当我跑步时:
model.compile(loss=evaluation_metric, optimizer='rmsprop', metrics=[evaluation_metric])
我收到以下错误:
TypeError:不允许将
tf.Tensor用作Pythonbool。使用if t is not None:而不是if t:来测试是否定义了张量,并使用TensorFlow ops(如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))
【问题讨论】:
-
如果我没记错的话,
y_true = y_true * (y_true != 0)如果值为 0,则将值乘以 0,否则乘以 1,或者换句话说,它什么都不做,因此可以删除 -
另外,在自定义损失函数中使用
y_pred = y_pred * (y_true != 0)时,我得到了TypeError: Input 'y' of 'Mul' Op has type bool that does not match type float32 of argument 'x'.。 -
我改用
y_pred = y_pred * tf.cast((y_true != 0), 'float32')
标签: python tensorflow machine-learning keras deep-learning