我是一个R user,希望对Python更加满意。我编写了一种mini-API,可以轻松比较适合同一数据的不同统计模型,从而可以预先设置所有模型超参数,然后遍历不同模型以适应它们。

这是我想做的事情的本质:


围绕Scikit学习Classifier构建包装类Pipeline,依次基于Scikit学习的内置估算器之一,例如RandomForestClassifier
创建这些不适合的Classifier的字典,以及不同的参数字典以进行循环
遍历两个字典,让每个不适合的Classifier生成基础管道的新实例,使用其[Pipeline.fit][1]方法对其进行拟合,然后将适合的新管道保存在其他字典中


但是,似乎不是在每次迭代中都生成管道的相同实例(或者可能是基础估算器),而不是生成管道的新实例。这是一个问题,因为Pipeline.fit方法修改了流水线(和基础估计量),因此以前迭代的拟合结果全部被最终迭代的拟合结果覆盖。

问题是我不知道在哪里创建这个“父实例”以及如何引用它。

问题的可重现示例的基本设置在this Gist中(仅在此处复制和粘贴有点太长了)。我在末尾添加了打印声明以说明该问题。

抱歉,这有点含糊,但我现在还不太容易描述。希望这个例子可以解决这个问题。

最佳答案

问题是results['0']['rf']results['1']['rf']实际上是同一对象。因此,当您在循环中放入管道时:

results = dict()
for k in features.keys():
    results[k] = dict()
    for m in classifiers.keys():
        print(len(features[k]))
        results[k][m] = classifiers[m].fit(features[k], 'species', iris)


您正在重新拟合已经合适的管道,从而丢失了先前的工作。

为了解决这个问题,您需要在每次安装Classifier时创建一个新实例。一种可行的方法是将您的classifiers字典从一个包含Classifier实例的字典更改为一个包含创建Classifier所需参数的字典:

classifiers = {
    'rf': (RandomForestClassifier, n_estimators=100, oob_score=True, bootstrap=True),
    'ab': (AdaBoostClassifier, n_estimators=50)
}


现在,在循环中,您应该使用称为“ tuple unpacking”的Python习惯用法来解压缩参数并为每种组合创建一个单独的Classifier实例

for k in features:
    results[k] = dict()
    for m in classifiers:
        print(len(features[k]))
        classifier = Classifier(*classifiers[m])
        results[k][m] = classifier.fit(features[k], 'species', iris)


请注意,要遍历字典的键,可以简单地写for key in dct:而不是for key in dct.keys()

10-08 07:14