1. 简介
在机器学习领域的数据预处理过程中,离散化(discretization)是一个常用的方法。其作用是将连续型变量转换为离散型变量,便于建模处理。分箱(binning)是离散化中的一种方法,其作用是将一段范围连续的数据划分为若干个区间,每个区间成为一个箱子,相当于将原来的连续区间离散化成了若干个离散的项,称为离散化、分箱或者分桶。本文将介绍 python 中基于卡方值分箱算法的实现示例。
2. 卡方值分箱算法
2.1 基本思想
卡方值分箱算法,顾名思义,是基于卡方值的一种分箱方法。其基本思想是首先进行最优分割点的搜索,然后按照分割点的位置,将连续的数据分成多个箱子。在搜索最优分割点的过程中,采用了卡方检验的方法,即判断样本分布与预期分布之间的差异是否足够显著,从而确定最优分割点。
2.2 分箱步骤
卡方值分箱算法的具体步骤如下:
对于连续型变量,我们需要先对其进行排序
将连续型变量分成若干个初始区间,例如 $n$ 个等分点,作为初始区间
计算每个区间的实际值分布以及预期分布,并计算卡方值
合并相邻卡方值最小的区间
重新计算每个区间的实际值分布以及预期分布,并计算卡方值
递归执行步骤4~5,直到满足停止条件(例如分成 $k$ 个区间,或者卡方值达到一定阈值等)
2.3 代码实现
基于上述思路,我们来看一下卡方值分箱算法的 python 实现。
def chiMerge(df, col, target_col, confidence_val=3.841, bin_num=10):
"""
df: 待分箱数据集
col: 待分箱列名
target_col: 标签列名
confidence_val: 卡方值显著性水平,默认为 0.05(自由度为 1,置信度为 95% 时的卡方值)
bin_num: 初始分箱数量
"""
# 创建初始分箱
data = df[[col, target_col]]
n = data.shape[0]
data[col] = pd.qcut(data[col], q=bin_num, duplicates='drop')
co_tab1 = pd.crosstab(data[col], data[target_col])
# 开始迭代
while True:
# 计算相邻区间卡方值
chi_val = [] # 表示相邻区间卡方值
for i in range(len(co_tab1) - 1):
chi = stats.chi2_contingency(co_tab1.iloc[i:i + 2])[0]
chi_val.append(chi)
if min(chi_val) >= confidence_val: # 如果不需要合并,则退出循环
break
# 合并卡方值最小的相邻区间
min_chi_index = chi_val.index(min(chi_val))
co_tab1.iloc[min_chi_index:min_chi_index + 2, :]\
= co_tab1.iloc[min_chi_index:min_chi_index + 2, :].sum()
# 最终分箱结果
bins = co_tab1.index.map(lambda x: x.right).tolist()
return bins
3. 示例
3.1 数据准备
我们使用 Kaggle 上的 titanic 数据集来演示卡方值分箱算法的使用。首先,我们需要将连续型变量 Age 进行分箱处理。
import pandas as pd
df = pd.read_csv('train.csv')
age_bins = chiMerge(df, 'Age', 'Survived')
运行上述代码,即可得到分好箱的结果:
[2.0, 15.0, 28.0, 36.0, 45.0, 55.0, 65.0, 80.0]
我们看到,原来的连续区间被离散化成了若干个离散的项,共分成了 7 个箱子。
3.2 可视化分箱结果
我们可以通过绘图来直观地展示分箱结果。
import seaborn as sns
sns.histplot(data=df, x='Age', hue='Survived', bins=age_bins[:-1], kde=True)
运行上述代码,即可得到下图:
3.3 模型建立
通过卡方值分箱方法,我们成功地将连续型变量进行了离散化,使之便于建模。下一步是使用分好箱的数据训练模型。
train_data = df.copy()
train_data['Age'] = pd.cut(train_data['Age'], bins=age_bins, right=True, include_lowest=True)
# 选择特征
cols = ['Pclass', 'Sex', 'Age', 'SibSp', 'Parch', 'Fare']
X = pd.get_dummies(train_data[cols])
y = train_data['Survived']
# 训练模型
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(random_state=0)
model.fit(X, y)
运行上述代码,即可得到训练好的决策树模型。
4. 总结
本文介绍了 python 中基于卡方值分箱算法的实现示例。通过使用卡方值分箱方法,我们将连续型变量进行了离散化,使之便于建模。卡方值分箱算法简单易懂,实现也比较容易,非常适合数据挖掘初学者使用。