算法原理
随机森林是一个用随机方式建立的,包含多个决策树的集成分类器。其输出的类别由各个树投票而定(如果是回归树则取平均)。假设样本总数为n,每个样本的特征数为a,则随机森林的生成过程如下:
- 从原始样本中采用有放回抽样的方法选取n个样本;
- 对n个样本选取a个特征中的随机k个,用建立决策树的方法获得最佳分割点;
- 重复m次,获得m个决策树;
- 对输入样例进行预测时,每个子树都产生一个结果,采用多数投票机制输出。
随机森林的随机性主要体现在两个方面:
数据集的随机选取:从原始的数据集中采取有放回的抽样(bagging),构造子数据集,子数据集的数据量是和原始数据集相同的。不同子数据集的元素可以重复,同一个子数据集中的元素也可以重复。
待选特征的随机选取:与数据集的随机选取类似,随机森林中的子树的每一个分裂过程并未用到所有的待选特征,而是从所有的待选特征中随机选取一定的特征,之后再在随机选取的特征中选取最优的特征。
以上两个随机性能够使得随机森林中的决策树都能够彼此不同,提升系统的多样性,从而提升分类性能。
随机森林的优点:
- 实现简单,训练速度快,泛化能力强,可以并行实现,因为训练时树与树之间是相互独立的;
- 相比单一决策树,能学习到特征之间的相互影响,且不容易过拟合;
- 能处理高维数据(即特征很多),并且不用做特征选择,因为特征子集是随机选取的;
- 对于不平衡的数据集,可以平衡误差;
- 相比SVM,不是很怕特征缺失,因为待选特征也是随机选取;
- 训练完成后可以给出哪些特征比较重要。
随机森林的缺点:
- 在噪声过大的分类和回归问题还是容易过拟合;
- 相比于单一决策树,它的随机性让我们难以对模型进行解释。
代码实现
在上一篇文章实现的决策树的基础上实现,代码如下:
#coding=utf-8
import decision_tree
from decision_tree import DecisionTree
from random import sample, choices, choice
class RandomForest(object):
def __init__(self):
self.trees = None
self.tree_features = None
def fit(self, X, y, n_estimators=10, max_depth=3, min_samples_split=2, max_features=None, n_samples=None):
self.trees = []
self.tree_features = []
for _ in range(n_estimators):
m = len(X[0])
n = len(y)
if n_samples:
idx = choices(population=range(n), k=min(n, n_samples))
else:
idx = range(n)
if max_features:
n_features = min(m, max_features)
else:
n_features = int(m ** 0.5)
features = sample(range(m), choice(range(1, n_features+1)))
X_sub = [[X[i][j] for j in features] for i in idx]
y_sub = [y[i] for i in idx]
clf = DecisionTree()
clf.fit(X_sub, y_sub, max_depth, min_samples_split)
self.trees.append(clf)
self.tree_features.append(features)
def _predict(self, Xi):
pos_vote = 0
for tree, features in zip(self.trees, self.tree_features):
score = tree._predict([Xi[j] for j in features])
if score >= 0.5:
pos_vote += 1
neg_vote = len(self.trees) - pos_vote
if pos_vote > neg_vote:
return 1
elif pos_vote < neg_vote:
return 0
else:
return choice([0, 1])
def predict(self, X):
return [self._predict(Xi) for Xi in X]
@decision_tree.run_time
def main():
print("Tesing the performance of RandomForest...")
# Load data
X, y = decision_tree.load_data()
# Split data randomly, train set rate 70%
X_train, X_test, y_train, y_test = decision_tree.train_test_split(X, y, random_state=40)
# Train model
rf = RandomForest()
rf.fit(X_train, y_train, n_samples=300, max_depth=3, n_estimators=20)
# Model evaluation
y_hat = rf.predict(X_test)
acc = decision_tree.get_acc(y_test, y_hat)
print("Accuracy is %.3f" % acc)
在肺癌数据集上测试结果如下
参考文章
https://blog.csdn.net/login_sonata/article/details/73929426