机器学习 | 树回归

由于近期学业繁重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()```


  [1]: /img/bVbqGCZ

相关推荐