随机森林算法&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)

其中,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()

在这里插入图片描述

随机森林实例

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")

报告具体形式:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
\vdots
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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', '原籍_ Taiwan', '原籍_ 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 原籍_ Taiwan 原籍_ 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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章