摘要:在本教程中,您將了解如何在中從頭開(kāi)始實(shí)現(xiàn)隨機(jī)森林算法。如何將隨機(jī)森林算法應(yīng)用于預(yù)測(cè)建模問(wèn)題。如何在中從頭開(kāi)始實(shí)現(xiàn)隨機(jī)森林圖片來(lái)自,保留部分權(quán)利。這被稱(chēng)為隨機(jī)森林算法。如何更新決策樹(shù)的創(chuàng)建以適應(yīng)隨機(jī)森林過(guò)程。
歡迎大家前往云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~
決策樹(shù)可能會(huì)受到高度變異的影響,使得結(jié)果對(duì)所使用的特定測(cè)試數(shù)據(jù)而言變得脆弱。
根據(jù)您的測(cè)試數(shù)據(jù)樣本構(gòu)建多個(gè)模型(稱(chēng)為套袋)可以減少這種差異,但是樹(shù)本身是高度相關(guān)的。
隨機(jī)森林是套袋(方法)的延伸,除了基于多個(gè)測(cè)試數(shù)據(jù)樣本構(gòu)建樹(shù)木之外,它還限制了可用于構(gòu)建樹(shù)木的特征,使得樹(shù)木間具有差異。這反過(guò)來(lái)可以提升算法的表現(xiàn)。
在本教程中,您將了解如何在Python中從頭開(kāi)始實(shí)現(xiàn)隨機(jī)森林算法。
完成本教程后,您將知道:
套袋決策樹(shù)和隨機(jī)森林算法的區(qū)別。
如何構(gòu)造更多方差的袋裝決策樹(shù)。
如何將隨機(jī)森林算法應(yīng)用于預(yù)測(cè)建模問(wèn)題。
讓我們開(kāi)始吧。
2017年1月更新:將cross_validation_split()中fold_size的計(jì)算更改為始終為整數(shù)。修復(fù)了Python 3的問(wèn)題。
2017年2月更新:修復(fù)了build_tree中的錯(cuò)誤。
2017年8月更新:修正了基尼計(jì)算中的一個(gè)錯(cuò)誤,增加了群組大小(基于邁克爾?。?。
如何在Python中從頭開(kāi)始實(shí)現(xiàn)隨機(jī)森林 圖片來(lái)自 InspireFate Photography,保留部分權(quán)利。
描述本節(jié)簡(jiǎn)要介紹本教程中使用的隨機(jī)森林算法和Sonar數(shù)據(jù)集。
隨機(jī)森林算法決策樹(shù)涉及從數(shù)據(jù)集中(利用)貪婪選擇選取最佳分割點(diǎn)過(guò)程中的每一步。
如果不精簡(jiǎn)(該算法),此算法容易使決策樹(shù)出現(xiàn)高方差。這種高方差(結(jié)果)可以通過(guò)創(chuàng)建包含測(cè)試數(shù)據(jù)集中(多個(gè))不同的實(shí)例(問(wèn)題的不同觀(guān)點(diǎn))的多重樹(shù),接著將實(shí)例所有的可能結(jié)果結(jié)合,這種方法簡(jiǎn)稱(chēng)為bootstrap聚合或套袋。
套袋的局限性在于,它使用相同的貪婪算法來(lái)創(chuàng)建每棵樹(shù),這意味著在每棵樹(shù)中可能會(huì)選擇相同或非常相似的分割點(diǎn),使得不同的樹(shù)非常相似(樹(shù)將被關(guān)聯(lián))。這反過(guò)來(lái)又使他們的預(yù)測(cè)相似,從而縮減了最初尋求的差異。
我們可以通過(guò)貪婪算法在創(chuàng)建樹(shù)時(shí)在每個(gè)分割點(diǎn)評(píng)估的特征(行)來(lái)限制決策樹(shù)不同。這被稱(chēng)為隨機(jī)森林算法。
像裝袋一樣,測(cè)試數(shù)據(jù)集的多個(gè)樣本在被采集后,接著在每個(gè)樣本上訓(xùn)練不同的樹(shù)。不同之處在于在每一點(diǎn)上,拆分是在數(shù)據(jù)中進(jìn)行并添加到樹(shù)中的,且只考慮固定的屬性子集。
對(duì)于分類(lèi)問(wèn)題,我們將在本教程中討論的問(wèn)題的類(lèi)型——分割中輸入特點(diǎn)數(shù)的平方根值對(duì)為分割操作考慮的屬性個(gè)數(shù)的限制。
num_features_for_split = sqrt(total_input_features)
這一小變化的結(jié)果是樹(shù)之間變得更加不同(不關(guān)聯(lián)),作為結(jié)果會(huì)有更加多樣化的預(yù)測(cè),這樣的結(jié)果往往好于一個(gè)多帶帶的樹(shù)或者多帶帶套袋得到的結(jié)果。
聲納數(shù)據(jù)集我們將在本教程中使用的數(shù)據(jù)集是Sonar數(shù)據(jù)集。
這是一個(gè)描述聲納聲音從不同曲面反彈后返回(數(shù)據(jù))的數(shù)據(jù)集。輸入的60個(gè)變量是聲吶從不同角度返回的力度值。這是一個(gè)二元分類(lèi)問(wèn)題,需要一個(gè)模型來(lái)區(qū)分金屬圓柱中的巖石。這里有208個(gè)觀(guān)察對(duì)象。
這是一個(gè)很好理解的數(shù)據(jù)集。所有變量都是連續(xù)的且范圍一般是0到1。輸出變量是“Mine”字符串中的“M”和“rock”中的“R”,需要轉(zhuǎn)換為整數(shù)1和0。
通過(guò)預(yù)測(cè)在數(shù)據(jù)集(“M”或“mines”)中觀(guān)測(cè)數(shù)最多的類(lèi),零規(guī)則算法可以達(dá)到53%的準(zhǔn)確度。
您可以在UCI Machine Learning repository了解關(guān)于此數(shù)據(jù)集的更多信息。
下載免費(fèi)的數(shù)據(jù)集,并將其放置在工作目錄中,文件名為sonar.all-data.csv。
教程本教程分為2個(gè)步驟。
計(jì)算分割。
聲納數(shù)據(jù)集案例研究。
這些步驟為您需要將隨機(jī)森林算法應(yīng)用于自己的預(yù)測(cè)建模問(wèn)題奠定了基礎(chǔ)。
1.計(jì)算分割在決策樹(shù)中,通過(guò)利用最低成本找到指定屬性和該屬性的值方法來(lái)確定分割點(diǎn)。
對(duì)于分類(lèi)問(wèn)題,這個(gè)成本函數(shù)通常是基尼指數(shù),它計(jì)算分割點(diǎn)創(chuàng)建的數(shù)據(jù)組的純度?;嶂笖?shù)為0是完美純度,其中在兩類(lèi)分類(lèi)問(wèn)題的情況下,將類(lèi)別值完全分成兩組。
在決策樹(shù)中找到最佳分割點(diǎn)涉及到為每個(gè)輸入的變量評(píng)估訓(xùn)練數(shù)據(jù)集中每個(gè)值的成本。
對(duì)于裝袋和隨機(jī)森林,這個(gè)程序是在測(cè)試數(shù)據(jù)集的樣本上執(zhí)行的,并且是可替換的。更換取樣意味著同一行(數(shù)據(jù))會(huì)不止一次的被選擇并將其添加到取樣中。
我們可以?xún)?yōu)化隨機(jī)森林的這個(gè)程序。我們可以創(chuàng)建一個(gè)輸入屬性樣本來(lái)考慮,而不是在搜索中枚舉輸入屬性的所有值。
這個(gè)輸入屬性的樣本可以隨機(jī)選擇而不需要替換,這意味著每個(gè)輸入屬性在查找具有最低成本的分割點(diǎn)的過(guò)程中只被考慮一次。
下面是實(shí)現(xiàn)此過(guò)程的函數(shù)名稱(chēng)get_split()。它將數(shù)據(jù)集和固定數(shù)量的輸入要素作為輸入?yún)?shù)進(jìn)行評(píng)估,此數(shù)據(jù)集可能是實(shí)際測(cè)試數(shù)據(jù)集的一個(gè)樣本。
helper函數(shù)test_split()用于通過(guò)候選分割點(diǎn)拆分?jǐn)?shù)據(jù)集,gini_index()用于根據(jù)創(chuàng)建的行組來(lái)計(jì)算給定拆分的花費(fèi)。
我們可以看到,通過(guò)隨機(jī)選擇特征索引并將其添加到列表(稱(chēng)為特征)來(lái)創(chuàng)建特征列表,然后枚舉該特征列表并且將測(cè)試數(shù)據(jù)集中的特定值評(píng)估作為分割點(diǎn)。
# Select the best split point for a dataset def get_split(dataset, n_features): class_values = list(set(row[-1] for row in dataset)) b_index, b_value, b_score, b_groups = 999, 999, 999, None features = list() while len(features) < n_features: index = randrange(len(dataset[0])-1) if index not in features: features.append(index) for index in features: for row in dataset: groups = test_split(index, row[index], dataset) gini = gini_index(groups, class_values) if gini < b_score: b_index, b_value, b_score, b_groups = index, row[index], gini, groups return {"index":b_index, "value":b_value, "groups":b_groups}
現(xiàn)在我們知道如何修改決策樹(shù)算法以便與隨機(jī)森林算法一起使用,我們可以將它與一個(gè)bagging實(shí)現(xiàn)一起使用,并將其應(yīng)用于現(xiàn)實(shí)生活中的數(shù)據(jù)集。
2.聲納數(shù)據(jù)集案例研究在本節(jié)中,我們將把隨機(jī)森林算法應(yīng)用到聲納數(shù)據(jù)集。
該示例假定數(shù)據(jù)集的CSV副本位于當(dāng)前工作目錄中,文件名為sonar.all-data.csv。
首先加載數(shù)據(jù)集,將字符串值轉(zhuǎn)換為數(shù)字,并將輸出列從字符串轉(zhuǎn)換為0和1的整數(shù)值。這可以通過(guò)使用幫助器函數(shù)load_csv(),str_column_to_float()和str_column_to_int()來(lái)加載和預(yù)備數(shù)據(jù)集。
我們將使用k-fold交叉驗(yàn)證來(lái)估計(jì)未知數(shù)據(jù)的學(xué)習(xí)模型的性能。這意味著我們將構(gòu)建和評(píng)估k個(gè)模型,并將性能估計(jì)為平均模型誤差。分類(lèi)準(zhǔn)確性將用于評(píng)估每個(gè)模型。這些工具或是算法在cross_validation_split(),accuracy_metric()和evaluate_algorithm()輔助函數(shù)中提供。
我們也將使用適合套袋包括輔助功能分類(lèi)和回歸樹(shù)(CART)算法的實(shí)現(xiàn))test_split(拆分?jǐn)?shù)據(jù)集分成組,gini_index()來(lái)評(píng)估分割點(diǎn),我們修改get_split()函數(shù)中討論在前一步中,to_terminal(),split()和build_tree()用于創(chuàng)建單個(gè)決策樹(shù),預(yù)測(cè)()使用決策樹(shù)進(jìn)行預(yù)測(cè),subsample()創(chuàng)建訓(xùn)練數(shù)據(jù)集的子采樣,以及bagging_predict()用決策樹(shù)列表進(jìn)行預(yù)測(cè)。
開(kāi)發(fā)了一個(gè)新的函數(shù)名稱(chēng)random_forest(),首先根據(jù)訓(xùn)練數(shù)據(jù)集的子樣本創(chuàng)建一個(gè)決策樹(shù)列表,然后使用它們進(jìn)行預(yù)測(cè)。
正如我們上面所說(shuō)的,隨機(jī)森林和袋裝決策樹(shù)之間的關(guān)鍵區(qū)別是對(duì)樹(shù)的創(chuàng)建方式中的一個(gè)小的改變,這里是在get_split()函數(shù)中。
完整的例子如下所示。
# Random Forest Algorithm on Sonar Dataset from random import seed from random import randrange from csv import reade from math import sqrt # Load a CSV file def load_csv(filename): dataset = list() with open(filename, "r") as file: csv_reader = reader(file) for row in csv_reader: if not row: continue dataset.append(row) return dataset # Convert string column to float def str_column_to_float(dataset, column): for row in dataset: row[column] = float(row[column].strip()) # Convert string column to intege def str_column_to_int(dataset, column): class_values = [row[column] for row in dataset] unique = set(class_values) lookup = dict() for i, value in enumerate(unique): lookup[value] = i for row in dataset: row[column] = lookup[row[column]] return lookup # Split a dataset into k folds def cross_validation_split(dataset, n_folds): dataset_split = list() dataset_copy = list(dataset) fold_size = int(len(dataset) / n_folds) for i in range(n_folds): fold = list() while len(fold) < fold_size: index = randrange(len(dataset_copy)) fold.append(dataset_copy.pop(index)) dataset_split.append(fold) return dataset_split # Calculate accuracy percentage def accuracy_metric(actual, predicted): correct = 0 for i in range(len(actual)): if actual[i] == predicted[i]: correct += 1 return correct / float(len(actual)) * 100.0 # Evaluate an algorithm using a cross validation split def evaluate_algorithm(dataset, algorithm, n_folds, *args): folds = cross_validation_split(dataset, n_folds) scores = list() for fold in folds: train_set = list(folds) train_set.remove(fold) train_set = sum(train_set, []) test_set = list() for row in fold: row_copy = list(row) test_set.append(row_copy) row_copy[-1] = None predicted = algorithm(train_set, test_set, *args) actual = [row[-1] for row in fold] accuracy = accuracy_metric(actual, predicted) scores.append(accuracy) return scores # Split a dataset based on an attribute and an attribute value def test_split(index, value, dataset): left, right = list(), list() for row in dataset: if row[index] < value: left.append(row) else: right.append(row) return left, right # Calculate the Gini index for a split dataset def gini_index(groups, classes): # count all samples at split point n_instances = float(sum([len(group) for group in groups])) # sum weighted Gini index for each group gini = 0.0 for group in groups: size = float(len(group)) # avoid divide by zero if size == 0: continue score = 0.0 # score the group based on the score for each class for class_val in classes: p = [row[-1] for row in group].count(class_val) / size score += p * p # weight the group score by its relative size gini += (1.0 - score) * (size / n_instances) return gini # Select the best split point for a dataset def get_split(dataset, n_features): class_values = list(set(row[-1] for row in dataset)) b_index, b_value, b_score, b_groups = 999, 999, 999, None features = list() while len(features) < n_features: index = randrange(len(dataset[0])-1) if index not in features: features.append(index) for index in features: for row in dataset: groups = test_split(index, row[index], dataset) gini = gini_index(groups, class_values) if gini < b_score: b_index, b_value, b_score, b_groups = index, row[index], gini, groups return {"index":b_index, "value":b_value, "groups":b_groups} # Create a terminal node value def to_terminal(group): outcomes = [row[-1] for row in group] return max(set(outcomes), key=outcomes.count) # Create child splits for a node or make terminal def split(node, max_depth, min_size, n_features, depth): left, right = node["groups"] del(node["groups"]) # check for a no split if not left or not right: node["left"] = node["right"] = to_terminal(left + right) return # check for max depth if depth >= max_depth: node["left"], node["right"] = to_terminal(left), to_terminal(right) return # process left child if len(left) <= min_size: node["left"] = to_terminal(left) else: node["left"] = get_split(left, n_features) split(node["left"], max_depth, min_size, n_features, depth+1) # process right child if len(right) <= min_size: node["right"] = to_terminal(right) else: node["right"] = get_split(right, n_features) split(node["right"], max_depth, min_size, n_features, depth+1) # Build a decision tree def build_tree(train, max_depth, min_size, n_features): root = get_split(train, n_features) split(root, max_depth, min_size, n_features, 1) return root # Make a prediction with a decision tree def predict(node, row): if row[node["index"]] < node["value"]: if isinstance(node["left"], dict): return predict(node["left"], row) else: return node["left"] else: if isinstance(node["right"], dict): return predict(node["right"], row) else: return node["right"] # Create a random subsample from the dataset with replacement def subsample(dataset, ratio): sample = list() n_sample = round(len(dataset) * ratio) while len(sample) < n_sample: index = randrange(len(dataset)) sample.append(dataset[index]) return sample # Make a prediction with a list of bagged trees def bagging_predict(trees, row): predictions = [predict(tree, row) for tree in trees] return max(set(predictions), key=predictions.count) # Random Forest Algorithm def random_forest(train, test, max_depth, min_size, sample_size, n_trees, n_features): trees = list() for i in range(n_trees): sample = subsample(train, sample_size) tree = build_tree(sample, max_depth, min_size, n_features) trees.append(tree) predictions = [bagging_predict(trees, row) for row in test] return(predictions) # Test the random forest algorithm seed(2) # load and prepare data filename = "sonar.all-data.csv" dataset = load_csv(filename) # convert string attributes to integers for i in range(0, len(dataset[0])-1): str_column_to_float(dataset, i) # convert class column to integers str_column_to_int(dataset, len(dataset[0])-1) # evaluate algorithm n_folds = 5 max_depth = 10 min_size = 1 sample_size = 1.0 n_features = int(sqrt(len(dataset[0])-1)) for n_trees in [1, 5, 10]: scores = evaluate_algorithm(dataset, random_forest, n_folds, max_depth, min_size, sample_size, n_trees, n_features) print("Trees: %d" % n_trees) print("Scores: %s" % scores) print("Mean Accuracy: %.3f%%" % (sum(scores)/float(len(scores))))
使用k值5進(jìn)行交叉驗(yàn)證,給定每個(gè)倍數(shù)值為208/5 = 41.6或者在每次迭代中剛好超過(guò)40個(gè)記錄被計(jì)算。
構(gòu)建深度樹(shù)的最大深度為10,每個(gè)節(jié)點(diǎn)的最小訓(xùn)練行數(shù)為1。訓(xùn)練數(shù)據(jù)集樣本的創(chuàng)建大小與原始數(shù)據(jù)集相同,這是隨機(jī)森林算法的默認(rèn)期望值。
在每個(gè)分割點(diǎn)處考慮的特征的數(shù)量被設(shè)置為sqrt(num_features)或者sqrt(60)= 7.74被保留為7個(gè)特征。
對(duì)一套有著3種不同數(shù)量的樹(shù)木(示例)進(jìn)行評(píng)測(cè)在此過(guò)程中進(jìn)行比較,結(jié)果表明隨著更多樹(shù)木的添加,(處理)技能也隨之提升。
運(yùn)行該示例將打印每個(gè)折疊的分?jǐn)?shù)和每個(gè)配置的平均分?jǐn)?shù)。
Trees: 1 Scores: [56.09756097560976, 63.41463414634146, 60.97560975609756, 58.536585365853654, 73.17073170731707] Mean Accuracy: 62.439% Trees: 5 Scores: [70.73170731707317, 58.536585365853654, 85.36585365853658, 75.60975609756098, 63.41463414634146] Mean Accuracy: 70.732% Trees: 10 Scores: [82.92682926829268, 75.60975609756098, 97.5609756097561, 80.48780487804879, 68.29268292682927] Mean Accuracy: 80.976%擴(kuò)展
本節(jié)列出了您可能有興趣探索的關(guān)于本教程的擴(kuò)展。
算法優(yōu)化。發(fā)現(xiàn)教程中使用的配置有一些試驗(yàn)和錯(cuò)誤,但沒(méi)有進(jìn)行優(yōu)化。嘗試更多的樹(shù)木,不同數(shù)量的特征,甚至不同的樹(shù)形配置來(lái)提高性能。
更多的問(wèn)題。將該技術(shù)應(yīng)用于其他分類(lèi)問(wèn)題,甚至將其應(yīng)用于回歸,具有新的成本函數(shù)和結(jié)合樹(shù)預(yù)測(cè)的新方法。
你有沒(méi)有嘗試這些擴(kuò)展? 在下面的評(píng)論中分享你的經(jīng)驗(yàn)。
評(píng)論在本教程中,您了解了如何從頭開(kāi)始實(shí)現(xiàn)隨機(jī)森林算法。
具體來(lái)說(shuō),你了解到:
隨機(jī)森林和Bagged決策樹(shù)的區(qū)別。
如何更新決策樹(shù)的創(chuàng)建以適應(yīng)隨機(jī)森林過(guò)程。
如何將隨機(jī)森林算法應(yīng)用于現(xiàn)實(shí)世界的預(yù)測(cè)建模問(wèn)題。
翻譯人:一只懶惰的小白,該成員來(lái)自云+社區(qū)翻譯社相關(guān)閱讀
原文鏈接:https://machinelearningmaster...
原文作者:Jason Brownlee
教程從頭開(kāi)始在Python中實(shí)現(xiàn)k最近鄰居
Python NLTK 自然語(yǔ)言處理入門(mén)與例程
淺談?dòng)肞ython計(jì)算文本BLEU分?jǐn)?shù)
此文已由作者授權(quán)云加社區(qū)發(fā)布,轉(zhuǎn)載請(qǐng)注明文章出處
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/41422.html
摘要:目前騰訊云提供的云服務(wù)器并未提供方面的監(jiān)控?cái)?shù)據(jù),本文旨在通過(guò)使用騰訊云的自定義監(jiān)控服務(wù)來(lái)自行實(shí)現(xiàn)對(duì)服務(wù)器的使用率的監(jiān)控。除了命令行工具,也提供了的供開(kāi)發(fā)者使用,本文就基于的用于讀取使用率,并將數(shù)據(jù)上傳到騰訊云自定義監(jiān)控對(duì)應(yīng)接口進(jìn)行監(jiān)控。 歡迎大家前往云+社區(qū),獲取更多騰訊海量技術(shù)實(shí)踐干貨哦~ 作者:李想 隨著人工智能以及比特幣的火熱,GPU云服務(wù)的使用場(chǎng)景是越來(lái)越廣,在很多場(chǎng)景下我們也...
馬上就要開(kāi)始啦這次共組織15個(gè)組隊(duì)學(xué)習(xí) 涵蓋了AI領(lǐng)域從理論知識(shí)到動(dòng)手實(shí)踐的內(nèi)容 按照下面給出的最完備學(xué)習(xí)路線(xiàn)分類(lèi) 難度系數(shù)分為低、中、高三檔 可以按照需要參加 - 學(xué)習(xí)路線(xiàn) - showImg(https://segmentfault.com/img/remote/1460000019082128); showImg(https://segmentfault.com/img/remote/...
摘要:翻譯自昨天收到推送了一篇介紹隨機(jī)森林算法的郵件,感覺(jué)作為介紹和入門(mén)不錯(cuò),就順手把它翻譯一下。隨機(jī)森林引入的隨機(jī)森林算法將自動(dòng)創(chuàng)建隨機(jī)決策樹(shù)群。回歸隨機(jī)森林也可以用于回歸問(wèn)題。結(jié)語(yǔ)隨機(jī)森林相當(dāng)起來(lái)非常容易。 翻譯自:http://blog.yhat.com/posts/python-random-forest.html 昨天收到y(tǒng)hat推送了一篇介紹隨機(jī)森林算法的郵件,感覺(jué)作為介紹和入門(mén)...
閱讀 2052·2021-11-08 13:22
閱讀 2513·2021-09-04 16:40
閱讀 1159·2021-09-03 10:29
閱讀 1726·2019-08-30 15:44
閱讀 2130·2019-08-30 11:13
閱讀 2800·2019-08-29 17:07
閱讀 1974·2019-08-29 14:22
閱讀 1254·2019-08-26 14:00