隨機之美,隨機森林
(點擊
上方藍字
,快速關注我們)
來源:伯樂在線 - 雲戒
如有好文章投稿,請點擊 → 這裡了解詳情
摘要:隨機森林和決策樹相比,能更好的防止過擬合。雖然每個基分類器很弱,但最後組合的結果通常很強,這也類似於:「三個臭皮匠頂個諸葛亮」的思想。對比發現Random Forest(隨機森林)和SVM(支持向量機)名列第一、第二名。
01 樹與森林
在構建決策樹的時候,可以讓樹進行完全生長,也可以通過參數控制樹的深度或者葉子節點的數量,通常完全生長的樹會帶來過擬合問題。過擬合一般由數據中的雜訊和離群點導致,一種解決過擬合的方法是進行剪枝,去除樹的一些雜亂的枝葉。
註:你可能需要參考前面的文章:《0x0B 菩提決策樹,姻緣演算法求》
實際應用中,一般可用隨機森林來代替,隨機森林在決策樹的基礎上,會有更好的表現,尤其是防止過擬合。
在機器學習演算法中,有一類演算法比較特別,叫組合演算法(Ensemble),即將多個基演算法(Base)組合起來使用。每個基演算法單獨預測,最後的結論由全部基演算法進行投票(用於分類問題)或者求平均(包括加權平均,用於回歸問題)。
組合演算法中,一類是Bagging(裝袋),另一類是Boosting(提升),隨機森林便是Bagging中的代表。使用多顆樹進行單獨預測,最後的結論由這些樹預測結果的組合共同來決定,這也是「森林」名字的來源。每個基分類器可以很弱,但最後組合的結果通常能很強,這也類似於:「三個臭皮匠頂個諸葛亮」的思想。
《統計學習方法》作者李航博士的文章:http://blog.sina.com.cn/s/blog_7ad48fee0102vb9c.html 有說明:「來自JMLR(Journal of Machine Learning Research,機器學習頂級期刊)雜誌的文章,有人讓179種不同的分類學習演算法在UCI 121個數據集上進行了「大比武」(UCI是機器學習公用數據集,每個數據集的規模都不大)。結果發現Random Forest(隨機森林)和SVM(支持向量機)名列第一、第二名,但兩者差異不大」。英文的原文在這兒http://jmlr.org/papers/v15/delgado14a.html, 感興趣的可以參考。
上面文章換一種理解,即為:掌握了隨機森林,基本上可以處理很多常見的機器學習問題。由此可見,組合演算法在很多時候,其預測的性能都會優於單獨的演算法,這也正是隨機森林的魅力所在。
02 處處隨機
多個人組成的團隊,是不是一定就強於一個人呢?團隊的產出並不能把每個人的力量相加,並非和「眾人拾柴火焰高」的道理一樣。要讓團隊的總產出高於單個人的產出,那必須是每個人都有其它人不具備的知識或者能力,如果大家都是完全相同的知識或者能力,在解決難題上並沒有幫助。假設對一個數據的預測,大家的結論都是1,最後組合結論依然是1,沒有任何改變。對預測準確率,沒有任何提升。
這也是「森林」前面還有「隨機」這個修飾詞的原因,隨機就是讓每個顆樹不一樣,如果都一樣,組合後的效果不會有任何提升。假設每顆樹不一樣,單獨預測錯誤率大概都是40%(夠弱了吧,很多時候都會犯錯),但三顆樹組合的後的錯誤率就變成了35.2%(至少一半以上(兩顆樹)同時犯錯結果才會犯錯),其計算方法為:
3個全錯(一種情況) + 2個錯1個對(3種組合):
1 0.4^3 + 3 0.4^2 * (1-0.4)^1 = 0.352
因此,隨機森林演算法中,「隨機」是其核心靈魂,「森林」只是一種簡單的組合方式而已。隨機森林在構建每顆樹的時候,為了保證各樹之間的獨立性,通常會採用兩到三層的隨機性。
從數據抽樣開始,每顆樹都隨機地在原有數據的基礎上進行有放回的抽樣。假定訓練數據有1萬條,隨機抽取8千條數據,因為是有放回的抽樣,可能原數據中有500條被抽了兩次,即最後的8千條中有500條是重複的數據。每顆樹都進行獨立的隨機抽樣,這樣保證了每顆樹學習到的數據側重點不一樣,保證了樹之間的獨立性。
抽取了數據,就可以開始構建決策分支了,在每次決策分支時,也需要加入隨機性,假設數據有20個特徵(屬性),每次只隨機取其中的幾個來判斷決策條件。假設取4個屬性,從這4個特徵中來決定當前的決策條件,即忽略其它的特徵。取特徵的個數,通常不能太小,太小了使得單顆樹的精度太低,太大了樹之間的相關性會加強,獨立性會減弱。通常取總特徵的平方根,或者log2(特徵數)+1,在scikit-learn的實現中,支持sqrt與log2,而spark還支持onethird(1/3)。
在結點進行分裂的時候,除了先隨機取固定個特徵,然後選擇最好的分裂屬性這種方式,還有一種方式,就是在最好的幾個(依然可以指定sqrt與log2)分裂屬性中隨機選擇一個來進行分裂。scikit-learn中實現了兩種隨機森林演算法,一種是RandomForest,另外一種是ExtraTrees,ExtraTrees就是用這種方式。在某些情況下,會比RandomForest精度略高。
總結起來,使用隨機性的三個地方:
隨機有放回的抽取數據,數量可以和原數據相同,也可以略小;
隨機選取N個特徵,選擇最好的屬性進行分裂;
在N個最好的分裂特徵中,隨機選擇一個進行分裂;
因此,理解了這幾個地方的隨機性,以及隨機性是為了保證各個基演算法模型之間的相互獨立,從而提升組合後的精度。當然,還需要保證每個基分類演算法不至於太弱,至少要強於隨機猜測,即錯誤率不能高於0.5。
03 sklearn與mllib
scikit-learn和spark中都實現了隨機森林,但各自有些細小的區別。
在scikit-learn中,同樣只是簡單幾行代碼即可:
# sklearn_rf.py
import
pandas
as
pd
from
sklearn
.
ensemble
import
RandomForestClassifier
df
=
pd
.
read_csv
(
"sklearn_data.csv"
)
train
,
test
=
df
.
query
(
"is_date != -1"
),
df
.
query
(
"is_date == -1"
)
y_train
,
X_train
=
train
[
"is_date"
],
train
.
drop
([
"is_date"
],
axis
=
1
)
X_test
=
test
.
drop
([
"is_date"
],
axis
=
1
)
model
=
RandomForestClassifier
(
n_estimators
=
50
,
criterion
=
"gini"
,
max_features
=
"sqrt"
,
min_samples_leaf
=
1
,
n_jobs
=
4
,
)
model
.
fit
(
X_train
,
y_train
)
model
.
predict
(
X_test
)
zip
(
X_train
.
columns
,
model
.
feature_importances_
)
調用RandomForestClassifier時的參數說明:
n_estimators:指定森林中樹的顆數,越多越好,只是不要超過內存;
criterion:指定在分裂使用的決策演算法;
max_features:指定了在分裂時,隨機選取的特徵數目,sqrt即為全部特徵的平均根;
min_samples_leaf:指定每顆決策樹完全生成,即葉子只包含單一的樣本;
n_jobs:指定並行使用的進程數;
從前面的隨機森林構建過程來看,隨機森林的每顆樹之間是獨立構建的,而且盡量往獨立的方向靠,不依賴其它樹的構建,這一特點,在當前的大數據環境下,尤其被人喜愛,因為它能並行,並行,並行……。
能完全並行的演算法,一定會被人們追捧,在資源夠的情況下,可以同時並行構建大量的決策樹。scikit-learn雖然是單機版本,不能做分散式,但也可以利用單機的多枋來並行。
spark中,更是能發揮分散式的特點了:
from
pprint
import
pprint
from
pyspark
import
SparkContext
from
pyspark
.
mllib
.
tree
import
RandomForest
from
pyspark
.
mllib
.
regression
import
LabeledPoint
sc
=
SparkContext
()
data
=
sc
.
textFile
(
"spark_data.csv"
).
map
(
lambda
x
:
x
.
split
(
","
)).
map
(
lambda
x
:
(
float
(
x
[
0
]),
int
(
x
[
1
]),
int
(
x
[
2
]),
float
(
x
[
3
]),
int
(
x
[
4
]),
int
(
x
[
5
])))
train
=
data
.
filter
(
lambda
x
:
x
[
5
]
!=-
1
).
map
(
lambda
v
:
LabeledPoint
(
v
[
-
1
],
v
[
:-
1
]))
test
=
data
.
filter
(
lambda
x
:
x
[
5
]
==-
1
)
#.map(lambda v: LabeledPoint(v[-1], v[:-1]))
model
=
RandomForest
.
trainClassifier
(
train
,
numClasses
=
2
,
numTrees
=
50
,
categoricalFeaturesInfo
=
{
1
:
2
,
2
:
2
,
4
:
3
},
impurity
=
"gini"
,
maxDepth
=
5
,
)
"The predict is:"
,
model
.
predict
(
test
).
collect
()
"The Decision tree is:"
,
model
.
toDebugString
()
和決策樹版本相比,唯一的變化,就是將DecistionTree換成了RandomForest,另外增加了一個指定樹顆數的參數:numTrees=50。
而和scikit-learn版本相比,spark中會通過categoricalFeaturesInfo={1:2, 2:2, 4:3}參數指定第5個屬性(工作屬性)具有3種不同的類別,因此spark在劃分的時候,是按類別變數進行處理。而scikit-learn中,依然當成連續的變數處理,所以在條件判斷的時候,才會有house
當有多個最優分割的時候,spark與scikit-learn在選擇上也有區別,spark會按屬性順序進行選擇,而scikit-learn會隨機選擇一個。這也是導致scikit-learn在多次運行中會輸出0和1的問題。
scikit-learn中,還可以輸出參數重要性,這也是決策樹和隨機森林的優點之一(目前pyspark還不支持輸入參數重要性):
# scikit-learn中
zip
(
X_train
.
columns
,
model
.
feature_importances_
)
[(『height』, 0.25), (『house』,』car』, 0.0), (『handsome』, 0.60), (『job』, 0.0)]
04 特點與應用
隨機森林基本上繼承決策樹的全部優點,只需做很少的數據準備,其他演算法往往需要數據歸一化。決策樹能處理連續變數,還能處理離散變數,當然也能處理多分類問題,多分類問題依然還是二叉樹。決策樹就是if-else語句,區別只是哪些條件寫在if,哪些寫在else,因此易於理解和解釋。
決策樹的可解釋性強 ,你可以列印出整個樹出來,從哪個因素開始決策,一目了然。但隨機森林的可解釋性就不強了。所謂可解釋性,就是當你通過各種調參進行訓練,得出一個結論,你老大來問你,這個結論是怎麼得出來的?你說是模型自己訓練出來的,老大又問了,比如舉一條具體的數據,你說一說得出結論的過程呢?因為隨機森林引入了隨機取特徵,而且是由多顆樹共同決定,樹一旦多了,很難說清楚得出結論的具體過程。雖然可以列印每顆樹的結構,但很難分析。
雖然不好解釋,但它解決了決策樹的過擬合問題,使模型的穩定性增加,對雜訊更加魯棒,從而使得整體預測精度得以提升。
因為隨機森林能計算參數的重要性,因此也可用於對數據的降維,只選取少量幾維重要的特徵來近似表示原數據。同理,在數據有眾多的特徵時,也可以用於特徵選擇,選擇關鍵的特徵用於演算法中。
隨機森林還有天生的並行性,可以很好的處理大規模數據,也可以很容易的在分散式環境中使用。
最後,在大數據環境下,隨著森林中樹的增加,最後生成的模型可能過大,因為每顆樹都是完全生長,存儲了用於決策的全部數據,導致模型可能達到幾G甚至幾十G。如果用於在線的預測,光把模型載入到內存就需要很長時間,因此比較適合離線處理。
看完本文有收穫?請轉發分享給更多人
關注「大數據與機器學習文摘」,成為Top 1%
※Django 使用 Celery 實現非同步任務
※用 Python 做股市數據分析(二)
※Python 爬蟲實戰:股票數據定向爬蟲
※Python: 受限制的 "函數調用"
※玩轉面試演算法,帶你佔領BAT!
TAG:Python開發者 |
※宇宙充滿了隨機性,真隨機與偽隨機,微觀隨機與宏觀隨機
※極端隨機森林
※真正隨機的隨機數
※契機、隨機與天機
※隨機森林預測
※殺手古德之隨機
※什麼是「隨機」?教你分清「偽隨機」和「真隨機」
※隨機殺人
※集成演算法與隨機森林
※決策樹進階版之隨機森林
※攝影人必備相機包,一機多鏡隨機組合,帶上你的相機說走就走!
※大腦的隨機漫步
※教育是隨機的
※巧於因借 得景隨機
※偷閑——隨機欄目
※祖師勸誡,守己之誠,隨機化導
※某市將雙隨機抽查葯企
※隨機世界裡的傻瓜
※從《雲頂之弈》探討競技遊戲中的隨機因素
※漫畫:給女朋友解釋為什麼隨機播放歌曲並不隨機