【机器学习实战】用决策树模型预测银行客户是否会认购定期存款

一、数据来源和数据说明

1.数据来源

本次实战选取UCI机器学习库中的银行营销数据集。

银行营销 - UCI 机器学习存储库 --- Bank Marketing - UCI Machine Learning Repository

该数据与葡萄牙银行机构的直接营销活动有关。营销活动是基于电话的。通常,需要与同一客户进行多次联系,才能了解产品(银行定期存款)是否(“是”)被认购(“否”)。因此,通过预测客户是否会认购定期存款,可以帮助他们了解客户的财务规划,有助于制定更精准的产品推荐和服务策略。

2.数据说明

数据集的输入变量是20个特征量,分为数值变量(numeric)和分类(categorical)变量。输出变量为y,即客户是否(yes/no) 已经认购定期存款。

1.age:客户年龄

2.job:客户工作类型 

3.marital:客户婚姻状况

4.education:客户教育程度

5.default:客户信用卡是否有违约记录

6.housing:客户住房情况

7.loan:客户是否有其他贷款

8.contact:通信联系类型

9. month:最后一次联系客户的月份

10. day_of_week:最后一次联系客户的星期几

11. duration:最后一次联系的持续时间

12.campaign:营销活动中对客户的接触次数

13.pdays: 客户自上一次营销活动后过去了多少天,若为999,则表示客户从未接受过之前的接触

14.previous: 在这次营销活动前对该客户的总接触次数,包含了所有以往的尝试

15.poutcome: 上次营销活动的结果

16.emp.var.rate: 就业变动率,按季度显示的指标

17.cons.price.idx: 消费者价格指数,月度数据

18.cons.conf.idx: 消费者信心指数,同样按月度计算

19.euribor3m: 欧元三个月期银行间欧元拆借利率,每日更新的数据

20.nr.employed: 季度员工人数,反映劳动力市场的状况

21.y:表示客户是否已经订阅了定期存款服务

二、数据清洗

1.数据读入

读取bank-additional-full.csv文件,通过查看前几行简单了解数据集情况。

import pandas as pd
import numpy as np

data = pd.read_csv('bank-additional-full.csv')
df=pd.DataFrame(data)
df.head()

a90a09a46478493d964aafe74c226734.png

可以看到数据集里数据只有一列,每列变量全都合并到一起。在检查数据集的缺失值、重复值前,需要把这些变量分开,生成单独一列。

#将df数据集的表头和内容分开,然后分别进行分割处理
column_names = df.columns.tolist()
label=column_names[0].replace('"', '').split(";")
data_values = df.values

#对内容进行分割,将每行里面的数据分成多个特征的值
def sp(dataset):
    list_splits=[]
    for line in dataset:   
        list_line=line.tolist()
        splits =list_line[0].replace('"', '').split(";")
        list_splits.append(splits)
    return list_splits
df1=pd.DataFrame(sp(data_values), columns=label)
df1.head()

d25fd554710c4cffb0b0a9d2195935ac.png

 现在每个变量都是单独一列。可以通过info函数查看数据集的大小、类型等信息。

df1.info()

60918f2d136b44b19303b390f4797400.png

 在处理数据之前,我们知道变量之中是含有数值变量的,但是df1数据集展示的变量类型是不符合预期的。为了后续的计算,需要把变量类型改为正确的类型。

number_cols = ['age','duration','campaign', 'pdays','previous', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m','nr.employed']
df1[number_cols]=df1[number_cols].apply(pd.to_numeric)

 可以用info函数再次检查。

2.处理缺失值

接下来,检查数据集中是否存在缺失值或重复项,并根据情况进行处理。

# 检查缺失值
print(df1.isnull().sum())

0c4bad6d756a4eb9a160c5427ede3c33.png

 不能从中看出缺失值。但是是否存在,数值变量中用0作为缺失值以及分类变量中用“unknown”作为缺失值?可以进一步探索。

#查看数值变量的取值分布情况
print(df1.describe())

#查看分类变量的所有可能取值
categorical_cols = ['job', 'marital', 'education','default', 'housing','loan', 'contact', 'month', 'day_of_week', 'poutcome'] 

def unique_values(dataset):
    unique_values ={}
    for column in dataset.columns:
        unique_values[column] = dataset[column].unique()
    return  unique_values

unique_values(df1[categorical_cols])
category= pd.DataFrame({k: pd.Series(v) for k, v in unique_values(df1[categorical_cols]).items()})     
category

7c5da02fd0544a0aa26cb0822187094a.png

3cac9bc106bc4ce8b0eaaa964d39c262.png

 通过观察最大最小值以及该变量的可能情况,判断数值变量是否出现用0作为缺失值的情况。

例如假设年龄变量最小值为0,那就是异常情况。在本数据集中,数值变量duration(最后一次联系的持续时间)、pdays( 客户自上一次营销活动后过去了多少天)、previous(在这次营销活动前对该客户的总接触次数)的最小值都是0,但是根据变量意义,属于正常情况。所有数值变量没有缺失。

至于分类变量,我们可以从上图知道,大部分分类变量都含有“unknown”这一类型。将未知值替换成空值。

#将未知值替换成空值
df1[categorical_cols] = df1[categorical_cols].replace('unknown', np.nan) 
df1.isnull().sum()

96ed9bfa1abe46e8a2efc346f99fd0f4.png

 处理缺失值有两种常见方法1.删除缺失值;2.填补缺失值。

是否要删除缺失值?

可以查看删除后数据的分布情况以及一些数值变量的均值是否发生改变。

删除前:

afcb54cc06bd4b7bb9960cc3d51f8628.png

 删除后:
947bbd3e57a44ff5ad92f2a126cfe4df.png

 正样本和负样本的分布变化相差不大,但是也可以从中看出,无论是删除前还是删除后,样本类型都不平衡。

比较删除缺失值后,数值变量均值变化:

plt.figure(figsize=(5, 5))
((df1_dropped[number_cols].mean()-df1[number_cols].mean()) / df1[number_cols].mean()).plot(kind="bar")

ae1b96d3215e4a5685d8c5e21d3bcd58.png

previous 的均值上升了12%,emp.var.rate的均值下降了187%,这两个变量变化都很大,特别是emp.var.rate,直接删除含有缺失值的行可能会对预测结果有影响。所以我选择填充缺失值。

因为缺失值都出现在分类特征中,所以采用常用的分类变量填充法:计算出最常见的类别进行填充。

#众数填充缺失值
for col in categorical_cols:
    df1[col].fillna(df1[col].value_counts().index[0],inplace=True)

 也可以用删除缺失值的模型和填充缺失值的模型比较预测结果,从而选择更优的处理方法。在此不做比较。

3.处理重复行

删除重复行

df1.duplicated().sum()
df1 = df1.drop_duplicates()

三、数据可视化

import matplotlib.pyplot as plt  
import seaborn as sns

 1.基于总体分布的可视化

可以通过柱状图、直方图等,来对数据集中的变量分布有一个大致的了解。

图形不会全部展示。

#通过直方图查看数值变量分布情况
number_cols= ['age','duration','campaign', 'pdays','previous', 'emp.var.rate', 'cons.price.idx', 'cons.conf.idx', 'euribor3m','nr.employed']
df1[number_cols].hist(figsize=(15,15))

89a9f2ae4c31449d91be4d80bf459fd7.png

#通过柱状图查看分类变量
categorical_cols = ['job', 'marital', 'education','default', 'housing','loan', 'contact', 'month', 'day_of_week', 'poutcome']

#月份和星期按照时间顺序排序显示
months=[ "mar", "apr", "may", "jun", "jul", "aug", "sep", "oct", "nov", "dec"]
days=['mon','tue','wed','thu','fri']
df1['month'] = pd.Categorical(df1['month'], categories=months, ordered=True)
df1['day_of_week'] = pd.Categorical(df1['day_of_week'], categories=days, ordered=True)

#绘制柱状图
fig, axes = plt.subplots(5,2,figsize=(28,30))
axe = axes.ravel()
for i, c in enumerate(df1[categorical_cols].columns):
    sns.countplot(x=c, data=df1,ax=axe[i],palette="Set2")

38e88d2c473b48bcb1d273b63e5e0ecd.png

 颜色、图片大小等参数可以根据自己的喜好调整。不用局限于上面两种图像类型,可以尝试探索更多的表现形式,比如用饼图表示。选取几个分类变量展示。

fea1f28240be46ffbc5999374713466f.png

可以发现

  • 客户群众中,教育程度为illiterate(文盲)的客户为0。
  • 数据集中的所有客户,信用卡都没有违约记录。

2.基于分类变量的可视化

我们的目标是根据这些变量来预测客户是否会认购定期存款。所以可以通过对比目标变量的结果来展示不同取值之间的差异。

fig, axes = plt.subplots(2, 5, figsize=(27,12))
axe = axes.ravel()
for i, c in enumerate(df1[categorical_cols].columns):
    sns.countplot(x=c, hue="y", data=df1,alpha=0.5,ax=axe[i])
    axe[i].tick_params(axis="x", labelrotation=30)

4d90df0995a241129f40e94b4a35ce76.png

会认购定期存款的客户里(y="yes")

  • 职业大多数为admin(行政人员)、blue-collar(蓝领工人)、technician(技术人员)。
  • 婚姻状态最多的情况为married(已婚)。
  • 教育程度出现最多的是university.degree(大学学位),其次是high.school(高中学历)。
  • 大部分有其他贷款。
  • 移动电话接触的客户占大多数。
  • 这些认购定期存款的客户里,66%左右的客户没有参与上一次市场营销活动。

3.基于数值变量的可视化

fig,axes= plt.subplots(2, 5, figsize=(26,10))
axe = axes.ravel()
for i, c in enumerate(df1[number_cols].columns):
    axe[i].hist(df1[df1["y"]=="no"][c],10,alpha=0.3,label="no")
    axe[i].hist(df1[df1["y"]=="yes"][c],10,alpha=1,label="yes")
    axe[i].legend(loc="upper right")
    axe[i].set_title(c)

0def0f43571c40039780a99c82962510.png 会认购定期存款的客户里(y="yes")

  • 大多数客户年龄在30-50岁之间。
  • 最后一次联系的持续时间大多在1000秒以内。

  • 营销活动中对客户的接触次数大部分小于5次。

  • 在这次营销活动前对该客户的总接触次数绝大多数为0次。

四.特征工程

1.标准化归一化

是否需要对数据进行归一化?

本案例中,我选择决策树算法对分类结果进行预测,而决策树通常不需要对特征进行特别的归一化处理。这是因为决策树算法对于数值型特征有比较好的处理能力,它们可以直接基于特征的原始值进行划分,而不依赖于特征尺度的一致性。

2.特征编码

由于sklearn的模型只能处理数值变量,需要先将分类变量数值化,然后进行预测。

因为分类变量default所有取值都为"no",所以把该变量删掉,简化计算。

选择编码类型:

  • one-hot 编码:当某项数据属于某个特定类别时,对应的特征值为1,其他特征值都为0。
  • Bin-counting:使用该值下目标变量的条件概率。 

对少类别分类变量(类别<3)使用独热编码,多类别分类变量(类别>=3)使用Bin-counting编码。(类别多少算多,这个由自己设定。)

因为对于大量类别的分类变量,独热编码可能会生成大量的列,这导致在同样的样本大小下,区分特征变得更加困难。

from sklearn.preprocessing import OneHotEncoder

#独热编码
few_class_var= [ 'housing','loan', 'contact','poutcome'] 
df1=pd.get_dummies(df1,columns=few_class_var)

#Bin-Counting编码
multi_class_var=['job', 'marital', 'education', 'month', 'day_of_week']

def y_counting(dataset, bin_column):
    y_yes = pd.Series(dataset[dataset['y'] == 'yes'][bin_column].value_counts(),name="y_yes")
    y_no = pd.Series(dataset[dataset['y'] == "no"][bin_column].value_counts(),name="y_no")
    counts = pd.DataFrame([y_yes, y_no]).T.fillna('0')#然后将这两个Series合并成一个DataFrame,并填充所有缺失的计数为0
    counts['total'] = counts['y_yes'].astype('int64') + counts['y_no'].astype('int64')
    return counts

def bin_counting(counts):
    counts['N+'] = counts['y_yes'].astype('int64').divide(counts['total'].astype('int64'))
    counts['N-'] = counts['y_no'].astype('int64').divide(counts['total'].astype('int64'))
    counts['log_N+'] = counts['N+'].divide(counts['N-'])
    bin_counts = counts['log_N+']
    return counts, bin_counts

#用字典来替换掉原先值  
def rep(dataset, dict_rep):
    for i in dict_rep:
        dataset = dataset.replace(i, dict_rep[i])
    return dataset


#把每一列分箱结果计算出来后替换到相应的位置
def bin_counting_result(dataset):
    for bin_column in dataset[multi_class_var].columns:
        device_y = y_counting(dataset, bin_column)
        device_all, device_bin_counts = bin_counting(device_y)
        dataset[bin_column]=rep(dataset[bin_column],dict(device_bin_counts))
    return dataset
    

bin_counting_result(df1)
   

#把目标变量y的取值转化为对应的0,1
def y_transf(dataset):
    y_trf={"yes":1,"no":0}
    dataset["y"]=rep(dataset["y"],y_trf)
    return dataset

    
df1=y_transf(df1)

 查看编码结果

6483e3326090446d89b0eb6375518a44.png

五、模型构建

1.划分数据集

将数据集按照6:2:2划分为训练集、验证集和测试集。

#划分数据集
from sklearn.model_selection import train_test_split

def dataset_split(dataset,rs1,rs2):
    X=dataset.drop("y",axis=1)
    y=dataset["y"]
    X_train0, X_test,y_train0,y_test= train_test_split(X,y,test_size=0.2, random_state=rs1)
    X_train,X_val,y_train,y_val= train_test_split(X_train0,y_train0, test_size=0.25, random_state=rs2)
    return X_train,X_val, X_test,y_train,y_val,y_test

    
X_train,X_val, X_test,y_train,y_val,y_test=dataset_split(df1,34,76)

2.模型训练

from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score,roc_auc_score,roc_curve

# 创建决策树模型并训练
model = DecisionTreeClassifier(random_state=45)
model.fit(X_train,y_train)


# 使用验证集进行预测
y_pred = model.predict(X_val)
y_pred_proba = model.predict_proba(X_val)[:, 1]
 

 3.模型评估

计算空准确率
空准确率:指的是模型只预测为一类,也能达到的一个准确率。

6da7ca95fd6b4238887b3906f66fda5c.png
在本数据集中,准确率需要超过88.73%才有意义。

# 评估模型
accuracy = accuracy_score(y_val, y_pred)
precision = precision_score(y_val, y_pred)
recall = recall_score(y_val, y_pred)
f1 = f1_score(y_val, y_pred)
roc_auc = roc_auc_score(y_val, y_pred_proba)
 
print(f"Accuracy: {accuracy}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1 Score: {f1}")
print(f"ROC AUC Score: {roc_auc}")

 c45e518d417d4d7295797bf6acd87644.png

 混淆矩阵:用于二分类或多分类问题中的模型性能评估。

from sklearn.metrics import confusion_matrix

# 计算混淆矩阵
cm = confusion_matrix(y_val, y_pred)
print(cm)

#绘制混淆矩阵
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Predicted 0', 'Predicted 1'], yticklabels=['Actual 0', 'Actual 1'])
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

 5ccedd2e94d9414c89418d25e6e040d6.png

六、模型调优

1.特征选择(RFECV)

RFECV(交叉验证递归特征消除法)是一个集成在Python scikit-learn库中的特征选择方法。它的主要目标是在机器学习建模过程中自动确定最优特征子集,减少过拟合的风险,提高模型的泛化能力。  

使用这个方法需要我们选择一个基模型计算特征重要性。比如决策树、逻辑回归、随机森林等。

 具体使用哪个基模型可以尝试多个模型对比它们的score。在这里我选择随机森林。

#交叉验证递归特征消除法
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import RFECV
from sklearn.model_selection import cross_val_score 

#选择基模型 
rfc = RandomForestClassifier(random_state=42)

#使用RFECV进行特征选择。
selector = RFECV(rfc, step=1, cv=5)   
#表示使用随机森作为基模型,每次迭代移除一个特征,共进行5次交叉验证。

#使用训练数据拟合特征选择器
X_selector = selector.fit(X_train,y_train)

#将训练数据转换为经过特征选择后的数据
X_wrapper = X_selector.transform(X_train)  

#用选择后的特征子集进行交叉验证,并计算模型的平均性能得分。  
score =cross_val_score(rfc, X_wrapper,y_train, cv=5).mean()   

print(score)

1e6c3d552aea47539d199beb1eeb850d.png

 RFECV还有一个好处,就是可以自动确定最佳的特征数量。

查看该方法选择的变量(特征)。

index_n=-1
feature_list=[]
for i in X_selector.ranking_:
    index_n=index_n+1
    if i == 1:
        feature_list.append(X_train.columns[index_n])
        
#最终选择的特征数量
print("最优特征数 : %d" %X_selector.n_features_) 
print ('最优特征为:',feature_list)

0111845fc11a4ed4a181df4c6c850e10.png

 经过特征选择后训练数据只保留了20个变量。

2.参数调整

特征选择后,结合网格搜索来寻找决策树模型的最佳超参数。

决策树要调整的参数主要有三个。

  • max_depth(树的最大深度):
  • min_samples_split(分割内部节点所需的最小样本数)
  • min_samples_leaf(叶子节点上的最小样本数)

调整参数的过程学习了这篇文章机器学习超详细实践攻略(9):手把手带你使用决策树算法与调参_决策树调参方法-CSDN博客

第一步:在大范围内搜索max_depth的参数范围。 

from sklearn.model_selection import GridSearchCV

#在大范围内搜索max_depth的参数范围。
ScoreAll = []
for i in range(10,100,10):
    model2 = DecisionTreeClassifier(max_depth = i,random_state=45,class_weight = 'balanced')
    score = cross_val_score(model2,X_train[feature_list],y_train,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] 
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

1d49b4a9be3e46aa8ccd8e9a162e453c.png

第二步:进一步缩小max_depth这个参数的范围。

#进一步缩小max_depth这个参数的范围

ScoreAll = []
for i in range(1,15):
    model2 = DecisionTreeClassifier(max_depth = i,random_state =45)
    score = cross_val_score(model2,X_train[feature_list],y_train,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] 
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

47c717e2bf294a1a9d9822a3d33078fd.png 第三步:利用暂定的max_depth参数,观察得分随着min_samples_split的变化规律,从而确定min_samples_split参数的大概范围。

ScoreAll = []
for i in range(2,30):
    model2 = DecisionTreeClassifier(max_depth = 5,min_samples_split = i,random_state = 45)
    score = cross_val_score(model2,X_train[feature_list],y_train,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0] 
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

ba4df5ba6778421eb2d90accd4e1039a.png

 min_samples_split参数暂定的取值为2,也是该参数的初始默认值。

第四步:确定min_samples_leaf参数的大概范围。


ScoreAll = []
for i in range(1,40):
    model2 = DecisionTreeClassifier(min_samples_leaf = i,max_depth = 5,min_samples_split = 2,random_state = 45)
    score = cross_val_score(model2,X_train[feature_list],y_train,cv=10).mean()
    ScoreAll.append([i,score])
ScoreAll = np.array(ScoreAll)

max_score = np.where(ScoreAll==np.max(ScoreAll[:,1]))[0][0]
print("最优参数以及最高得分:",ScoreAll[max_score])  
plt.figure(figsize=[20,5])
plt.plot(ScoreAll[:,0],ScoreAll[:,1])
plt.show()

a346889425d84523be9337ed5645430e.png 根据我们前边的一系列操作,我们确定max_depth在5附近,min_samples_split在2附近,min_samples_leaf在20附近是最优参数,所以我们分别在这个附近利用网格搜索得到最优参数

第五步:结合网格搜索寻找max_depth、min_samples_leaf和min_samples_split最佳组合。

from sklearn.model_selection import GridSearchCV
#定义参数网格 
param_grid = {
    'max_depth':np.arange(1, 10),
    'min_samples_leaf':np.arange(2, 10),
    'min_samples_split':np.arange(15,25)}

model = DecisionTreeClassifier(random_state=45)
GS = GridSearchCV(model,param_grid,cv=10, scoring='accuracy')
GS.fit(X_train[feature_list],y_train)
print(GS.best_params_)
print(GS.best_score_)

a8730426c18b4a429c9637e509ed8d47.png

3.模型验证

使用验证集对该模型进行验证。

# 进行预测
y_pred_2 = GS.best_estimator_.predict(X_val[feature_list])
y_pred_proba_2 = GS.best_estimator_.predict_proba(X_val[feature_list])[:, 1]
 
# 评估模型
accuracy = accuracy_score(y_val, y_pred_2)
precision = precision_score(y_val, y_pred_2)
recall = recall_score(y_val, y_pred_2)
f1 = f1_score(y_val, y_pred_2)
roc_auc = roc_auc_score(y_val, y_pred_proba_2)
 
print(f"Accuracy: {accuracy}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1 Score: {f1}")
print(f"ROC AUC Score: {roc_auc}")

ca368b3ddcee4b6f930e69a3e195fa0e.png

将未优化的模型和优化后的模型进行对比

55d564e0cf56413db11bb3c5f69b90ae.png

优化后的模型准确率为91.2%大于空准确率88.73%,模型是有意义的。

七、模型结果

1.最终模型评估

用得出的最佳参数组合决策树模型,训练之前划分出的测试集。

# 进行预测
y_pred_3 = GS.best_estimator_.predict(X_test[feature_list])
y_pred_proba_3 = GS.best_estimator_.predict_proba(X_test[feature_list])[:, 1]
 
# 评估模型
accuracy = accuracy_score(y_test,y_pred_3)
precision = precision_score(y_test,y_pred_3)
recall = recall_score(y_test,y_pred_3)
f1 = f1_score(y_test,y_pred_3)
roc_auc = roc_auc_score(y_test,y_pred_proba_3)
 
print(f"Accuracy: {accuracy}")
print(f"Precision: {precision}")
print(f"Recall: {recall}")
print(f"F1 Score: {f1}")
print(f"ROC AUC Score: {roc_auc}")

13973cccd5f44791b40d58febac2a86f.png

混淆矩阵

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test, y_pred_3)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['Predicted 0', 'Predicted 1'], yticklabels=['Actual 0', 'Actual 1'])
plt.title('Confusion Matrix')
plt.xlabel('Predicted')
plt.ylabel('Actual')
plt.show()

89ef1e54249e493eadf9cecd2111205d.png

ROC 曲线 

from sklearn.metrics import roc_curve, auc

# 计算ROC曲线的真正率(TPR)和假正率(FPR)
fp, tp, thresholds = roc_curve(y_test,y_pred_proba_3)

# 计算AUC值
roc_auc = auc(fp, tp)

# 绘制ROC曲线
plt.figure()
lw = 2#线条宽度为2
plt.plot(fp, tp, color='darkorange', lw=lw, label='ROC curve (area = %0.2f)' % roc_auc)
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
plt.show()

ea035e4443614b499d7d2684a206c475.png

2.思考

除了以上几种优化还可以从其他方面进行改进:

1.本案例中,填充缺失值的方法选择常见类别填充,除此之外还可以选择使用一些机器学习算法预测缺失值进行填充;

2.特征编码方法的选择也会影响模型的构建,可以尝试其他编码方法后,选择最佳一种;

3.本数据集的正样本和负样本明显不均衡,下一个优化方向可以是对此进行改进;

4.调整RFECV方法的基模型或者是选择其他特征选择方法,得到新的特征子集,新的特征子集有可能带来更好的结果;

5.我为了熟悉对决策树的应用,只训练了决策树模型。本案例还可以选择其他更好的分类算法进行预测。


八、参考文章

【转】分类变量的encoding处理_效应编码-CSDN博客

【数据处理系列】深入理解递归特征消除法(RFE):基于Python的应用-CSDN博客

机器学习超详细实践攻略(9):手把手带你使用决策树算法与调参_决策树调参方法-CSDN博客

正在学习,如有错误,欢迎指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值