随机森林(Random Forest,RF)指的是利用多棵树对样本进行训练并预测的一种分类器。RF在以决策树为基学习器构建Bagging的基础上,进一步在决策树的训练过程中引入了随机属性选择。在对树训练的时候,采用bootstrap sample的方法,随机选取样本,样本间保持独立不相干;在树的内部节点分裂过程中,不再是将所有特征,而是随机抽样一部分特征纳入分裂的候选项。这样一来,基模型之间的相关性降低,从而在方差公式中,继续导致整体方差仍是减少。
基本原理(过程)
主要思想就是对行(数据)和列(特征)进行随机化有放回地抽样,构建多棵分类树,再利用结合策略进行整合得到的结果。
- 原始训练集为N,对于每棵树而言,利用自助法(bootstrap sample方法)随机且有放回地从训练集中的抽取k个新的自助样本集,并由此构建k个分类树(预测结果f*b(x)),作为该树的训练集;而每次为被抽到的样本组成袋外样本(out-of-bag);
- 如果每个样本的特征维度为M,指定一个常数m<<M,在每一棵树的每个节点上随机选取m个特征子集,并从这m个特征中选择最优的;
- 每棵树都尽最大程度的生长,并且没有剪枝过程。
- 将生成的多棵分类树组成的随机森林用随机森林分类器对新数据进行判别和分类,分类结果按树分类器的投票决定。
袋外样本(OOB)说明:设样本容量为n,为了保证样本间的独立,对每个样本进行随机取样,每个样本被选取的概率为1/n,则不被选取的概率为1-1/n,当从n中又放回的取n个样本,取出的n个样本不相干且独立,其概率为:
当,,因此当样本容量足够的时候,约有0.3的数据没有参加训练,这部分数据为袋外数据。这部分未参加训练数据可以用来验证集,是对预测误差的无偏估计。
使用sklearn中随机森林对iris进行分类:
http://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
if __name__ == "__main__":
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
iris_feature = u'花萼长度', u'花萼宽度', u'花瓣长度', u'花瓣宽度'
path = './iris.data' # 数据文件路径
data = pd.read_csv(path, header=None)
x_prime = data[0:4]
y = pd.Categorical(data[4]).codes
x_prime_train, x_prime_test, y_train, y_test = train_test_split(x_prime, y, train_size=0.7, random_state=0)
feature_pairs = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]
plt.figure(figsize=(11, 8), facecolor='#FFFFFF')
for i, pair in enumerate(feature_pairs):
# 准备数据
x_train = x_prime_train[pair]
x_test = x_prime_test[pair]
# 决策树学习
model = RandomForestClassifier(n_estimators=100, criterion='entropy', max_depth=5, oob_score=True)
model.fit(x_train, y_train)
# 画图
N, M = 500, 500 # 横纵各采样多少个值
x1_min, x2_min = x_train.min()
x1_max, x2_max = x_train.max()
t1 = np.linspace(x1_min, x1_max, N)
t2 = np.linspace(x2_min, x2_max, M)
x1, x2 = np.meshgrid(t1, t2) # 生成网格采样点
x_show = np.stack((x1.flat, x2.flat), axis=1) # 测试点
# 训练集上的预测结果
y_train_pred = model.predict(x_train)
acc_train = accuracy_score(y_train, y_train_pred)
y_test_pred = model.predict(x_test)
acc_test = accuracy_score(y_test, y_test_pred)
print ('特征:', iris_feature[pair[0]], ' + ', iris_feature[pair[1]])
print ('OOB Score:', model.oob_score_)
print ('\t训练集准确率: %.4f%%' % (100*acc_train))
print ('\t测试集准确率: %.4f%%\n' % (100*acc_test))
cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])
y_hat = model.predict(x_show)
y_hat = y_hat.reshape(x1.shape)
plt.subplot(2, 3, i+1)
plt.contour(x1, x2, y_hat, colors='k', levels=[0, 1], antialiased=True, linestyles='--', linewidths=1.5)
plt.pcolormesh(x1, x2, y_hat, cmap=cm_light) # 预测值
plt.scatter(x_train[pair[0]], x_train[pair[1]], c=y_train, s=20, edgecolors='k', cmap=cm_dark, label=u'训练集')
plt.scatter(x_test[pair[0]], x_test[pair[1]], c=y_test, s=100, marker='*', edgecolors='k', cmap=cm_dark, label=u'测试集')
plt.xlabel(iris_feature[pair[0]], fontsize=14)
plt.ylabel(iris_feature[pair[1]], fontsize=14)
# plt.legend(loc='upper right', fancybox=True, framealpha=0.3)
plt.xlim(x1_min, x1_max)
plt.ylim(x2_min, x2_max)
plt.grid(b=True)
plt.suptitle(u'随机森林对鸢尾花数据两特征组合的分类结果', fontsize=18)
plt.tight_layout(1, rect=(0, 0, 1, 0.92)) # (left, bottom, right, top)
plt.show()