【机器学习基础】数学推导+纯Python实现机器学习算法26:随机森林
Python機(jī)器學(xué)習(xí)算法實(shí)現(xiàn)
Author:louwill
Machine Learning Lab
? ? ?
? ? 自從第14篇文章結(jié)束,所有的單模型基本就講完了。而后我們進(jìn)入了集成學(xué)習(xí)的系列,整整花了5篇文章的篇幅來(lái)介紹集成學(xué)習(xí)中最具代表性的Boosting框架。從AdaBoost到GBDT系列,對(duì)XGBoost、LightGBM和CatBoost作了較為詳細(xì)的了解。本文作為集成學(xué)習(xí)的最后一篇文章,來(lái)介紹與Boosting框架有所不同的Bagging框架。
Bagging與隨機(jī)森林
? ? Bagging是并行式集成學(xué)習(xí)方法最典型的代表框架。其核心概念在于自助采樣(Bootstrap Sampling),給定包含m個(gè)樣本的數(shù)據(jù)集,有放回的隨機(jī)抽取一個(gè)樣本放入采樣集中,經(jīng)過(guò)m次采樣,可得到一個(gè)和原始數(shù)據(jù)集一樣大小的采樣集。我們可以采樣得到T個(gè)包含m個(gè)樣本的采樣集,然后基于每個(gè)采樣集訓(xùn)練出一個(gè)基學(xué)習(xí)器,最后將這些基學(xué)習(xí)器進(jìn)行組合。這便是Bagging的主要思想。Bagging與Boosting圖示如下:
? ? 可以清楚的看到,Bagging是并行的框架,而Boosting則是序列框架(但也可以實(shí)現(xiàn)并行)。
? ? 有了之前多篇關(guān)于決策樹的基礎(chǔ)以及前述關(guān)于Bagging基本思想的闡述,隨機(jī)森林(Random Forest)就沒有太多難以理解的地方了。所謂隨機(jī)森林,就是有很多棵決策樹構(gòu)建起來(lái)的森林,因?yàn)闃?gòu)建過(guò)程中的隨機(jī)性,故而稱之為隨機(jī)森林。隨機(jī)森林算法是Bagging框架的一個(gè)典型代表。
? ? 關(guān)于構(gòu)建決策樹的過(guò)程,可以參考前述第4~5篇,這里不做重復(fù)闡述。因?yàn)榛A(chǔ)的推導(dǎo)工作都是前述章節(jié)都已完成,這里我們可以直接闡述隨機(jī)森林的算法過(guò)程,簡(jiǎn)單來(lái)說(shuō)就是兩個(gè)隨機(jī)性。具體如下:
假設(shè)有M個(gè)樣本,有放回的隨機(jī)選擇M個(gè)樣本(每次隨機(jī)選擇一個(gè)放回后繼續(xù)選)。
假設(shè)樣本有N個(gè)特征,在決策時(shí)的每個(gè)節(jié)點(diǎn)需要分裂時(shí),隨機(jī)地從這N個(gè)特征中選取n個(gè)特征,滿足n<<N,從這n個(gè)特征中選擇特征進(jìn)行節(jié)點(diǎn)分裂。
基于抽樣的M個(gè)樣本n個(gè)特征按照節(jié)點(diǎn)分裂的方式構(gòu)建決策樹。
按照1~3步構(gòu)建大量決策樹組成隨機(jī)森林,然后將每棵樹的結(jié)果進(jìn)行綜合(分類使用投票法,回歸可使用均值法)。
? ? 所以,當(dāng)我們熟悉了Bagging的基本思想和決策樹構(gòu)建的過(guò)程后,隨機(jī)森林就很好理解了。
隨機(jī)森林算法實(shí)現(xiàn)
? ? 本文我們使用numpy來(lái)手動(dòng)實(shí)現(xiàn)一個(gè)隨機(jī)森林算法。隨機(jī)森林算法本身是實(shí)現(xiàn)思路我們是非常清晰的,但其原始構(gòu)建需要大量搭建決策樹的工作,比如定義樹節(jié)點(diǎn)、構(gòu)建基本決策樹、在基本決策樹基礎(chǔ)上構(gòu)建分類樹和回歸樹等。這些筆者在前述章節(jié)均已實(shí)現(xiàn)過(guò),這里不再重復(fù)。
? ? 在此基礎(chǔ)上,隨機(jī)森林算法的構(gòu)建主要包括隨機(jī)選取樣本、隨機(jī)選取特征、構(gòu)造森林并擬合其中的每棵樹、基于每棵樹的預(yù)測(cè)結(jié)果給出隨機(jī)森林的預(yù)測(cè)結(jié)果。
? ? 導(dǎo)入相關(guān)模塊并生成模擬數(shù)據(jù)集。
定義第一個(gè)隨機(jī)性,行抽樣選取樣本:
然后基于分類樹構(gòu)建隨機(jī)森林:
定義訓(xùn)練函數(shù),對(duì)隨機(jī)森林中每棵樹進(jìn)行擬合。
? ? 我們將上述過(guò)程進(jìn)行封裝,分別定義自助抽樣方法、隨機(jī)森林訓(xùn)練方法和預(yù)測(cè)方法。完整代碼如下:
class RandomForest():def __init__(self, n_estimators=100, min_samples_split=2, min_gain=0,max_depth=float("inf"), max_features=None):# 樹的棵樹self.n_estimators = n_estimators# 樹最小分裂樣本數(shù)self.min_samples_split = min_samples_split# 最小增益self.min_gain = min_gain# 樹最大深度self.max_depth = max_depth# 所使用最大特征數(shù)self.max_features = max_featuresself.trees = []# 基于決策樹構(gòu)建森林for _ in range(self.n_estimators):tree = ClassificationTree(min_samples_split=self.min_samples_split, min_impurity=self.min_gain,max_depth=self.max_depth)self.trees.append(tree)# 自助抽樣def bootstrap_sampling(self, X, y):X_y = np.concatenate([X, y.reshape(-1,1)], axis=1)np.random.shuffle(X_y)n_samples = X.shape[0]sampling_subsets = []for _ in range(self.n_estimators):# 第一個(gè)隨機(jī)性,行抽樣idx1 = np.random.choice(n_samples, n_samples, replace=True)bootstrap_Xy = X_y[idx1, :]bootstrap_X = bootstrap_Xy[:, :-1]bootstrap_y = bootstrap_Xy[:, -1]sampling_subsets.append([bootstrap_X, bootstrap_y])return sampling_subsets# 隨機(jī)森林訓(xùn)練def fit(self, X, y):# 對(duì)森林中每棵樹訓(xùn)練一個(gè)雙隨機(jī)抽樣子集sub_sets = self.bootstrap_sampling(X, y)n_features = X.shape[1]# 設(shè)置max_featureif self.max_features == None:self.max_features = int(np.sqrt(n_features))for i in range(self.n_estimators):# 第二個(gè)隨機(jī)性,列抽樣sub_X, sub_y = sub_sets[i]idx2 = np.random.choice(n_features, self.max_features, replace=True)sub_X = sub_X[:, idx2]self.trees[i].fit(sub_X, sub_y)# 保存每次列抽樣的列索引,方便預(yù)測(cè)時(shí)每棵樹調(diào)用self.trees[i].feature_indices = idx2print('The {}th tree is trained done...'.format(i+1))# 隨機(jī)森林預(yù)測(cè)def predict(self, X):y_preds = []for i in range(self.n_estimators):idx = self.trees[i].feature_indicessub_X = X[:, idx]y_pred = self.trees[i].predict(sub_X)y_preds.append(y_pred)y_preds = np.array(y_preds).Tres = []for j in y_preds:res.append(np.bincount(j.astype('int')).argmax())return res? ? 基于上述隨機(jī)森林算法封裝來(lái)對(duì)模擬數(shù)據(jù)集進(jìn)行訓(xùn)練并驗(yàn)證:
rf = RandomForest(n_estimators=10, max_features=15) rf.fit(X_train, y_train) y_pred = rf.predict(X_test) print(accuracy_score(y_test, y_pred)) 0.78? ? sklearn也為我們提供了隨機(jī)森林算法的api,我們也嘗試一下與numpy手寫的進(jìn)行效果對(duì)比:
? ? 可以看到sklearn的預(yù)測(cè)結(jié)果要略高于我們手寫的結(jié)果。當(dāng)然我們的訓(xùn)練結(jié)果還可以經(jīng)過(guò)調(diào)參進(jìn)一步提高。隨機(jī)森林調(diào)參可參考sklearn官方文檔,這里略過(guò)。
參考資料:
機(jī)器學(xué)習(xí) 周志華
往期精彩:
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法25:CatBoost【機(jī)器學(xué)習(xí)基礎(chǔ)】數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法25:CatBoost
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法24:LightGBM
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法23:kmeans聚類
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法22:最大熵模型
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法21:馬爾科夫鏈蒙特卡洛
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法20:LDA線性判別分析
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法19:PCA降維
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法18:奇異值分解SVD
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法17:XGBoost
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法16:Adaboost
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法15:GBDT
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法14:Ridge嶺回歸
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法13:Lasso回歸
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法12:貝葉斯網(wǎng)絡(luò)
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法11:樸素貝葉斯
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法10:線性不可分支持向量機(jī)
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法8-9:線性可分支持向量機(jī)和線性支持向量機(jī)
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法7:神經(jīng)網(wǎng)絡(luò)
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法6:感知機(jī)
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法5:決策樹之CART算法
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法4:決策樹之ID3算法
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法3:k近鄰
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法2:邏輯回歸
數(shù)學(xué)推導(dǎo)+純Python實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法1:線性回歸
往期精彩回顧適合初學(xué)者入門人工智能的路線及資料下載機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機(jī)器學(xué)習(xí)在線手冊(cè)深度學(xué)習(xí)筆記專輯《統(tǒng)計(jì)學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專輯 AI基礎(chǔ)下載機(jī)器學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)專輯獲取一折本站知識(shí)星球優(yōu)惠券,復(fù)制鏈接直接打開:https://t.zsxq.com/yFQV7am本站qq群1003271085。加入微信群請(qǐng)掃碼進(jìn)群:總結(jié)
以上是生活随笔為你收集整理的【机器学习基础】数学推导+纯Python实现机器学习算法26:随机森林的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【机器学习基础】Python数据预处理:
- 下一篇: 励志:他读书时挣了五十万,找工作时收获阿