線性回歸包含一些強大的方法,但是這些方法建立的模型需要擬合所有的樣本點(區域性線性回歸除外)。當資料擁有眾多特徵,且特徵之間關係十分複雜時,構建全域性模型的想法顯得困難。並且,生活中很多問題都是非線性的,不可能使用全域性線性模型來擬合任何模型。
一種可行的方法是將資料集切分成很多份易建模的資料,然後利用線性回歸技術來建模。如果首次切分後仍然難以擬合線性模型就繼續切分。這種切分方式下,數結構和回歸法就相當有用。
接下來將介紹乙個新的叫做cart(classification and regression trees)的數建構演算法。該演算法既可用於分類,亦可用於回歸。
樹回歸
優點:可以對複雜和非線性的資料建模;
缺點:結果不易理解;
適用資料型別:數值型和標稱型資料
回顧決策樹:
1)決策樹不斷將資料切分為小資料集,直到所有目標變數完全相同,或者資料不能再切分為止。決策樹是一種貪心演算法,它要在給定時間內做出最佳選擇,但並不關心能否達到全域性最優。
2)使用的數構建演算法是id3。
2.1)id3的做法是每次選取當前最佳的特徵來分隔資料,並按照該特徵的所有取值來切分。
2.2)例:如果乙個特徵有四種取值,那麼資料將被切成4份。一旦按照某特徵切分後,該特徵在之後的演算法執行中將不會起作用,所以有觀點認為該切分方式過於迅速。
2.3)另一種切分方法是二分切分法:每次把資料集切分兩份。如果資料的某特徵值等於切分要求的值,那麼這些資料就進入數的左子樹,反之進入數的右子樹。
3)id3演算法的問題與二分切分法的優勢:
3.1)由於切分過於迅速,不能直接處理連續型特徵。只有事先將連續型特徵轉換成離散型,才能在id3演算法中使用。但是這種轉換過程會破壞連續型變數的內在性質。
3.2)二分切分法易於對樹構建過程進行調整以處理連續型特徵。另外能節省樹的構建時間,但是這點的意義不是特別大,因為樹構建一般是離線完成。
cart使用二元切分來處理連續型變數。決策樹中使用夏農熵來度量集合的無組織程度,如果選用其他方法來代替夏農熵,則可以使用樹構建演算法來完成回歸。
在樹的構建過程中,需要解決多種型別資料的儲存問題。這裡將使用一部字典來儲存樹的資料結構,該字典將包含以下4個元素:
這與決策樹的樹結構有一點不同。
1)決策樹中用一部字典來儲存每個切分,但該字典可以包含兩個或者以上的值。
2)cart演算法只做二元切分,所以這裡固定樹的資料結構。樹包含左鍵和右鍵,可以儲存另一顆子樹或者單個值。字典還包含特徵和特徵值兩個鍵,它們給出切分演算法所有的特徵和特徵值。
當然也可以使用物件導向的程式設計模式來建立這個資料結構,如下:
**程式清單2-1:**建立樹節點
class
treenode()
:def
__init__
(self, feat, val, right, left)
: feature_to_split_on = feat #特徵
value_of_split = val #特徵值
right_branch = right #左鍵
left_branch = left #右鍵
隨後將構建兩種樹:
1)回歸樹(regression tree):每個葉節點包含單個值;
2)模型樹(model tree):每個節點包含乙個線性方程。
建立者兩種樹時,為了使得**復用,以下先給出構建兩種樹的共用**。其偽**如下:
找到最佳的待切分特徵:
如果該節點不能再分:
將該節點存為葉節點
執行二元分類
在右子樹呼叫create_tree()方法
在左子樹呼叫create_tree()方法
建立regtrees.py檔案並新增以下**:
程式清單2-2:cart演算法的實現**
from numpy import
*"""資料載入,但是返回對映後的資料"""
defload_data_set
(file_name)
:with
open
(file_name)
as fd:
fd_data = fd.readlines(
) data_set =
for data in fd_data:
data = data.strip(
).split(
'\t'
) data =
map(
float
, data)
#將每行對映為一組浮點數
return data_set
"""劃分資料集合"""
defbin_split_data_set
(data_set, feature, value)
:#輸入引數:資料集合、待切分特徵、待切分特徵的某個值
mat0 = data_set[nonzero(data_set[
:, feature]
> value)[0
],:]
[0] mat1 = data_set[nonzero(data_set[
:, feature]
<= value)[0
],:]
[0]return mat0, mat1
"""建立葉節點"""
defreg_leaf()
:pass
"""計算總方差"""
defreg_err()
:pass
"""構建樹"""
defcreate_tree
(data_set, leaf_type=reg_leaf, err_type=reg_err, ops=(1
,4))
:#ops包含樹構建所需其他引數的元組
feat, val = choose_best_split(data_set, leaf_type, err_type, ops)
if feat ==
none
:return val
ret_tree =
ret_tree[
'sp_ind'
]= feat
ret_tree[
'sp_val'
]= val
l_tree, r_tree = bin_split_data_set(data_set, feat, val)
ret_tree[
'left'
]= create_tree(l_tree, leaf_type, err_type, ops)
ret_tree[
'right'
]= create_tree(r_tree, leaf_type, err_type, ops)
return ret_tree
defchoose_best_split
(data_set, leaf_type, err_type, ops)
:return0,
0def
test1()
: data_set = load_data_set(
'e:\machine learing\mymachinelearning\data\ex0.txt'
)print
(data_set)
if __name__ ==
'__main__'
: test1(
)
待續… 機器學習實戰 09 樹回歸
機器學習實戰 第9章的樹回歸執行時頻繁出錯,這裡主要有兩點 出錯的 行是 for splitval in set dataset featindex 應改為 for splitval in set dataset featindex t a.tolist 0 具體分析過程檢視 出錯的 行是 def ...
機器學習實戰之線性回歸
之前我們學習的機器學習演算法都是屬於分類演算法,也就是 值是離散值。當 值為連續值時,就需要使用回歸演算法。本文將介紹線性回歸的原理和 實現。如圖所示,這時一組二維的資料,我們先想想如何通過一條直線較好的擬合這些散點了?直白的說 盡量讓擬合的直線穿過這些散點 這些點離擬合直線很近 目標函式 要使這些...
機器學習實戰之線性回歸
線性回歸原理與推導 如圖所示,這時一組二維的資料,我們先想想如何通過一條直線較好的擬合這些散點了?直白的說 盡量讓擬合的直線穿過這些散點 這些點離擬合直線很近 目標函式 要使這些點離擬合直線很近,我們需要用數學公式來表示。首先,我們要求的直線公式為 y xtw。我們這裡要求的就是這個w向量 類似於l...