【数据挖掘】数据挖掘综合案例—银行精准营销
要求:
1、根据相关的信息预测通过电话推销,用户是否会在银行进行存款
2、数据bank.csv,约4520条数据,17个属性值 提示: 17个属性,分别是年龄,工作类型,婚姻状况,受教育背景,信用情况,房贷,个人贷款,联系电话是手机还是固定电话,最后联系月份,最后联系日,通话持续时间,本次活动中联系的次数,最后一次接触距离上一次接触的时间,以前的活动中联系的次数,上一次活动成功与否,是否会进行存款
代码实现:
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score, confusion_matrix, roc_auc_score
import matplotlib.pyplot as plt
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False #加载本地的数据
file_path = r'D:\课程\数据挖掘\实验八\实验8-bank.csv'
df = pd.read_csv(file_path, sep=';', quotechar='"')#进行数据预处理
df = df.replace('unknown', np.nan)
for col in ['default', 'housing', 'loan', 'y']:df[col] = df[col].map({'yes': 1, 'no': 0, 'unknown': np.nan})#处理缺失值
mode_values = {'job': df['job'].mode()[0] if not df['job'].mode().empty else 'unknown','education': df['education'].mode()[0] if not df['education'].mode().empty else 'unknown','contact': df['contact'].mode()[0] if not df['contact'].mode().empty else 'unknown','poutcome': df['poutcome'].mode()[0] if not df['poutcome'].mode().empty else 'unknown'
}
df = df.fillna(mode_values)
#标识特征
df['pdays'] = df['pdays'].replace(-1, 999) #未联系过的特殊标记
df['contacted_before'] = np.where(df['pdays'] != 999, 1, 0) #是否曾经联系过#检查并处理目标变量中的NaN
print(f"目标变量y中的缺失值数量: {df['y'].isna().sum()}")
df = df.dropna(subset=['y']) #特征编码
categorical_features = ['job', 'marital', 'education', 'contact', 'month', 'poutcome']
numeric_features = ['age', 'balance', 'day', 'duration', 'campaign', 'pdays', 'previous']preprocessor = ColumnTransformer(transformers=[('num', StandardScaler(), numeric_features),('cat', OneHotEncoder(handle_unknown='ignore', sparse_output=False), categorical_features)])X = df.drop('y', axis=1)
y = df['y']#进行数据集划分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y
)#模型训练
rf = RandomForestClassifier(n_estimators=100, max_depth=8,min_samples_split=5,class_weight='balanced',random_state=42
)X_train_processed = preprocessor.fit_transform(X_train)
rf.fit(X_train_processed, y_train)#模型评估
X_test_processed = preprocessor.transform(X_test)
y_pred = rf.predict(X_test_processed)
y_proba = rf.predict_proba(X_test_processed)[:, 1]print(f"准确率: {accuracy_score(y_test, y_pred):.4f}")
print(f"F1分数: {f1_score(y_test, y_pred):.4f}")
print(f"AUC: {roc_auc_score(y_test, y_proba):.4f}")#混淆矩阵可视化
cm = confusion_matrix(y_test, y_pred)
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', xticklabels=['不会存款', '会存款'], yticklabels=['不会存款', '会存款'])
plt.xlabel('预测标签')
plt.ylabel('真实标签')
plt.title('混淆矩阵')
plt.show()#获取特征名称
cat_encoder = preprocessor.named_transformers_['cat']
cat_features = cat_encoder.get_feature_names_out(categorical_features)
all_features = np.concatenate([numeric_features, cat_features])#绘制特征重要性
importances = rf.feature_importances_
indices = np.argsort(importances)[::-1][:15]plt.figure(figsize=(12, 8))
plt.title("Top 15 特征重要性")
plt.barh(range(15), importances[indices][::-1], align='center')
plt.yticks(range(15), all_features[indices][::-1])
plt.xlabel('重要性')
plt.tight_layout()
plt.show()#精准营销建议
def marketing_recommendation(model, preprocessor, customer_data):processed_data = preprocessor.transform(customer_data)proba = model.predict_proba(processed_data)[0][1]return proba > 0.4
#客户数据
sample_customer = pd.DataFrame({'age': [42],'job': ['management'],'marital': ['married'],'education': ['tertiary'],'default': [0],'balance': [1500],'housing': [1],'loan': [0],'contact': ['cellular'],'day': [15],'month': ['may'],'duration': [300],'campaign': [2],'pdays': [100],'previous': [3],'poutcome': ['success']
})if marketing_recommendation(rf, preprocessor, sample_customer):print("推荐对该客户进行存款营销")
else:print("不建议对该客户进行存款营销")
运行结果:
混淆矩阵:
Top15特征重要性
控制台输出,推荐对该客户进行存款营销