随机森林是集成学习分(Ensemble Learning)中的一种。随机森林主要体现在‘随机’和‘森林’上。
随机森林是一种实现简单但是又很有效的方法,其随机性体现在样本选取的随机性上和特征选取的随机性上。
下面主要讨论一下样本有放回的抽取: 设有个样本,有放回的抽取次,样本在次采样中始终不被踩到的概率是,取极限就可以得到:
也可以画个图看看:
def plot_sample():
import matplotlib.pyplot as plt
m = [i for i in range(10, 1000)]
y = [pow(1 - 1 / i, i) for i in m]
plt.plot(m, y)
plt.show()
即有36.8%的样本没有放入训练中,这些样本可以抽取出来再作为‘包外估计’。
决策树部分的实现见:机器学习之决策树原理及python实现.
import numpy as np
import pandas as pd
from ml.decision_tree.basic_tree import MyDecisionTree
class MyRF(object):
def __init__(self, max_depth=3, criterion="entropy", n_estimator=5):
"""
随机森林的实现
:param max_depth: 每棵决策树的最大深度
:param criterion: 筛选特征用的策略:
'mse': 均方误差计算,用来实现回归树
'entropy': 用信息增益来筛选特征
'gini':用gini系数来筛选特征
:param n_estimator: 评估器个数,这儿也就是决策树的个数
"""
self.max_depth = max_depth
self.n_estimator = n_estimator
self.criterion = criterion
self.trees = []
def _sample(self, data_set, columns):
"""
随机森林的随机性在这儿体现,这儿仅仅是对样本做了随机性,也可以对特征进行随机抽取
:param data_set: 输入数据:待采样的数据
:param columns: 特征名称
:return: 采样后的结果
"""
n = len(data_set)
indexs = np.random.choice(n, n)
return data_set[indexs], columns
def fit(self, data_set, columns):
"""
训练模型
:param data_set: 输入的训练数据
:param columns: 特征名称
:return:
"""
# 随机森林的'森林'就在这儿体现,也就是由多棵决策树构成
for _ in range(self.n_estimator):
data_sample, columns_sample = self._sample(data_set, columns)
tree = MyDecisionTree(max_depth=self.max_depth, criterion=self.criterion)
tree.fit(data_sample, columns_sample)
self.trees.append(tree)
def predict(self, data_set, columns):
"""
通过投票机制选择出最优的结果
:param data_set: 输入数据
:param columns: 特征名称
:return: 结果列表
"""
# 对所有样本预测
result_list = []
# 随机森林中的每棵决策树都输出结果
for tree in self.trees:
result_list.append(tree.predict(data_set, columns))
# 下面的逻辑就是投票选择出最优的结果
# 如果是'mse'作为特征选择,即是回归树,输出结果为所有树结果的均值
final_result = []
result_list = np.array(result_list)
for i in range(len(result_list[0])):
single = result_list[:, i]
if self.criterion == 'mse':
final_result.append(np.mean(single))
else:
result_dict = {}
for s in single:
if s not in result_dict.keys():
result_dict[s] = 1
else:
result_dict[s] += 1
max_ = 0
r = None
for key, value in result_dict.items():
if value > max_:
r = key
final_result.append(r)
return final_result
def run_my_model():
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
iris_data = load_iris()
my = MyRF()
df = pd.DataFrame(iris_data['data'], columns=['f1', 'f2', 'f3', 'f4'])
df['label'] = iris_data['target']
train_data, test_data = train_test_split(df)
print('train:')
my.fit(train_data.values, train_data.columns)
print(my.trees)
test_result = my.predict(test_data.values, test_data.columns)
test = [int(y) for y in test_data['label'].values]
pred = [int(y) for y in test_result]
print('result:')
print('test: ', test)
print('pred: ', pred)
运行结果:
result:
test: [2, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 2, 0, 0, 1, 1, 2, 0, 0, 0, 2, 2, 1, 0, 1, 2, 2, 2, 0, 0, 1, 0, 2, 0, 0, 1, 1, 0]
pred: [2, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 2, 0, 0, 1, 1, 1, 0, 0, 0, 2, 2, 1, 0, 1, 2, 2, 2, 0, 0, 1, 0, 2, 0, 0, 1, 1, 0]
参考资料: 《机器学习》 周志华著