1. 前言

Python其实已经实现过随机森林, 而且有并行化的参数n_jobs 来设置可以使用多个可用的cpu核并行计算。

n_jobs : int or None, optional (default=None)

The number of jobs to run in parallel for both fit and predict. None means 1 unless in a joblib.parallel_backend context. -1 means using all processors. See Glossary for more details.

当然我们使用的是多进程来实现并行化, 和scikit-learn有些不同

2. 随机森林原理

随机森林是一种集成算法(Ensemble Learning),它属于Bagging类型,通过组合多个弱分类器,最终结果通过投票或取均值,使得整体模型的结果具有较高的精确度和泛化性能。其可以取得不错成绩,主要归功于“随机”和“森林”,一个使它具有抗过拟合能力,一个使它更加精准。



Bagging

Bagging也叫自举汇聚法(bootstrap aggregating),是一种在原始数据集上通过有放回抽样重新选出k个新数据集来训练分类器的集成技术。它使用训练出来的分类器的集合来对新样本进行分类,然后用多数投票或者对输出求均值的方法统计所有分类器的分类结果,结果最高的类别即为最终标签。此类算法可以有效降低bias,并能够降低variance。

3.实现原理

3.1并行化训练

由于随机森林是 通过bagging方法分成多个数据集,然后在生成的数据集上训练生成多个决策树, 因为每个决策树是相互独立的, 则可以在开启多个进程,每个进程都生成决策树, 然后把生成的决策树放到队列,用于训练

3.1.1训练函数

首先平均分出每个线程应该生成几颗决策树, 然后生成进程, 进行训练, 把训练生成的决策树加入到决策树队列(决策树森林)中, 这里用的决策树是直接调用的库决策树,若有兴趣,可以单撸一个决策树出来。

注意这里我选择让每个进程生成的决策树的个数相同, 所以 参数输入的决策树个数可能不是实际生成的决策树个数,例如 100颗决策树 8个进程, 则每个进程只会生成 int(100/8) = 12颗决策树

   def fit(self, X, Y):

        # 分出每个线程 应该生成几颗决策树
job_tree_num = int ( self.n_estimators / self.n_jobs) processes = list() #随机森林的决策树参数
dtr_args = {
"criterion": self.criterion,
"max_depth": self.max_depth,
"max_features": self.max_features,
"max_leaf_nodes": self.max_leaf_nodes,
"min_impurity_decrease": self.min_impurity_decrease,
"min_impurity_split": self.min_impurity_split,
"min_samples_leaf": self.min_samples_leaf,
"min_samples_split": self.min_samples_split,
"min_weight_fraction_leaf": self.min_weight_fraction_leaf,
"random_state": self.random_state,
"splitter": self.splitter
} # 生成N个进程
for i in range(self.n_jobs):
# 参数
#job_forest_queue 为决策树队列 每个进程生成的决策树将加入到此队列 这是随机森林对象的一个属性
#i 为进程号
#job_tree_num 表示该进程需要生成的决策树
#X Y 表示训练数据 和结果数据
#dtr_args 表示传入的决策树参数
p = Process(target=signal_process_train, args=(self.job_forest_queue, i,job_tree_num , X, Y, dtr_args))
print ('process Num. ' + str(i) + " will start train")
p.start()
processes.append(p) for p in processes:
p.join() print ("Train end")

3.1.2 单进程训练函数

生成数据集模块——生成部分数据集

首先生成一个index, 长度为原来数据集的0.7倍,然后将其打乱,按照打乱的index加入数据,即可生成打乱的数据集, 大小为原来数据集的0.7倍

len = int(Y.shape[0] * 0.7)
indexs = np.arange(len)
np.random.shuffle(indexs)
x = []
y = []
for ind in indexs:
x.append(X.values[ind])
y.append(Y.values[ind])

单进程训练函数代码

循环生成决策树, 并且把生成的决策树加入到队列中

#单进程训练函数
def signal_process_train(job_forest_queue,process_num,job_tree_num,X, Y, dtr_args):
#循环生成决策树, 并且把生成的决策树加入到job_forest_queue 队列中
for i in range(0, job_tree_num):
# 使用bootstrap 方法生成 1个 训练集 len = int(Y.shape[0] * 0.7)
indexs = np.arange(len)
np.random.shuffle(indexs)
x = []
y = []
for ind in indexs:
x.append(X.values[ind])
y.append(Y.values[ind]) # 对这个样本 进行训练 并且根据传入的决策树参数 生成1棵决策树
dtr = DecisionTreeRegressor(n_job=1 ,criterion=dtr_args['criterion'], max_depth=dtr_args['max_depth'],
max_features=dtr_args['max_features'],max_leaf_nodes=dtr_args['max_leaf_nodes'],
min_impurity_decrease=dtr_args['min_impurity_decrease'],
min_impurity_split=dtr_args['min_impurity_split'],
min_samples_leaf=dtr_args['min_samples_leaf'], min_samples_split=dtr_args['min_samples_split'],
min_weight_fraction_leaf=dtr_args['min_weight_fraction_leaf'],
random_state=dtr_args['random_state'], splitter=dtr_args['splitter']) dtr.fit(x,y) if (i% int(job_tree_num/10 or i<10) == 0):
print ('process Num. ' + str(process_num) + " trained " + str(i) + ' tree') # 决策树存进森林(决策树队列)
job_forest_queue.put(dtr)
print('process Num. ' + str(process_num) + ' train Done!!')

3.2 并行化预测

同理, 生成多个进程,每个进程在随机森林里得到树来进行预测, 每个进程返回这个进程处理的所有决策树的预测结果的平均值, 然后将每个进程返回的平均值再一次进行平均,则得到结果

3.2.1 预测函数

    def predict(self, X):

        result_queue = Manager().Queue()

        processes = list()
# 分出每个线程 应该预测几颗决策树
job_tree_num = int(self.n_estimators / self.n_jobs)
# 生成N个进程
for i in range(self.n_jobs):
# 参数
# job_forest_queue 为决策树队列 这是随机森林对象的一个属性
# i 为进程号
# job_tree_num 表示该进程需要生成的决策树
# X 表示待预测数据
# result_queue 表示用于存放预测结果的数据
p = Process(target=signal_process_predict, args=(self.job_forest_queue, i, job_tree_num, X, result_queue))
print('process Num. ' + str(i) + " will start predict")
p.start()
processes.append(p) for p in processes:
p.join() result = np.zeros(X.shape[0]) #把每个进程的平均结果再一次加起来求平均, 得到最终结果
for i in range(result_queue.qsize()):
result = result + result_queue.get() result = result / self.n_jobs
print("Predict end")
return result

3.2.2 单进程预测函数

每一次去除一棵树, 预测结果,然后将结果加起来,最后进程结束时, 把预测结果求平均,进行返回

#单进程预测函数
def signal_process_predict(job_forest_queue,process_num,job_tree_num,X,result_queue): # 生成结果矩阵
result = np.zeros(X.shape[0]) for i in range(job_tree_num):
# 从队列中取出一颗树 进行预测
tree = job_forest_queue.get()
result_single = tree.predict(X)
# 将得出的结果加到总结果中
result = result +result_single # 算出平均结果 放入结果队列中
result = result / job_tree_num
result_queue.put(result)
print('process ' + str(process_num) + ' predict Done!!')

4. 并行化结果分析

可以发现当进程数增加时, 训练时间会减少,并行化成功

但是当进程数到一定大小后, 进程间的调度可能会消耗更多时间, 减少也不明显了

5. 源码

完整github地址如下: 若有错误,欢迎指正!

https://github.com/wangjiwu/parallel_random_forest

参考资料

https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html

https://www.jianshu.com/p/a779f0686acc

https://docs.python.org/3.7/library/multiprocessing.html#multiprocessing.Queue

https://www.cnblogs.com/shixisheng/p/7119217.html

Python多进程实现并行化随机森林的更多相关文章

  1. 如何在Python中从零开始实现随机森林

    欢迎大家前往云+社区,获取更多腾讯海量技术实践干货哦~ 决策树可能会受到高度变异的影响,使得结果对所使用的特定测试数据而言变得脆弱. 根据您的测试数据样本构建多个模型(称为套袋)可以减少这种差异,但是 ...

  2. 机器学习之路:python 集成回归模型 随机森林回归RandomForestRegressor 极端随机森林回归ExtraTreesRegressor GradientBoostingRegressor回归 预测波士顿房价

    python3 学习机器学习api 使用了三种集成回归模型 git: https://github.com/linyi0604/MachineLearning 代码: from sklearn.dat ...

  3. 吴裕雄 python 机器学习——集成学习随机森林RandomForestRegressor回归模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  4. 吴裕雄 python 机器学习——集成学习随机森林RandomForestClassifier分类模型

    import numpy as np import matplotlib.pyplot as plt from sklearn import datasets,ensemble from sklear ...

  5. 随机森林random forest及python实现

    引言想通过随机森林来获取数据的主要特征 1.理论根据个体学习器的生成方式,目前的集成学习方法大致可分为两大类,即个体学习器之间存在强依赖关系,必须串行生成的序列化方法,以及个体学习器间不存在强依赖关系 ...

  6. sklearn_随机森林random forest原理_乳腺癌分类器建模(推荐AAA)

     sklearn实战-乳腺癌细胞数据挖掘(博主亲自录制视频) https://study.163.com/course/introduction.htm?courseId=1005269003& ...

  7. 机器学习 —— 决策树及其集成算法(Bagging、随机森林、Boosting)

    本文为senlie原创,转载请保留此地址:http://www.cnblogs.com/senlie/ 决策树--------------------------------------------- ...

  8. Python 实现的随机森林

    随机森林是一个高度灵活的机器学习方法,拥有广泛的应用前景,从市场营销到医疗保健保险. 既可以用来做市场营销模拟的建模,统计客户来源,保留和流失.也可用来预测疾病的风险和病患者的易感性. 随机森林是一个 ...

  9. Python中随机森林的实现与解释

    使用像Scikit-Learn这样的库,现在很容易在Python中实现数百种机器学习算法.这很容易,我们通常不需要任何关于模型如何工作的潜在知识来使用它.虽然不需要了解所有细节,但了解机器学习模型是如 ...

随机推荐

  1. 【运维--安全相关】cerbot证书自动化续期

    前言 Certbot可以配置为在证书过期之前自动更新证书.由于Let’s Encrypt SSL证书有效期时间为90天,所以建议您利用此功能.您可以通过运行以下命令来测试证书的自动续订: 安装 yum ...

  2. Oracle DataGuard主库丢失归档日志后备库的RMAN增量恢复一例

    第一部分  问题描述和环境状态确认 ----1. 问题场景 Oracle DataGuard主库丢失archivelog,如何不重建备库完成同步? 在Oracle DataGuard主从同步过程中可能 ...

  3. LeetCode 86 | 链表基础,一次遍历处理链表中所有符合条件的元素

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode专题第53篇文章,我们一起来看LeetCode第86题,Partition List(链表归并). 本题的官方难度是M ...

  4. 定长比较环状字符串-------strcat与strncpy的妙用

    题目链接:https://vjudge.net/problem/UVA-1584 题解:用strcpy与strcmp定长比较字符串即可,strcat与strcmp对string不适用,所以只能改写为c ...

  5. 设备管理的数据库路径是/storage/sdcard0/data/devuce-db

    设备管理的数据库路径是/storage/sdcard0/data/devuce-db 数据库文件名全路径是/storage/sdcard0/data/devuce-db/device.db 数据库文件 ...

  6. IT运维面试问题总结

    IT运维面试总结如下,后期更新于:https://www.yuque.com/docs/share/d3dd1e8e-6828-4da7-9e30-6a4f45c6fa8e. 欢迎基于学习.交流目的的 ...

  7. Python long() 函数

    描述 long() 函数将数字或字符串转换为一个长整型.高佣联盟 www.cgewang.com 语法 long() 函数语法: class long(x, base=10) 参数 x -- 字符串或 ...

  8. PHP array_reduce() 函数

    实例 发送数组中的值到用户自定义函数,并返回一个字符串: <?phpfunction myfunction($v1,$v2){return $v1 . "-" . $v2;} ...

  9. PHP xml_set_unparsed_entity_decl_handler() 函数

    定义和用法 xml_set_unparsed_entity_decl_handler() 函数规定当解析器在 XML 文档中找到无法解析的实体时被调用的函数. 如果成功,该函数则返回 TRUE.如果失 ...

  10. setOff与scrollTop区别

    1.offsetTop     : 当前对象到其上级层顶部的距离. 不能对其进行赋值.设置对象到页面顶部的距离请用style.top属性. 2.offsetLeft    : 当前对象到其上级层左边的 ...