案例背景
数据集“online_shoppers_intention”给出了网购人群是否将浏览行为转化为购买行为的相关数据,包括 10 个数值型属性与 8 个类别型属性,其中“revenue”可以作为分类的类标签。请将该数据集随机划分为训练集(80%)和测试集(20%)并进行分类。
数据预处理
导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
import os
from sklearn.metrics import confusion_matrix
from sklearn.metrics import classification_report
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve,roc_auc_score
import time
读取数据
os.chdir('E:\\input')
df=pd.read_csv('online_shoppers_intention.csv')
数据了解
df.columns
[‘Administrative’, ‘Administrative_Duration’, ‘Informational’, ‘Informational_Duration’, ‘ProductRelated’, ‘ProductRelated_Duration’, ‘BounceRates’, ‘ExitRates’, ‘PageValues’, ‘SpecialDay’, ‘Month’, ‘OperatingSystems’, ‘Browser’, ‘Region’, ‘TrafficType’, ‘VisitorType’, ‘Weekend’, ‘Revenue’]
df.dtypes
处理缺失值
查看缺失值情况
df.isna().sum()
每一列的数据都是完整的,没有缺失值。
划分训练集测试集
x=df.drop('Revenue',axis=1)
y=df['Revenue']
x=pd.get_dummies(x)
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.2,random_state=1)
Logistics 回归
要求
请建立带有 L1 惩罚项的 Logistics 回归模型对数据集进行分类,并利用基于 5 折交叉验证的格子搜索技术确定最优惩罚因子;在最优惩罚因子下,分别评价模型在训练集和测试集的预测效果(包括混肴矩阵、准确率、F1-Score、AUC 等)。
模型参数
LogisticRegression().get_params()
{‘C’: 1.0, ‘class_weight’: None, ‘dual’: False, ‘fit_intercept’: True, ‘intercept_scaling’: 1, ‘max_iter’: 100, ‘multi_class’: ‘warn’, ‘n_jobs’: None, ‘penalty’: ‘l2’, ‘random_state’: None, ‘solver’: ‘warn’, ‘tol’: 0.0001, ‘verbose’: 0, ‘warm_start’: False}
调参
logit=LogisticRegression(penalty='l1')
parameters={'C':np.arange(0.1,30,1)}
logit_cv=GridSearchCV(logit,param_grid=parameters,cv=5)
logit_cv.fit(x,y)
print(logit_cv.best_params_) #22.1
print(logit_cv.best_score_)
best_params_:{‘C’: 22.1} best_score:0.884
用最优参数训练模型
logit=LogisticRegression(penalty='l1',C=22.1)
logit.fit(x_train,y_train)
y_pre=logit.predict(x_test)
logit.score(x_train,y_train)
logit.score(x_test,y_test)
训练集精度:0.883 测试集精度:0.892
模型评价
混淆矩阵
classification_report(y_test,y_pre)
AUC
y_prob=logit.predict_proba(x_test)
fpr,tpr,_=roc_curve(y_test,y_prob[:,1])
plt.figure()
plt.plot(fpr,tpr,color='r',lw=2)
auc=roc_auc_score(y_test,y_prob[:,1])
print(auc)
auc=0.9058
平衡正负样例
要求
原始数据存在比较明显的类别不平衡问题,请采用样本复制法修正训练集的类别不平衡问题(也就是将训练集中 revenue=True 的样例复制多次,使得 revenue=True 与 revenue=False 的样例数相等);在修正后的训练集中重新训练模型,并比较类别不平衡修正前后模型预测效果的差异。
平衡样例
查看正负样例情况
df['Revenue'].value_counts()
2. 复制较少的样例并合并到数据框中
df_true=df[df['Revenue']==True]
df_balanced=pd.concat([df,df_true],axis=0)
df_balanced=pd.concat([df_balanced,df_true],axis=0)
df_balanced=pd.concat([df_balanced,df_true],axis=0)
df_balanced=pd.concat([df_balanced,df_true],axis=0)
#还差882个
df_true882=df[df['Revenue']==True].sample(882)
df_balanced=pd.concat([df_balanced,df_true882],axis=0)
查看平衡结果
df_balanced['Revenue'].value_counts()
用新训练集训练模型
x1=df_balanced.drop('Revenue',axis=1)
y1=df_balanced['Revenue']
x1=pd.get_dummies(x1)
x_train1,x_test1,y_train1,y_test1=train_test_split(x1,y1,test_size=0.2,random_state=1)
logit=LogisticRegression(penalty='l1',C=22.1)
logit.fit(x_train1,y_train1)
y_pre1=logit.predict(x_test1)
平衡样例结果
classification_report(y_test1,y_pre1)
平衡样例以后,True类的查准率和召回率都显著的提高。
模型预测效果差异
原始结果 样本类别为True的查准率和召回率都提高
SVM模型
要求
请建立 SVM 模型对数据集进行分类,并利用基于 5 折交叉验证的格子搜索技术调参;在最优算法参数下,分别评价模型在训练集和测试集的预测效果(包括混肴矩阵、准确率、F1-Score、AUC 等)。
模型参数
from sklearn.svm import SVC
SVC().get_params()
{‘C’: 1.0, ‘cache_size’: 200, ‘class_weight’: None, ‘coef0’: 0.0, ‘decision_function_shape’: ‘ovr’, ‘degree’: 3, ‘gamma’: ‘auto_deprecated’, ‘kernel’: ‘rbf’, ‘max_iter’: -1, ‘probability’: False, ‘random_state’: None, ‘shrinking’: True, ‘tol’: 0.001, ‘verbose’: False} 核技巧:使用一个变化将原空间的数据映射到新空间;然后在新空间里用线性分类的学习的方法从训练数据中学习分类模型。 SVM模型有两个非常重要的参数C与gamma。其中 C是惩罚系数,即对误差的宽容度。c越高,说明越不能容忍出现误差,容易过拟合。C越小,容易欠拟合。C过大或过小,泛化能力变差。 gamma是选择RBF函数作为kernel后,该函数自带的一个参数。隐含地决定了数据映射到新的特征空间后的分布,gamma越大,支持向量越少,gamma值越小,支持向量越多。支持向量的个数影响训练与预测的速度。
调参
svc=SVC(kernel='rbf')
parameters={'gamma':[0.0001,0.0005,0.001],'C':[0.1,0.2,0.5,0.6,0.7,0.8,0.9,1,2,3,4]}
svc_grid=GridSearchCV(svc,param_grid=parameters,cv=5)
svc_grid.fit(x,y)
svc_grid.cv_results_
print(svc_grid.best_params_)
print(svc_grid.best_score_)
best_params_:{‘C’: 0.7, ‘gamma’: 0.0001} best_score:0.8769
用最优参数训练模型
svc=SVC(kernel='rbf',C=0.7,gamma= 0.0001,probability=True)
#svc画auc时probability=True才能运行
svc.fit(x_train,y_train)
ypred=svc.predict(x_test)
yhat=svc.predict(x_train)
np.mean(y_train==yhat)
np.mean(y_test==ypred)
训练集精度:0.9943 测试集精度:0.857
模型评价
混淆矩阵
classification_report(y_test,ypred)
比logit回归查准率提高,但是召回率下降。 2. AUC
y_prob=svc.predict_proba(x_test)
fpr,tpr,_=roc_curve(y_test,y_prob[:,1])
plt.figure()
plt.plot(fpr,tpr,color='r',lw=2)
auc=roc_auc_score(y_test,y_prob[:,1])
print(auc)
AUC=0.808
决策树
要求
请建立决策树模型(max_depth=3)对数据集进行分类,并绘制相应的决策树;在此基础上利用基于 5 折交叉验证的格子搜索技术确定最优 max_depth,并分别评价模型在训练集和测试集的预测效果;利用产生的决策树确定属性重要性。
导入库
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import export_graphviz
from sklearn.externals.six import StringIO
import pydotplus
from IPython.core.display import Image
模型参数
DecisionTreeClassifier().get_params()
{‘class_weight’: None, ‘criterion’: ‘gini’, ‘max_depth’: None, ‘max_features’: None, ‘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, ‘presort’: False, ‘random_state’: None, ‘splitter’: ‘best’}
画出决策树
tree=DecisionTreeClassifier(max_depth=3)
tree.fit(x_train,y_train)
tree.score(x_test,y_test) #0.9
dot_data=StringIO()
export_graphviz(tree,
out_file=dot_data,
filled=True,
feature_names=x.columns,
class_names=y.unique().astype(str),
rounded=True,
special_characters=True,
)
graph=pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
graph.write_pdf("online_shop.pdf")
最优 max_depth
tree=DecisionTreeClassifier()
parameters={'max_depth':np.arange(1,20,1)}
tree_grid=GridSearchCV(tree,param_grid=parameters,cv=5)
tree_grid.fit(x,y)
print(tree_grid.best_params_)
print(tree_grid.best_score_)
best_params_:{‘max_depth’:5} best_score_:0.8953
在最优 max_depth的基础上评价模型效果
tree=DecisionTreeClassifier(max_depth=5)
tree.fit(x_train,y_train)
pre=tree.predict(x_test)
acc_train=tree.score(x_train,y_train)
acc_test=tree.score(x_test,y_test)
训练集精度:0.909 测试集精度:0.9018
属性重要性
stat=pd.DataFrame(columns=['importance','feature'])
stat['importance']=tree.feature_importances_
stat['feature']=x.columns
stat.sort_values(by='importance',ascending=False,inplace=True)
Bagging、AdaBoost 、随机森林
要求
以 Logistic 模型(L1 惩罚项、惩罚因子 C=1)与 max_depth=2 的决策树模型为基学习器,然后分别基于 Bagging、AdaBoost 以及随机森林构造集成学习(基学习器个数均为 100),请比较不同集成学习算法在训练集和测试集上的预测效果以及算法的执行时间。
模型训练
logit=LogisticRegression(penalty='l1',C=1)
tree=DecisionTreeClassifier(max_depth=2)
from sklearn.ensemble import BaggingClassifier
bag_train_=[]
bag_test_=[]
bag_time=[]
for i in [logit,tree]:
a=time.time()
model=BaggingClassifier(base_estimator=i,n_estimators=100)
model.fit(x_train,y_train)
bag_train = accuracy_score(y_train,model.predict(x_train))
bag_test = accuracy_score(y_test,model.predict(x_test))
print("Bagging train/test accuracies : %.3f/%.3f"%(bag_train,bag_test))
bag_train_.append(str(bag_train)[:5])
bag_test_.append(str(bag_test)[:5])
bag_time.append(time.time()-a)
from sklearn.ensemble import AdaBoostClassifier
ada_train_=[]
ada_test_=[]
ada_time=[]
for i in [logit,tree]:
a=time.time()
model=AdaBoostClassifier(base_estimator=i,n_estimators=100)
model.fit(x_train,y_train)
ada_train = accuracy_score(y_train,model.predict(x_train))
ada_test = accuracy_score(y_test,model.predict(x_test))
print("AdaBoost train/test accuracies : %.3f/%.3f"%(ada_train,ada_test))
ada_train_.append(str(ada_train)[:5])
ada_test_.append(str(ada_test)[:5])
ada_time.append(time.time()-a)
from sklearn.ensemble import RandomForestClassifier
stat={}
stat['bag_train']=bag_train_
stat['bag_test']=bag_test_
stat['bag_time']=bag_time
stat['ada_train']=ada_train
stat['ada_test']=ada_test_
stat['ada_time']=ada_time
stat=pd.DataFrame(stat,index=['logit','tree'])
stat.to_excel('online_shop_ensemble.xls')
对于bagging集成学习模型, 基学习器用Logistic或者决策树在训练集上和测试集上的表现效果都差不多 ,但时间上决策树作为基学习器的速度明显快于Logistic。 对于adaboost集成学习模型,基学习器用Logistic或者决策树在训练集上和测试集上的表现效果都差不多 ,时间上的差异比bagging更大,原因可能是因为bagging每个基学习期可以同时训练,而adaboost的基学习器只能一个一个的训练,所以时间上的差异会更明显。
from sklearn.ensemble import RandomForestClassifier
model=RandomForestClassifier(n_estimators=100)
model.get_params()
{‘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’: 100, ‘n_jobs’: None, ‘oob_score’: False, ‘random_state’: None, ‘verbose’: 0, ‘warm_start’: False}
随机深林的基学习器只能是决策树,没有改变基学习器的这个参数,
a=time.time()
model=RandomForestClassifier(n_estimators=100)
model.fit(x_train,y_train)
rf_train = accuracy_score(y_train,model.predict(x_train))
rf_test = accuracy_score(y_test,model.predict(x_test))
rf_time=time.time()-a
在训练集和测试你集上的精度都高于前两个模型,时间也是最短的。