Sklearn的克隆显示了在python多处理红帽

问题描述:

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_ 

输出Windows 7的机器上(Python的2.7.13)意外行为:
(PIP冻结:numpy的== 1.11.0,scikit图像== 0.12 0.3,scikit学习== 0.17,SciPy的== 0.17.0或更新)Sklearn的克隆显示了在python多处理红帽

A类
0.82
0.826
0.832
0.822
0.816

裸RF
0.814
0.81
0.818
0.818
0.818

红帽4.8.3-9 Linux机器上输出(Python的2.7.5):
(PIP冻结:numpy的= = 1.11.0,scikit学习== 0.17,SciPy的== 0.17.0或更新,sklearn == 0.0)
A类
0.818
0.818
0.818
0.818
0.818

裸RF
0.814
0.81
0.818
0.818
0.818

因此,综上所述:
在Linux中, “A类”(使用多处理)似乎在训练相同的确切模型,因此得分相同。然而,我期望的行为将是其中分数不重合的“裸RF”部分之一(这是一种随机算法)。在Windows(Pycharm)中,无法复制问题。

你能帮忙吗?

BIG EDIT:创建了一个可重现的代码示例。

+0

虽然我不能说我跟你所提供的实施同意,我想您所提供的解决方案,正在发生的事情在这里:)的一部分:'克隆(base_model)'。在合适的'base_model = clone(self.model)'中使用它,在分发之前 – mkaran

+1

添加到@mkaran的答案。问题是估计器的初始化。在你的情况,你是不是重新初始化在各装配模型,这意味着该模型在前面配合了解到的权重或coeffs大多是相同的(即使配合()被再次调用),而scikit学习的克隆将重新初始化模型和权重。 –

+0

@ Vivek库马尔可以请你详细说明(也许有一些代码?)。谢谢! – user152245

解决方案是在并行执行的“train_model”中添加种子。

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 

的理由:

什么情况是,在Unix上每一个工作进程继承父进程的随机数字生成器的相同状态。这就是他们产生相同的伪随机序列的原因。

这是多处理,它实际上启动工作进程,这就是为什么这是相关的。所以这不是一个scikit-learn克隆问题。

我已经找到了答案herehere