侯体宗的博客
  • 首页
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python实现的随机森林算法与简单总结

Python  /  管理员 发布于 7年前   451

本文实例讲述了Python实现的随机森林算法。分享给大家供大家参考,具体如下:

随机森林是数据挖掘中非常常用的分类预测算法,以分类或回归的决策树为基分类器。算法的一些基本要点:

*对大小为m的数据集进行样本量同样为m的有放回抽样;
*对K个特征进行随机抽样,形成特征的子集,样本量的确定方法可以有平方根、自然对数等;
*每棵树完全生成,不进行剪枝;
*每个样本的预测结果由每棵树的预测投票生成(回归的时候,即各棵树的叶节点的平均)

著名的python机器学习包scikit learn的文档对此算法有比较详尽的介绍: http://scikit-learn.org/stable/modules/ensemble.html#random-forests

出于个人研究和测试的目的,基于经典的Kaggle 101泰坦尼克号乘客的数据集,建立模型并进行评估。比赛页面及相关数据集的下载:https://www.kaggle.com/c/titanic

泰坦尼克号的沉没,是历史上非常著名的海难。突然感到,自己面对的不再是冷冰冰的数据,而是用数据挖掘的方法,去研究具体的历史问题,也是饶有兴趣。言归正传,模型的主要的目标,是希望根据每个乘客的一系列特征,如性别、年龄、舱位、上船地点等,对其是否能生还进行预测,是非常典型的二分类预测问题。数据集的字段名及实例如下:

PassengerId Survived Pclass Name Sex Age SibSp Parch Ticket Fare Cabin Embarked
1 0 3 Braund, Mr. Owen Harris male 22 1 0 A/5 21171 7.25 S
2 1 1 Cumings, Mrs. John Bradley (Florence Briggs Thayer) female 38 1 0 PC 17599 71.2833 C85 C
3 1 3 Heikkinen, Miss. Laina female 26 0 0 STON/O2. 3101282 7.925 S
4 1 1 Futrelle, Mrs. Jacques Heath (Lily May Peel) female 35 1 0 113803 53.1 C123 S
5 0 3 Allen, Mr. William Henry male 35 0 0 373450 8.05 S

值得说明的是,SibSp是指sister brother spouse,即某个乘客随行的兄弟姐妹、丈夫、妻子的人数,Parch指parents,children

下面给出整个数据处理及建模过程,基于ubuntu+python 3.4( anaconda科学计算环境已经集成一系列常用包,pandas numpy sklearn等,这里强烈推荐)

懒得切换输入法,写的时候主要的注释都是英文,中文的注释是后来补充的:-)

# -*- coding: utf-8 -*-"""@author: kim"""from model import *#载入基分类器的代码#ETL:same procedure to training set and test settraining=pd.read_csv('train.csv',index_col=0)test=pd.read_csv('test.csv',index_col=0)SexCode=pd.DataFrame([1,0],index=['female','male'],columns=['Sexcode']) #将性别转化为01training=training.join(SexCode,how='left',on=training.Sex)training=training.drop(['Name','Ticket','Embarked','Cabin','Sex'],axis=1)#删去几个不参与建模的变量,包括姓名、船票号,船舱号test=test.join(SexCode,how='left',on=test.Sex)test=test.drop(['Name','Ticket','Embarked','Cabin','Sex'],axis=1)print('ETL IS DONE!')#MODEL FITTING#===============PARAMETER AJUSTMENT============min_leaf=1min_dec_gini=0.0001n_trees=5n_fea=int(math.sqrt(len(training.columns)-1))#=============================================='''''BEST SCORE:0.83min_leaf=30min_dec_gini=0.001n_trees=20'''#ESSEMBLE BY RANDOM FORESTFOREST={}tmp=list(training.columns)tmp.pop(tmp.index('Survived'))feaList=pd.Series(tmp)for t in range(n_trees):#  fea=[]  feasample=feaList.sample(n=n_fea,replace=False)#select feature  fea=feasample.tolist()  fea.append('Survived')#    feaNew=fea.append(target)  subset=training.sample(n=len(training),replace=True)#generate the dataset with replacement  subset=subset[fea]#  print(str(t)+' Classifier built on feature:')#  print(list(fea))  FOREST[t]=tree_grow(subset,'Survived',min_leaf,min_dec_gini) #save the tree#MODEL PREDICTION#======================currentdata=trainingoutput='submission_rf_20151116_30_0.001_20'#======================prediction={}for r in currentdata.index:#a row  prediction_vote={1:0,0:0}  row=currentdata.get(currentdata.index==r)  for n in range(n_trees):    tree_dict=FOREST[n] #a tree    p=model_prediction(tree_dict,row)    prediction_vote[p]+=1  vote=pd.Series(prediction_vote)  prediction[r]=list(vote.order(ascending=False).index)[0]#the vote resultresult=pd.Series(prediction,name='Survived_p')#del prediction_vote#del prediction#result.to_csv(output)t=training.join(result,how='left')accuracy=round(len(t[t['Survived']==t['Survived_p']])/len(t),5)print(accuracy)

上述是随机森林的代码,如上所述,随机森林是一系列决策树的组合,决策树每次分裂,用Gini系数衡量当前节点的“不纯净度”,如果按照某个特征的某个分裂点对数据集划分后,能够让数据集的Gini下降最多(显著地减少了数据集输出变量的不纯度),则选为当前最佳的分割特征及分割点。代码如下:

# -*- coding: utf-8 -*-"""@author: kim"""import pandas as pdimport numpy as np#import sklearn as skimport mathdef tree_grow(dataframe,target,min_leaf,min_dec_gini):  tree={} #renew a tree  is_not_leaf=(len(dataframe)>min_leaf)  if is_not_leaf:    fea,sp,gd=best_split_col(dataframe,target)    if gd>min_dec_gini:      tree['fea']=fea      tree['val']=sp#      dataframe.drop(fea,axis=1) #1116 modified      l,r=dataSplit(dataframe,fea,sp)      l.drop(fea,axis=1)      r.drop(fea,axis=1)      tree['left']=tree_grow(l,target,min_leaf,min_dec_gini)      tree['right']=tree_grow(r,target,min_leaf,min_dec_gini)    else:#return a leaf      return leaf(dataframe[target])  else:    return leaf(dataframe[target])  return treedef leaf(class_lable):  tmp={}  for i in class_lable:    if i in tmp:      tmp[i]+=1    else:      tmp[i]=1  s=pd.Series(tmp)  s.sort(ascending=False)  return s.index[0]def gini_cal(class_lable):  p_1=sum(class_lable)/len(class_lable)  p_0=1-p_1  gini=1-(pow(p_0,2)+pow(p_1,2))  return ginidef dataSplit(dataframe,split_fea,split_val):  left_node=dataframe[dataframe[split_fea]<=split_val]  right_node=dataframe[dataframe[split_fea]>split_val]  return left_node,right_nodedef best_split_col(dataframe,target_name):  best_fea=''#modified 1116  best_split_point=0  col_list=list(dataframe.columns)  col_list.remove(target_name)  gini_0=gini_cal(dataframe[target_name])  n=len(dataframe)  gini_dec=-99999999  for col in col_list:    node=dataframe[[col,target_name]]    unique=node.groupby(col).count().index    for split_point in unique: #unique value      left_node,right_node=dataSplit(node,col,split_point)      if len(left_node)>0 and len(right_node)>0:        gini_col=gini_cal(left_node[target_name])*(len(left_node)/n)+gini_cal(right_node[target_name])*(len(right_node)/n)        if (gini_0-gini_col)>gini_dec:          gini_dec=gini_0-gini_col#decrease of impurity          best_fea=col          best_split_point=split_point    #print(col,split_point,gini_0-gini_col)  return best_fea,best_split_point,gini_decdef model_prediction(model,row): #row is a df  fea=model['fea']  val=model['val']  left=model['left']  right=model['right']  if row[fea].tolist()[0]<=val:#get the value    branch=left  else:    branch=right  if ('dict' in str( type(branch) )):    prediction=model_prediction(branch,row)  else:    prediction=branch  return prediction

实际上,上面的代码还有很大的效率提升的空间,数据集不是很大的情况下,如果选择一个较大的输入参数,例如生成100棵树,就会显著地变慢;同时,将预测结果提交至kaggle进行评测,发现在测试集上的正确率不是很高,比使用sklearn里面相应的包进行预测的正确率(0.77512)要稍低一点 :-(  如果要提升准确率,两个大方向: 构造新的特征;调整现有模型的参数。

这里是抛砖引玉,欢迎大家对我的建模思路和算法的实现方法提出修改意见。

更多关于Python相关内容感兴趣的读者可查看本站专题:《Python数据结构与算法教程》、《Python编码操作技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》及《Python入门与进阶经典教程》

希望本文所述对大家Python程序设计有所帮助。


  • 上一条:
    Python实现带参数与不带参数的多重继承示例
    下一条:
    Python决策树和随机森林算法实例详解
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在windows10中升级go版本至1.24后LiteIDE的Ctrl+左击无法跳转问题解决方案(0个评论)
    • 智能合约Solidity学习CryptoZombie第四课:僵尸作战系统(0个评论)
    • 智能合约Solidity学习CryptoZombie第三课:组建僵尸军队(高级Solidity理论)(0个评论)
    • 智能合约Solidity学习CryptoZombie第二课:让你的僵尸猎食(0个评论)
    • 智能合约Solidity学习CryptoZombie第一课:生成一只你的僵尸(0个评论)
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(95个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客