Python Optunity:如何将额外的参数传递给优化例程

4

背景

我正在使用支持向量机来进行二分类,但我的训练数据中正负标签的比例不平衡(即正标签与负标签的比例约为100:1)。我希望优化以下参数:m(我从训练数据中抽取的正标签与负标签的比例)、w(类别权重)和SVM参数C。

问题

我想通过网格搜索来优化这些参数,并将得分函数定义如下:

def svm_acc(X, y, m, w, c):
  X, y = balanceClasses(X, y, m)
  clf = svm.SVC(kernel='rbf', C=c, class_weight = {1: w})
  scores = cross_validation.cross_val_score(clf, X, y, 5)
  return( scores.mean() )

其中X是特征矩阵,y是二元分类标签,svm_acc返回5折交叉验证的平均准确率。我已经在optunity中尝试了以下方法:

import optunity as opt
s = opt.solvers.GridSearch(mult=[1,10], w=[1,10], c=[1,10])
best_pars, _ = s.optimize(svm_acc, X=X, y=y)

但是我遇到了这个错误:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: optimize() got an unexpected keyword argument 'X'

我从文档中了解到optimize不需要任何额外的关键字参数(Xy)。我尝试了上述代码的不同变化,但一直无法弄清如何传递不应该被优化到程序中的其他参数。
据我所知,我不能使用scikit-learn的gridsearch,因为我想优化m参数,这个参数不是估计器的内在属性。是否有人可以指点我找到解决方案,或者其他用于进行网格搜索的Python包?
1个回答

3

在回答实际问题之前,有几点需要注意:

  1. 使用RBF核时,您必须调整gamma以获得良好结果。仅调整错误分类罚款(Cweights)是不够的。
  2. 主要API函数optunity.maximizeoptunity.minimizeoptunity.optimize,而不是您正在使用的特定于求解器的方法。虽然两者都提供类似的功能,但API函数可能更容易使用。
  3. 对于真正的调整任务,我强烈建议使用默认粒子群优化器而不是网格搜索。在更少的函数评估(=时间)中,您将获得更好的结果。
  4. 使用Optunity的交叉验证工具比使用scikit-learn的工具更容易。当然,这完全是可选的。您可以在这里找到更多信息。
  5. 超参数mw有些冗余。如果您要优化类权重,则无需平衡类别。我会停止优化类别平衡(对于这一点,您必须进行欠采样或过采样=更改数据)。

解决方法

您在optimize中指定的函数必须是目标函数,也就是说,这个函数的唯一参数必须是您想要优化的超参数。有关此更多信息,请参阅Optunity的论文。在您的特定示例中,这意味着参数应该是cmw

要修复Xy,您可以使用任何标准的Python方法,例如functools.partial或闭包。在我看来,闭包是最干净的方法:

def fix_data(X_fixed, y_fixed):
    def svm_acc(m, w, c):
        X, y = balanceClasses(X_fixed, y_fixed, m)
        clf = svm.SVC(kernel='rbf', C=c, class_weight = {1: w})
        scores = cross_validation.cross_val_score(clf, X, y, 5)
        return( scores.mean() )

    return svm_acc

函数fix_data修复了一个特定的数据集X_fixedy_fixed,并生成一个只有超参数作为参数的函数。然后你可以像这样做(假设你已经构建了求解器等):

svm_acc_with_fixed_data = fix_data(X, y)
best_pars, _ = s.optimize(svm_acc_with_fixed_data)

感谢您的建议和快速回复! - Elias

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接