《机器学习》客户流失判断-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 LabelEncoder

columns_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.values

def 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_report

gbm = 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 LabelEncoder

columns_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 accuracy

param_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.mfbz.cn/a/337943.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

二叉树的直径(LeetCode 543)

文章目录 1.问题描述2.难度等级3.热门指数4.解题思路参考文献 1.问题描述 给你一棵二叉树的根节点,返回该树的直径 。 二叉树的 直径 是指树中任意两个节点之间最长路径的长度 。这条路径可能经过也可能不经过根节点 root 。 两节点之间路径的长度由它们之间边数…

安卓平板局域网内远程控制工控机方法

安卓平板局域网内远程控制工控机方法 将所需要远程控制的工控机通过网线连接到具有WiFi功能的路由器上,将安卓平板连接上WiFi,如下图所示 下载NoMachine远程软件安装包,官网地址:https://www.nomachine.com/ 点击Download now按钮…

C++实战:类的包含编译模型

文章目录 一、实战概述二、实战步骤(一)C普通类的包含编译模型1、创建普通类定义文件2、创建普通类实现文件3、创建主程序文件4、运行主程序,查看结果 (二)C模板类的包含编译模型1、创建模板类定义文件2、创建模板类实…

微前端框架篇一,了解qiankun

微前端框架篇一,了解qiankun ① 前置知识补充Ⅰ 什么是微前端?Ⅱ 什么是JS CSS沙箱?Ⅲ 什么是spa单页面应用?Ⅳ SystemJS 与 import-html-entryⅤ 现有的微前端方案 ② 了解single-spa 微前端框架③ 了解qiankun框架 ① 前置知识补…

[超级详细系列]ubuntu22.04配置深度学习环境(显卡驱动+CUDA+cuDNN+Pytorch)--[1]安装显卡驱动

[写在前面] 👇👇👇 如果这篇博客写的还可以的话,希望各位好心的读者朋友们到最下面点击关注一下Franpper的公众号,或者也可以直接通过名字搜索:Franpper的知识铺。快要过年了,Franpper想制作一…

腾讯云代金券如何领取?详细领取教程来了!

随着云计算的快速发展,越来越多的用户意识到云服务的重要性。腾讯云作为国内领先的云服务提供商,为广大用户提供了丰富的云计算解决方案。为了吸引用户上云,腾讯云推出了代金券活动,让用户在购买云服务时可以享受到更多的优惠。 那…

【Linux】Linux基本操作(二):rm rmdir man cp mv cat echo

承接上文: 【【Linux】Linux基本操作(一):初识操作系统、ls、cd、touch、mkdir、pwd 】 目录 1.rmdir指令 && rm 指令: rmdir -p #当子目录被删除后如果父目录也变成空目录的话,就连带父目录一…

线性表的案例引入 | 稀疏多项式的运算

#include <iostream> using namespace std;#define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2typedef int Status;// 定义单链表 typedef struct PNode {float coef; //系数int expn; //指数struct PNode *nex…

「优选算法刷题」:查找总价格为目标值的两个商品

一、题目 购物车内的商品价格按照升序记录于数组 price。请在购物车中找到两个商品的价格总和刚好是 target。若存在多种情况&#xff0c;返回任一结果即可。 示例 1&#xff1a; 输入&#xff1a;price [3, 9, 12, 15], target 18 输出&#xff1a;[3,15] 或者 [15,3]示例…

windows下载安装ImageMagick

windows环境搭建专栏&#x1f517;点击跳转 win系统环境搭建&#xff08;十七&#xff09;——windows下载安装ImageMagick 文章目录 win系统环境搭建&#xff08;十七&#xff09;——windows下载安装ImageMagick1.下载2.安装3.验证3.1 依赖缺失问题3.2 依赖缺失解决 1.下载 …

二叉树 - 堆 | 数据结构中的小技巧大作用

&#x1f4f7; 江池俊&#xff1a; 个人主页 &#x1f525;个人专栏&#xff1a; ✅数据结构冒险记 ✅C语言进阶之路 &#x1f305; 有航道的人&#xff0c;再渺小也不会迷途。 文章目录 一、堆的概念及介绍二、结构图示三、堆的代码实现&#xff08;图解&#xff09;3.1 创…

6种解决msvcp140.dll文件丢失的有效方法讲解

msvcp140.dll是一个动态链接库文件&#xff0c;它是Microsoft Visual C 2015 Redistributable的一部分。这个文件通常位于Windows操作系统的System32文件夹中&#xff0c;它包含了许多用于支持C编程语言的函数和类。当您在运行一个需要使用这些函数和类的应用程序时&#xff0c…

cpp_12_异常处理

1 异常理论 1.1 何为异常&#xff1f; 在实际运行环境中发生&#xff0c;却在设计、编码、测试阶段无法预料的&#xff0c;各种潜在的问题。 1.2 报告异常的2种机制 1&#xff09;通过 return 返回值报告异常信息&#xff1a; 所有局部对象都能正确地被析构、被释放 定位错…

代码随想录算法训练营第四天 | 24.两两交换链表中的节点 19.删除链表的倒数第N个节点 160.链表相交 142.环形链表II

两两交换链表中的节点 两两交换节点&#xff0c;思路如下&#xff1a; 这样三步操作就实现了2和1两个节点的交换&#xff0c;循环操作&#xff0c;每一次循环移动到交换好的最后一个节点。循环的截止条件就是没有节点剩余了&#xff0c;或者只剩一个节点。翻转链表的精髓还是在…

机器学习实验报告- KNN算法

目录 一、算法介绍 1.1算法背景 1.2基本假设 1.3算法原理阐述 1.4算法关键点 二、数据集描述 2.1数据集介绍 2.2 数据处理 三、算法实现 3.1代码实现&#xff08;python&#xff09; 3.2代码复现结果 四、实验讨论 4.1关于KNN算法优缺点的讨论 4.2关于k值对实验结…

HTML JavaScript 数字变化特效

效果 案例一&#xff1a;上下滚动 案例二&#xff1a;本身变化 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><met…

【Python代码】以线性模型为例,详解深度学习算法流程,包括数据生成、定义模型、损失函数、优化算法和训练

**使用带有噪声的线性模型构造数据集&#xff0c;并根据有限的数据恢复该线性模型的参数。**其中包括数据集构造、模型参数初始化、损失函数定义、定义优化算法和训练等过程。是大多数算法实现过程的一个缩影&#xff0c;理解此过程有助于在开发或改进算法时更深刻了解其算法的…

【Oracle】收集Oracle数据库内存相关的信息

文章目录 【Oracle】收集Oracle数据库内存相关的信息收集Oracle数据库内存命令例各命令的解释输出结果例参考 【声明】文章仅供学习交流&#xff0c;观点代表个人&#xff0c;与任何公司无关。 编辑|SQL和数据库技术(ID:SQLplusDB) 【Oracle】收集Oracle数据库内存相关的信息 …

受电端协议芯片是如何让Type-C接口设备实现快充?

随着科技的不断进步&#xff0c;USB Type-C接口在电子产品中越来越普及。而在这个接口中&#xff0c;Type-c受电端协议芯片起着至关重要的作用。那么&#xff0c;什么是Type-c受电端协议芯片&#xff1f;它又是如何工作的呢&#xff1f;本文将为您揭开Type-c受电端协议芯片的神…

pip安装之后还是无法使用问题处理

最近由于需要使用到Python 相关功能&#xff0c; 记录下一些入门小技巧 1 python 下载安装 在window10 环境下载免安装版本&#xff0c; 并解压 安装包下载地址&#xff1a; https://www.python.org/ftp/python/3.12.1/python-3.12.1-embed-amd64.zip 2. 安装pip, 由于是内嵌…
最新文章