Scikit learn Sklearn';s clone在Red Hat上使用python进行多处理时显示意外行为

Scikit learn Sklearn';s clone在Red Hat上使用python进行多处理时显示意外行为,scikit-learn,multiprocessing,clone,python-multiprocessing,Scikit Learn,Multiprocessing,Clone,Python Multiprocessing,Windows 7计算机(Python 2.7.13)上的输出: (pip冻结:numpy==1.11.0,scikit图像==0.12.3,scikit学习==0.17,scipy==0.17.0) A类 0.82 0.826 0.832 0.822 0.816 裸射频 0.814 0.81 0.818 0.818 0.818 在Red Hat 4.8.3-9 Linux机器(Python 2.7.5)上的输出: (pip冻结:numpy==1.11.0,scikit-learn==0.17,

Windows 7计算机(Python 2.7.13)上的输出:
(pip冻结:numpy==1.11.0,scikit图像==0.12.3,scikit学习==0.17,scipy==0.17.0)

A类
0.82
0.826
0.832
0.822
0.816

裸射频
0.814
0.81
0.818
0.818
0.818

在Red Hat 4.8.3-9 Linux机器(Python 2.7.5)上的输出:
(pip冻结:numpy==1.11.0,scikit-learn==0.17,scipy==0.17.0,sklearn==0.0)
A类
0.818
0.818
0.818
0.818
0.818

裸射频
0.814
0.81
0.818
0.818
0.818

总之:
在Linux中,“Class A”(使用多处理)似乎在训练相同的精确模型,因此分数相同。然而,我所期望的行为是“裸RF”部分的行为,其中分数不一致(这是一个随机算法)。在Windows(Pycharm)中,无法再现该问题

你能帮忙吗


大编辑:创建了一个可复制的代码示例

解决方案是在并行执行的“train_模型”中添加重新设定的种子

from sklearn.datasets import make_classification
from sklearn.ensemble import RandomForestClassifier
from sklearn import clone
import multiprocessing
import functools
import numpy as np

def train_model(n_estimators, base_model, X, y):
    model = clone(base_model)
    model.set_params(n_estimators=n_estimators)
    model.fit(X,y)
    return model


class A():
    def __init__(self, random_state, jobs, **kwargs):
        self.model = RandomForestClassifier(oob_score=True, random_state=random_state, **kwargs)
        self.jobs = jobs


    def fit(self, X, y):
        job_pool = multiprocessing.Pool(self.jobs)
        n_estimators = [100]
        for output in job_pool.imap_unordered(functools.partial(train_model,
                                                                base_model=self.model,
                                                                X=X,
                                                                y=y),n_estimators):
            model = output
        job_pool.terminate()
        self.model = model


if __name__ == '__main__':

    np.random.seed(42)
    X, y = make_classification(n_samples=500,n_informative=6,n_redundant=6, flip_y=0.1)

    print "Class A"
    for i in range(5):
        base_model = A(random_state=None, jobs=1)
        base_model.fit(X,y)
        print base_model.model.oob_score_

    print "Bare RF"
    base_model = RandomForestClassifier(n_estimators=500, max_features=2, oob_score=True, random_state=None)
    for i in range(5):
        model = clone(base_model)
        model.fit(X,y)
        print model.oob_score_
理由是:

在Unix上,每个工作进程都从父进程继承相同的随机数生成器状态。这就是它们生成相同伪随机序列的原因

实际上是多处理启动了辅助进程,这就是为什么这是相关的。所以这不是scikit学习克隆问题


我已经找到了答案,

尽管我不能说我同意您提供的实现,但我认为您已经提供了部分解决方案来解决这里发生的问题:):
clone(base\u model)
。在fit
base\u model=clone(self.model)
中使用它,然后将其分发到@mkaran的答案中。问题是估计量的初始化。在您的情况下,您没有在每次拟合中重新初始化模型,这意味着模型在上一次拟合中学习到的权重或系数基本相同(即使再次调用fit()),而scikit learn的克隆将重新初始化模型和权重。@Vivek Kumar您能详细说明一下(可能需要一些代码吗?)。非常感谢。你能提供这样我们可以复制粘贴和分析它吗?你说你尝试了mkaran的
base\u model=clone(self.model)
建议。你能告诉我你是怎么用的吗?您需要在
functools.partial()方法中使用它。
def train_model(n_estimators, base_model, X, y):
    np.random.seed()
    model = clone(base_model)
    model.set_params(n_estimators=n_estimators)
    model.fit(X,y)
    return model