随机森林(总结)
一、算法定义
将多棵树集成的一种算法(集成学习,Ensemble Learning),树分类结果次数最多的类别指定为最终的输出(Bagging)。
- 随机:
1.1 样本随机:随机有放回地抽取N个样本(bootstrap sample方法);
1.2 特征随机:随机从特征集中选取m个特征子集,每次树分裂时,从m个特征中选择最优; - 森林:
2.1. 多棵决策树的集合,每棵决策树都是一个分类器;
二、算法流程
- 1、训练样本总数为N,从训练样本中有放回且随机抽取n个样本作为此颗树的训练集(bootstrap有放回取样).
- 2、若训练样本的输入特征的个数为M(m远小于M),在每颗决策树的节点上进行分裂时,从M个输入特征里随机选择m个输入特征,然后从这些特征里选择一个最好的进行分裂。
- 注意:
- m在构建决策树的过程中不会改变。
- 要为每个节点随机选出m个特征,然后选择最好的那个特征来分裂。
- 决策树中分裂属性的两个选择度量:信息增益和基尼指数。
- 3、每棵树都这样分裂下去,直到该节点的所有训练样例完成分类。
三、算法优缺点
- 优点
1. 可以给出特征重要性(特征删选方法);
2. 能够处理高维度数据,不需要进行特征删选;
3. 特征遗失对效果影响不大,模型泛化能力强。
4. 对不平衡的数据集也有较好的效果(可以平衡误差)。 - 缺点
1. 结果不容易解释;
2. 在噪音比较大的情况下,会出现过拟合;
3. 在样本量较大时候,训练时间与空间花费较大;
四、算法参数
sklearn参数 | 默认值 | 可选项 | 介绍 | 使用技巧 |
---|---|---|---|---|
criterion | 基尼系数 | ID3信息增益,C4.5信息增益比,CART基尼系数 | 特征选择的标准 | 依据训练数据选择 |
splitter | best | best与random | 特征切分点选择标准 | 选择决策树最优切分点 |
max_depth | 5 | int(>0) | 决策树最大深度 | 限制数据集进行切分次数。 |
min_samples_split | 2 | int(>0) | 子数据集再切分需要的最小样本量 | 数据量较小,使用默认值;数据量较大,增大切分次数。 |
min_samples_leaf | 1 | int | 叶节点(子数据集)最小样本数 | 子集样本数小于该值,则该叶节点和其兄弟节点都会被剪枝。 |
min_weight_fraction_leaf | 权重一致 | float | 在叶节点处的所有输入样本权重总和的最小加权分数。 | |
max_features | 所有特征切分 | int,float,sqrt,log2 | 特征切分时考虑的最大特征数量。 | 依据模型选择 |
random_state | 随机种子的设置。 | |||
max_leaf_nodes | 最大叶节点数 | 即数据集切分成子数据集的最大个数。 | ||
min_impurity_decrease | 切分点不纯度最小减少程度 | 如果某个结点的不纯度减少小于这个值,那么该切分点就会被移除。 | ||
min_impurity_split | 切分点最小不纯度 | 用来限制决策树的生成 | ||
class_weight | 权重一致 | float | 处理不平衡样本 | 自定义类别权重\balanced参数值 |
presort | 默认False | 是否进行特征预排序 | 提前排序特征,优先分割信息增益/基尼系数大的特征。 |
五、算法实现一(sklearn)
# 导包
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.cross_validation import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import confusion_matrix
from matplotlib.colors import ListedColormap
# 数据导入
dataset = pd.read_csv('TrainData.csv')
X = dataset.iloc[:, [2, 3]].values
y = dataset.iloc[:, 4].values
# 获得Train和Test
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
# 数据标准化
sc = StandardScaler()
X_train = sc.fit_transform(X_train)
X_test = sc.transform(X_test)
# 模型训练
classifier = RandomForestClassifier(n_estimators = 10, criterion = 'entropy', random_state = 0)
classifier.fit(X_train, y_train)
# 模型预测
y_pred = classifier.predict(X_test)
# 模型评估(混淆矩阵)
cm = confusion_matrix(y_test, y_pred)
# 结果可视化
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()
六、算法实现二(python,dt.py)
import numpy as np
from dt import DecisionTree
def bootstrap_sample(X, Y):
N, M = X.shape
idxs = np.random.choice(N, N, replace=True)
return X[idxs], Y[idxs]
class RandomForest:
def __init__(self, n_trees, max_depth, n_feats, classifier=True, criterion="entropy"):
self.trees = []
self.n_trees = n_trees
self.n_feats = n_feats
self.max_depth = max_depth
self.criterion = criterion
self.classifier = classifier
def fit(self, X, Y):
self.trees = []
for _ in range(self.n_trees):
X_samp, Y_samp = bootstrap_sample(X, Y)
tree = DecisionTree(n_feats=self.n_feats,max_depth=self.max_depth,
criterion=self.criterion,classifier=self.classifier,)
tree.fit(X_samp, Y_samp)
self.trees.append(tree)
def predict(self, X):
tree_preds = np.array([[t._traverse(x, t.root) for x in X] for t in self.trees])
return self._vote(tree_preds)
def _vote(self, predictions):
if self.classifier:
out = [np.bincount(x).argmax() for x in predictions.T]
else:
out = [np.mean(x) for x in predictions.T]
return np.array(out)