import pandas as pd
from sklearn import metrics
import numpy as np
import sklearn.ensemble as ensemble # ensemble learning: 集成学习
from sklearn.ensemble import RandomForestClassifier
df = pd.read_excel('regression.xlsx') # 宽带客户数据
# print(df.head()) # 输出数据预览
df.info()
# 首先将列名全部小写
df.rename(str.lower, axis='columns', inplace=True)
#现在查看因变量broadband分布情况,看是否存在不平衡
from collections import Counter
print('Broadband: ', Counter(df['broadband']))
## Broadband: Counter({0: 908, 1: 206}) 比较不平衡。
## 根据原理部分,可知随机森林是处理数据不平衡问题的利器
y = df['broadband']
X = df.iloc[:, 0:4]
future_labels = X.columns[0:]
print(future_labels)
# print(X)
#区分测试集与训练集
from sklearn.model_selection import train_test_split, GridSearchCV
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=0.4, random_state=12345)
#特征重要性
forest = RandomForestClassifier(n_estimators=200, random_state=1) # n_estimators:决策树个数-随机森林特有参数
forest.fit(X_train, y_train)
importances = forest.feature_importances_
print(len(importances))
importances
indices = np.argsort(importances)[::-1] # 取反后是从大到小
indices
'''
numpy.argsort(a, axis=-1, kind=’quicksort’, order=None) 功能:
将矩阵a在指定轴axis上排序,并返回排序后的下标
参数: a:输入矩阵, axis:需要排序的维度
返回值: 输出排序后的下标
'''
for i in range(X_train.shape[1]):
print("%2d) %-*s %f" % (i + 1, 30, future_labels[indices[i]], importances[indices[i]]))
# 随机森林建模一样是使用网格搜索,有关Python实现随机森林建模的详细参数解释可以看代码的注释
# # 直接使用交叉网格搜索来优化决策树模型,边训练边优化
# from sklearn.model_selection import GridSearchCV
# # 网格搜索的参数:正常决策树建模中的参数 - 评估指标,树的深度,
# ## 最小拆分的叶子样本数与树的深度
param_grid = {
'criterion': ['entropy', 'gini'],
'max_depth': [5, 6, 7, 8], # 深度:这里是森林中每棵决策树的深度
'n_estimators': [11, 13, 15], # 决策树个数-随机森林特有参数
'max_features': [0.3, 0.4, 0.5],
# 每棵决策树使用的变量占比-随机森林特有参数(结合原理)
'min_samples_split': [ 2, 3, 4, 5, 6, 8] # 叶子的最小拆分样本量
}
import sklearn.ensemble as ensemble # ensemble learning: 集成学习
rfc = ensemble.RandomForestClassifier()
#参数说明:
'''
sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, random_state=None, min_samples_split=2)
n_estimators:integer,optional(default = 10)森林里的树木数量120,200,300,500,800,1200
Criterion:string,可选(default =“gini”)分割特征的测量方法
max_depth:integer或None,可选(默认=无)树的最大深度 5,8,15,25,30
max_features="auto”,每个决策树的最大特征数量
If "auto", then max_features=sqrt(n_features).
If "sqrt", then max_features=sqrt(n_features)(same as "auto").
If "log2", then max_features=log2(n_features).
If None, then max_features=n_features.
bootstrap:boolean,optional(default = True)是否在构建树时使用放回抽样
min_samples_split:节点划分最少样本数
min_samples_leaf:叶子节点的最小样本数
超参数:n_estimator, max_depth, min_samples_split,min_samples_leaf 需要网格搜索调优
'''
rfc_cv = GridSearchCV(estimator=rfc, param_grid=param_grid,
scoring='roc_auc', cv=4)
# 传入模型,网格搜索的参数,评估指标,cv交叉验证的次数
# 这里也只是定义,还没有开始训练模型
rfc_cv.fit(X_train, y_train)
# 使用随机森林对测试集进行预测
test_est = rfc_cv.predict(X_test)
print('随机森林精确度...')
print(metrics.classification_report(test_est, y_test))
print('随机森林 AUC...')
fpr_test, tpr_test, th_test = metrics.roc_curve(test_est, y_test)
# 构造 roc 曲线
print('AUC = %.4f' %metrics.auc(fpr_test, tpr_test))
best = rfc_cv.best_params_
print(best)
# 搜索最优的参数
# 重新构建
param_grid = {
'criterion': ['entropy', 'gini'],
'max_depth': [5, 6, 7, 8], # 深度:这里是森林中每棵决策树的深度
'n_estimators': [11, 13, 15], # 决策树个数-随机森林特有参数
'max_features': [0.1, 0.2, 0.3, 0.4, 0.5],
# 每棵决策树使用的变量占比-随机森林特有参数(结合原理)
'min_samples_split': [2, 3, 4, 5, 6, 8] # 叶子的最小拆分样本量
}
rfc_cv = GridSearchCV(estimator=rfc, param_grid=param_grid,
scoring='roc_auc', cv=4)
rfc_cv.fit(X_train, y_train)
# 使用随机森林对测试集进行预测
test_est = rfc_cv.predict(X_test)
print('随机森林精确度...')
#随机森林的评价函数
print(metrics.classification_report(test_est, y_test))
print('随机森林 AUC...')
fpr_test, tpr_test, th_test = metrics.roc_curve(test_est, y_test)
# 构造 roc 曲线
print('AUC = %.4f' %metrics.auc(fpr_test, tpr_test))
#特征重要性
importances = rfc.feature_importances_
print(len(importances))
importances
##特征重要性排序
indices = np.argsort(rfc.feature_importances_)[::-1] # 取反后是从大到小
print("特征重要性排序:")
for i in range(X_train.shape[1]):
print("%2d) %-*s %f" % (i+1 , 30, future_labels[indices[i]], rfc.feature_importances_[indices[i]]))
# 绘制特征重要性条形图
import matplotlib.pyplot as plt
plt.title('Feature Importance')
plt.bar(range(X_train.shape[1]), rfc.feature_importances_[indices], align='center')
plt.xticks(range(X_train.shape[1]), future_labels[indices], rotation=90)
plt.xlim([-1, X_train.shape[1]])
plt.tight_layout()
plt.show()