13

有没有办法使用 GridSearchCV 或任何其他内置的 sklearn 函数来找到 OneClassSVM 分类器的最佳超参数?

我目前所做的是使用这样的训练/测试拆分自己执行搜索:

Gamma 和 nu 值定义为:

gammas = np.logspace(-9, 3, 13)
nus = np.linspace(0.01, 0.99, 99)

探索所有可能的超参数并找到最佳超参数的函数:

clf = OneClassSVM()

results = []

train_x = vectorizer.fit_transform(train_contents)
test_x = vectorizer.transform(test_contents)

for gamma in gammas:
    for nu in nus:
        clf.set_params(gamma=gamma, nu=nu)

        clf.fit(train_x)

        y_pred = clf.predict(test_x)

        if 1. in y_pred:  # Check if at least 1 review is predicted to be in the class
            results.append(((gamma, nu), (accuracy_score(y_true, y_pred),
                                              precision_score(y_true, y_pred),
                                              recall_score(y_true, y_pred),
                                              f1_score(y_true, y_pred),
                                              roc_auc_score(y_true, y_pred),
                                              ))
                               )

    # Determine and print the best parameter settings and their performance
    print_best_parameters(results, best_parameters(results))

结果存储在形式的元组列表中:

((伽玛,nu)(accuracy_score,precision_score,recall_score,f1_score,roc_auc_score))

为了找到最佳准确度、f1、roc_auc 分数和参数,我编写了自己的函数:

最佳参数(结果)

4

2 回答 2

9

我在寻找解决方案时遇到了同样的问题并发现了这个问题。我最终找到了一个解决方案,该解决方案使用GridSearchCV并将此答案留给搜索并找到此问题的任何其他人。

GridSearchCV类的cv参数可以将可迭代的产生(训练、测试)拆分作为索引数组作为其输入。您可以生成仅使用训练折叠中正类中的数据以及正类中的剩余数据以及测试折叠中负类中的所有数据的拆分。

你可以sklearn.model_selection.KFold用来做分裂

from sklearn.model_selection import KFold

假设Xpos是正类的 nXp numpy 数据数组,OneClassSVM并且Xneg是已知异常示例的 mXp 数据数组。

您可以首先生成拆分以供Xpos使用

splits = KFold(n_splits=5).split(Xpos)

这将构造一个元组的生成器,其形式为(train, test)wheretrain是一个 int 的 numpy 数组,其中包含训练折叠中示例的索引,并且test是一个包含测试折叠中示例索引的 numpy 数组。

然后Xpos,您可以Xneg使用

X = np.concatenate([Xpos, Xneg], axis=0)

OneClassSVM它将1.0对其认为属于正类的示例进行预测,并对其-1.0认为异常的示例进行预测。我们可以使用为我们的数据制作标签

y = np.concatenate([np.repeat(1.0, len(Xpos)), np.repeat(-1.0, len(Xneg))])

然后,我们可以(train, test)为测试折叠中包含的异常示例创建一个带有索引的新拆分生成器。

n, m = len(Xpos), len(Xneg)

splits = ((train, np.concatenate([test, np.arange(n, n + m)], axis=0)
          for train, test in splits)

然后,您可以将这些拆分传递给GridSearchCV使用数据X, y以及您希望的任何评分方法和其他参数。

grid_search = GridSearchCV(estimator, param_grid, cv=splits, scoring=...)

编辑:我没有注意到 Vivek Kumar 在另一个答案的评论中建议了这种方法,并且 OP 拒绝了它,因为他们不相信它会与他们选择最佳参数的方法一起使用。我仍然更喜欢我所描述的方法,因为 GridSearchCV 将自动处理多处理并提供异常处理以及信息性警告和错误消息。

它在评分方法的选择上也很灵活。您可以通过将字典映射字符串传递给评分可调用对象来使用多种评分方法,甚至可以定义自定义评分可调用对象。这在此处的 Scikit-learn 文档中有描述。选择最佳参数的定制方法可能会使用自定义评分功能来实现。OP 使用的所有指标都可以使用文档中描述的字典方法包含在内。

你可以在这里找到一个真实的例子。当它合并到 master 时,我会记下更改链接。

于 2019-10-18T23:44:01.417 回答
5

是的,有一种方法可以在不对输入数据执行交叉验证的情况下搜索超参数。该方法被调用ParameterGrid()并存储在sklearn.model_selection. 这是官方文档的链接:

http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.ParameterGrid.html

您的案例可能如下所示:

grid = {'gamma' : np.logspace(-9, 3, 13),
        'nu' : np.linspace(0.01, 0.99, 99)}

要使用网格断言所有可能的步骤,您可以键入list(ParameterGrid(grid)). 我们还可以检查它的长度,通过len(list(ParameterGrid(grid)))它总共给出了 1287 个模型,因此有 1287 个模型适合训练数据。

要使用该方法,您必然需要一个for循环。暗示您有clfsklearn.svm变量,因为您不适合从循环导入的一类 SVM,如下所示:

for z in ParameterGrid(grid):
    clf.set_params(**z)
    clf.fit(X_train, y_train)
    clf.predict(X_test)
    ...

我希望这就足够了。不要忘记网格中的名称应该与一类 SVM 的参数一致。要获取这些参数的名称,您可以键入clf.get_params().keys(),然后您会看到“gamma”和“nu”。

于 2017-06-23T05:45:38.623 回答