python机器学习实战之树回归详解


Posted in Python onDecember 20, 2017

本文实例为大家分享了树回归的具体代码,供大家参考,具体内容如下

#-*- coding:utf-8 -*- 
#!/usr/bin/python 
''''' 
回归树  连续值回归预测 的 回归树 
''' 
# 测试代码 
# import regTrees as RT RT.RtTreeTest() RT.RtTreeTest('ex0.txt') RT.RtTreeTest('ex2.txt') 
# import regTrees as RT RT.RtTreeTest('ex2.txt',ops=(10000,4)) 
# import regTrees as RT RT.pruneTest() 
# 模型树 测试 
# import regTrees as RT RT.modeTreeTest(ops=(1,10) 
# 模型回归树和普通回归树 效果比较 计算相关系数  
# import regTrees as RT RT.MRTvsSRT() 
from numpy import * 
 
 
# Tab 键值分隔的数据 提取成 列表数据集 成浮点型数据 
def loadDataSet(fileName):   #   
  dataMat = []        # 目标数据集 列表 
  fr = open(fileName) 
  for line in fr.readlines(): 
    curLine = line.strip().split('\t') 
    fltLine = map(float,curLine) #转换成浮点型数据 
    dataMat.append(fltLine) 
  return dataMat 
 
# 按特征值 的数据集二元切分  特征(列)  对应的值 
# 某一列的值大于value值的一行样本全部放在一个矩阵里,其余放在另一个矩阵里 
def binSplitDataSet(dataSet, feature, value): 
  mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:][0] # 数组过滤 
  mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:][0] #  
  return mat0,mat1 
 
# 常量叶子节点 
def regLeaf(dataSet):# 最后一列为标签 为数的叶子节点 
  return mean(dataSet[:,-1])# 目标变量的均值 
# 方差 
def regErr(dataSet): 
  return var(dataSet[:,-1]) * shape(dataSet)[0]# 目标变量的平方误差 * 样本个数(行数)的得到总方差 
 
# 选择最优的 分裂属性和对应的大小 
def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): 
  tolS = ops[0] # 允许的误差下降值 
  tolN = ops[1] # 切分的最少样本数量 
  if len(set(dataSet[:,-1].T.tolist()[0])) == 1: # 特征剩余数量为1 则返回 
    return None, leafType(dataSet)       #### 返回 1 ####  
  m,n = shape(dataSet) # 当前数据集大小 形状 
  S = errType(dataSet) # 当前数据集误差 均方误差 
  bestS = inf; bestIndex = 0; bestValue = 0 
  for featIndex in range(n-1):# 遍历 可分裂特征 
    for splitVal in set(dataSet[:,featIndex]):# 遍历对应 特性的 属性值 
      mat0, mat1 = binSplitDataSet(dataSet, featIndex, splitVal)# 进行二元分割 
      if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): continue #样本数量 小于设定值,则不切分 
      newS = errType(mat0) + errType(mat1)# 二元分割后的 均方差 
      if newS < bestS: # 弱比分裂前小 则保留这个分类 
        bestIndex = featIndex 
        bestValue = splitVal 
        bestS = newS 
  if (S - bestS) < tolS: # 弱分裂后 比 分裂前样本方差 减小的不多 也不进行切分 
    return None, leafType(dataSet)       #### 返回 2 ####  
  mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue) 
  if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN): #样本数量 小于设定值,则不切分 
    return None, leafType(dataSet)       #### 返回 3 ####  
  return bestIndex,bestValue # 返回最佳的 分裂属性 和 对应的值 
 
# 创建回归树 numpy数组数据集 叶子函数  误差函数  用户设置参数(最小样本数量 以及最小误差下降间隔) 
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)): 
 # 找到最佳的待切分特征和对应 的值 
  feat, val = chooseBestSplit(dataSet, leafType, errType, ops)# 
 # 停止条件 该节点不能再分,该节点为叶子节点 
  if feat == None: return val  
  retTree = {} 
  retTree['spInd'] = feat #特征 
  retTree['spVal'] = val #值 
 # 执行二元切分  
  lSet, rSet = binSplitDataSet(dataSet, feat, val)# 二元切分 左树 右树 
 # 创建左树 
  retTree['left'] = createTree(lSet, leafType, errType, ops)  # 左树 最终返回子叶子节点 的属性值 
 # 创建右树 
  retTree['right'] = createTree(rSet, leafType, errType, ops) # 右树 
  return retTree  
 
# 未进行后剪枝的回归树测试  
def RtTreeTest(filename='ex00.txt',ops=(1,4)): 
  MyDat = loadDataSet(filename) # ex00.txt y = w*x 两维  ex0.txt y = w*x+b 三维 
  MyMat = mat(MyDat) 
  print createTree(MyMat,ops=ops) 
# 判断是不是树 (按字典形式存储) 
def isTree(obj): 
  return (type(obj).__name__=='dict') 
 
# 返回树的平均值 塌陷处理 
def getMean(tree): 
  if isTree(tree['right']):  
  tree['right'] = getMean(tree['right']) 
  if isTree(tree['left']):  
  tree['left'] = getMean(tree['left']) 
  return (tree['left']+tree['right'])/2.0 # 两个叶子节点的 平均值 
 
# 后剪枝  待剪枝的树  剪枝所需的测试数据 
def prune(tree, testData): 
  if shape(testData)[0] == 0:  
  return getMean(tree) #没有测试数据 返回 
  if (isTree(tree['right']) or isTree(tree['left'])): # 如果回归树的左右两边是树 
    lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal'])#对测试数据 进行切分 
  if isTree(tree['left']):  
  tree['left'] = prune(tree['left'], lSet)  # 对左树进行剪枝 
  if isTree(tree['right']):  
  tree['right'] = prune(tree['right'], rSet)# 对右树进行剪枝 
  if not isTree(tree['left']) and not isTree(tree['right']):#两边都是叶子 
    lSet, rSet = binSplitDataSet(testData, tree['spInd'], tree['spVal'])#对测试数据 进行切分 
    errorNoMerge = sum(power(lSet[:,-1] - tree['left'],2)) +\ 
      sum(power(rSet[:,-1] - tree['right'],2)) # 对两边叶子合并前计算 误差  
    treeMean = (tree['left']+tree['right'])/2.0 # 合并后的 叶子 均值 
    errorMerge = sum(power(testData[:,-1] - treeMean,2))# 合并后 的误差 
    if errorMerge < errorNoMerge: # 合并后的误差小于合并前的误差 
      print "merging"      # 说明合并后的树 误差更小 
      return treeMean      # 返回两个叶子 的均值 作为 合并后的叶子节点 
    else: return tree 
  else: return tree 
   
def pruneTest(): 
  MyDat = loadDataSet('ex2.txt')  
  MyMat = mat(MyDat) 
  MyTree = createTree(MyMat,ops=(0,1))  # 为了得到 最大的树 误差设置为0 个数设置为1 即不进行预剪枝 
  MyDatTest = loadDataSet('ex2test.txt') 
  MyMatTest = mat(MyDatTest) 
  print prune(MyTree,MyMatTest) 
 
 
######叶子节点为线性模型的模型树######### 
# 线性模型 
def linearSolve(dataSet):   
  m,n = shape(dataSet) # 数据集大小 
  X = mat(ones((m,n))) # 自变量 
  Y = mat(ones((m,1))) # 目标变量  
  X[:,1:n] = dataSet[:,0:n-1]# 样本数据集合 
  Y = dataSet[:,-1]     # 标签 
  # 线性模型 求解 
  xTx = X.T*X         
  if linalg.det(xTx) == 0.0: 
    raise NameError('行列式值为零,不能计算逆矩阵,可适当增加ops的第二个值') 
  ws = xTx.I * (X.T * Y) 
  return ws,X,Y 
 
# 模型叶子节点 
def modelLeaf(dataSet):  
  ws,X,Y = linearSolve(dataSet) 
  return ws 
 
# 计算模型误差 
def modelErr(dataSet): 
  ws,X,Y = linearSolve(dataSet) 
  yHat = X * ws 
  return sum(power(Y - yHat,2)) 
 
# 模型树测试 
def modeTreeTest(filename='ex2.txt',ops=(1,4)): 
  MyDat = loadDataSet(filename) #  
  MyMat = mat(MyDat) 
  print createTree(MyMat,leafType=modelLeaf, errType=modelErr,ops=ops)#带入线性模型 和相应 的误差计算函数 
 
 
# 模型效果计较 
# 线性叶子节点 预测计算函数 直接返回 树叶子节点 值 
def regTreeEval(model, inDat): 
  return float(model) 
 
def modelTreeEval(model, inDat): 
  n = shape(inDat)[1] 
  X = mat(ones((1,n+1)))# 增加一列 
  X[:,1:n+1]=inDat 
  return float(X*model) # 返回 值乘以 线性回归系数 
 
# 树预测函数 
def treeForeCast(tree, inData, modelEval=regTreeEval): 
  if not isTree(tree):  
  return modelEval(tree, inData) # 返回 叶子节点 预测值 
  if inData[tree['spInd']] > tree['spVal']:   # 左树 
    if isTree(tree['left']):  
    return treeForeCast(tree['left'], inData, modelEval)# 还是树 则递归调用 
    else:  
    return modelEval(tree['left'], inData) # 计算叶子节点的值 并返回 
  else: 
    if isTree(tree['right']):         # 右树 
    return treeForeCast(tree['right'], inData, modelEval) 
    else:  
    return modelEval(tree['right'], inData)# 计算叶子节点的值 并返回 
 
# 得到预测值     
def createForeCast(tree, testData, modelEval=regTreeEval): 
  m=len(testData) 
  yHat = mat(zeros((m,1)))#预测标签 
  for i in range(m): 
    yHat[i,0] = treeForeCast(tree, mat(testData[i]), modelEval) 
  return yHat 
 
# 常量回归树和线性模型回归树的预测结果比较 
def MRTvsSRT(): 
  TestMat = mat(loadDataSet('bikeSpeedVsIq_test.txt')) 
  TrainMat = mat(loadDataSet('bikeSpeedVsIq_train.txt')) 
# 普通回归树 预测结果 
  # 得到普通回归树树 
  StaTree = createTree(TrainMat, ops=(1,20)) 
  # 得到预测结果 
  StaYHat = createForeCast(StaTree, TestMat[:,0], regTreeEval)# 第一列为 自变量 
  # 预测结果和真实标签的相关系数 
  StaCorr = corrcoef(StaYHat, TestMat[:,1], rowvar=0)[0,1] # NumPy 库函数  
# 模型回归树 预测结果 
  # 得到模型回归树 
  ModeTree = createTree(TrainMat,leafType=modelLeaf, errType=modelErr, ops=(1,20)) 
  # 得到预测结果 
  ModeYHat = createForeCast(ModeTree, TestMat[:,0], modelTreeEval)  
  # 预测结果和真实标签的相关系数 
  ModeCorr = corrcoef(ModeYHat, TestMat[:,1], rowvar=0)[0,1] # NumPy 库函数   
  print "普通回归树 预测结果的相关系数R2: %f" %(StaCorr)                        
  print "模型回归树 预测结果的相关系数R2: %f" %(ModeCorr) 
  if ModeCorr>StaCorr: 
  print "模型回归树效果优于普通回归树" 
  else: 
  print "回归回归树效果优于模型普通树"

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python实现快速多线程ping的方法
Jul 15 Python
详解flask表单提交的两种方式
Jul 21 Python
Python中修改字符串的四种方法
Nov 02 Python
Django处理多用户类型的方法介绍
May 18 Python
python3使用腾讯企业邮箱发送邮件的实例
Jun 28 Python
Django 拆分model和view的实现方法
Aug 16 Python
PyTorch中topk函数的用法详解
Jan 02 Python
解决django无法访问本地static文件(js,css,img)网页里js,cs都加载不了
Apr 07 Python
解决Jupyter notebook中.py与.ipynb文件的import问题
Apr 21 Python
Python小白学习爬虫常用请求报头
Jun 03 Python
python集合能干吗
Jul 19 Python
Python如何获取文件路径/目录
Sep 22 Python
使用python 和 lint 删除项目无用资源的方法
Dec 20 #Python
python机器学习实战之K均值聚类
Dec 20 #Python
Python绘制3d螺旋曲线图实例代码
Dec 20 #Python
python机器学习实战之最近邻kNN分类器
Dec 20 #Python
python3.6 +tkinter GUI编程 实现界面化的文本处理工具(推荐)
Dec 20 #Python
浅谈Python实现Apriori算法介绍
Dec 20 #Python
利用Python如何生成hash值示例详解
Dec 20 #Python
You might like
php下尝试使用GraphicsMagick的缩略图功能
2011/01/01 PHP
PHP自定义图片缩放函数实现等比例不失真缩放的方法
2016/08/19 PHP
PHP getNamespaces()函数讲解
2019/02/03 PHP
JAVASCRIPT 对象的创建与使用
2021/03/09 Javascript
jQuery函数map()和each()介绍及异同点分析
2014/11/08 Javascript
jQuery中prependTo()方法用法实例
2015/01/08 Javascript
JQuery中serialize() 序列化
2015/03/13 Javascript
创建你的第一个AngularJS应用的方法
2015/06/16 Javascript
Android中Okhttp3实现上传多张图片同时传递参数
2017/02/18 Javascript
jQuery Ajax自定义分页组件(jquery.loehpagerv1.0)实例详解
2017/05/01 jQuery
js实现图片轮播效果学习笔记
2017/07/26 Javascript
JS实现根据指定值删除数组中的元素操作示例
2018/08/02 Javascript
element-ui 设置菜单栏展开的方法
2018/08/22 Javascript
vue使用pdfjs显示PDF可复制的实现方法
2018/12/14 Javascript
浅谈vue.watch的触发条件是什么
2020/11/07 Javascript
[15:41]教你分分钟做大人——灰烬之灵
2015/03/11 DOTA
Python FTP操作类代码分享
2014/05/13 Python
python使用multiprocessing模块实现带回调函数的异步调用方法
2015/04/18 Python
Python 通配符删除文件的实例
2018/04/24 Python
Python实现求两个数组交集的方法示例
2019/02/23 Python
numpy数组之存取文件的实现示例
2019/05/24 Python
Python3中urlencode和urldecode的用法详解
2019/07/23 Python
django 自定义filter 判断if var in list的例子
2019/08/20 Python
学会python自动收发邮件 代替你问候女友
2020/05/20 Python
浅谈keras2 predict和fit_generator的坑
2020/06/17 Python
浅析Python迭代器的高级用法
2020/07/16 Python
两种CSS3伪类选择器详细介绍
2013/12/24 HTML / CSS
H5仿微信界面教程(一)
2017/07/05 HTML / CSS
Airbnb爱彼迎官网:成为爱彼迎房东,赚取收入
2019/03/14 全球购物
财务经理岗位职责
2013/11/09 职场文书
医大实习自我鉴定
2013/12/07 职场文书
运动会稿件100字
2014/02/21 职场文书
公务员个人年终总结
2015/02/12 职场文书
书法社团活动总结
2015/05/07 职场文书
nginx如何将http访问的网站改成https访问
2021/03/31 Servers
详解MySQL的主键查询为什么这么快
2022/04/03 MySQL