1. 项目背景介绍
在这篇文章中,我们将使用 Python 搭建逻辑回归(Logistic Regression),随机森林(Random Forest),XGBoost,Bagging,KNN (K-Nearest Neighbors) ,神经网络(Neural Network)等6种机器学习/深度学习模型,对某个银行的营销活动数据集进行分类预测,尝试找出那些潜在客户。
银行通常会打电话给一些潜在客户来销售一些存款/投资产品,这些投资产品会使银行获得更多利润以及资金的灵活性,因此银行希望能定位那些会购买产品的客户,来进行精准营销提高利润。同时,如果银行能预测哪些客户不会购买产品,那么银行则可以不对这部分客户进行电话营销,从而减少营销成本。本文将使用 UCI Machine Learning Repository 提供的一家葡萄牙银行针对定期存款开展的营销活动数据集进行分类预测。
2. 数据集介绍 & 数据处理
该数据集包含 41,188 个观测值和 21 列(20 个输入变量和 1 个输出变量)。 输入变量有4类:
- (i) 银行客户数据:年龄、工作、学历、学历、信用违约、住房贷款、个人贷款;
- (ii) 与客户联系相关的数据:联系类型、联系的月份、联系的工作日、联系时长;
- (iii) 客户的其他数据:联系次数、距离上一次营销活动的天数、上一次营销活动的结果;
- (iv) 社会和经济数据:就业变化率、消费者价格指数、消费者信心指数、欧元银行同业拆借利率、就业人数。
输出变量 y 则是“客户是否购买了定期存款”。
该数据集不包含任何缺失值或空值,因此我们能够直接对数据进行初步分析。
通过检查,我们发现“工作”、“婚姻”、“教育”、“住房”和“贷款”中有一部分“未知”值,由于每个变量的“未知”数据比例不到5%,我们将“未知”值删除。
for col in return_categorical(df):
if 'unknown'in df[col].unique():
print("Proportion of'unknown'in " +"'"+ col+"':",df[col].value_counts()["unknown"]/41188*100)
此外,我们删除了“联系时长”(通话时长)和“联系次数”(在此活动期间执行的联系次数)这两个变量,因为如果我们试图对未来某一次营销活动进行预测,那么在活动开始之前这两个变量都是未知的。
接下来,我们计算变量之间的相关性。我们发现“previous”和“poutcome”变量之高度相关,由于前一个变量中的“0”其实就等于“poutcome”中的“不存在”,因此我们将其中一个变量删除。
plt.figure(figsize=(12,10))
corr= df.corr()
corr = corr[~(np.abs(corr) < 0.2)]
mask = np.triu(np.ones_like(corr, dtype=bool))
heatmap=sns.heatmap(corr,mask=mask, annot=True,cmap ='RdYlGn',linewidths=.5)
heatmap.set_title('Correlation Heatmap', fontdict={
'fontsize':18}, pad=20)
并且,我们将“教育水平”变量进行重新归类(因为原本的分类过多且过于细分)
最后,因为“pdays”变量(距离上一次联系客户的天数)的分布极其倾斜,我们将其删除。
def data_prepose(df):
df.drop(["duration","campaign","pdays","previous"],axis=1,inplace = True)
df = df[(df["job"]!= "unknown")&(df["marital"]!= "unknown")&(df["education"]!= "unknown")&(df["housing"]!= "unknown")&(df["loan"]!= "unknown")&(df["education"]!="illiterate")]
df["education"].replace({
"basic.4y":"primary","basic.6y":"primary","basic.9y":"primary",
"high.school":"secondary",
"professional.course":"tertiary","university.degree":"tertiary"},inplace = True)
return df
df['log_cpi'] = np.log10(df['cons.price.idx'])
df['log_euribor'] = np.log10(df['euribor3m'])
df['log_num'] = np.log10(df['nr.employed'])
df = df.drop(columns = ['cons.price.idx','euribor3m','nr.employed'])
# df = df.drop(["duration","campaign","pdays","previous"],axis=1,inplace = False)
p=sns.pairplot(df, hue = 'y')
初步检查处理完数据后,我们发现预测变量 y 中,“yes” 和 “no” 数据之间的比例非常不平衡(约为1:8)。 为了解决这个问题,我们使用 SMOTE 算法来平衡训练数据集。 在训练数据集-测试数据集的拆分过程中,我们选取25%的数据作为测试集。
from sklearn.model_selection import train_test_split
train, test = train_test_split(df, test_size = 0.25