目錄
1. 樹迴歸簡介
上一節介紹了線性迴歸模型,但是在實際生活中許多問題都是非線性的,或者分段線性的因此很難建立一個全局的線性模型。爲了解決這一問題,可以使用樹迴歸。樹迴歸的基本原理是將問題劃分成一個個較小的子問題,如果子問題可以建立線性模型,那麼就可以自底向上解決全局的迴歸問題。
2. 樹迴歸模型
迴歸樹模型和決策樹類似,包括特徵選擇、迴歸樹生成和迴歸規則
2.1 特徵選擇
在決策樹中,我們使用了信息增益作爲特徵選擇的依據。但是對於迴歸樹來說,由於需要預測的是連續的數值,其經驗熵不能很好的表達有用的信息(因爲迴歸標籤幾乎每個都不同),因此這裏使用預測誤差作爲特徵選擇的依據。這裏採用平方差作爲誤差的評價,即
其中 爲迴歸樹將輸入空間劃分成
個單元(相當於子樹),並且在每個單元上有固定的輸出值,即
也就是說,被劃到 這個單元裏的
,不論其特徵值爲什麼,其結果都是固定的。每個單元上的預測結果爲劃分到該單元上的所有樣本的平均值。因此
特徵選擇與劃分同決策樹類似,遍歷所有特徵和其所有對應的值使得預測誤差最小
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
迴歸樹生成算法於決策樹類似,假設已經獲得了切分特徵和其對應特徵值組 ,那麼劃分規則如下
兩個單元對應的輸出值爲
決策樹生成代碼如下:
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