【问题标题】:Sampling values for class_weight in RandomizedSearchCVRandomizedSearchCV 中 class_weight 的采样值
【发布时间】:2018-05-10 21:45:05
【问题描述】:

我正在尝试使用 RandomizedSearchCV 在 Scikit learn SVM 分类器中使用类权重。

clf= svm.SVC(probability=True, random_state=0)
parameters = {'clf__C': scipy.stats.expon(scale=100), 'clf__gamma': scipy.stats.expon(scale=.1),
    'clf__kernel': ['rbf'], 'clf__class_weight':['balanced', None]}
search=RandomizedSearchCV(estimator=clf, param_distributions=parameters, scoring='f1_micro',
                                       cv=5, n_iter=100, random_state=0)
search.fit(features,labels)

我有 4 节课。现在对于 class_weight,我希望四个类中的每一个都有 0 到 1 之间的随机值。可以用

'class_weight':[{0: w} for w in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]]

但这仅适用于一个类,并且值是离散的,而不仅仅是在 0 和 1 之间采样。

我该如何解决这个问题?

最后但同样重要的是,我使用 0 到 1 或 1 到 10 之间的值是否重要(即是否重新调整了权重)?

所有 4 个类的权重总和是否应该总是相同的值(例如 1)?

【问题讨论】:

  • 不,值可以是任意的,总和不能为 1。
  • @VivekKumar 非常感谢。请问您是否还有其他问题的答案?
  • 您可以对权重使用随机抽样。但这需要对多次迭代进行调整。例如,从 [0,1] 范围内的随机数开始。在下一次迭代中,选择与上一次迭代中选择的范围相近的范围。可能是 [0.45, 0.65]。以此类推。
  • 查看this question 进行随机抽样。

标签: python scikit-learn hyperparameters


【解决方案1】:

您可以尝试列表理解而不是冗长的解决方案它适用于我在 RandomForest 中并且我已经检查了 RandomizedSearchCV

l1 = np.arange(0,1,0.01)
l2 = np.arange(0,1,0.01)
class_weight = [{0:i,1:j} for i,j in zip(l1,l2)]

【讨论】:

    【解决方案2】:

    我不知道将分布作为字典键传递的可能性。作为对您提出的解决方法的改进,您可以使用:

    from sklearn.utils.class_weight import compute_class_weight
    from scipy.stats import lognorm
    
    class_weight = compute_class_weight("balanced", np.unique(y), y)
    class_weights = []
    for mltp in lognorm(s = 1, loc = 1, scale = class_weight[0]).rvs(50):
        class_weights.append(dict(zip([0, 1], class_weight * [mltp, 1/mltp])))
    

    然后您可以将class_weights 传递给parameters 中的clf__class_weight 条目以获取RandomizedSearchCV。将此扩展到多类场景或使用不同的分布很简单。 请注意,您实际上采样了两次。一次来自真实分布,然后通过此示例中的RandomizedSearchCV。如果您确保在每次调用之前重新生成 class_weights 以使其适合,或者确保初始样本足够大,则此解决方法应该适用于您的情况。


    编辑: 更好的解决方案是定义您自己的实现rvs 方法的类。即使不必将现有的scipy.stats 分配子类化为:

    class ClassWeights(object):
        """
        Draw random variates for cases when parameter is a dict.
        Should be personalized as needed.
        """
        def __init__(self,y, *args, **kwargs):
            self.class_weights = compute_class_weight("balanced", np.unique(y), y)
            self._make_dists()
    
        def _make_dists(self):
            self.dist0 = gamma(self.class_weights[0])
            self.dist1 = gamma(self.class_weights[1])
    
        def rvs(self, *args, **kwargs):
            """override method for drawing random variates"""
            ret_val = { 0: self.dist0.rvs(*args, **kwargs),
                        1: self.dist1.rvs(*args, **kwargs)}
            return ret_val
    

    回答你的另外两个问题:

    权重可以取任何正值(包括 0),它们的总和不必为 1。重要的是它们的相对大小,而不是绝对大小。

    【讨论】:

      猜你喜欢
      • 2017-09-10
      • 1970-01-01
      • 2020-08-10
      • 1970-01-01
      • 1970-01-01
      • 2014-08-28
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多