仅评估tf.Tensor的非零值

时间:2018-01-24 20:44:22

标签: python tensorflow keras

我正在训练使用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的evaluation_metric函数训练网络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)) 

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:-1)

我会自己在tensorflow中编写指标,如:

import tensorflow as tf
import numpy as np


data = np.array([0, 1, 2, 0, 0, 3, 7, 0]).astype(np.float32)
pred = np.random.randn(8).astype(np.float32)
gt = np.random.randn(8).astype(np.float32)

data_op = tf.convert_to_tensor(data)
pred_op = tf.convert_to_tensor(pred)
gt_op = tf.convert_to_tensor(gt)

expected = np.sqrt(((gt[data != 0] - pred[data != 0]) ** 2).mean())


def nonzero_mean(gt_op, pred_op, data_op):
    mask_op = 1 - tf.cast(tf.equal(data_op, 0), tf.float32)

    actual_op = ((gt_op - pred_op) * mask_op)**2
    actual_op = tf.reduce_sum(actual_op) / tf.cast(tf.count_nonzero(mask_op), tf.float32)
    actual_op = tf.sqrt(actual_op)
    return actual_op

with tf.Session() as sess:

    actual = sess.run(nonzero_mean(gt_op, pred_op, data_op))

print actual, expected

普通Tensorflow中无法y_true != 0。不确定,如果keras在这里做了一些魔术。