從零實現機器學習算法(十)樹迴歸(Tree Regression)

目錄

1. 樹迴歸簡介

2. 樹迴歸模型

2.1 特徵選擇

2.2 迴歸樹生成

2.3 迴歸規則

3. 總結與分析


1. 樹迴歸簡介

上一節介紹了線性迴歸模型,但是在實際生活中許多問題都是非線性的,或者分段線性的因此很難建立一個全局的線性模型。爲了解決這一問題,可以使用樹迴歸。樹迴歸的基本原理是將問題劃分成一個個較小的子問題,如果子問題可以建立線性模型,那麼就可以自底向上解決全局的迴歸問題。

2. 樹迴歸模型

迴歸樹模型和決策樹類似,包括特徵選擇、迴歸樹生成和迴歸規則

2.1 特徵選擇

在決策樹中,我們使用了信息增益作爲特徵選擇的依據。但是對於迴歸樹來說,由於需要預測的是連續的數值,其經驗熵不能很好的表達有用的信息(因爲迴歸標籤幾乎每個都不同),因此這裏使用預測誤差作爲特徵選擇的依據。這裏採用平方差作爲誤差的評價,即

\sum_{x_{i}\in R_{m}}\left(y_{i}-f\left(x_{i}\right)\right)^{2}

其中 R_{m} 爲迴歸樹將輸入空間劃分成 M 個單元(相當於子樹),並且在每個單元上有固定的輸出值,即

f\left(x\right)=\sum_{m=1}^{M}c_{m}I\left(x\in R_{m}\right)

也就是說,被劃到 R_{m} 這個單元裏的 x ,不論其特徵值爲什麼,其結果都是固定的。每個單元上的預測結果爲劃分到該單元上的所有樣本的平均值。因此

c_{m}=\arg \left(y_{i}|x_{i}\in R_{m}\right)

特徵選擇與劃分同決策樹類似,遍歷所有特徵和其所有對應的值使得預測誤差最小

\min\limits_{j,s}\left[\min\limits_{c_{1}}\sum_{x_{i}\in R_{1}\left(j,s\right)}\left(y_{i}-c_{1}\right)+\min\limits_{c_{2}}\sum_{x_{i}\in R_{2}\left(j,s\right)}\left(y_{i}-c_{2}\right)\right]

2.2 迴歸樹生成

迴歸樹生成同決策樹生成一樣,採用遞歸的方式生成樹。存儲結構也類似

    def __init__(self, index=-1, value=None, result=None, right_tree=None, left_tree=None):
        self.index = index
        self.value = value
        self.result = result
        self.right_tree = right_tree
        self.left_tree = left_tree

迴歸樹生成算法於決策樹類似,假設已經獲得了切分特徵和其對應特徵值組 \left(j,s\right) ,那麼劃分規則如下

R_{1}\left(j,s\right)=\left\{ x|x^{(j)}\leq s\right\}

R_{2}\left(j,s\right)=\left\{ x|x^{(j)}> s\right\}

兩個單元對應的輸出值爲

c_{m}=\frac{1}{N_{m}}\sum_{x_{i}\in R_{m}\left(j,s\right)}y_{i},x\in R_{m} ,m=1,2

決策樹生成代碼如下:

    def createRegressionTree(self, data):
        # if there is no feature
        if len(data) == 0:
            self.tree_node = treeNode(result=self.getMean(data[:, -1]))
            return self.tree_node

        sample_num, feature_dim = np.shape(data)

        best_criteria = None
        best_error = np.inf
        best_set = None
        initial_error = self.getVariance(data)

        # get the best split feature and value
        for index in range(feature_dim - 1):
            uniques = np.unique(data[:, index])
            for value in uniques:
                left_set, right_set = self.divideData(data, index, value)
                if len(left_set) < self.N or len(right_set) < self.N:
                    continue
                new_error = self.getVariance(left_set) + self.getVariance(right_set)
                if new_error < best_error:
                    best_criteria = (index, value)
                    best_error = new_error
                    best_set = (left_set, right_set)

        if best_set is None:
            self.tree_node = treeNode(result=self.getMean(data[:, -1]))
            return self.tree_node
        # if the descent of error is small enough, return the mean of the data
        elif abs(initial_error - best_error) < self.error_threshold:
            self.tree_node = treeNode(result=self.getMean(data[:, -1]))
            return self.tree_node
        # if the split data is small enough, return the mean of the data
        elif len(best_set[0]) < self.N or len(best_set[1]) < self.N:
            self.tree_node = treeNode(result=self.getMean(data[:, -1]))
            return self.tree_node
        else:
            ltree = self.createRegressionTree(best_set[0])
            rtree = self.createRegressionTree(best_set[1])
            self.tree_node = treeNode(index=best_criteria[0], value=best_criteria[1], left_tree=ltree, right_tree=rtree)
            return self.tree_node

2.3 迴歸規則

迴歸樹迴歸規則也和決策樹類似,二叉排序樹類似,根據待檢測樣本的指定特徵和其特徵值與決策樹結點存儲的特徵值進行比較,根據結果將其送入左子樹或者右子樹,其代碼如下:

    def classify(self, sample, tree):
        if tree.result is not None:
            return tree.result
        else:
            value = sample[tree.index]
            if value >= tree.value:
                branch = tree.right_tree
            else:
                branch = tree.left_tree
            return self.classify(sample, branch)

3. 總結與分析

迴歸樹和決策樹可以組合成分類迴歸樹(CART),我將其拆分爲決策樹和迴歸樹。因爲我覺得雖然它們有很多類似之處但是採用的一些標準有所不同。關於剪枝,分爲預剪枝和後剪枝。最後貼一下本文實現的迴歸樹與Sklearn檢測性能的比較:

Sklearn 樹迴歸結果

本文實現樹迴歸結果

可以發現效果差不多,但是Sklearn的運行時間要少得多。

本文相關代碼和數據集:https://github.com/Ryuk17/MachineLearning

 

[1] 李航, 統計學習方法

[2] Peter Harrington, Machine Learning IN ACTION

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章