【机器学习案例三】网购人群购买意图分析(分类)

    xiaoxiao2022-07-05  325

    案例背景

    数据集“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

    在训练集和测试你集上的精度都高于前两个模型,时间也是最短的。

    最新回复(0)