欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

随机森林算法&python应用

程序员文章站 2022-07-14 14:13:57
...

随机森林算法

决策树算法可以很容易的将模型进行可视化,同时它是将每个样本特征进行单独处理,故而不需要的对数据进行转换。但是决策树会很容易出现过拟合,为了避免过拟合现象,可以使用集合学习的方法,像:随机森林算法。

随机森林又被称为:随机决策森林,是一种集合学习方法(参见下图),既可以用于分类,也可以用作回归。分类:在森林内部会进行“投票”,每棵树预测出数据类别的概率,随机森林会把这些概率值求平均,让后将样本放入概率最大的分类中。回归:随机森林会把所有决策树预测的值取平均数。
随机森林算法&python应用
随机森林算法之所以可以解决过拟合问题:因为随机森林是把不同的几棵决策树打包到一起,每棵树的参数都不相同,然后我们把每棵树预测的结果取平均值,这样不仅可以保留决策树工作的高效,又可以降低过拟合的风险。

随机森林算法可以大致分为两个步骤:第一,创建决策树,第二,根据第一步中决策树的分类器结果做出预测。随机森林算法与决策树算法之间的区别是:前者查找根节点和分割特征节点的过程是随机进行的。

  • 构建过程:

(1)数据的随机选取,若训练集中有NN个样本,又放回的随机抽取nn个。这nn个样本就作为生成该决策树的训练集。

(2)特征的随机选取,对于每个样本,如果有MM个输入变量(特征),指定一个常数mm,然后随机的从MM中选取mm个最优的分裂特征开分裂节点。

  • 预测过程:

(1)使用每一个随机创建的决策树的规则来测试特征的结果(标签)

(2)计算每个预测目标的票数

(3)获得票数最高的结果将作为随机森林算法的最终预测。

:随机森林算法也不要求对数据进行预处理,同时支持并行处理。此外,随机森林生成每一棵决策树的方法是随机的,则不同的random_state参数会导致模型完全不同,所以为了模型的相对稳定,要固化random_state这个参数的值。但是!!!随机森林,对于高维数据集、稀疏数据集来说,很不适应。

构建决策树

author by xiaoyao

# 导入libraries
import numpy as np
# 导入画图工具
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
# 导入tree模型和数据集加载工具
from sklearn import datasets
from sklearn.ensemble import RandomForestClassifier
# 导入数据集拆分工具
from sklearn.model_selection import train_test_split
wine = datasets.load_wine()
# 这里只选取数据集的前两个特征
X = wine.data[:,:2]
y = wine.target
# 将数据集划分为训练集个测试集
X_train, X_test, y_train, y_test = train_test_split(X, y)

# 忽略警告
import warnings
warnings.filterwarnings("ignore")
# 暂时设定随机森林中有6棵树
forest = RandomForestClassifier(n_estimators=6, random_state=3)
# 使用模型拟合数据
forest.fit(X_train, y_train)
RandomForestClassifier(bootstrap=True, class_weight=None, criterion='gini',
                       max_depth=None, max_features='auto', max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=6,
                       n_jobs=None, oob_score=False, random_state=3, verbose=0,
                       warm_start=False)

随机森林算法&python应用

其中,bootstrap参数:代表的是bootstrap sample。也就是又放回抽样,bootstrap生成的数据集和原始数据集在数据量上是一致的,但由于进行了重复采样,因此其中有一些数据点会丢失。通过重新生成数据集,可以让随机森林中的每一棵决策树在构建的时候,彼此之间有差异。max_features的取值越高,随机森林中的每一棵树就会"越相似",从而因为有更多的不同特征值可以取,也就会更容易取拟合数据。

# 定义图像中分区的颜色和散点的颜色
cmap_light = ListedColormap(["#FFAAAA", "#AAFFAA", "#AAAAFF"])
cmap_bold = ListedColormap(["#FF0000", "#00FF00", "#0000FF"])

# 分别用样本的两个特征值创建图像和横轴、纵轴
x_min, x_max = X_train[:,0].min() - 1, X_train[:,0].max() + 1
y_min, y_max = X_train[:,1].min() - 1, X_train[:,1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, .02),np.arange(y_min, y_max, .02))
z = forest.predict(np.c_[xx.ravel(), yy.ravel()])
# 给每个分类中的样本分配不同的颜色
z = z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, z, cmap=cmap_light)

# 使用散点图进行表示
plt.scatter(X[:,0], X[:,1], c=y, cmap=cmap_bold, edgecolor="k",s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("Classifier:(max_depth = 3)")
plt.show()

随机森林算法&python应用

随机森林实例

author by xiaoyao

# 导入相应的libraries
import pandas as pd
from sklearn import tree
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
# 忽略警告
import warnings
warnings.filterwarnings("ignore")
# 导入数据集,数据集下载地址:http://archive.ics.uci.edu/ml/machine-learning-databases/adult/
# 原始数据无列名(属性名)
data = pd.read_csv("./datasets/adult.csv", header=None,index_col=False,
                  names=['年龄','单位性质','权重','学历','受教育时常',
                         '婚姻状况','职业','家庭情况','种族','性别',
                         '资产所得','资产损失','周工作时长','原籍','收入'])
data.head()
年龄 单位性质 权重 学历 受教育时常 婚姻状况 职业 家庭情况 种族 性别 资产所得 资产损失 周工作时长 原籍 收入
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K
import pandas_profiling
rep = pandas_profiling.ProfileReport(data)
# 将生成的数据分析报告保存至本地html文件
rep.to_file("./rep.html")

报告具体形式:
随机森林算法&python应用
随机森林算法&python应用
随机森林算法&python应用
\vdots
随机森林算法&python应用
随机森林算法&python应用
随机森林算法&python应用

data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 32561 entries, 0 to 32560
Data columns (total 15 columns):
年龄       32561 non-null int64
单位性质     32561 non-null object
权重       32561 non-null int64
学历       32561 non-null object
受教育时常    32561 non-null int64
婚姻状况     32561 non-null object
职业       32561 non-null object
家庭情况     32561 non-null object
种族       32561 non-null object
性别       32561 non-null object
资产所得     32561 non-null int64
资产损失     32561 non-null int64
周工作时长    32561 non-null int64
原籍       32561 non-null object
收入       32561 non-null object
dtypes: int64(6), object(9)
memory usage: 3.7+ MB

可以看到在数据集中,很多的列取值都是字符串,不方便进行建模。我将其处理为:整型数值,操作如下:

# 使用get_dummies将文本数据转化为数值
data_dummies = pd.get_dummies(data)
# 分别输出原始特征和处理之后的特征
print("原始特征:",(data.columns))
print("处理后的特征:",(data_dummies.columns))
原始特征: Index(['年龄', '单位性质', '权重', '学历', '受教育时常', '婚姻状况', '职业', '家庭情况', '种族', '性别',
       '资产所得', '资产损失', '周工作时长', '原籍', '收入'],
      dtype='object')
处理后的特征: Index(['年龄', '权重', '受教育时常', '资产所得', '资产损失', '周工作时长', '单位性质_ ?',
       '单位性质_ Federal-gov', '单位性质_ Local-gov', '单位性质_ Never-worked',
       ...
       '原籍_ Scotland', '原籍_ South', '原籍_ *', '原籍_ Thailand',
       '原籍_ Trinadad&Tobago', '原籍_ United-States', '原籍_ Vietnam',
       '原籍_ Yugoslavia', '收入_ <=50K', '收入_ >50K'],
      dtype='object', length=110)
data.head()
年龄 单位性质 权重 学历 受教育时常 婚姻状况 职业 家庭情况 种族 性别 资产所得 资产损失 周工作时长 原籍 收入
0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K
1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K
2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K
3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K
4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K
data_dummies.head()
年龄 权重 受教育时常 资产所得 资产损失 周工作时长 单位性质_ ? 单位性质_ Federal-gov 单位性质_ Local-gov 单位性质_ Never-worked ... 原籍_ Scotland 原籍_ South 原籍_ * 原籍_ Thailand 原籍_ Trinadad&Tobago 原籍_ United-States 原籍_ Vietnam 原籍_ Yugoslavia 收入_ <=50K 收入_ >50K
0 39 77516 13 2174 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
1 50 83311 13 0 0 13 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
2 38 215646 9 0 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
3 53 234721 7 0 0 40 0 0 0 0 ... 0 0 0 0 0 1 0 0 1 0
4 28 338409 13 0 0 40 0 0 0 0 ... 0 0 0 0 0 0 0 0 1 0

5 rows × 110 columns

将各列分配给特征向量XX和分类标签yy

# 定义数据集的特征值
features = data_dummies.loc[:, '年龄':'原籍_ Yugoslavia']
X = features.values
# 将收入大于50k作为预测的目标
y = data_dummies['收入_ >50K'].values
# 输出特征与标签的形态
print("特征形态:{} 标签形态:{}".format(X.shape, y.shape))
特征形态:(32561, 108) 标签形态:(32561,)
# 先使用决策数模型进行预测
# 将数据拆分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state = 1)
# 设最大深度为5
dt_tree =tree.DecisionTreeClassifier(max_depth=5)
dt_tree.fit(X_train, y_train)
dt_tree.score(X_test, y_test)
0.8550546615894853
# 使用交叉验证,平均水平依然接近上面的
from sklearn.model_selection import cross_val_score
scores = cross_val_score(dt_tree, X, y, cv=20,scoring='accuracy')
print(scores)
print(scores.mean())
[0.83977901 0.84275184 0.8482801  0.84336609 0.85012285 0.8531941
 0.82555283 0.84398034 0.8458231  0.85380835 0.85995086 0.83783784
 0.85257985 0.84889435 0.86425061 0.85257985 0.8507371  0.86302211
 0.84766585 0.84643735]
0.8485307193180122
# 使用随机森林算法
forest = RandomForestClassifier(n_estimators = 5,random_state=0)
forest.fit(X_train, y_train)
forest.score(X_test, y_test)
0.8431396634320109
# 使用交叉验证
scores = cross_val_score(forest, X, y,cv=5,scoring='accuracy')
print(scores)
print(scores.mean())
[0.82320442 0.83968059 0.83230958 0.84336609 0.82862408 0.85012285
 0.82678133 0.8458231  0.84336609 0.83108108 0.83722359 0.83046683
 0.84336609 0.83599509 0.8482801  0.84213759 0.84766585 0.85257985
 0.83169533 0.84459459]
0.8389182062524604