【问题标题】:Issues with custom scorer自定义记分器的问题
【发布时间】:2019-10-30 17:16:34
【问题描述】:

我正在做一些机器学习的在线课程,我们在 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'.

在这里:

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)

然后导致:

ValueError: scoring must return a number, got Tensor("mul:0", shape=(), dtype=float32) (<class 'tensorflow.python.framework.ops.Tensor'>) instead. (scorer=score)

虽然我了解错误并且可以在调试器中确认它,但我发现即使使用谷歌搜索错误也无法解决问题。这可能是由于 - 无需提及 - 对 tensorflow 还不够熟悉。

那么如何从张量中获取值?我在这里做的是正确的事情,还是有其他问题?

【问题讨论】:

    标签: python tensorflow keras scikit-learn deep-learning


    【解决方案1】:

    问题正在混合TensoRFlow / Keras和Scikit-Learn的用法。需要使用keras.backend函数来实现Keras度量,但Scikit-Searning函数不是符号的,并且必须使用NUMPY实现。

    幸运的是scikit-seather已经有一个实施R ^ 2得分为sklearn.metrics.r2_score,所以你可以像这样用它:

    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_squared将接受培训至0.63(接近1更好),而分类将产生这样的结果:Best: -3.003969 using {'layers': [64], 'learning_rate': 0.005, 'optimizer': &lt;class 'keras.optimizers.Adam'&gt;} 100时epochs,具有相同参数的100个时期。所以似乎sklearn.metrics.r2_score @不是计算相同的度量标准。 span>
    • @ user826955我没有得到你的意思是“分类”,可能是你的r2实现不正确。我相信更多sklearn实现。 span>
    • 网格搜索。显得突然,sklearn.metrics.r2_score函数产生的数量不同于我的r_squared(因为实现显得不同)。这意味着,我想在GridSearchCV中使用我的r_squared,所以我可以将输出与我的正常传出运行进行比较(这也使用我的r_squared函数)。 span>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-23
    • 2019-12-17
    相关资源
    最近更新 更多