裝袋(Bagging)
全稱Bootstrap Aggregation的集成算法笔时。每個(gè)基學(xué)習(xí)器都會(huì)對(duì)訓(xùn)練集進(jìn)行有放回抽樣得到子訓(xùn)練集,比較著名的采樣法為 0.632 自助法。每個(gè)基學(xué)習(xí)器基于不同子訓(xùn)練集進(jìn)行訓(xùn)練,并綜合所有基學(xué)習(xí)器的預(yù)測(cè)值得到最終的預(yù)測(cè)結(jié)果麸折。Bagging 常用的綜合方法是投票法,票數(shù)最多的類別為預(yù)測(cè)類別粘昨。
Boosting
Boosting 訓(xùn)練過(guò)程為階梯狀垢啼,基模型的訓(xùn)練是有順序的窜锯,每個(gè)基模型都會(huì)在前一個(gè)基模型學(xué)習(xí)的基礎(chǔ)上進(jìn)行學(xué)習(xí),最終綜合所有基模型的預(yù)測(cè)值產(chǎn)生最終的預(yù)測(cè)結(jié)果芭析,用的比較多的綜合方式為加權(quán)法锚扎。
Stacking
Stacking 是先用全部數(shù)據(jù)訓(xùn)練好基模型,然后每個(gè)基模型都對(duì)每個(gè)訓(xùn)練樣本進(jìn)行的預(yù)測(cè)馁启,其預(yù)測(cè)值將作為訓(xùn)練樣本的特征值驾孔,最終會(huì)得到新的訓(xùn)練樣本,然后基于新的訓(xùn)練樣本進(jìn)行訓(xùn)練得到模型进统,然后得到最終預(yù)測(cè)結(jié)果。
那么浪听,為什么集成學(xué)習(xí)會(huì)好于單個(gè)學(xué)習(xí)器呢螟碎?原因可能有三:
訓(xùn)練樣本可能無(wú)法選擇出最好的單個(gè)學(xué)習(xí)器,由于沒(méi)法選擇出最好的學(xué)習(xí)器迹栓,所以干脆結(jié)合起來(lái)一起用掉分;
假設(shè)能找到最好的學(xué)習(xí)器,但由于算法運(yùn)算的限制無(wú)法找到最優(yōu)解克伊,只能找到次優(yōu)解酥郭,采用集成學(xué)習(xí)可以彌補(bǔ)算法的不足;
可能算法無(wú)法得到最優(yōu)解愿吹,而集成學(xué)習(xí)能夠得到近似解不从。比如說(shuō)最優(yōu)解是一條對(duì)角線,而單個(gè)決策樹(shù)得到的結(jié)果只能是平行于坐標(biāo)軸的犁跪,但是集成學(xué)習(xí)可以去擬合這條對(duì)角線椿息。
不是所有集成學(xué)習(xí)框架中的基模型都是弱模型。Bagging 和 Stacking 中的基模型為強(qiáng)模型(偏差低坷衍,方差高)寝优,而B(niǎo)oosting 中的基模型為弱模型(偏差高,方差低)枫耳。
Bagging 的偏差與方差
對(duì)于 Bagging 來(lái)說(shuō)乏矾,每個(gè)基模型的權(quán)重等于 1/m 且期望近似相等,故我們可以得到:
通過(guò)上式我們可以看到:
-
整體模型的期望等于基模型的期望迁杨,這也就意味著整體模型的偏差和基模型的偏差近似钻心。 -
整體模型的方差小于等于基模型的方差,當(dāng)且僅當(dāng)相關(guān)性為 1 時(shí)取等號(hào)铅协,隨著基模型數(shù)量增多扔役,整體模型的方差減少,從而防止過(guò)擬合的能力增強(qiáng)警医,模型的準(zhǔn)確度得到提高亿胸。但是坯钦,模型的準(zhǔn)確度一定會(huì)無(wú)限逼近于 1 嗎?并不一定侈玄,當(dāng)基模型數(shù)增加到一定程度時(shí)婉刀,方差公式第一項(xiàng)的改變對(duì)整體方差的作用很小,防止過(guò)擬合的能力達(dá)到極限序仙,這便是準(zhǔn)確度的極限了突颊。
在此我們知道了為什么 Bagging 中的基模型一定要為強(qiáng)模型,如果 Bagging 使用弱模型則會(huì)導(dǎo)致整體模型的偏差提高潘悼,而準(zhǔn)確度降低律秃。Random Forest 是經(jīng)典的基于 Bagging 框架的模型,并在此基礎(chǔ)上通過(guò)引入特征采樣和樣本采樣來(lái)降低基模型間的相關(guān)性治唤,在公式中顯著降低方差公式中的第二項(xiàng)棒动,略微升高第一項(xiàng),從而使得整體降低模型整體方差宾添。
Boosting 的偏差與方差
對(duì)于 Boosting 來(lái)說(shuō)船惨,由于基模型共用同一套訓(xùn)練集,所以基模型間具有強(qiáng)相關(guān)性缕陕,故模型間的相關(guān)系數(shù)近似等于 1粱锐,針對(duì) Boosting 化簡(jiǎn)公式為:
通過(guò)觀察整體方差的表達(dá)式我們?nèi)菀装l(fā)現(xiàn):
- 整體模型的方差等于基模型的方差,如果基模型不是弱模型扛邑,其方差相對(duì)較大怜浅,這將導(dǎo)致整體模型的方差很大,即無(wú)法達(dá)到防止過(guò)擬合的效果蔬崩。因此海雪,Boosting 框架中的基模型必須為弱模型。
- 此外 Boosting 框架中采用基于貪心策略的前向加法舱殿,整體模型的期望由基模型的期望累加而成奥裸,所以隨著基模型數(shù)的增多,整體模型的期望值增加沪袭,整體模型的準(zhǔn)確度提高湾宙。
基于 Boosting 框架的 Gradient Boosting Decision Tree 模型中基模型也為樹(shù)模型,同 Random Forrest冈绊,我們也可以對(duì)特征進(jìn)行隨機(jī)抽樣來(lái)使基模型間的相關(guān)性降低侠鳄,從而達(dá)到減少方差的效果。
2.4 小結(jié)
- 我們可以使用模型的偏差和方差來(lái)近似描述模型的準(zhǔn)確度死宣;
- 對(duì)于 Bagging 來(lái)說(shuō)伟恶,整體模型的偏差與基模型近似,而隨著模型的增加可以降低整體模型的方差毅该,故其基模型需要為強(qiáng)模型博秫;
- 對(duì)于 Boosting 來(lái)說(shuō)潦牛,整體模型的方差近似等于基模型的方差,而整體模型的偏差由基模型累加而成挡育,故基模型需要為弱模型巴碗。
?那么這里有一個(gè)小小的疑問(wèn),Bagging 和 Boosting 到底用的是什么模型呢即寒?
隨機(jī)森林的思想
隨機(jī)森林就是通過(guò)集成學(xué)習(xí)的思想將多棵樹(shù)集成的一種算法橡淆,它的基本單元是決策樹(shù),而它的本質(zhì)屬于集成學(xué)習(xí)方法母赵。隨機(jī)森林的名稱中有兩個(gè)關(guān)鍵詞逸爵,一個(gè)是“隨機(jī)”,一個(gè)就是“森林”凹嘲∈螅“森林”我們很好理解,一棵叫做樹(shù)施绎,那么成百上千棵就可以叫做森林了溯革,這也是隨機(jī)森林的主要思想--集成思想的體現(xiàn)贞绳。然而谷醉,bagging的代價(jià)是不用單棵決策樹(shù)來(lái)做預(yù)測(cè),具體哪個(gè)變量起到重要作用變得未知冈闭,所以bagging改進(jìn)了預(yù)測(cè)準(zhǔn)確率但損失了解釋性俱尼。
“森林”容易理解,就是由很多“樹(shù)”組成萎攒,那么“隨機(jī)”體現(xiàn)在什么方面呢遇八?
(1)訓(xùn)練集隨機(jī)的選取:如果訓(xùn)練集大小為N耍休,對(duì)于每棵樹(shù)而言刃永,隨機(jī)且有放回地從訓(xùn)練集中的抽取N個(gè)訓(xùn)練樣本(這種采樣方式稱為bootstrap sample方法),作為該樹(shù)的訓(xùn)練集羊精;這樣保證了每顆樹(shù)的訓(xùn)練集都不同斯够,從而構(gòu)建的樹(shù)也不同
(2)特征的隨機(jī)選取:從M個(gè)特征中選取m個(gè)特征喧锦,這樣可以避免某個(gè)特征與分類結(jié)果具有強(qiáng)相關(guān)性读规,如果所有特征都選取,那么所有的樹(shù)都會(huì)很相似燃少,那樣就不夠“隨機(jī)”了
另外還有一點(diǎn)束亏,隨機(jī)森林法構(gòu)建樹(shù)的時(shí)候不需要做額外的剪枝操作。個(gè)人理解:因?yàn)榍皟蓚€(gè)“隨機(jī)”操作阵具,以及多顆樹(shù)的建立碍遍,已經(jīng)避免了過(guò)擬合現(xiàn)象定铜,所以這種情況下,我們只需要讓每棵樹(shù)在它自己的領(lǐng)域內(nèi)做到最好就可以了雀久。
隨機(jī)森林算法的預(yù)測(cè)性能與兩個(gè)因素有關(guān):
(1)森林中任意兩棵樹(shù)的相關(guān)性宿稀,相關(guān)性越強(qiáng),則總體性能越容易差
(2)森林中每棵樹(shù)的預(yù)測(cè)性能赖捌,每棵樹(shù)越好祝沸,則總體性能越好
其實(shí)可以理解為要求“好而不同”。然而特征數(shù)m的選擇越大越庇,則相關(guān)性與個(gè)體性能都比較好罩锐,特征數(shù)m選擇越小,則相關(guān)性與個(gè)體性能都更小卤唉,所以m的選擇影響著隨機(jī)森林的預(yù)測(cè)性能涩惑。
過(guò)程如下:
- 構(gòu)建多個(gè)數(shù)據(jù)集
在包括N個(gè)樣本的數(shù)據(jù)集中,采用有放回的抽樣方式選擇N個(gè)樣本桑驱,構(gòu)成中間數(shù)據(jù)集竭恬,然后在這個(gè)中間數(shù)據(jù)集的所有特征中隨機(jī)選擇幾個(gè)特征,作為最終的數(shù)據(jù)集熬的。以上述方式構(gòu)建多個(gè)數(shù)據(jù)集痊硕;一般回歸問(wèn)題選用全部特征,分類問(wèn)題選擇全部特征個(gè)數(shù)的平方根個(gè)特征
- 為每個(gè)數(shù)據(jù)集建立完全分裂的決策樹(shù)
利用CART為每個(gè)數(shù)據(jù)集建立一個(gè)完全分裂押框、沒(méi)有經(jīng)過(guò)剪枝的決策樹(shù)岔绸,最終得到多棵CART決策樹(shù);
- 預(yù)測(cè)新數(shù)據(jù)
根據(jù)得到的每一個(gè)決策樹(shù)的結(jié)果來(lái)計(jì)算新數(shù)據(jù)的預(yù)測(cè)值橡伞。
- 回歸問(wèn)題:采用多棵樹(shù)的平均值盒揉。
- 分類問(wèn)題:采用投票計(jì)數(shù)的方法,票數(shù)大的獲勝兑徘,相同的隨機(jī)選擇刚盈。可以把樹(shù)的棵樹(shù)設(shè)置為奇數(shù)避免這一問(wèn)題挂脑。
隨機(jī)森林的推廣
由于RF在實(shí)際應(yīng)用中的良好特性藕漱,基于RF,有很多變種算法最域,應(yīng)用也很廣泛谴分,不光可以用于分類回歸,還可以用于特征轉(zhuǎn)換镀脂,異常點(diǎn)檢測(cè)等牺蹄。下面對(duì)于這些RF家族的算法中有代表性的做一個(gè)總結(jié)。
4.1 extra trees
extra trees是RF的一個(gè)變種, 原理幾乎和RF一模一樣薄翅,有區(qū)別有:
對(duì)于每個(gè)決策樹(shù)的訓(xùn)練集沙兰,RF采用的是隨機(jī)采樣bootstrap來(lái)選擇采樣集作為每個(gè)決策樹(shù)的訓(xùn)練集氓奈,而extra trees一般不采用隨機(jī)采樣,即每個(gè)決策樹(shù)采用原始訓(xùn)練集鼎天。
在選定了劃分特征后舀奶,RF的決策樹(shù)會(huì)基于基尼系數(shù),均方差之類的原則斋射,選擇一個(gè)最優(yōu)的特征值劃分點(diǎn)育勺,這和傳統(tǒng)的決策樹(shù)相同。但是extra trees比較的激進(jìn)罗岖,他會(huì)隨機(jī)的選擇一個(gè)特征值來(lái)劃分決策樹(shù)涧至。
從第二點(diǎn)可以看出,由于隨機(jī)選擇了特征值的劃分點(diǎn)位桑包,而不是最優(yōu)點(diǎn)位南蓬,這樣會(huì)導(dǎo)致生成的決策樹(shù)的規(guī)模一般會(huì)大于RF所生成的決策樹(shù)。 也就是說(shuō)哑了,模型的方差相對(duì)于RF進(jìn)一步減少赘方,但是偏倚相對(duì)于RF進(jìn)一步增大。在某些時(shí)候弱左,extra trees的泛化能力比RF更好窄陡。
4.2 Totally Random Trees Embedding
Totally Random Trees Embedding(以下簡(jiǎn)稱 TRTE)是一種非監(jiān)督學(xué)習(xí)的數(shù)據(jù)轉(zhuǎn)化方法。它將低維的數(shù)據(jù)集映射到高維科贬,從而讓映射到高維的數(shù)據(jù)更好的運(yùn)用于分類回歸模型泳梆。我們知道鳖悠,在支持向量機(jī)中運(yùn)用了核方法來(lái)將低維的數(shù)據(jù)集映射到高維榜掌,此處TRTE提供了另外一種方法。
TRTE在數(shù)據(jù)轉(zhuǎn)化的過(guò)程也使用了類似于RF的方法乘综,建立T個(gè)決策樹(shù)來(lái)擬合數(shù)據(jù)憎账。當(dāng)決策樹(shù)建立完畢以后,數(shù)據(jù)集里的每個(gè)數(shù)據(jù)在T個(gè)決策樹(shù)中葉子節(jié)點(diǎn)的位置也定下來(lái)了卡辰。比如我們有3顆決策樹(shù)胞皱,每個(gè)決策樹(shù)有5個(gè)葉子節(jié)點(diǎn),某個(gè)數(shù)據(jù)特征x劃分到第一個(gè)決策樹(shù)的第2個(gè)葉子節(jié)點(diǎn)九妈,第二個(gè)決策樹(shù)的第3個(gè)葉子節(jié)點(diǎn)反砌,第三個(gè)決策樹(shù)的第5個(gè)葉子節(jié)點(diǎn)。則x映射后的特征編碼為(0,1,0,0,0, 0,0,1,0,0, 0,0,0,0,1), 有15維的高維特征萌朱。這里特征維度之間加上空格是為了強(qiáng)調(diào)三顆決策樹(shù)各自的子編碼宴树。
映射到高維特征后,可以繼續(xù)使用監(jiān)督學(xué)習(xí)的各種分類回歸算法了晶疼。
4.3 Isolation Forest
Isolation Forest(以下簡(jiǎn)稱IForest)是一種異常點(diǎn)檢測(cè)的方法酒贬。它也使用了類似于RF的方法來(lái)檢測(cè)異常點(diǎn)又憨。
對(duì)于在T個(gè)決策樹(shù)的樣本集,IForest也會(huì)對(duì)訓(xùn)練集進(jìn)行隨機(jī)采樣,但是采樣個(gè)數(shù)不需要和RF一樣锭吨,對(duì)于RF蠢莺,需要采樣到采樣集樣本個(gè)數(shù)等于訓(xùn)練集個(gè)數(shù)。但是IForest不需要采樣這么多零如,一般來(lái)說(shuō)躏将,采樣個(gè)數(shù)要遠(yuǎn)遠(yuǎn)小于訓(xùn)練集個(gè)數(shù)?為什么呢考蕾?因?yàn)槲覀兊哪康氖钱惓|c(diǎn)檢測(cè)耸携,只需要部分的樣本我們一般就可以將異常點(diǎn)區(qū)別出來(lái)了。
對(duì)于每一個(gè)決策樹(shù)的建立辕翰, IForest采用隨機(jī)選擇一個(gè)劃分特征夺衍,對(duì)劃分特征隨機(jī)選擇一個(gè)劃分閾值。這點(diǎn)也和RF不同喜命。
另外沟沙,IForest一般會(huì)選擇一個(gè)比較小的最大決策樹(shù)深度max_depth,原因同樣本采集,用少量的異常點(diǎn)檢測(cè)一般不需要這么大規(guī)模的決策樹(shù)壁榕。
對(duì)于異常點(diǎn)的判斷矛紫,則是將測(cè)試樣本點(diǎn)x擬合到T顆決策樹(shù)。計(jì)算在每顆決策樹(shù)上該樣本的葉子節(jié)點(diǎn)的深度ht(x),從而可以計(jì)算出平均高度h(x)牌里。此時(shí)我們用下面的公式計(jì)算樣本點(diǎn)x的異常概率:
其中颊咬,m為樣本個(gè)數(shù)。c(m)的表達(dá)式為:
s(x,m)的取值范圍是[0,1],取值越接近于1牡辽,則是異常點(diǎn)的概率也越大喳篇。
隨機(jī)森林的優(yōu)缺點(diǎn)
RF的主要優(yōu)點(diǎn)有:
訓(xùn)練可以高度并行化,對(duì)于大數(shù)據(jù)時(shí)代的大樣本訓(xùn)練速度有優(yōu)勢(shì)态辛。
由于可以隨機(jī)選擇決策樹(shù)節(jié)點(diǎn)劃分特征麸澜,這樣在樣本特征維度很高的時(shí)候,仍然能高效的訓(xùn)練模型奏黑。
在訓(xùn)練后炊邦,可以給出各個(gè)特征對(duì)于輸出的重要性
由于采用了隨機(jī)采樣,訓(xùn)練出的模型的方差小熟史,泛化能力強(qiáng)馁害。
相對(duì)于Boosting系列的Adaboost和GBDT, RF實(shí)現(xiàn)比較簡(jiǎn)單蹂匹。
對(duì)部分特征缺失不敏感碘菜。
缺點(diǎn):
在某些噪音比較大的樣本集上,RF模型容易陷入過(guò)擬合。
取值劃分比較多的特征容易對(duì)RF的決策產(chǎn)生更大的影響炉媒,從而影響擬合的模型的效果踪区。
隨機(jī)森林的應(yīng)用場(chǎng)景
數(shù)據(jù)維度相對(duì)低(幾十維),同時(shí)對(duì)準(zhǔn)確性有較高要求時(shí)吊骤。
因?yàn)椴恍枰芏鄥?shù)調(diào)整就可以達(dá)到不錯(cuò)的效果缎岗,基本上不知道用什么方法的時(shí)候都可以先試一下隨機(jī)森林。
sklearn
sklearn.ensemble.RandomForestClassifier(n_estimators=100, criterion='gini', max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features='auto', max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None)
- n_estimators:基礎(chǔ)分類器數(shù)量
- criterion:劃分衡量指標(biāo)
- max_depth:決策樹(shù)最大深度
- min_samples_split:決策樹(shù)葉結(jié)點(diǎn)繼續(xù)分裂最小樣本數(shù)量
- min_samples_leaf:決策樹(shù)葉結(jié)點(diǎn)最小樣本數(shù)量
- min_weight_fraction_leaf:決策樹(shù)葉結(jié)點(diǎn)最小加權(quán)樣本數(shù)量
- max_features:搜索劃分時(shí)考慮的特征數(shù)量
- max_leaf_nodes:決策樹(shù)最大葉結(jié)點(diǎn)數(shù)量
- min_impurity_decrease:決策樹(shù)葉結(jié)點(diǎn)最小衡量指標(biāo)提升
- bootstrap:是否進(jìn)行有放回取樣
- oob_score:是否通過(guò)未參加訓(xùn)練的樣本估計(jì)模型效果
- n_jobs:控制并行
- random_state:隨機(jī)種子
- verbose:控制輸出
- warm_start:是否使用之前的輸出
- class_weight:類別權(quán)重
- RandomForestRegressor類似
名稱 | 解釋 | 默認(rèn)值 | 經(jīng)驗(yàn)值 |
---|---|---|---|
n_estimators | 森林中決策樹(shù)的個(gè)數(shù) | 100 | |
criterion | 度量分裂標(biāo)準(zhǔn) | (可選值)mse白粉,mae | |
oobscore | 采用袋外樣本來(lái)評(píng)估模型的好壞 | False | 推薦True 反應(yīng)模型擬合后的泛化能力 |
RF決策樹(shù)參數(shù)(和GBDT基本是相同的)
名稱 | 解釋 | 默認(rèn)值 | 經(jīng)驗(yàn)值 |
---|---|---|---|
max_features | RF劃分時(shí)考慮的最大特征數(shù) |
auto(defult): 劃分時(shí)最多考慮 |
|
max_depth | 決策樹(shù)最大深度 | 可以不輸入 | 10 ~ 100 |
min_samples_split | 內(nèi)部節(jié)點(diǎn)再劃分所需最小樣本數(shù) 如果某節(jié)點(diǎn)的樣本數(shù)少于該值,則不會(huì)繼續(xù)再嘗試選擇最優(yōu)特征來(lái)劃分 | 2 | |
min_samples_leaf | 葉子節(jié)點(diǎn)最少樣本數(shù) | 1 | 如果樣本量不大鸭巴,可以不管這個(gè)值 |
n_jobs | 設(shè)定fit和predict階段并列執(zhí)行得任務(wù)個(gè)數(shù) |
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
## 導(dǎo)入數(shù)據(jù)集
dataset = pd.read_csv('../datasets/Social_Network_Ads.csv')
X = dataset.iloc[:, [2, 3]].values
y = dataset.iloc[:, 4].values
## 將數(shù)據(jù)集拆分成訓(xùn)練集和測(cè)試集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
## 特征縮放
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
### 調(diào)試訓(xùn)練集的隨機(jī)森林
from sklearn.ensemble import RandomForestClassifier
classifier = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)
classifier.fit(X_train, y_train)
## 預(yù)測(cè)測(cè)試集結(jié)果
```python
y_pred = classifier.predict(X_test)
## 生成混淆矩陣眷细,也稱作誤差矩陣
from sklearn.metrics import confusion_matrix
cm = confusion_matrix(y_test, y_pred)
from matplotlib.colors import ListedColormap
X_set, y_set = X_train, y_train
X1, X2 = np.meshgrid(np.arange(start = X_set[:, 0].min() - 1, stop = X_set[:, 0].max() + 1, step = 0.01),
np.arange(start = X_set[:, 1].min() - 1, stop = X_set[:, 1].max() + 1, step = 0.01))
plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape),
alpha = 0.75, cmap = ListedColormap(('red', 'green')))
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
for i, j in enumerate(np.unique(y_set)):
plt.scatter(X_set[y_set == j, 0], X_set[y_set == j, 1],
c = ListedColormap(('red', 'green'))(i), label = j)
plt.title('Random Forest Classification (Training set)')
plt.xlabel('Age')
plt.ylabel('Estimated Salary')
plt.legend()
plt.show()
from matplotlib.colors import ListedColormap
X_set, y_set = X_test, y_test
X1, X2 = np.meshgrid(np.arange(start = X_set[:, 0].min() - 1, stop = X_set[:, 0].max() + 1, step = 0.01),
np.arange(start = X_set[:, 1].min() - 1, stop = X_set[:, 1].max() + 1, step = 0.01))
plt.contourf(X1, X2, classifier.predict(np.array([X1.ravel(), X2.ravel()]).T).reshape(X1.shape),
alpha = 0.75, cmap = ListedColormap(('red', 'green')))
plt.xlim(X1.min(), X1.max())
plt.ylim(X2.min(), X2.max())
for i, j in enumerate(np.unique(y_set)):
plt.scatter(X_set[y_set == j, 0], X_set[y_set == j, 1],
c = ListedColormap(('red', 'green'))(i), label = j)
plt.title('Random Forest Classification (Test set)')
plt.xlabel('Age')
plt.ylabel('Estimated Salary')
plt.legend()
plt.show()