Python 自定义记分器的问题

Python 自定义记分器的问题,python,tensorflow,keras,scikit-learn,deep-learning,Python,Tensorflow,Keras,Scikit Learn,Deep Learning,我正在做一些机器学习的在线课程,我们在DNN模型中使用以下评分函数进行回归: def r_squared(y_true, y_pred): # 1 - ((y_i - y_hat_i)^2 / (y_i - y_sum)^2) numerator = tf.reduce_sum(tf.square(tf.subtract(y_true, y_pred))) denominator = tf.reduce_sum(tf.square(tf.

我正在做一些机器学习的在线课程,我们在DNN模型中使用以下评分函数进行回归:

    def r_squared(y_true, y_pred):
        # 1 - ((y_i - y_hat_i)^2 / (y_i - y_sum)^2)

        numerator = tf.reduce_sum(tf.square(tf.subtract(y_true, y_pred)))
        denominator = tf.reduce_sum(tf.square(tf.subtract(y_pred, tf.reduce_mean(y_true))))
        r2 = tf.clip_by_value(tf.subtract(1.0, tf.div(numerator, denominator)), clip_value_min = 0.0, clip_value_max = 1.0)

        return r2

... later ...

        model.compile(loss = "mse", # mean-square-error,
                    optimizer = optimizer(lr = learning_rate),
                    metrics = [r_squared])
现在,当模型和所有工具都工作时,我想进行网格搜索,以确定模型的最佳参数。但是,当尝试将
r_squared
函数与gridsearch作为记分器一起使用时,我遇到了几个错误:


        grid = GridSearchCV(estimator = estimator, 
                            param_grid = param_grid,
                            n_jobs = 1,
                            verbose = 1,
                            cv = folds,
                            scoring = make_scorer(FeedForward.r_squared, greater_is_better=True))
结果:

TypeError: Input 'y' of 'Sub' Op has type float64 that does not match type float32 of argument 'x'.
ValueError: scoring must return a number, got Tensor("mul:0", shape=(), dtype=float32) (<class 'tensorflow.python.framework.ops.Tensor'>) instead. (scorer=score)
在这附近:

r2 = tf.clip_by_value(tf.subtract(1.0, tf.div(numerator, denominator)), clip_value_min = 0.0, clip_value_max = 1.0)
因此,我将行更改如下:

r2 = tf.clip_by_value(tf.subtract(1.0, tf.div(tf.cast(numerator, tf.float32), tf.cast(denominator, tf.float32))), clip_value_min = 0.0, clip_value_max = 1.0)

这将导致:

TypeError: Input 'y' of 'Sub' Op has type float64 that does not match type float32 of argument 'x'.
ValueError: scoring must return a number, got Tensor("mul:0", shape=(), dtype=float32) (<class 'tensorflow.python.framework.ops.Tensor'>) instead. (scorer=score)
ValueError:scoring必须返回一个数字,改为获得张量(“mul:0”,shape=(),dtype=float32)()。(记分员=得分)
虽然我理解错误并可以在调试器中确认它,但我发现自己无法解决问题,即使用谷歌搜索错误。这可能是由于-不必提及-对tensorflow还不够熟悉


那么如何从张量中求出值呢?我在这里做的事情是对的,还是别的什么错了?

问题是TensorFlow/Keras和scikit learn的用法混用了。Keras度量需要使用
Keras.backend
函数来实现,但是scikit学习函数不是符号,必须使用numpy来实现

幸运的是,scikit learn已经实现了R^2分数
sklearn.metrics.r2_分数
,因此您可以这样使用它:

from sklearn.metrics import r2_score

grid = GridSearchCV(estimator = estimator, 
                            param_grid = param_grid,
                            n_jobs = 1,
                            verbose = 1,
                            cv = folds,
                            scoring = make_scorer(r2_score, greater_is_better=True))

您的Keras度量不需要更改,您必须保留度量的两个实现,这有点奇怪,但它是这样的。

我尝试了这个方法,但是分类为来自sklearn的r2提供了不同的值,作为我使用自定义
r_squared
函数的训练度量。在100个纪元之后,
r_平方
将被训练为0.63(接近1更好),而分类将产生如下结果:
Best:-3.003969使用{'layers':[64],'learning_rate':0.005,'optimizer':}
在具有相同参数的100个纪元之后。因此,似乎
sklearn.metrics.r2\u分数
没有计算相同的度量。@user826955我不明白你所说的“分类”是什么意思,可能是你的r2实现不正确。我更信任sklearn的实现,网格搜索。显然,
sklearn.metrics.r2_score
函数生成的数字与my
r_squared
不同(因为实现明显不同)。这意味着,我想在
GridSearchCV
中使用我的
r_平方
函数,这样我可以将输出与我的正常训练运行(也使用我的
r_平方
函数)进行比较。