6.4 随机森林实战

首页 » 算法 » 正文

1. 鸢尾花数据集分类

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
np.random.seed(42)

# 特征
iris_feature = '花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'

if __name__ == '__main__':
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False

    try:
        data = pd.read_parquet('iris.parquet')
    except:
        data = pd.read_csv('DATA/iris.data')
        data.to_parquet('iris.parquet')

    X = data.iloc[:, :4]
    y = pd.Categorical(data.iloc[:, 4]).codes

    # 特征组合-共6个
    feature_iris = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]

    plt.figure(facecolor='#FFFFFF', figsize=(10, 9))
    for i, pair in enumerate(feature_iris):
        X_pair = X.iloc[:, pair]

        # 随机森林
        clf = RandomForestClassifier(n_estimators=200, criterion='entropy', max_depth=3)
        clf.fit(X_pair, y)

        # 预测
        y_hat = clf.predict(X_pair)
        # 统计结果
        c = np.count_nonzero(y_hat == y)
        print('特征 :', iris_feature[pair[0]], '+', iris_feature[pair[1]])
        print('/t预测正确的数目为:', c)
        print('/t预测准确率为:%.2f%%' % (100 * (float(c) / float(len(y)))))

        # 画决策边界图
        M, N = 50, 50
        x1_min, x1_max = min(X_pair.iloc[:, 0]) - 0.05, max(X_pair.iloc[:, 0]) + 0.05
        x2_min, x2_max = min(X_pair.iloc[:, 1]) - 0.05, max(X_pair.iloc[:, 1]) + 0.05
        t1 = np.linspace(x1_min, x1_max, M)
        t2 = np.linspace(x2_min, x2_max, N)
        # 生成网格点坐标矩阵
        x1, x2 = np.meshgrid(t1, t2)
        # 测试点
        x_test = np.stack((x1.flat, x2.flat), axis=1)
        y_test = clf.predict(x_test).reshape(x1.shape)
        cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
        cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])

        plt.subplot(2, 3, i + 1)
        plt.pcolormesh(x1,x2,y_test,shading='auto',cmap=cm_light)
        # 画样本点
        plt.scatter(X_pair.iloc[:, 0],X_pair.iloc[:,1],c=y,cmap=cm_dark,edgecolors='k')
        plt.xlabel(iris_feature[pair[0]],fontsize=14)
        plt.xlabel(iris_feature[pair[1]],fontsize=14)
        plt.xlim(x1_min,x1_max)
        plt.ylim(x2_min,x2_max)
        plt.grid(b=True)
    plt.tight_layout()
    plt.suptitle('随机森林对鸢尾花数据集的特征组合的分类结果',fontsize=18)
    plt.show()

运行结果

特征 : 花萼长度 + 花萼宽度
	预测正确的数目为: 122
	预测准确率为:81.88%
特征 : 花萼长度 + 花瓣长度
	预测正确的数目为: 142
	预测准确率为:95.30%
特征 : 花萼长度 + 花瓣宽度
	预测正确的数目为: 144
	预测准确率为:96.64%
特征 : 花萼宽度 + 花瓣长度
	预测正确的数目为: 142
	预测准确率为:95.30%
特征 : 花萼宽度 + 花瓣宽度
	预测正确的数目为: 143
	预测准确率为:95.97%
特征 : 花瓣长度 + 花瓣宽度
	预测正确的数目为: 144
	预测准确率为:96.64%

6.4 随机森林实战

使用袋外数据作为测试集

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestClassifier
np.random.seed(42)

# 特征
iris_feature = '花萼长度', '花萼宽度', '花瓣长度', '花瓣宽度'

if __name__ == '__main__':
    mpl.rcParams['font.sans-serif'] = ['SimHei']
    mpl.rcParams['axes.unicode_minus'] = False

    try:
        data = pd.read_parquet('iris.parquet')
    except:
        data = pd.read_csv('DATA/iris.data')
        data.to_parquet('iris.parquet')

    X = data.iloc[:, :4]
    y = pd.Categorical(data.iloc[:, 4]).codes

    # 特征组合-共6个
    feature_iris = [[0, 1], [0, 2], [0, 3], [1, 2], [1, 3], [2, 3]]

    plt.figure(facecolor='#FFFFFF', figsize=(10, 9))
    for i, pair in enumerate(feature_iris):
        X_pair = X.iloc[:, pair]

        # 随机森林
        clf = RandomForestClassifier(n_estimators=200, criterion='entropy', max_depth=3,oob_score=True)
        clf.fit(X_pair, y)
        print(clf.oob_score_,end='/t')
        # 预测
        y_hat = clf.predict(X_pair)
        # 统计结果
        c = np.count_nonzero(y_hat == y)
        print('特征 :', iris_feature[pair[0]], '+', iris_feature[pair[1]],end='/t')
        print('预测正确的数目为:', c,end='/t')
        print('预测准确率为:%.2f%%' % (100 * (float(c) / float(len(y)))))

        # 画决策边界图
        M, N = 50, 50
        x1_min, x1_max = min(X_pair.iloc[:, 0]) - 0.05, max(X_pair.iloc[:, 0]) + 0.05
        x2_min, x2_max = min(X_pair.iloc[:, 1]) - 0.05, max(X_pair.iloc[:, 1]) + 0.05
        t1 = np.linspace(x1_min, x1_max, M)
        t2 = np.linspace(x2_min, x2_max, N)
        # 生成网格点坐标矩阵
        x1, x2 = np.meshgrid(t1, t2)
        # 测试点
        x_test = np.stack((x1.flat, x2.flat), axis=1)
        y_test = clf.predict(x_test).reshape(x1.shape)
        cm_light = mpl.colors.ListedColormap(['#A0FFA0', '#FFA0A0', '#A0A0FF'])
        cm_dark = mpl.colors.ListedColormap(['g', 'r', 'b'])

        plt.subplot(2, 3, i + 1)
        plt.pcolormesh(x1,x2,y_test,shading='auto',cmap=cm_light)
        # 画样本点
        plt.scatter(X_pair.iloc[:, 0],X_pair.iloc[:,1],c=y,cmap=cm_dark,edgecolors='k')
        plt.xlabel(iris_feature[pair[0]],fontsize=14)
        plt.xlabel(iris_feature[pair[1]],fontsize=14)
        plt.xlim(x1_min,x1_max)
        plt.ylim(x2_min,x2_max)
        plt.grid(b=True)
    plt.tight_layout()
    plt.suptitle('随机森林对鸢尾花数据集的特征组合的分类结果',fontsize=18)
    plt.show()

0.7583892617449665	特征 : 花萼长度 + 花萼宽度	预测正确的数目为: 122	预测准确率为:81.88%
0.9261744966442953	特征 : 花萼长度 + 花瓣长度	预测正确的数目为: 142	预测准确率为:95.30%
0.9530201342281879	特征 : 花萼长度 + 花瓣宽度	预测正确的数目为: 144	预测准确率为:96.64%
0.9261744966442953	特征 : 花萼宽度 + 花瓣长度	预测正确的数目为: 142	预测准确率为:95.30%
0.9463087248322147	特征 : 花萼宽度 + 花瓣宽度	预测正确的数目为: 143	预测准确率为:95.97%
0.959731543624161	特征 : 花瓣长度 + 花瓣宽度	预测正确的数目为: 144	预测准确率为:96.64%

当max_depth=10时,出现过拟合

0.7046979865771812	特征 : 花萼长度 + 花萼宽度	预测正确的数目为: 138	预测准确率为:92.62%
0.9395973154362416	特征 : 花萼长度 + 花瓣长度	预测正确的数目为: 148	预测准确率为:99.33%
0.9261744966442953	特征 : 花萼长度 + 花瓣宽度	预测正确的数目为: 145	预测准确率为:97.32%
0.9395973154362416	特征 : 花萼宽度 + 花瓣长度	预测正确的数目为: 147	预测准确率为:98.66%
0.9194630872483222	特征 : 花萼宽度 + 花瓣宽度	预测正确的数目为: 146	预测准确率为:97.99%
0.9463087248322147	特征 : 花瓣长度 + 花瓣宽度	预测正确的数目为: 148	预测准确率为:99.33%

2.泰坦尼克号

数据集下载-提取码:foib
变量说明

survival : 是否活着 (0 = No; 1 = Yes)
pclass : Passenger Class (1 = 1st; 2 = 2nd; 3 = 3rd)
name :名字
sex : 性别
age :年龄
sibsp :配偶的人数
parch:父母子女人数
ticket:机票编号
fare :乘客票价
cabin:船舱
embarked:登船的港口(C =瑟堡; Q =皇后镇; S =南安普敦)
特别说明:
Pclass是社会经济地位(SES)状态
1st〜上层; 2nd〜中间; 3〜下
年龄以年为单位; 如果年龄小于一(1),则为分数

#!usr/bin/env python
# -*- coding:utf-8 -*-
"""
@author: admin
@file: 泰坦尼克号.py
@time: 2021/01/25
@desc:
"""
import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import csv
import xgboost as xgb


# 读取数据,并数据处理
def loaddata(filename, is_train):
    # 输出显示设置
    pd.set_option('display.width', 200)
    # 加载数据
    data = pd.read_csv(filename, header=0, index_col=0)
    # 查看数据前几行
    print(data.head())
    # 显示数据整体情况-数据快速统计摘要
    print('data.describe =/n', data.describe())
    # 将空格转换为空值
    data.replace(to_replace=' ', value=np.NAN, inplace=True)
    # 数据的空值统计
    print(data.isnull().sum())

    # 将类别数据转换成数值数据-字典映射
    data['Sex'] = data['Sex'].map({'female': 0, 'male': 1}).astype(int)

    # 补充船票价格缺失值
    # print(len(data['Fare'][data['Fare'] == 0])) # 15
    if len(data.Fare[data['Fare'] == 0]) > 0:
        fare = np.zeros(3)
        for i in range(0, 3):
            fare[i] = data[data.Pclass == i + 1]['Fare'].dropna().median()
        print(fare)

        # 填充对应等级船票价格
        for i in range(0, 3):
            data.loc[(data.Fare.isnull()) & (data.Pclass == i + 1), 'Fare'] = fare[i]

    # 年龄处理
    # 一种是常见的用均值代替缺失值
    # mean_age = data['Age'].dropna().mean()
    # data['Age'].fillna(mean_age, inplace=True)

    # 使用随机森林预测年龄
    if is_train:
        print('随机森林开始预测年龄')
        data_for_age = data[['Age', 'Survived', 'Fare', 'Parch', 'SibSp', 'Pclass']]
        age_exist = data_for_age.loc[(data.Age.notnull())]
        age_null = data_for_age.loc[(data.Age.isnull())]
        print(age_exist)
        print(age_null)
        x = age_exist.iloc[:, 1:]
        y = age_exist.iloc[:, 0]
        clf = RandomForestRegressor(n_estimators=1000)
        clf.fit(x, y)
        age_hat = clf.predict(age_null.values[:, 1:])
        # print(age_hat)
        #  把预测的数据填充到Age列的空的那些行中
        data.loc[(data.Age.isnull()), 'Age'] = age_hat
        print('随机森林预测缺失年龄:--over--')
    else:
        # 如果是测试数据,则没有Survived这一项,
        # 所以前面加一个is_train用来判段是测试数据还是训练数据
        print('随机森林预测缺失年龄2:--start--')
        data_for_age = data[['Age', 'Fare', 'Parch', 'SibSp', 'Pclass']]
        age_exist = data_for_age.loc[(data.Age.notnull())]  # 年龄不缺失的数据
        age_null = data_for_age.loc[(data.Age.isnull())]
        print(age_exist.isnull().sum())
        x = age_exist.values[:, 1:]
        y = age_exist.values[:, 0]
        rfr = RandomForestRegressor(n_estimators=1000)
        rfr.fit(x, y)
        age_hat = rfr.predict(age_null.values[:, 1:])
        # print age_hat
        data.loc[(data.Age.isnull()), 'Age'] = age_hat
        print('随机森林预测缺失年龄2:--over--')

    # 起始城市
    data.loc[(data.Embarked.isnull()), 'Embarked'] = 'S'  # 保留缺失出发城市
    # data['Embarked'] = data['Embarked'].map({'S': 0, 'C': 1, 'Q': 2, 'U': 0}).astype(int)
    # print(data['Embarked'])

    # 取出Embarked这一列的数据,pd.get_dummies表示获得出发城市的哑元,就是有什么值
    embarked_data = pd.get_dummies(data.Embarked)
    print('embarked_data = /n', embarked_data)
    # 把所有出发城市拿出来,加上后缀,形成三个特征
    embarked_data = embarked_data.rename(columns=lambda x: 'Embarked_' + str(x))
    # 数据和这个新的特征组合在一起,形成新的数据
    data = pd.concat([data, embarked_data], axis=1)
    print(data.describe())
    # 保存数据
    data.to_csv('New_Data.csv')

    # 把清洗后的数据提取出来作为x
    x = data[['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare', 'Embarked_C', 'Embarked_Q', 'Embarked_S']]
    y = None
    # 如果是训练集,提取y
    if 'Survived' in data:
        y = data['Survived']

    # 转成对应的矩阵
    x = np.array(x)
    y = np.array(y)

    # 平铺五行,让测试数据变得更多
    # 可以显著提高准确率
    x = np.tile(x, (5, 1))
    y = np.tile(y, (5,))
    if is_train:
        return x, y
    # print(data.index)
    return x, data.index


# 输出结果
def write_result(c, c_type):
    file_name = 'Titanic.test.csv'
    x, passenger_id = loaddata(file_name, False)

    if c_type == 3:
        x = xgb.DMatrix(x)
    y = c.predict(x)
    y[y > 0.5] = 1
    y[~(y > 0.5)] = 0

    predictions_file = open("Prediction_%d.csv" % c_type, "w")
    open_file_object = csv.writer(predictions_file)
    open_file_object.writerow(["PassengerId", "Survived"])
    open_file_object.writerows(zip(passenger_id, y))
    predictions_file.close()


if __name__ == "__main__":
    # 读取数据
    x, y = loaddata('Titanic.train.csv', True)
    # 数据集的分割,这里的test其实是验证数据
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25, random_state=1)

    # 逻辑回归
    lr = LogisticRegression(penalty='l2')
    lr.fit(x_train, y_train)
    y_hat = lr.predict(x_test)
    lr_acc = accuracy_score(y_test, y_hat)
    write_result(lr, 1)

    # 随机森林
    rfc = RandomForestClassifier(n_estimators=100)
    rfc.fit(x_train, y_train)
    y_hat = rfc.predict(x_test)
    rfc_acc = accuracy_score(y_test, y_hat)
    write_result(rfc, 2)

    # XGBoost
    data_train = xgb.DMatrix(x_train, label=y_train)
    data_test = xgb.DMatrix(x_test, label=y_test)
    watch_list = [(data_test, 'eval'), (data_train, 'train')]
    param = {'max_depth': 6, 'eta': 0.8, 'silent': 1, 'objective': 'binary:logistic'}
    # 'subsample': 1, 'alpha': 0, 'lambda': 0, 'min_child_weight': 1}
    bst = xgb.train(param, data_train, num_boost_round=100, evals=watch_list,
                    early_stopping_rounds=30, verbose_eval=True)
    y_hat = bst.predict(data_test, ntree_limit=bst.best_ntree_limit)
    write_result(bst, 3)
    y_hat[y_hat > 0.5] = 1
    y_hat[~(y_hat > 0.5)] = 0
    xgb_acc = accuracy_score(y_test, y_hat)

    print('Logistic回归:%.3f%%' % lr_acc)
    print('随机森林:%.3f%%' % rfc_acc)
    print('XGBoost:%.3f%%' % xgb_acc)

Logistic回归:0.797%
随机森林:0.983%
XGBoost:0.983%

未经允许不得转载:作者:1147-柳同学, 转载或复制请以 超链接形式 并注明出处 拜师资源博客
原文地址:《6.4 随机森林实战》 发布于2021-01-25

分享到:
赞(0) 打赏

评论 抢沙发

评论前必须登录!

  注册



长按图片转发给朋友

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏

Vieu3.3主题
专业打造轻量级个人企业风格博客主题!专注于前端开发,全站响应式布局自适应模板。

登录

忘记密码 ?

您也可以使用第三方帐号快捷登录

Q Q 登 录
微 博 登 录