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颗决策树

  1. def fit(self, X, Y):
  2. # 分出每个线程 应该生成几颗决策树
  3. job_tree_num = int ( self.n_estimators / self.n_jobs)
  4. processes = list()
  5. #随机森林的决策树参数
  6. dtr_args = {
  7. "criterion": self.criterion,
  8. "max_depth": self.max_depth,
  9. "max_features": self.max_features,
  10. "max_leaf_nodes": self.max_leaf_nodes,
  11. "min_impurity_decrease": self.min_impurity_decrease,
  12. "min_impurity_split": self.min_impurity_split,
  13. "min_samples_leaf": self.min_samples_leaf,
  14. "min_samples_split": self.min_samples_split,
  15. "min_weight_fraction_leaf": self.min_weight_fraction_leaf,
  16. "random_state": self.random_state,
  17. "splitter": self.splitter
  18. }
  19. # 生成N个进程
  20. for i in range(self.n_jobs):
  21. # 参数
  22. #job_forest_queue 为决策树队列 每个进程生成的决策树将加入到此队列 这是随机森林对象的一个属性
  23. #i 为进程号
  24. #job_tree_num 表示该进程需要生成的决策树
  25. #X Y 表示训练数据 和结果数据
  26. #dtr_args 表示传入的决策树参数
  27. p = Process(target=signal_process_train, args=(self.job_forest_queue, i,job_tree_num , X, Y, dtr_args))
  28. print ('process Num. ' + str(i) + " will start train")
  29. p.start()
  30. processes.append(p)
  31. for p in processes:
  32. p.join()
  33. print ("Train end")

3.1.2 单进程训练函数

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

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

  1. len = int(Y.shape[0] * 0.7)
  2. indexs = np.arange(len)
  3. np.random.shuffle(indexs)
  4. x = []
  5. y = []
  6. for ind in indexs:
  7. x.append(X.values[ind])
  8. y.append(Y.values[ind])

单进程训练函数代码

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

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

3.2 并行化预测

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

3.2.1 预测函数

  1. def predict(self, X):
  2. result_queue = Manager().Queue()
  3. processes = list()
  4. # 分出每个线程 应该预测几颗决策树
  5. job_tree_num = int(self.n_estimators / self.n_jobs)
  6. # 生成N个进程
  7. for i in range(self.n_jobs):
  8. # 参数
  9. # job_forest_queue 为决策树队列 这是随机森林对象的一个属性
  10. # i 为进程号
  11. # job_tree_num 表示该进程需要生成的决策树
  12. # X 表示待预测数据
  13. # result_queue 表示用于存放预测结果的数据
  14. p = Process(target=signal_process_predict, args=(self.job_forest_queue, i, job_tree_num, X, result_queue))
  15. print('process Num. ' + str(i) + " will start predict")
  16. p.start()
  17. processes.append(p)
  18. for p in processes:
  19. p.join()
  20. result = np.zeros(X.shape[0])
  21. #把每个进程的平均结果再一次加起来求平均, 得到最终结果
  22. for i in range(result_queue.qsize()):
  23. result = result + result_queue.get()
  24. result = result / self.n_jobs
  25. print("Predict end")
  26. return result

3.2.2 单进程预测函数

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

  1. #单进程预测函数
  2. def signal_process_predict(job_forest_queue,process_num,job_tree_num,X,result_queue):
  3. # 生成结果矩阵
  4. result = np.zeros(X.shape[0])
  5. for i in range(job_tree_num):
  6. # 从队列中取出一颗树 进行预测
  7. tree = job_forest_queue.get()
  8. result_single = tree.predict(X)
  9. # 将得出的结果加到总结果中
  10. result = result +result_single
  11. # 算出平均结果 放入结果队列中
  12. result = result / job_tree_num
  13. result_queue.put(result)
  14. 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. P1039 侦探推理(洛谷)

    昨天做了一个非常神奇的题,告诉我们做题之前一定要好好检测评测姬! 明明同学最近迷上了侦探漫画<柯南>并沉醉于推理游戏之中,于是他召集了一群同学玩推理游戏.游戏的内容是这样的,明明的同学们先 ...

  2. ref和动态组件

    ref--------指引 另一种获取表单值的方法 是Vue环境中一个内置的属性.它可以使用this.$refs可以快速拿到DOM对象.

  3. 【揭秘】C语言类型转换时发生了什么?

    ID:技术让梦想更伟大 作者:李肖遥 链接:https://mp.weixin.qq.com/s/ZFf3imVaJgeesuhl1Kn9sQ 在C语言中,数据类型指的是用于声明不同类型的变量或函数的 ...

  4. 我把JVM的类加载器整理了一下

    前言 ​ 之前去面试的时候面试官问了我关于关于JVM性能调优的问题,由于自己之前公司的项目里自己没有接触到JVM性能调优的相关问题(感觉这些都是公司架构师考虑的问题),所有面试官问的时候自己一脸懵逼, ...

  5. Java基础(二)流程语句与数组

    Java流程语句详解:https://www.cnblogs.com/jiajia-16/p/6008200.html Java数组详解:https://www.cnblogs.com/jiajia- ...

  6. MySQL(一)简介与入门

    一.数据库简介 这个博客详细介绍:http://www.cnblogs.com/progor/p/8729798.html 二.MySQL的安装 这个博客详细介绍:https://blog.csdn. ...

  7. 2020数字中国创新大赛虎符网络安全赛道-pwn count

    比赛结束前半个小时才看的题,等我做出来比赛已经结束了.难受Orz 本地文件无法执行,远程调试. 题目大概意思就是让你计算200道四则运算.(实际上格式是固定的.先乘一次然后再加两次).200道题都正确 ...

  8. awk格式化

    1,获取指定列和行,在指定列和行内插入 指定符号. /p/v2/api/winapi/mini/merchant/admin/notice/list/1/10?current=1&size=1 ...

  9. cpp求职

    //Created by Arc on 2020/5/23 //////// Created by snnnow on 2020/5/20.//////面向对象的程序设计-期中测试// 根据题目实现求 ...

  10. 从RNN到BERT

    一.文本特征编码 1. 标量编码 美国:1 中国:2 印度:3 … 朝鲜:197 标量编码问题:美国 + 中国 = 3 = 印度 2. One-hot编码 美国:[1,0,0,0,…,0]中国:[0, ...