数据预处理
通过网盘分享的文件:银行流失预测数据和代码
链接: https://pan.baidu.com/s/1loiB8rMvZArfjJccu4KW6w?pwd=pfcs 提取码: pfcs
非数值特征处理
- 目的:将非数值特征转换为数值型,以便模型能够处理。
- 方法:
- 地理位置:可以使用独热编码(One-Hot Encoding)或标签编码(Label Encoding)将不同国家/地区转换为数值。
- 性别:可以使用标签编码,将“男”和“女”分别编码为0和1。
- 结果文件:保存为
Churn-Modelling-newT.csv
数据离散化处理
- 目的:将连续变量转换为离散变量,简化模型复杂度,提高模型的可解释性。
- 方法:
- 统计分析:对连续数据进行描述性统计分析,了解数据的分布情况。
- 离散化方法:
- 等宽离散化:将数据分为等宽的区间。
- 等频离散化:将数据分为等频的区间。
- 基于聚类的离散化:使用聚类算法确定离散化的区间。
- 结果文件:保存为
Churn-Modelling-new-tree.csv
数据筛选
- 目的:去除与模型训练无关的特征列,保留有意义的数据,解决数据不均衡问题。
- 方法:
- 特征筛选:舍去如行号、用户编号、用户姓名等无关特征。
- 数据平衡:
- 过采样:增加少数类别的样本数量。
- 欠采样:减少多数类别的样本数量。
- 结果文件:保存为
final.csv
数据分割
- 目的:将数据集分为训练集和测试集,用于模型训练和评估。
- 方法:按照4:1的比例分割数据集。
- 结果文件:
- 训练集:
Churn-Modelling-train.csv
- 测试集:
Churn-Modelling-test.csv
- 训练集:
数据集预览
数据特征列描述
RowNumber:行号
CustomerID:用户编号
Surname:用户姓名
CreditScore:信用分数
Geography:用户所在国家/地区
Gender:用户性别
Age:年龄
Tenure:当了本银行多少年用户
Balance:存贷款情况
NumOfProducts:使用产品数量
HasCrCard:是否有本银行信用卡
IsActiveMember:是否活跃用户
EstimatedSalary:估计收入
Exited:是否已流失,作为标签数据
代码部分
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder, KBinsDiscretizer
# 过采样与欠采样解决数据不均衡问题
from imblearn.over_sampling import RandomOverSampler
from imblearn.under_sampling import RandomUnderSampler# 读取数据
df = pd.read_csv('Churn-Modelling.csv')# a) 非数值特征处理
# 地理位置 - 独热编码
geography_dummies = pd.get_dummies(df['Geography'], prefix='Geography')
df = pd.concat([df, geography_dummies], axis=1)
df.drop('Geography', axis=1, inplace=True)# 性别 - 标签编码
label_encoder = LabelEncoder()
df['Gender'] = label_encoder.fit_transform(df['Gender'])# 保存处理后的文件
df.to_csv('Churn-Modelling-newT.csv', index=False)# b) 数据离散化处理
# 信用分数、年龄、存贷款情况、估计收入 - 等宽离散化
discretizer = KBinsDiscretizer(n_bins=5, encode='ordinal', strategy='uniform')
columns_to_discretize = ['CreditScore', 'Age', 'Balance', 'EstimatedSalary']
df[columns_to_discretize] = discretizer.fit_transform(df[columns_to_discretize])# 保存处理后的文件
df.to_csv('Churn-Modelling-new-tree.csv', index=False)# c) 数据筛选
# 去除无关特征列
df.drop(['RowNumber', 'Customerid', 'Surname'], axis=1, inplace=True)X = df.drop('Exited', axis=1)
y = df['Exited']# 过采样
over_sampler = RandomOverSampler(sampling_strategy=0.5)
X_over, y_over = over_sampler.fit_resample(X, y)# 欠采样
under_sampler = RandomUnderSampler(sampling_strategy=0.8)
X_resampled, y_resampled = under_sampler.fit_resample(X_over, y_over)# 保存筛选后的文件
final_df = pd.concat([X_resampled, y_resampled], axis=1)
final_df.to_csv('final.csv', index=False)# d) 数据分割
X_train, X_test, y_train, y_test = train_test_split(X_resampled, y_resampled, test_size=0.2, random_state=42)train_df = pd.concat([X_train, y_train], axis=1)
test_df = pd.concat([X_test, y_test], axis=1)train_df.to_csv('Churn-Modelling-train.csv', index=False)
test_df.to_csv('Churn-Modelling-test.csv', index=False)
小注
要查看LabelEncoder
是如何将类别值映射到整数的,你可以使用LabelEncoder
对象的classes_
属性。这个属性是一个数组,包含了原始类别值的排序列表,其索引位置对应于转换后的整数值。
以下是如何查看性别类别值映射的方法:
label_encoder = LabelEncoder()
df['Gender'] = label_encoder.fit_transform(df['Gender'])# 查看类别值的映射
print(label_encoder.classes_)
假设df['Gender']
列包含两个唯一值'Male'
和'Female'
,LabelEncoder
会根据它们在数据中出现的顺序进行排序(通常是字典序),然后进行编码。例如,如果输出是:
['Female' 'Male']
这意味着'Female'
被编码为0,'Male'
被编码为1。如果顺序相反,那么'Male'
将被编码为0,'Female'
被编码为1。
如果你想要明确地指定编码方式,可以使用map
函数手动设置映射:
# 假设我们想要将'Male'编码为0,'Female'编码为1
gender_mapping = {'Male': 0, 'Female': 1}
df['Gender'] = df['Gender'].map(gender_mapping)
这样就可以确保'Male'
总是被编码为0,'Female'
总是被编码为1。