《机器学习》客户流失判断-python实现

客户流失判断

  • 题目
    • 赛题描述
    • 数据说明
    • 赛题来源-DataCastle
  • 问题描述
  • 解题思路
  • Python实现
    • 读取数据并初步了解
      • 导入宏包
      • 读取数据
      • 查看数据类型
      • 检查缺失值
      • 描述性统计分析
    • 可视化分析
      • 用户流失分析
      • 特征分析
      • 任期年数与客户流失的关系:
      • 服务类属性分析
      • 特征相关性分析
    • 数据预处理
      • 类别编码转换
      • 划分训练数据与测试数据
      • 归一化处理
    • 模型建立
      • 逻辑回归
      • 支持向量机(SVM)
      • K近邻(KNN)
      • XGBoost-贝叶斯搜索超参数调优
      • 随机森林(Random Forest)
      • AdaBoost
      • MLP
      • 朴素贝叶斯分类器
      • LightGBM
      • MLP-pytorch版
      • XGBoost-MLP-随机森林加权组合-效果最优

题目

赛题描述

给定企业客户信息,建立分类模型,判断企业客户是否会流失。

数据说明

数据主要包括企业客户样本信息。 数据分为训练数据和测试数据,分别保存在train.csv和test_noLabel.csv两个文件中。 字段说明如下:
(1)ID:编号
(2)Contract:是否有合同
(3)Dependents:是否有家属
(4)DeviceProtection:是否有设备保护
(5)InternetService:是否有互联网服务
(6)MonthlyCharges:月度费用
(7)MultipleLines:是否有多条线路
(8)Partner:是否有配偶
(9)PaymentMethod:付款方式
(10)PhoneService:是否有电话服务
(11)SeniorCitizen:是否为老年人
(12)TVProgram:是否有电视节目
(15)TotalCharges:总费用
(16)gender:用户性别
(17)tenure:任期年数
(18)Churn:用户是否流失
如遇数据下载打开乱码问题: 不要用excel打开,用notepad++或者vs code。文件格式是通用的编码方式utf-8。

赛题来源-DataCastle

https://challenge.datacastle.cn/v3/cmptDetail.html?id=356
在这里插入图片描述
数据可在网站上下载

问题描述

通过题目给定的企业客户信息,选择适当的分类算法,建立多个分类模型,使用准确率指标评估模型性能,准确率越高,说明正确预测出企业客户流失情况的效果越好,以此找到最优的分类模型用于预测企业客户是否会流失。通过模型可以帮助企业更好地了解客户流失的趋势,从而采取相应的措施来维护客户关系。

解题思路

在这里插入图片描述
数据预处理:

1.检查处理缺失值、重复值、异常值
2.标签编码转化

数据可视化:
3. 各标签对流失率的影响
4. 相关性热力图绘制

建立分类模型与对比模型:
朴素贝叶斯、AdaBoost、逻辑回归、KNN、SVM、
随机森林、XGBoost、MLP、 LightGBM、GBDT、
随机森林-MLP-XGBoost组合模型

使用随机搜索及贝叶斯优化 进行超参数调优

Python实现

读取数据并初步了解

导入宏包

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from scipy.special import boxcox1p
import missingno as msno
import warnings
warnings.filterwarnings("ignore")
%matplotlib inline

读取数据

train = pd.read_csv('train.csv')
test = pd.read_csv('test_noLabel.csv')
train.shape,test.shape
train.head()
test.head()

在这里插入图片描述

查看数据类型

train.info()
test.info()

在这里插入图片描述

检查缺失值

使用 pd.isnull(train).sum() 查看缺失值情况。并通过 msno.matrix() 绘制缺失值热力图,从结果可以看出数据集不存在缺失值

# 检查训练集是否有缺失值并绘制缺失值分布的图,无缺失值
pd.isnull(train).sum()msno.matrix(train, labels=True)

在这里插入图片描述

# 检查测试集是否有缺失值并绘制缺失值分布的图   ,训练集和测试集都没有缺失值,不需要填充。
pd.isnull(test).sum()
msno.matrix(test, labels=True)

在这里插入图片描述

描述性统计分析

使用 train.describe().T 对数值型列进行描述性统计分析,包括平均值、标准差、最大值、最小值等。

train.describe()
test.describe()

在这里插入图片描述
这份数据描述统计结果提供了关于客户信息的多个方面的信息。其中包括每月费用的平均值约为66.82,老年人占比约为11.86%,客户的平均任期约为 28.78个月,以及总费用的平均值约为2084.48。这些数据能够描绘出客户的消费情况、老年人比例以及服务使用时长等信息,另外提供查看最大最小 值,可以初步确定数据无逻辑异常。

可视化分析

用户流失分析

使用 train['Label'].value_counts() 统计不同标签(流失与否)的数量。并绘制了用户流失比例的扇形图和不同特征对客户流失率的影响的柱状 图。通过结果可以看出数据集中有62.75%用户没流失,337.25%客户流失,数据集是不均衡。

#流失用户数量和占比
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = 4, 4
plt.pie(train['Label'].value_counts(), labels=train['Label'].value_counts().index, autopct='%1.2f%%', explode=(0.1, 0))
plt.title('Label (Yes=1/No=0) Ratio')
plt.show()

在这里插入图片描述

特征分析

#用户属性柱状图
import seaborn as sns
import matplotlib.pyplot as plt# 设置中文字体为 SimHei
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 设置图表尺寸
plt.rcParams['figure.figsize'] = (12, 10)# 绘制性别对客户流失率的影响
plt.subplot(2, 2, 1)
sns.countplot(x='gender', hue='Label', data=train)
plt.title('性别对客户流失率的影响')# 绘制老人对客户流失率的影响
plt.subplot(2, 2, 2)
sns.countplot(x='SeniorCitizen', hue='Label', data=train)
plt.title('老人对客户流失率的影响')# 绘制配偶对客户流失率的影响
plt.subplot(2, 2, 3)
sns.countplot(x='Partner', hue='Label', data=train)
plt.title('配偶对客户流失率的影响')# 绘制亲属对客户流失率的影响
plt.subplot(2, 2, 4)
sns.countplot(x='Dependents', hue='Label', data=train)
plt.title('亲属对客户流失率的影响')# 显示图表
plt.show()

在这里插入图片描述
对于性别、老人、配偶、亲属等特征,使用 sns.countplot() 绘制柱状图,分析其对客户流失率的影响。
可以得出下面结论:
1. 性别对用户流失影响不大;
2. 年轻用户的流失率显著高于年长用户;
3. 有伴侣的用户流失比例低于无伴侣用户;
4. 用户中有家属的数量较少;
5. 有家属的用户流失比例低于无家属用户。

任期年数与客户流失的关系:

使用 sns.kdeplot() 绘制核密度估计图,在网时长越久,流失率越低,符合一般经验;在网时间达到三个月,流失率小于在网率,证明用户心理稳定 期一般是三个月。

import seaborn as sns
import matplotlib.pyplot as plt# 设置中文字体为 SimHei
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# Kernel density estimaton核密度估计
def kdeplot(feature, xlabel, df):plt.figure(figsize=(9, 4))plt.title("{0}的核密度估计".format(xlabel))  # 中文标题ax0 = sns.kdeplot(df[df['Label'] == 'No'][feature].dropna(), color='navy', label='流失:否', shade='True')ax1 = sns.kdeplot(df[df['Label'] == 'Yes'][feature].dropna(), color='orange', label='流失:是', shade='True')plt.xlabel(xlabel)plt.legend(fontsize=10)# 调用函数绘制核密度图
kdeplot('tenure', '任期年数',train )
plt.show()# 在网时长越久,流失率越低,符合一般经验;
# 在网时间达到三个月,流失率小于在网率,证明用户心理稳定期一般是三个月。# 这个核密度估计图展示了用户任期年数 (`tenure`) 与客户流失 (`Label`) 的关系。在这张图中:# - **横轴 (`tenure`):** 表示用户的任期年数。这个轴展示了用户在服务提供商(可能是电信公司等)停留的时间跨度。# - **纵轴(密度):** 表示在每个任期年数上流失与不流失客户的密度估计。密度估计通常显示了不同任期年数上客户流失的相对频率。在这里,越高的密度意味着在特定的任期年数上,流失或不流失的用户数量较多。# - **曲线:** 图中有两条曲线,一条代表流失为 "No"(蓝色),另一条代表流失为 "Yes"(橙色)。这两条曲线代表了任期年数对于流失与否的概率密度分布。当曲线较高的区域重叠时,表示在这些任期年数上流失与不流失的用户数量相近;而当曲线差异较大时,则代表在该任期年数上流失和不流失的用户数量有显著差异。# 这个图可以帮助你理解在不同的任期年数下,用户流失和不流失的趋势。例如,你可以观察到在哪些任期年数上流失率较高或较低,以及是否存在明显的任期年数区间,对流失率有重要影响。

在这里插入图片描述

服务类属性分析

#服务属性分析
import seaborn as sns
import matplotlib.pyplot as plt
# 设置中文字体为 SimHei
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题# 设置图表尺寸
plt.figure(figsize=(10, 5))# 绘制 MultipleLines 对用户流失的影响的柱状图
plt.subplot(1, 2, 1)  # 创建第一个子图
sns.countplot(x='MultipleLines', hue='Label', data=train)
plt.title('多条线路对用户流失的影响')
plt.xlabel('是否有多条线路')
plt.ylabel('用户数量')
plt.legend(title='流失')# 绘制 InternetService 对用户流失的影响的柱状图
plt.subplot(1, 2, 2)  # 创建第二个子图
sns.countplot(x='InternetService', hue='Label', data=train)
plt.title('互联网服务对用户流失的影响')
plt.xlabel('是否有互联网服务')
plt.ylabel('用户数量')
plt.legend(title='流失')# 调整子图布局
plt.tight_layout()# 显示图表
plt.show()

使用 sns.countplot() 分析不同服务属性对用户流失的影响,如多条线路和互联网服务。
电话服务整体对用户流失影响较大。
单光纤用户的流失占比较高;
光纤用户绑定了安全、备份、保护、技术支持服务的流失率较低;
光纤用户附加流媒体电视、电影服务的流失率占比较低。

特征相关性分析

import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns# 生成关联矩阵,排除 "ID" 列
corr = train.corr()# 创建掩码矩阵
mask = np.triu(np.ones_like(corr, dtype=bool))# 创建图表
f, ax = plt.subplots(figsize=(20, 15))# 选择调色板
cmap = sns.diverging_palette(220, 10, as_cmap=True)# 绘制热力图(半三角)
plt.title('Correlation Matrix', fontsize=18)
sns.heatmap(corr, mask=mask, cmap=cmap, vmax=.3, center=0, square=True, linewidths=.5, cbar_kws={"shrink": .5}, annot=True)plt.show()

在这里插入图片描述

数据预处理

类别编码转换

from sklearn.preprocessing import LabelEncodercolumns_to_encode = ['Contract', 'Dependents', 'DeviceProtection', 'InternetService', 'MultipleLines', 'Partner', 'PaymentMethod', 'PhoneService', 'TVProgram', 'gender']for column in columns_to_encode:label_encoder = LabelEncoder()# 合并训练集和测试集的数据进行拟合combined_data = pd.concat([train[column], test[column]])label_encoder.fit(combined_data)# 对训练集进行映射train[column] = label_encoder.transform(train[column])test[column] = label_encoder.transform(test[column])# 初始化LabelEncoder并对训练集中的标签列进行映射
label_encoder = LabelEncoder()
train['Label'] = label_encoder.fit_transform(train['Label'])train.head()

在这里插入图片描述

划分训练数据与测试数据

train.drop('ID', axis=1, inplace=True)
test.drop('ID', axis=1, inplace=True)
# 提取特征数据与目标数据
train_noLabel = train.iloc[:, :-1]  # 选择除最后一列外的所有列作为特征
y= train['Label']  # 标签列
# 把train数据划分成80%训练数据跟20%测试数据
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(train_noLabel,y,test_size=0.2)
print("x_train shape:", x_train.shape, "x_test shape:", x_test.shape, "y_train shape:", y_train.shape, "y_test shape:", y_test.shape)

在这里插入图片描述

归一化处理

from sklearn.preprocessing import MinMaxScaler# 需要归一化的列
columns_to_normalize = ['MonthlyCharges', 'TotalCharges', 'tenure']# 初始化MinMaxScaler
scaler = MinMaxScaler()# 对训练集中的指定列进行归一化
x_train[columns_to_normalize] = scaler.fit_transform(x_train[columns_to_normalize])# 对测试集中的相同列进行归一化
x_test[columns_to_normalize] = scaler.transform(x_test[columns_to_normalize])
test[columns_to_normalize] = scaler.transform(test[columns_to_normalize])

模型建立

逻辑回归

from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import RandomizedSearchCV, GridSearchCV
from sklearn.metrics import accuracy_score
from scipy.stats import uniform# 定义逻辑回归模型
base_model = LogisticRegression()# 超参数调优——随机搜索#定义超参数搜索空间
param_dist = {'C': uniform(loc=1, scale=5), 'max_iter': [100, 200, 300, 400, 500]}#进行随机搜索
random_search = RandomizedSearchCV(base_model, param_distributions=param_dist, n_iter=10, cv=5, scoring='accuracy', random_state=42, n_jobs=-1)
random_search.fit(x_train, y_train)# 输出随机搜索的最佳超参数
print("随机搜索最佳超参数:", random_search.best_params_)# 获取随机搜索的最佳模型
best_model_random = random_search.best_estimator_# 进行预测和评估
predictions_random = best_model_random.predict(x_test)
accuracy_random = accuracy_score(y_test, predictions_random)
report_random = classification_report(y_test, predictions_random)
print(f"模型准确率:{accuracy_random}")# 超参数调优——网格搜索
#定义超参数搜索空间
param_grid = {'C': [0.001, 0.01, 0.1, 1, 10, 100, 1000], 'max_iter': range(1, 110, 10), 'penalty': ['l1', 'l2']}#进行网格搜索
grid_search = GridSearchCV(base_model, param_grid, cv=5, scoring='accuracy')
grid_search.fit(x_train, y_train)# 输出网格搜索的最佳超参数
print("网格搜索最佳超参数:", grid_search.best_params_)# 获取网格搜索的最佳模型
best_model_grid = grid_search.best_estimator_# 进行预测和评估
predictions_grid = best_model_grid.predict(x_test)
accuracy_grid = accuracy_score(y_test, predictions_grid)
report_grid = classification_report(y_test, predictions_grid)
print(f"模型准确率:{accuracy_grid}")

在这里插入图片描述

支持向量机(SVM)

from sklearn.svm import SVC
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import loguniform# 定义超参数搜索空间
param_dist = {'C': loguniform(1e-3, 1e3),  # 正则化参数C的对数均匀分布'gamma': loguniform(1e-3, 1e3),  # 核函数的参数gamma的对数均匀分布'kernel': ['linear', 'rbf'],  # 核函数的选择'probability': [True],  # 是否启用概率估计'random_state': [42],  # 随机种子,确保结果可重现
}# 初始化支持向量机模型
base_model = SVC()# 初始化随机搜索
random_search = RandomizedSearchCV(base_model,param_distributions=param_dist,n_iter=10,  # 设置迭代次数cv=5,  # 交叉验证折数scoring='accuracy',  # 评估指标random_state=42,  # 随机种子,确保结果可重现n_jobs=-1  # 使用所有可用的CPU核心
)# 执行随机搜索
random_search.fit(x_train, y_train)# 输出最佳参数
print("随机搜索最佳超参数: ", random_search.best_params_)# 获取最佳模型
best_model = random_search.best_estimator_# 进行预测
predictions = best_model.predict(x_test)# 评估最佳模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"模型准确率:{accuracy}")

在这里插入图片描述

K近邻(KNN)

from sklearn.model_selection import RandomizedSearchCV, GridSearchCV
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score# 定义KNN模型
knn_model = KNeighborsClassifier()# 超参数调优——随机搜索
# 定义参数搜索空间
param_space = {'n_neighbors': range(1, 31),  # 邻居数量范围'weights': ['uniform', 'distance'],  # 权重参数'p': [1, 2],  # 距离度量参数
}# 定义随机搜索CV对象
random_search = RandomizedSearchCV(knn_model, param_distributions=param_space, n_iter=20, cv=5, scoring='accuracy', random_state=42, n_jobs=-1)# 进行随机搜索
random_search.fit(x_train, y_train)# 输出最佳参数
best_params_random = random_search.best_params_
print("随机搜索最佳超参数:", best_params_random)# 使用最佳参数的模型进行预测和评估
best_knn_model_random = random_search.best_estimator_
predictions_random = best_knn_model_random.predict(x_test)
accuracy_random = accuracy_score(y_test, predictions_random)
report_random = classification_report(y_test, predictions_random)print(f"模型准确率:{accuracy_random}")# 超参数调优——网格搜索
# 定义超参数的范围
param_grid = {'n_neighbors': list(range(1, 30, 1)),  # 尝试不同的邻居数量'weights': ['uniform', 'distance'],  # 尝试不同的权重'p': [1, 2]  # 尝试不同的距离度量
}# 使用GridSearchCV进行超参数调优
grid_search = GridSearchCV(knn_model, param_grid, cv=5, scoring='accuracy')
grid_search.fit(x_train, y_train)# 输出最佳超参数组合
best_params_grid = grid_search.best_params_
print(f"网格搜索最佳超参数:{best_params_grid}")# 使用最佳超参数训练最终模型
best_knn_model_grid = grid_search.best_estimator_
best_knn_model_grid.fit(x_train, y_train)# 进行预测和评估
best_predictions_grid = best_knn_model_grid.predict(x_test)
best_accuracy_grid = accuracy_score(y_test, best_predictions_grid)
best_report_grid = classification_report(y_test, best_predictions_grid)print(f"模型准确率:{best_accuracy_grid}")

在这里插入图片描述

XGBoost-贝叶斯搜索超参数调优

from xgboost import XGBClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split
from bayes_opt import BayesianOptimization# 定义贝叶斯优化的目标函数
def xgb_cv(learning_rate, n_estimators, max_depth, min_child_weight, subsample, gamma):xgb_model = XGBClassifier(learning_rate=learning_rate,n_estimators=int(n_estimators),max_depth=int(max_depth),min_child_weight=int(min_child_weight),subsample=subsample,gamma=gamma,random_state=42)xgb_model.fit(x_train, y_train)predictions = xgb_model.predict(x_test)accuracy = accuracy_score(y_test, predictions)return accuracy# 超参数搜索范围
param_bounds = {'learning_rate': (0.001, 0.5 ),'n_estimators': (50, 300),'max_depth': (3, 20),'min_child_weight': (1, 30),'subsample': (0.1, 1),'gamma': (0, 5)
}# 初始化贝叶斯优化对象
xgb_bayesian = BayesianOptimization(f=xgb_cv, pbounds=param_bounds, random_state=42)# 执行贝叶斯优化
xgb_bayesian.maximize(init_points=5, n_iter=100)# 输出最佳超参数
best_params = xgb_bayesian.max['params']
print("贝叶斯搜素最佳超参数:", best_params)# 使用最佳超参数构建最终模型
best_xgb_model = XGBClassifier(learning_rate=best_params['learning_rate'],n_estimators=int(best_params['n_estimators']),max_depth=int(best_params['max_depth']),min_child_weight=int(best_params['min_child_weight']),subsample=best_params['subsample'],gamma=best_params['gamma'],random_state=42
)# 训练最终模型
best_xgb_model.fit(x_train, y_train)# 进行预测
predictions = best_xgb_model.predict(x_test)# 评估最终模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"最佳模型准确率:{accuracy}")

在这里插入图片描述

随机森林(Random Forest)

from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report
from sklearn.model_selection import train_test_split
from bayes_opt import BayesianOptimization# 数据集划分(如果没有的话)
# X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)# 定义贝叶斯优化的目标函数
def rf_cv(n_estimators, max_depth, min_samples_split, min_samples_leaf):rf_model = RandomForestClassifier(n_estimators=int(n_estimators),max_depth=int(max_depth),min_samples_split=int(min_samples_split),min_samples_leaf=int(min_samples_leaf),random_state=42)rf_model.fit(x_train, y_train)predictions = rf_model.predict(x_test)accuracy = accuracy_score(y_test, predictions)return accuracy# 定义超参数的搜索范围
param_bounds = {'n_estimators': (50, 150),'max_depth': (3, 20),'min_samples_split': (2, 20),'min_samples_leaf': (1, 10)
}# 初始化贝叶斯优化对象
rf_bayesian = BayesianOptimization(f=rf_cv, pbounds=param_bounds, random_state=42)# 执行贝叶斯优化
rf_bayesian.maximize(init_points=5, n_iter=100)# 输出最佳超参数
best_params = rf_bayesian.max['params']
print("最佳超参数:", best_params)# 使用最佳超参数构建最终模型
best_rf_model = RandomForestClassifier(n_estimators=int(best_params['n_estimators']),max_depth=int(best_params['max_depth']),min_samples_split=int(best_params['min_samples_split']),min_samples_leaf=int(best_params['min_samples_leaf']),random_state=42
)# 训练最终模型
best_rf_model.fit(x_train, y_train)# 进行预测
predictions = best_rf_model.predict(x_test)# 评估最终模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"最佳模型准确率:{accuracy}")
print(f"最佳分类报告:\n{report}")

在这里插入图片描述
对测试集进行预测 并提交网站

# 进行预测
test_lable = best_rf_model.predict(test)  # 使用最佳模型进行测试数据集的预测
submit_example = pd.read_csv('submit_example.csv')  # 读取提交示例文件
# 替换 submit_example 的 Label 列
submit_example['Label'] = test_lable  # 将预测结果填入 submit_example 的 Label 列
submit_example['Label'] = label_encoder.inverse_transform(submit_example['Label'])  # 对 Label 进行反向转换
# 将结果写入 CSV 文件
submit_example.to_csv('Random Forest_predict.csv', index=False)  # 将结果保存为 CSV 文件,不保存索引列

AdaBoost

from sklearn.ensemble import AdaBoostClassifier
from sklearn.metrics import accuracy_score, classification_report# 初始化 AdaBoost 分类器
adaboost_model = AdaBoostClassifier(n_estimators=300, random_state=42,learning_rate=0.1)# 训练模型
adaboost_model.fit(X_train, y_train)# 进行预测
predictions = adaboost_model.predict(X_test)# 评估模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"模型准确率:{accuracy}")
print(f"分类报告:\n{report}")

MLP

from sklearn.neural_network import MLPClassifier
from sklearn.metrics import accuracy_score, classification_report# 初始化MLP模型
mlp = MLPClassifier(hidden_layer_sizes=(128, ), max_iter=100, alpha=1e-4,solver='adam', verbose=10, tol=1e-4, random_state=42,learning_rate_init=0.01)# 训练模型
mlp.fit(X_train, y_train)# 进行预测
predictions = mlp.predict(X_test)# 评估模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"模型准确率:{accuracy}")
print(f"分类报告:\n{report}")

朴素贝叶斯分类器

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
from sklearn.pipeline import Pipeline# 加载数据集
def load_data(file_path):df = pd.read_csv(file_path)X = df.drop('Label', axis=1)  # 特征y = df['Label']  # 标签return X.values, y.valuesdef test_data(file_path):x = pd.read_csv(file_path)return x.values# 计算高斯概率密度函数
def gaussian_probability(x, mean, std):exponent = np.exp(-((x - mean) ** 2 / (2 * std ** 2)))   # 计算高斯分布的指数部分return (1 / (np.sqrt(2 * np.pi) * std)) * exponent     # 计算高斯概率密度函数的值# 计算类别先验概率
def calculate_class_priors(y):classes, counts = np.unique(y, return_counts=True)   # 获取标签 y 中的唯一类别和每个类别的出现次数priors = {}for c, count in zip(classes, counts):priors[c] = count / len(y)   # 计算先验概率,即该类别出现的次数除以总样本数,键为类别 'c'return priors# 计算每个特征的均值和标准差
def calculate_mean_std(X, y):class_values = list(np.unique(y))    # 获取标签y中的唯一类别,并转为列表。summaries = {}for class_value in class_values:X_class = X[y == class_value]summaries[class_value] = [(np.mean(attribute), np.std(attribute)) for attribute in X_class.T]  # 计算当前类别中每个特征的均值和标准差,并存储在字典中return summaries# 训练高斯朴素贝叶斯模型
def train_naive_bayes(X_train, y_train):priors = calculate_class_priors(y_train)summaries = calculate_mean_std(X_train, y_train)return priors, summaries# 高斯朴素贝叶斯分类器预测
def predict(priors, summaries, X_test):predictions = []   # 用于存储预测结果for row in X_test:probabilities = {}   # 用于存储每个类别的概率# class_value 获取字典中的键,即类别的标签,而 class_summaries 获取字典中的值,即包含该类别中每个特征的均值和标准差的列表。for class_value, class_summaries in summaries.items():      probabilities[class_value] = priors[class_value]    # 初始化概率为类别的先验概率for i in range(len(class_summaries)):   # 遍历每个特征mean, std = class_summaries[i]probabilities[class_value] *= gaussian_probability(row[i], mean, std)   # 计算当前特征在当前类别下的高斯概率密度predicted_class = max(probabilities, key=probabilities.get)   # 选择具有最大后验概率的类别作为预测结果predictions.append(predicted_class)return predictions# 读取训练集和测试集
X_train, y_train = load_data('train_new.csv')
X_test = test_data('test_new.csv')# 划分训练集和验证集
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train, test_size=0.2, random_state=42)# 训练朴素贝叶斯模型
priors, summaries = train_naive_bayes(X_train, y_train)# 预测验证集
y_val_pred = predict(priors, summaries, X_val)# 评估基准模型
accuracy_baseline = accuracy_score(y_val, y_val_pred)
print(f"基准模型准确性: {accuracy_baseline:}")############# 使用GridSearchCV进行超参数调优
pipeline = Pipeline([('classifier', GaussianNB())])
#定义超参数搜索空间
param_grid = {'classifier__var_smoothing': [1e-9, 1e-8, 1e-7, 1e-6]}
grid_search = GridSearchCV(pipeline, param_grid=param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)# 打印找到的最佳参数及其对应的准确性
print("GridSearchCV找到的最佳参数:", grid_search.best_params_)
print("GridSearchCV最佳交叉验证准确性:{}".format(grid_search.best_score_))# 从GridSearchCV中获取最佳模型
best_model_grid = grid_search.best_estimator_# 使用最佳模型对测试集进行预测
y_test_grid = best_model_grid.predict(X_test)############### 使用RandomizedSearchCV进行超参数调优
pipeline = Pipeline([('classifier', GaussianNB())])
param_dist = {'classifier__var_smoothing': [1e-10, 1e-9, 1e-8, 1e-7, 1e-6, 1e-5]}
random_search = RandomizedSearchCV(pipeline, param_distributions=param_dist, n_iter=4, cv=5, scoring='accuracy', random_state=42)
random_search.fit(X_train, y_train)# 打印找到的最佳参数及其对应的准确性
print("RandomizedSearchCV找到的最佳参数:", random_search.best_params_)
print("RandomizedSearchCV最佳交叉验证准确性:{}".format(random_search.best_score_))# 从随机搜索中获取最佳模型
best_model_random = random_search.best_estimator_# 使用最佳模型对测试集进行预测
y_test_random = best_model_random.predict(X_test)

在这里插入图片描述

LightGBM

from lightgbm import LGBMClassifier
from sklearn.metrics import accuracy_score, classification_reportgbm = LGBMClassifier(learning_rate=0.02,n_estimators=100,max_depth=100)
# 训练模型
gbm.fit(X_train, y_train)# 进行预测
predictions = gbm.predict(X_test)# 评估模型
accuracy = accuracy_score(y_test, predictions)
report = classification_report(y_test, predictions)print(f"模型准确率:{accuracy}")
print(f"分类报告:\n{report}")

MLP-pytorch版

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt# 假设 X_train、y_train、X_test、y_test 是 Pandas DataFrame
# 将 DataFrame 转换为 NumPy 数组
X_train_array = X_train.to_numpy().astype(np.float32)
y_train_array = y_train.to_numpy().astype(np.float32)
X_test_array = X_test.to_numpy().astype(np.float32)
y_test_array = y_test.to_numpy().astype(np.float32)# 转换数据为 PyTorch 张量
X_train_tensor = torch.from_numpy(X_train_array)
y_train_tensor = torch.from_numpy(y_train_array)
X_test_tensor = torch.from_numpy(X_test_array)
y_test_tensor = torch.from_numpy(y_test_array)# 定义简单的 MLP 模型
class MLP(nn.Module):def __init__(self):super(MLP, self).__init__()self.fc1 = nn.Linear(in_features=INPUT_SIZE, out_features=128)# 线性层self.relu = nn.ReLU()# 激活函数self.fc2 = nn.Linear(in_features=128, out_features=1)# 线性层self.sigmoid = nn.Sigmoid()# 激活函数def forward(self, x):x = self.relu(self.fc1(x))x = self.sigmoid(self.fc2(x))return x# 初始化模型、损失函数和优化器
INPUT_SIZE = X_train.shape[1]
mlp = MLP()
criterion = nn.BCELoss()
optimizer = optim.Adam(mlp.parameters(), lr=0.01)# 训练模型,并记录损失值
train_losses = []
val_losses = []
mlp.train()
for epoch in range(50):  # 迭代50次optimizer.zero_grad()outputs = mlp(X_train_tensor)loss = criterion(outputs, y_train_tensor.view(-1, 1))loss.backward()optimizer.step()train_losses.append(loss.item())mlp.eval()
with torch.no_grad():outputs_val = mlp(X_test_tensor)val_loss = criterion(outputs_val, y_test_tensor.view(-1, 1))val_losses.append(val_loss.item())# 计算预测准确率
accuracy = accuracy_score(y_test, predictions)
print(f"模型准确率:{accuracy}")

XGBoost-MLP-随机森林加权组合-效果最优

重新读取数据并转换编码和归一化操作

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import stats
from scipy.special import boxcox1p
import missingno as msno
import warnings
warnings.filterwarnings("ignore")%matplotlib inline
train = pd.read_csv('train.csv')
test = pd.read_csv('test_noLabel.csv')
train.shape,test.shape

from sklearn.preprocessing import LabelEncodercolumns_to_encode = ['Contract', 'Dependents', 'DeviceProtection', 'InternetService', 'MultipleLines', 'Partner', 'PaymentMethod', 'PhoneService', 'TVProgram', 'gender']for column in columns_to_encode:label_encoder = LabelEncoder()# 合并训练集和测试集的数据进行拟合combined_data = pd.concat([train[column], test[column]])label_encoder.fit(combined_data)# 对训练集进行映射train[column] = label_encoder.transform(train[column])test[column] = label_encoder.transform(test[column])# 初始化LabelEncoder并对训练集中的标签列进行映射
label_encoder = LabelEncoder()
train['Label'] = label_encoder.fit_transform(train['Label'])
train.drop('ID', axis=1, inplace=True)
test.drop('ID', axis=1, inplace=True)
# 提取特征数据与目标数据
train_noLabel = train.iloc[:, :-1]  # 选择除最后一列外的所有列作为特征
y= train['Label']  # 标签列
# 把train数据划分成训练数据0.8跟测试数据0.2,
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test = train_test_split(train_noLabel,y,test_size=0.2)print("x_train shape:", x_train.shape, "x_test shape:", x_test.shape, "y_train shape:", y_train.shape, "y_test shape:", y_test.shape)from sklearn.preprocessing import MinMaxScaler# 需要归一化的列
columns_to_normalize = ['MonthlyCharges', 'TotalCharges', 'tenure']# 初始化MinMaxScaler
scaler = MinMaxScaler()# 对训练集中的指定列进行归一化
x_train[columns_to_normalize] = scaler.fit_transform(x_train[columns_to_normalize])# 对测试集中的相同列进行归一化
x_test[columns_to_normalize] = scaler.transform(x_test[columns_to_normalize])
test[columns_to_normalize] = scaler.transform(test[columns_to_normalize])

在这里插入图片描述

from xgboost import XGBClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split, RandomizedSearchCV
from scipy.stats import randint, uniform
from sklearn.metrics import accuracy_score, classification_report
from bayes_opt import BayesianOptimization# XGBoost 超参数调优
def xgb_cv(learning_rate, n_estimators, max_depth, min_child_weight, subsample, gamma):xgb_model = XGBClassifier(learning_rate=learning_rate,n_estimators=int(n_estimators),max_depth=int(max_depth),min_child_weight=int(min_child_weight),subsample=subsample,gamma=gamma,random_state=42)xgb_model.fit(x_train, y_train)predictions = xgb_model.predict(x_test)accuracy = accuracy_score(y_test, predictions)return accuracyparam_bounds_xgb = {'learning_rate': (0.001, 0.01),'n_estimators': (50, 300),'max_depth': (3, 20),'min_child_weight': (1, 30),'subsample': (0.1, 1),'gamma': (0, 5)
}xgb_bayesian = BayesianOptimization(f=xgb_cv, pbounds=param_bounds_xgb, random_state=42)
xgb_bayesian.maximize(init_points=5, n_iter=100)
best_params_xgb = xgb_bayesian.max['params']
best_xgb_model = XGBClassifier(learning_rate=best_params_xgb['learning_rate'],n_estimators=int(best_params_xgb['n_estimators']),max_depth=int(best_params_xgb['max_depth']),min_child_weight=int(best_params_xgb['min_child_weight']),subsample=best_params_xgb['subsample'],gamma=best_params_xgb['gamma'],random_state=42
)
best_xgb_model.fit(x_train, y_train)# MLP 超参数调优
mlp = MLPClassifier(random_state=42)
param_dist_mlp = {'hidden_layer_sizes': [(64,), (128,), (256,)],'activation': ['relu', 'tanh', 'logistic'],'max_iter': randint(50, 200),'learning_rate_init': uniform(0.001, 0.1),
}
random_search_mlp = RandomizedSearchCV(mlp, param_distributions=param_dist_mlp, n_iter=10, cv=3, scoring='accuracy', random_state=42)
random_search_mlp.fit(x_train, y_train)
best_params_mlp = random_search_mlp.best_params_
best_model_mlp = random_search_mlp.best_estimator_# 随机森林超参数调优
base_model_rf = RandomForestClassifier()
param_dist_rf = {'n_estimators': randint(10, 200),'max_features': ['auto', 'sqrt', 'log2', None],'max_depth': [None, 10, 20, 30, 40, 50],'min_samples_split': randint(2, 20),'min_samples_leaf': randint(1, 20),'bootstrap': [True, False],'random_state': [42],
}
random_search_rf = RandomizedSearchCV(base_model_rf,param_distributions=param_dist_rf,n_iter=10,cv=5,scoring='accuracy',random_state=42,n_jobs=-1
)
random_search_rf.fit(x_train, y_train)
best_params_rf = random_search_rf.best_params_
best_model_rf = random_search_rf.best_estimator_# 组合模型并加权
predictions_xgb = best_xgb_model.predict(x_test)
predictions_mlp = best_model_mlp.predict(x_test)
predictions_rf = best_model_rf.predict(x_test)# 组合模型结果并加权
weighted_predictions = (0.4 * predictions_xgb) + (0.3 * predictions_mlp) + (0.3 * predictions_rf)# 将连续值转换为二元分类值
threshold = 0.5
binary_predictions = [1 if pred > threshold else 0 for pred in weighted_predictions]# 计算二元分类准确率
accuracy_binary = accuracy_score(y_test, binary_predictions)
report_binary = classification_report(y_test, binary_predictions)print(f"模型准确率: {accuracy_binary}")
print(f"二元分类模型准确率: {accuracy_binary}")
print(f"分类报告:\n{report_binary}")

在这里插入图片描述
对测试数据进行分类预测并提交网站

# 进行预测# 组合模型并加权
predictions_xgb = best_xgb_model.predict(test)
predictions_mlp = best_model_mlp.predict(test)
predictions_rf = best_model_rf.predict(test)# 组合模型结果并加权
weighted_predictions = (0.4 * predictions_xgb) + (0.3 * predictions_mlp) + (0.3 * predictions_rf)# 将连续值转换为二元分类值
threshold = 0.5
binary_predictions = [1 if pred > threshold else 0 for pred in weighted_predictions]submit_example = pd.read_csv('submit_example.csv')  # 读取提交示例文件
# 替换 submit_example 的 Label 列
submit_example['Label'] = binary_predictions  # 将预测结果填入 submit_example 的 Label 列
submit_example['Label'] = label_encoder.inverse_transform(submit_example['Label'])  # 对 Label 进行反向转换
# 将结果写入 CSV 文件
submit_example.to_csv('zuhe_predict.csv', index=False)  # 将结果保存为 CSV 文件,不保存索引列

在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/245018.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重生之我是学神,小小c语言题目可笑可笑

#include<stdio.h> int main(void) { float score[10]{0}; int i 0; for(i0;i<10;i) { printf("请输入%d学生成绩",i1); scanf("%f",&score[i]); } float sum0; int m…

【轮式平衡机器人】——TMS320F28069片内外设之GPIO

引入 接下来的几期博客会介绍轮式平衡机器人TMS320F28069片内外设&#xff0c;了解片内外设的基本原理&#xff0c;内容较为基础&#xff0c;都是些简单的simulink模型&#xff0c;旨在将复杂的原理过渡到simulink软件应用。足够了解的博友可跳过。 后续还将会结合MATLAB/Sim…

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别

分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别 目录 分类预测 | Matlab实现GRU-Attention-Adaboost基于门控循环单元融合注意力机制的Adaboost数据分类预测/故障识别分类效果基本描述程序设计参考资料 分类效果 …

JVM/GC复习1---更新中

JVM/GC JVMGC垃圾回收算法1.引用计数法2.标记清除发3.标记压缩算法4.复制算法5.分代算法 收集器1.串行垃圾收集器2.并行垃圾收集器2.CMS垃圾收集器 3.G1垃圾收集器(重点)jdk1.7开始1.9默认的回收器Young GC模式Mixed GC 可视化的GC日志分析工具 JVM 待更新中ing GC 垃圾回收:…

【并发编程】ReentrantLock

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;并发编程 ⛺️稳重求进&#xff0c;晒太阳 相对于synchronized 它具备如下特点&#xff1a; 可中断可以设置超时时间可以设置公平锁支持多个条件变量 与synchronized一样&#xff0c;都支…

unity学习笔记----游戏练习06

一、豌豆射手的子弹控制 创建脚本单独控制子弹的运动 用transform来控制移动 void Update() { transform.Translate(Vector3.right * speed * Time.deltaTime); } 创建一个控制子弹速度的方法&#xff0c;方便速度的控制 private void SetSpeed(float spee…

安全防御第二次作业

将内网中各个接口能够ping通自己的网关 1.划分vlan [sw6]vlan batch 2 3 [sw6]int g0/0/2 [sw6-GigabitEthernet0/0/2]port link-type access [sw6-GigabitEthernet0/0/2]port default vlan 2 [sw6-GigabitEthernet0/0/2]int g0/0/3 [sw6-GigabitEthernet0/0/3]port link-t…

系统登录的时候的密码如何做到以加密的形式进行登录【java.security包下的api】工具类。

/** description: 将普通的publicKey转化得到一个RSAPublicKey* author: zkw* date: 2024/1/24 16:17* param: publicKey 普通的publicKey* return: RSAPublicKey 得到一个新的RSAPublicKey**/public static RSAPublicKey getPublicKey(String publicKey) throws NoSuchAlgorit…

Pandas ------ 向 Excel 文件中写入含有合并表头的数据

Pandas ------ 向 Excel 文件中写入含有合并表头的数据 推荐阅读引言正文 推荐阅读 Pandas ------ 向 Excel 文件中写入含有 multi-index 和 Multi-column 表头的数据 引言 这里给大家介绍一下如何向 Excel 中写入带有合并表头的数据。 正文 import pandas as pddf1 pd.D…

自定义注解与拦截器实现不规范sql拦截(拦截器实现篇)

最近考虑myBatis中sql语句使用规范的问题&#xff0c;如果漏下条件或者写一些不规范语句会对程序性能造成很大影响。最好的方法就是利用代码进行限制&#xff0c;通过拦截器进行sql格式的判断在自测环节就能找到问题。写了个简单情景下的demo&#xff0c;并通过idea插件来将myB…

leaflet学习笔记-带过滤的图例(九)

前言 图例不只能够帮助我们在查看地图的时候更加方便容易地分辨不同颜色代表的要素&#xff0c;本文要介绍的图例组件还可以按需求过滤掉不用显示的要素&#xff0c;使地图的更能清晰的显示我们需要显示的内容 技术核心 说到过滤要素&#xff0c;第一时间想到的就是滑块组件…

内网穿透、远程桌面、VPN的理解

最近在研究内网穿透的相关技术&#xff0c;然后回想起一些相关的技术&#xff0c;比如说要远程桌面公司的电脑&#xff0c;VPN连入内网等。然后想着在此处记录一下&#xff0c;各个的区别&#xff0c;这个纯粹是从技术层面的理解&#xff0c;此处不详细解释怎么去实现或者用什么…

【C++】stack、queue的使用及模拟实现

目录 一、stack1.1 stack的使用1.2 stack的模拟实现 二、queue2.1 queue的使用2.2 queue的模拟实现 一、stack 1.1 stack的使用 stack是一种容器适配器&#xff0c;它的特点是后进先出&#xff0c;只能在容器的一端进行插入和删除操作。 stack的使用很简单&#xff0c;主要有…

在IDEA中创建SpringBoot项目

概述 SpringBoot是由Pivotal团队提供的全新的框架&#xff0c;其设计的目的是用来简化Spring应用的初始搭建以及开发过程。 传统方式构建Spring应用程序 导入依赖繁琐 依赖冲突 项目配置繁琐 SpringBoot特性 1、起步依赖 本质上就行一个Maven坐标&#xff0c;整合了完成一…

Java 集合List相关面试题

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于java面试题系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基…

dataGrip连接数据库mysql和intersystems的iris

文章目录 前言创建新项目选择对应的数据库产品类型新建数据库资源连接sql命令窗体手动配置本地驱动 前言 intersystems公司的产品iris是cache的升级版本&#xff0c;目前绝大多数数据库工具都没法连接这个数据库 datagrip下载地址 https://download-cdn.jetbrains.com.cn/da…

eBay在人工智能道路上的成败得失:衡量标准是关键

我是2006年加入eBay的。2009年&#xff0c;这家公司的运营状况非常糟糕&#xff0c;其股价创历史新低&#xff08;远低于近24美元的历史高位&#xff09;&#xff0c;还出现削减各项成本、负增长、市场占有率降低、技术团队缺乏创新能力等情况。 简而言之&#xff0c;eBay公司…

CentOS7自动备份数据库到git

虽然数据库没什么数据&#xff0c;但是有就是珍贵的啦&#xff0c;为了服务器什么的无了&#xff0c;所以还是要自动备份一下比较好。 Open备忘第一页 步骤 在Gitee&#xff08;github&#xff09;上创建一个私有仓库Gitee&#xff08;github&#xff09;配置好服务器的ssh在服…

Oracle BIEE 示例(一)数据透视表2

1 背景 版本:BIEE 12C 视图:数据透视表 实现内容(顺序与具体内容不一致): 2 空列显示(方法一) 2.1 问题 列为空时,标题栏不显示信息。 2.2 期望 即使数据为空,也要显示列名。 2.3 官方资料 2.3.1 操作步骤 2.3.1.1 要在分析级别关闭空值隐藏,请执行以下操作…

MySQL与PostgreSQL对比

对比 许可证 License MySQL 社区版采用 GPL 许可证。Postgres 发布在 PostgreSQL 许可下&#xff0c;是一种类似于 BSD 或 MIT 的自由开源许可。 即便 MySQL 采用了 GPL&#xff0c;仍有人担心 MySQL 归 Oracle 所有&#xff0c;这也是为什么 MariaDB 从 MySQL 分叉出来。 …