乐趣区

机器学习 | 树回归

由于近期学业繁重 QAQ,所以我就不说废话了,直接上代码~
运行结果

代码
from numpy import *
#使用二元切分法——每次将数据集切成两份
#如果数据的某特征值等于切分所要求的值,
#那么这些数据就进入树的左子树,反之则
# 进入右子树
def loadDataSet(fileName):
dataMat=[]
fr=open(fileName)
for line in fr.readlines():
curLine=line.strip().split(‘\t’)
#将每行映射成浮点数
fltLine=list(map(float,curLine))
dataMat.append(fltLine)
#将文件中的所有数据都保存在同一个矩阵中
return dataMat

# 参数:数据集,待切分的特征,该特征的某个值
def binSplitDataSet(dataSet,feature,value):
#将数据集合切分得到两个子集并返回
mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:]
mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:]

return mat0,mat1

# 建立叶结点的函数
#当 chooseBestSplit 函数决定不再对数据集进行切分时,将调用该 regLeaf 函数
#来得到叶节点的模型。在回归树种,该模型其实就是目标变量的均值
def regLeaf(dataSet):
return mean(dataSet[:,-1])

# 计算误差的函数——这里计算的是总方差
def regErr(dataSet):
#均方差函数 var* 数据集中样本的个数 = 总方差
return var(dataSet[:,-1]) * shape(dataSet)[0]

# 给定某个误差计算方法,该函数会找到数据集上最佳的二元切割方式
#(他遍历所有的特征及可能的取值来找到使误差最小化的切分阈值)
#另外,该函数还要确定什么时候停止切分,一旦停止切分就会生成一个叶节点
#errType 为平方误差的总值(总方差)
def chooseBestSplit(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):
#用户指定的参数,用于控制函数停止时机
#tolS 为误差下降值,tolN 为切分的最少样本数
tolS = ops[0]; tolN = ops[1]
#如果所有值相等则退出
if len(set(dataSet[:,-1].T.tolist()[0])) == 1:
#找不到一个“好”的二元切分,返回 None 并同时调用 leafType 来生成叶节点
return None, leafType(dataSet)
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].T.A.tolist())[0]):
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)
mat0, mat1 = binSplitDataSet(dataSet, bestIndex, bestValue)
#如果切分出的数据集很小则退出
if (shape(mat0)[0] < tolN) or (shape(mat1)[0] < tolN):
return None, leafType(dataSet)
#找到了一个“好”的切分方式,返回特征编号和切分特征值
#找到了最佳的切分方式:切分后能达到最低误差的切分
return bestIndex,bestValue

# 构建树的函数
#dataSet 为数据集
#leafType 为建立叶结点的函数,errType 为误差计算函数
#ops 是一个包含书构建所需其他参数的元组
def createTree(dataSet, leafType=regLeaf, errType=regErr, ops=(1,4)):
#chooseBestSplit 为切分函数
#若满足停止条件 chooseBestSplit 将返回 None 和某类模型的值
#如果构建的是回归树,该模型是一个常数,如果是模型树,其
#模型是一个线性方程 (回归树假设叶节点是常数值)
#若不满足停止条件,chooseBestSplit 将创建一个新的 python
#字典,并将数据集分成两份,在这两份数据集上分别继续递归调
#用 createTree 函数
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 drawFigure1():
# import matplotlib.pyplot as plt
# myDat=loadDataSet(‘ex00.txt’)
# myMat=mat(myDat)
# createTree(myMat)
# plt.plot(myMat[:,0],myMat[:,1],’ro’)
# plt.show()
import matplotlib.pyplot as plt
myDat=loadDataSet(‘ex0.txt’)
myMat=mat(myDat)
createTree(myMat)
plt.plot(myMat[:,1],myMat[:,2],’ro’)
plt.show()

def main():
drawFigure1()
# myDat=loadDataSet(‘ex00.txt’)
# myMat=mat(myDat)
# myTree=createTree(myMat)
# print(myTree)

#建立一个主对角线元素全为 1 的矩阵
#testMat=mat(eye(4))
#print(testMat)
#要分割的特征位于第一列
#按照 0.5 去划分
#mat0,mat1=binSplitDataSet(testMat,0,0.5)
# print(mat0)
# print(mat1)

if __name__==’__main__’:
main()“`

退出移动版