【问题标题】:How to create/customize your own scorer function in scikit-learn?如何在 scikit-learn 中创建/自定义自己的记分器功能?
【发布时间】:2015-11-30 19:33:42
【问题描述】:

我在GridSearchCV 中使用Support Vector Regression 作为估计器。但是我想更改误差函数:我想定义自己的自定义误差函数,而不是使用默认值(R-squared:确定系数)。

我尝试用make_scorer 制作一个,但没有成功。

我阅读了文档,发现可以创建custom estimators,但我不需要重新制作整个估算器 - 只需重新制作错误/评分函数。

我想我可以通过将可调用对象定义为记分员来做到这一点,就像 docs 中所说的那样。

但我不知道如何使用估算器:在我的例子中是 SVR。我是否必须切换到分类器(例如 SVC)?我将如何使用它?

我的自定义错误函数如下:

def my_custom_loss_func(X_train_scaled, Y_train_scaled):
    error, M = 0, 0
    for i in range(0, len(Y_train_scaled)):
        z = (Y_train_scaled[i] - M)
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
            error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
            error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
        if X_train_scaled[i] > M and Y_train_scaled[i] < M:
            error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
    error += error_i
    return error

变量M 不为空/零。为简单起见,我只是将其设置为零。

谁能展示这个自定义评分功能的示例应用程序?感谢您的帮助!

【问题讨论】:

  • 这个例子:(estimator, X, y)

标签: python scikit-learn


【解决方案1】:

Jamie 有一个充实的示例,但这里有一个直接来自 scikit-learn documentation 的使用 make_scorer 的示例:

import numpy as np
def my_custom_loss_func(ground_truth, predictions):
    diff = np.abs(ground_truth - predictions).max()
    return np.log(1 + diff)

# loss_func will negate the return value of my_custom_loss_func,
#  which will be np.log(2), 0.693, given the values for ground_truth
#  and predictions defined below.
loss  = make_scorer(my_custom_loss_func, greater_is_better=False)
score = make_scorer(my_custom_loss_func, greater_is_better=True)
ground_truth = [[1, 1]]
predictions  = [0, 1]
from sklearn.dummy import DummyClassifier
clf = DummyClassifier(strategy='most_frequent', random_state=0)
clf = clf.fit(ground_truth, predictions)
loss(clf,ground_truth, predictions) 

score(clf,ground_truth, predictions)

通过sklearn.metrics.make_scorer 定义自定义记分器时,约定是以_score 结尾的自定义函数返回一个值以最大化。对于以_loss_error 结尾的记分员,返回一个值以使其最小化。您可以通过在make_scorer 中设置greater_is_better 参数来使用此功能。也就是说,该参数将是True 用于较高值更好的得分者,False 用于较低值更好的得分者。 GridSearchCV 然后可以在适当的方向进行优化。

然后您可以将您的函数转换为记分员,如下所示:

from sklearn.metrics.scorer import make_scorer

def custom_loss_func(X_train_scaled, Y_train_scaled):
    error, M = 0, 0
    for i in range(0, len(Y_train_scaled)):
        z = (Y_train_scaled[i] - M)
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
            error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
            error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
        if X_train_scaled[i] > M and Y_train_scaled[i] < M:
            error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
    error += error_i
    return error


custom_scorer = make_scorer(custom_loss_func, greater_is_better=True)

然后将custom_scorer 传递给GridSearchCV,就像其他任何评分函数一样:clf = GridSearchCV(scoring=custom_scorer)

【讨论】:

  • 感谢您的回复。我在 Scikit 中阅读了这个文档,也阅读了关于自定义函数的内容,但我没有得到它的工作。之后 Jamie Bull 写了他的“make_scorer”,我又试了一次......它有效!我不知道如何或为什么。我正在切换到 Windows 10 并重新安装我的所有程序......可能是:Windows 10 加上新版本的 Anaconda(我在 Anaconda 下运行 python)。无论如何,非常感谢! (我不是程序员或计算机科学家......所以这对我来说很难)。
【解决方案2】:

如您所见,这是通过使用 make_scorer (docs) 完成的。

from sklearn.grid_search import GridSearchCV
from sklearn.metrics import make_scorer
from sklearn.svm import SVR

import numpy as np

rng = np.random.RandomState(1)

def my_custom_loss_func(X_train_scaled, Y_train_scaled):
    error, M = 0, 0
    for i in range(0, len(Y_train_scaled)):
        z = (Y_train_scaled[i] - M)
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) > 0:
            error_i = (abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z))
        if X_train_scaled[i] > M and Y_train_scaled[i] > M and (X_train_scaled[i] - Y_train_scaled[i]) < 0:
            error_i = -(abs((Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(z)))
        if X_train_scaled[i] > M and Y_train_scaled[i] < M:
            error_i = -(abs(Y_train_scaled[i] - X_train_scaled[i]))**(2*np.exp(-z))
    error += error_i
    return error

# Generate sample data
X = 5 * rng.rand(10000, 1)
y = np.sin(X).ravel()

# Add noise to targets
y[::5] += 3 * (0.5 - rng.rand(X.shape[0]/5))

train_size = 100

my_scorer = make_scorer(my_custom_loss_func, greater_is_better=True)

svr = GridSearchCV(SVR(kernel='rbf', gamma=0.1),
                   scoring=my_scorer,
                   cv=5,
                   param_grid={"C": [1e0, 1e1, 1e2, 1e3],
                               "gamma": np.logspace(-2, 2, 5)})

svr.fit(X[:train_size], y[:train_size])

print svr.best_params_
print svr.score(X[train_size:], y[train_size:])

【讨论】:

  • 嗨。我知道 make_scorer 但我想定义一个包含条件的新函数(如果在那里)。那么如何在函数错误中使用“if”和“for”呢?谢谢。
  • 对不起,我不明白这个问题。我不清楚你想做什么。
  • 我的英语说得很差,对不起。我正在尝试在“my_custom_loss_function”中使用“if conditional”和“for”。像
    def my_custom_loss_func(X_train_scaled, Y_train_scaled): error, M = 0, 0 for i in range(0, len(Y_train_scaled)): z = (Y_train_scaled[i] - M) if X_train_scaled[i] > M和 Y_train_scaled[i] > M 和 (X_train_scaled[i] - Y_train_scaled[i]) > 0:...
    我可以这样做吗?我的笔记本电脑似乎被阻塞了。而我想在“X_train_scaled”中把我所有的数据一个一个的看一遍,然后对它进行操作。谢谢。
  • 别担心,你的英语很好。这个例子对你有用吗?如果没有,你能告诉我问题出在哪里吗?
  • 我试过这个例子。我不知道,但是……不,它有效!我认为我的 dtype 有错误(在数组和 python 之间;也许我有“n_job=-1”)。我真的不知道,但我很高兴,因为它现在有效!非常感谢!
猜你喜欢
  • 2015-12-17
  • 2014-08-09
  • 2018-09-22
  • 2018-02-22
  • 2014-05-01
  • 2020-06-24
  • 2022-08-12
  • 1970-01-01
相关资源
最近更新 更多