Scikit learn 有没有一种方法可以在一类SVM上执行网格搜索超参数优化

Scikit learn 有没有一种方法可以在一类SVM上执行网格搜索超参数优化,scikit-learn,svm,grid-search,multilabel-classification,hyperparameters,Scikit Learn,Svm,Grid Search,Multilabel Classification,Hyperparameters,有没有办法使用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_transf

有没有办法使用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))
结果存储在以下形式的元组列表中:

((gamma,nu)(准确度评分、精密度评分、回忆度评分、f1评分、, roc_auc_分数)

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

最佳参数(结果)


是的,有一种方法可以搜索超参数,而无需对输入数据执行交叉验证。此方法称为
ParameterGrid()
,存储在
sklearn.model\u selection
中。以下是官方文件的链接:

您的案例可能如下所示:

grid = {'gamma' : np.logspace(-9, 3, 13),
        'nu' : np.linspace(0.01, 0.99, 99)}
要使用网格断言所有可能的步骤,可以键入
列表(ParameterGrid(grid))
。我们还可以通过
len(list(ParameterGrid(grid))
检查其长度,这总共提供了1287个模型,因此1287个模型适合列车数据

要使用该方法,您必须为此使用for循环。这意味着您有clf变量,因为您不适合从
sklearn.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”。

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

类的
cv
参数可以将一个可匹配的屈服(训练、测试)分裂作为索引数组作为其输入。您可以生成拆分,该拆分仅使用训练折叠中正类的数据,以及测试折叠中正类的剩余数据加上负类的所有数据

您可以使用
sklearn.model\u selection.KFold
进行拆分

from sklearn.model_selection import KFold
假设
Xpos
OneClassSVM
正类的nXp numpy数据数组,
Xneg
是已知异常示例的mXp数据数组

您可以首先使用

splits = KFold(n_splits=5).split(Xpos)
这将构造一个元组生成器,其形式为
(train,test)
,其中
train
是一个int的numpy数组,包含训练折叠中示例的索引,
test
是一个numpy数组,包含测试折叠中示例的索引

然后,您可以使用

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))])
然后,我们可以制作一个新的
(训练,测试)
分裂生成器,其中包含测试褶皱中异常示例的索引

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

splits = ((train, np.concatenate([test, np.arange(n, n + m)], axis=0)
          for train, test in splits)
然后,您可以使用数据
X,y
以及任何评分方法和您希望的其他参数将这些拆分传递到
GridSearchCV

grid_search = GridSearchCV(estimator, param_grid, cv=splits, scoring=...)
编辑:我没有注意到Vivek Kumar在另一个答案的评论中提出了这种方法,OP拒绝了这种方法,因为他们认为这种方法不适合他们选择最佳参数的方法。我仍然更喜欢我描述的方法,因为GridSearchCV将自动处理多处理,并提供异常处理和信息性警告和错误消息

它在评分方法的选择上也很灵活。通过将字典映射字符串传递给评分可调用项,甚至可以定义自定义方法,您可以使用多种评分方法 为可调用项评分。Scikit学习文档中对此进行了描述。选择最佳参数的定制方法可能通过自定义评分函数实现。OP使用的所有指标都可以使用文档中描述的字典方法包括在内


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

您用GridSearchCV尝试过吗?您是否有任何错误?我如何在不应用交叉验证的情况下做到这一点,因为一个类SVM只需要拟合属于分类器正在处理的类的数据。我所做的是:对80%属于该类的实例进行训练,然后将剩余的20%与不属于该类的实例结合起来并使用它们进行测试。您如何将数据划分为训练和测试?@Yustx请您与OC-SVM分享您如何解决此问题。我正在努力解决同样的问题,我不知道如何将你的问题与答案结合起来才能让它工作。这个解决方案很好。但同样,OP必须维护有关分数、拟合、参数等的所有信息。GridSearchCV将自动执行此操作。由于用户将数据分为训练和测试,因此我们可以使用定制的cv迭代器来相应地分割数据。这对我来说也有点混乱。我会像你指出的那样做。不过,我不确定这个for循环是否比基本的GridSearchCV更耗时,或者它们是否几乎相等。我不能肯定这个for循环,但GridSearchCV将并行化不同参数的内部拟合,因此可能会有比这个稍高的性能