分箱 hscredit.core.binning
提供 17 种分箱算法与二维交互分箱,全部继承统一基类 BaseBinning,并由工厂类
OptimalBinning 作为统一入口。所有分箱指标统一通过 core.metrics 计算。
类别变量分箱
类别变量会先转换为有序编码,再交给所选 method 的原生数值分箱算法决定边界。
因此等宽、等频、树、卡方、KS、IV、MDLP 等方法仍分别使用自己的切分和合并标准,
不会在 OptimalBinning 中被替换为同一种类别合并结果。
默认顺序按训练集坏样本率升序生成;坏样本率相同的类别保持首次出现顺序。也可以通过
category_order 为指定字段提供完整顺序。下面使用 hscredit_hsk.xlsx 的 工资
字段主动指定顺序:
import pandas as pd
from hscredit.core.binning import OptimalBinning
df = pd.read_excel("examples/hscredit_hsk.xlsx")
X = df.drop(columns="target")
y = df["target"]
wage_order = X["工资"].dropna().drop_duplicates().tolist()
binner = OptimalBinning(
method="best_iv",
max_n_bins=5,
cat_cutoff=10,
category_order={"工资": wage_order},
).fit(X, y)
assert binner._category_orders_["工资"] == wage_order
category_order 也可传入 callable(feature, x, y)。函数应返回当前字段的完整非缺失
类别序列;缺少类别、重复类别或包含训练集以外的类别都会抛出中文 ValueError。
数值编码的状态字段不会默认当作类别变量,需要通过 cat_cutoff 显式启用。例如
cat_cutoff=10 表示唯一值数量不超过 10 的数值字段按类别处理。
自定义类别分箱
自定义类别分箱使用 List[List],必须完整覆盖训练类别,且类别和缺失标记不能重复。
缺失值既可以单独成箱,也可以与普通类别放在同一箱:
import numpy as np
missing_alone = {
"工资": [wage_order[:4], wage_order[4:8], wage_order[8:], [np.nan]],
}
missing_mixed = {
"工资": [wage_order[:4], wage_order[4:8], [*wage_order[8:], np.nan]],
}
strict = OptimalBinning(
user_splits=missing_alone,
user_splits_fixed=True,
).fit(X[["工资"]], y)
mixed = OptimalBinning(
user_splits=missing_mixed,
user_splits_fixed=True,
missing_separate=False,
).fit(X[["工资"]], y)
user_splits_fixed=True 会完整保留用户分组;非严格模式把每个用户组视为不可拆分的
原子单位,再用当前 method 决定是否合并相邻组。未知预测期类别默认转换为索引 -3、
标签 unknown 和中性 WOE 0.0。handle_unknown='value' 与默认 -3 等价;
handle_unknown='raise' 会在 transform 遇到训练期未知类别时直接报错;也可指定任意已记录的整数箱号。
max_n_bins、min_bin_size、max_bin_size、min_bad_rate 和明确的单调方向同样
适用于类别路径。如果单个类别或用户原子组本身已使约束不可满足,分箱器会指出字段、参数和
实际值,而不是静默忽略限制。
分箱算法模块 - 统一接口整合所有分箱方法.
提供多种分箱算法的统一接口,所有方法都可以通过 OptimalBinning 访问:
基础方法: - uniform: 等宽分箱 - quantile: 等频分箱 - tree: 决策树分箱 - chi: 卡方分箱
优化方法: - best_ks: 最优KS分箱 - best_iv: 最优IV分箱 - mdlp: MDLP分箱(基于信息论,默认)
运筹规划方法: - or_tools: OR-Tools 启发式+DP 最优化分箱 - cp_sat: CP-SAT 约束规划分箱(全局最优解)
高级方法: - cart: CART分箱(参考optbinning实现) - monotonic: 单调性约束分箱(支持U型/倒U型/凸/凹) - genetic: 遗传算法分箱 - smooth: 平滑/正则化分箱 - kernel_density: 核密度分箱 - best_lift: Best Lift分箱 - target_bad_rate: 目标坏样本率分箱
主要类
BaseBinning: 分箱算法基类
OptimalBinning: 统一分箱接口(推荐)
各具体分箱类: UniformBinning, QuantileBinning, TreeBinning, CartBinning, ChiMergeBinning, BestKSBinning, BestIVBinning, MDLPBinning, ORBinning, CPSATBinning, CustomObjectives, KMeansBinning, MonotonicBinning, GeneticBinning, SmoothBinning, KernelDensityBinning, BestLiftBinning, TargetBadRateBinning
快速开始
>>> from hscredit.core.binning import OptimalBinning
>>> # 使用MDLP分箱(默认)
>>> binner = OptimalBinning(method='mdlp', max_n_bins=5)
>>>
>>> # 使用最优IV分箱
>>> binner = OptimalBinning(method='best_iv', max_n_bins=5)
>>> binner.fit(X_train, y_train)
>>> X_binned = binner.transform(X_test)
>>> bin_table = binner.get_bin_table('feature_name')
>>> # 使用单调性约束(支持U型/倒U型)
>>> binner = OptimalBinning(method='monotonic', monotonic='peak')
>>> binner.fit(X, y)
>>> # 指定切分点
>>> binner = OptimalBinning(user_splits={'age': [25, 35, 45]})
>>> binner.fit(X, y)
>>> # 自动选择最优方法
>>> best_method = OptimalBinning.auto_select_method(X, y, 'feature')
>>> binner = OptimalBinning(method=best_method)
>>> binner.fit(X, y)
- class hscredit.core.binning.BaseBinning(target='target', missing_separate=True, min_n_bins=2, max_n_bins=5, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, cat_cutoff=None, user_splits=None, user_splits_fixed=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, verbose=False, decimal=4, woe_clip=None, parallel_backend=None, parallel_config=None)[源代码]
基类:
ParallelizableMixin,ArtifactSerializableMixin,BaseEstimator,TransformerMixin,ABC分箱算法基类.
所有分箱算法都继承此类,实现统一的fit/transform接口。 支持16种分箱方法,适用于风控评分卡开发场景。
参数
- 参数:
target (str) -- 目标变量列名,默认为'target'。在scorecardpipeline风格中使用, 当fit时只传入df且y为None时,从df中提取该列作为目标变量。
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
min_n_bins (int) -- 最小分箱数,默认为2
max_n_bins (int) -- 最大分箱数,默认为5
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,用于避免极端情况,默认为0.0
monotonic (bool | str) -- 坏样本率单调性约束,默认为False - False: 不要求单调性 - True 或 'auto': 自动检测最佳趋势(允许单增、单减、正U、倒U) - 'auto_asc_desc': 自动检测,但只允许单增或单减(不允许U型) - 'auto_heuristic': 使用启发式方法自动确定单调方向 - 'ascending': 强制坏样本率递增(分箱索引增大时坏样本率增大) - 'descending': 强制坏样本率递减(分箱索引增大时坏样本率减小) - 'peak': 倒U型/峰值(先增后降) - 'valley': U型/谷值(先降后增) - 'peak_heuristic': 使用启发式方法检测峰值 - 'valley_heuristic': 使用启发式方法检测谷值
special_codes (List | None) -- 特殊值列表,这些值会被单独分箱,例如[-99, -98, 'missing']
cat_cutoff (int | float | None) -- 类别型变量处理阈值,默认为None - 如果 < 1, 表示保留占比超过该值的类别 - 如果 >= 1, 表示保留频率最高的N个类别
user_splits (Dict[str, List] | Callable | None) -- 用户自定义分箱规则,例如{'feature': [0, 10, 20, 30]}
user_splits_fixed (bool | Mapping[str, bool | Sequence[bool]] | None) -- 用户切分点固定配置,可按字段或节点选择性固定
random_state (int | None) -- 随机种子,用于可复现性,默认为None
n_jobs (int | float | None) -- 并行工作数,默认为-1;None沿用旧串行行为
parallel_backend (str | None) -- joblib并行后端,默认为None
parallel_config (Mapping[str, Any] | None) -- joblib扩展配置,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
decimal (int) -- 数值型切分点小数点保留精度,默认为4
woe_clip (float | None) -- WOE值截断阈值,默认为None 当某个分箱无坏样本或无好样本时,WOE可能变得极大(如±10以上), 这会导致评分卡中对应分箱的分数异常。 设置此参数可将WOE限制在[-woe_clip, woe_clip]范围内。 例如 woe_clip=5.0 可将WOE限制在[-5, 5]之间。
category_order (Dict[str, Sequence[Any]] | Callable[[str, Series, Series], Sequence[Any]] | None)
handle_unknown (int | Literal['value', 'raise'])
属性
splits_: 每个特征的分箱切分点,数值型特征为numpy数组,类别型特征为列表n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表,包含中文列名:分箱: 分箱索引
分箱标签: 分箱区间标签
样本总数: 样本数
样本占比: 样本占比
好样本数: 好样本数
坏样本数: 坏样本数
坏样本率: 坏样本率
分档WOE值: WOE值
分档IV值: IV值
指标IV值: 总IV值
LIFT值: Lift值
坏账改善: 坏账改善
累积LIFT值: 累积Lift值
累积坏账改善: 累积坏账改善
累积好样本数: 累积好样本数
累积坏样本数: 累积坏样本数
分档KS值: KS值
feature_types_: 每个特征的类型 ('numerical' 或 'categorical')
支持的分箱方法
方法
类名
说明
uniform
UniformBinning
等宽分箱,将数值范围等分
quantile
QuantileBinning
等频分箱,每箱样本数相等
tree
TreeBinning
决策树分箱,基于信息增益
chi
ChiMergeBinning
卡方分箱,基于卡方统计量合并
best_ks
BestKSBinning
最优KS分箱,最大化KS统计量
best_iv
BestIVBinning
最优IV分箱,最大化IV值(推荐)
mdlp
MDLPBinning
MDLP分箱,信息论方法
or_tools
ORBinning
运筹规划分箱(基于Google OR-Tools)
cart
CartBinning
CART分箱,参考optbinning实现
monotonic
MonotonicBinning
单调性约束分箱,支持U型/倒U型
genetic
GeneticBinning
遗传算法分箱,全局优化
smooth
SmoothBinning
平滑分箱,正则化方法
kernel_density
KernelDensityBinning
核密度分箱,密度估计
best_lift
BestLiftBinning
Best Lift分箱,提升度优化
target_bad_rate
TargetBadRateBinning
目标坏样本率分箱
kmeans
KMeansBinning
K-Means聚类分箱
optimal
OptimalBinning
统一接口,支持上述所有方法
参考样例
基本使用 (sklearn风格):
>>> from hscredit.core.binning import OptimalBinning >>> binner = OptimalBinning(method='best_iv', max_n_bins=5) >>> binner.fit(X, y) >>> X_binned = binner.transform(X) >>> bin_table = binner.get_bin_table('feature_name')
scorecardpipeline风格 (目标列在DataFrame中):
>>> from hscredit.core.binning import OptimalBinning >>> # 初始化时指定目标列名,fit时传入完整DataFrame >>> binner = OptimalBinning(target='target', method='best_iv', max_n_bins=5) >>> binner.fit(df) >>> X_binned = binner.transform(df.drop(columns=['target'])) >>> bin_table = binner.get_bin_table('feature_name')
混合风格 (y参数优先):
>>> # 即使初始化时指定了target,fit时传入y会优先使用y >>> binner = OptimalBinning(target='target', method='best_iv') >>> binner.fit(df, y=external_y)
设置切分点精度:
>>> # 默认4位小数 >>> binner = OptimalBinning(method='best_iv', decimal=4) >>> # 设置为2位小数 >>> binner = OptimalBinning(method='best_iv', decimal=2)
单调性约束:
>>> binner = OptimalBinning(method='best_iv', monotonic='descending') >>> binner.fit(X, y)
使用独立分箱类:
>>> from hscredit.core.binning import ChiMergeBinning, BestIVBinning >>> chi_binner = ChiMergeBinning(max_n_bins=5) >>> chi_binner.fit(X, y)
注意
分箱算法的一般流程: 1. fit(): 训练分箱模型
数据预处理 (缺失值处理、特殊值处理)
检测特征类型 (数值型/类别型)
计算最优分箱切分点
对数值型切分点进行四舍五入(精度由decimal参数控制)
生成分箱统计表
transform(): 应用分箱 - 根据切分点对数据进行分箱 - 支持多种输出格式: 'indices'(分箱索引), 'labels'(分箱标签),
'woe'(WOE值), 'bin_code'(分箱编码)
- artifact_kind = '分箱器'
- export(to_json=None)[源代码]
导出 hscredit 严格分箱规则.
数值型变量返回切分点列表,类别型变量返回分组列表。 同时导出WOE映射信息,支持加载后直接进行WOE转换。
- 参数:
to_json (str | None) -- 可选,JSON 文件保存路径。如果提供,将规则保存到该文件
- 返回:
分箱规则字典 - 数值型: {'age': [25, 35, 45, 55]} - 类别型: {'city': [['北京', '上海'], ['广州', '深圳'], [np.nan]]} - WOE映射: {'_woe_maps_': {'age': {0: 0.5, 1: -0.3, ...}}}
- 返回类型:
Dict[str, List | List[List]]
参考样例
>>> binner = OptimalBinning() >>> binner.fit(X, y) >>> >>> # 导出为字典 >>> rules = binner.export() >>> >>> # 导出并保存到 JSON 文件 >>> rules = binner.export(to_json='binning_rules.json')
WOE转换支持
导出的规则包含WOE映射信息,加载后可直接进行WOE转换:
>>> binner = OptimalBinning() >>> binner.load('binning_rules.json') >>> X_woe = binner.transform(X_test, metric='woe') # 直接使用,无需重新fit
- export_rules()[源代码]
导出分箱规则.
数值型变量返回切分点列表,类别型变量返回分组列表。
- 返回:
分箱规则字典 - 数值型: key为特征名,value为切分点列表,如 [25, 35, 45, 55] - 类别型: key为特征名,value为分组列表,如 [['A', 'B'], ['C'], [np.nan]]
- 返回类型:
Dict[str, List | List[List]]
参考样例
>>> binner = OptimalBinning() >>> binner.fit(X, y) >>> rules = binner.export_rules() >>> >>> # 数值型变量 >>> print(rules['age']) # [25, 35, 45, 55] >>> >>> # 类别型变量 >>> print(rules['city']) # [['北京', '上海'], ['广州', '深圳'], [np.nan]] >>> >>> # 保存规则 >>> import json >>> import numpy as np >>> >>> # 处理np.nan以便JSON序列化 >>> def convert_nan(obj): ... if isinstance(obj, dict): ... return {k: convert_nan(v) for k, v in obj.items()} ... elif isinstance(obj, list): ... return [convert_nan(item) for item in obj] ... elif isinstance(obj, float) and np.isnan(obj): ... return "NaN" ... return obj >>> >>> with open('binning_rules.json', 'w') as f: ... json.dump(convert_nan(rules), f, indent=2)
- abstractmethod fit(X, y=None, **kwargs)[源代码]
拟合分箱。
支持两种API风格: 1. sklearn风格: fit(X, y) - X是特征矩阵,y是目标变量 2. scorecardpipeline风格: fit(df) - df是完整数据框,目标列名在初始化时通过target参数传入
优先级规则:如果y不是None,直接使用y(优先);否则从X中提取target列。
- 参数:
X (DataFrame | ndarray) -- 训练数据 - sklearn风格: 特征矩阵,shape (n_samples, n_features),可以是数值型或类别型特征 - scorecardpipeline风格: 完整数据框,包含特征列和目标列 - 支持DataFrame或numpy数组
y (ndarray | Series | None) -- 目标变量(可选) - sklearn风格: 传入目标变量,必须是二分类 (0/1 或 False/True) - scorecardpipeline风格: 不传,从X中提取 - 如果传入y,优先使用y而忽略X中的target列
kwargs -- 其他参数,传递给具体的分箱算法
- 返回:
拟合后的分箱器
- 返回类型:
注意
fit方法会进行以下操作: 1. 数据验证和预处理(通过_check_input方法) 2. 识别特征类型 (数值型/类别型) 3. 处理缺失值和特殊值 4. 计算最优分箱切分点 5. 生成分箱统计表
使用示例
sklearn风格:
>>> X = pd.DataFrame({'age': [25, 30, 35], 'income': [5000, 6000, 7000]}) >>> y = pd.Series([0, 1, 0]) >>> binner.fit(X, y)
scorecardpipeline风格:
>>> df = pd.DataFrame({ ... 'age': [25, 30, 35], ... 'income': [5000, 6000, 7000], ... 'target': [0, 1, 0] ... }) >>> binner = OptimalBinning(target='target') >>> binner.fit(df) # 自动从df中提取'target'列
混合风格(y参数优先):
>>> binner = OptimalBinning(target='target') >>> binner.fit(df, y=external_y)
- fit_transform(X, y=None, metric='indices', **kwargs)[源代码]
拟合并应用分箱。
支持两种API风格: 1. sklearn风格: fit_transform(X, y) - X是特征矩阵,y是目标变量 2. scorecardpipeline风格: fit_transform(df) - df是完整数据框,目标列名在初始化时通过target参数传入
- 参数:
X (DataFrame | ndarray) -- 训练数据 - sklearn风格: 特征矩阵,shape (n_samples, n_features) - scorecardpipeline风格: 完整数据框,包含特征列和目标列
y (ndarray | Series | None) -- 目标变量(可选) - sklearn风格: 传入目标变量 - scorecardpipeline风格: 不传,从X中提取
metric (str) -- 返回值的类型,默认为'indices' - 'indices': 返回分箱索引 - 'bins': 返回分箱标签 - 'woe': 返回WOE值
- 返回:
分箱后的数据
- 返回类型:
DataFrame | ndarray
使用示例
sklearn风格:
>>> X_binned = binner.fit_transform(X, y, metric='woe')
scorecardpipeline风格:
>>> binner = OptimalBinning(target='target') >>> X_binned = binner.fit_transform(df, metric='woe')
- get_bin_table(feature)[源代码]
获取指定特征的分箱表.
- 参数:
feature (str) -- 特征名
- 返回:
分箱统计表(返回副本,修改不会影响分箱器内部数据)
- 抛出:
NotFittedError -- 如果分箱器尚未拟合
FeatureNotFoundError -- 如果特征不存在
- 返回类型:
DataFrame
- get_splits(feature)[源代码]
获取指定特征的切分点(scorecardpipeline 格式).
数值型特征:np.nan 的位置表示缺失值归属的普通箱。 类别型特征:返回 List[List] 分组列表。
- 参数:
feature (str) -- 特征名
- 返回:
切分点列表
- 返回类型:
ndarray | list
- import_rules(rules)[源代码]
导入分箱规则.
支持数值型切分点和类别型分组列表。
- 参数:
rules (Dict[str, List | List[List]]) -- 分箱规则字典 - 数值型: {'age': [25, 35, 45, 55]} - 类别型: {'city': [['北京', '上海'], ['广州', '深圳'], [np.nan]]}
调用本方法时沿用增量覆盖语义,导入后可立即 transform。随后调用 fit 时, 仅把最近一次导入规则中同时属于本轮 X 的特征作为候选输入;普通分箱器仍 重新运行其算法,OptimalBinning 则保留这些导入切点并补充分箱统计。
参考样例
>>> # 导入数值型规则 >>> rules = {'age': [25, 35, 45, 55]} >>> binner.import_rules(rules) >>> >>> # 导入类别型规则 >>> rules = {'city': [['北京', '上海'], ['广州', '深圳'], [np.nan]]} >>> binner.import_rules(rules) >>> >>> # 从JSON文件导入 >>> import json >>> import numpy as np >>> >>> def convert_nan_back(obj): ... if isinstance(obj, dict): ... return {k: convert_nan_back(v) for k, v in obj.items()} ... elif isinstance(obj, list): ... return [convert_nan_back(item) for item in obj] ... elif obj == "NaN": ... return np.nan ... return obj >>> >>> with open('binning_rules.json', 'r') as f: ... rules = json.load(f) >>> rules = convert_nan_back(rules) >>> binner.import_rules(rules)
- load(from_json, update=False)[源代码]
加载 hscredit 严格分箱规则.
从字典或 JSON 文件加载数值规则或严格
List[List]类别规则。 同时加载WOE映射信息,支持加载后直接进行WOE转换。- 参数:
from_json (str | Dict) -- 分箱规则字典或 JSON 文件路径 - 字典: {'age': [25, 35, 45, 55]} - 文件路径: 'binning_rules.json'
update (bool) -- 是否更新现有规则(而非替换),默认为 False
- 返回:
self,支持链式调用
- 返回类型:
参考样例
>>> binner = OptimalBinning() >>> >>> # 从字典加载 >>> rules = {'age': [25, 35, 45, 55], 'gender': [['M'], ['F']]} >>> binner.load(rules) >>> >>> # 从 JSON 文件加载 >>> binner.load('binning_rules.json') >>> >>> # 更新现有规则 >>> binner.load({'new_feature': [1, 2, 3]}, update=True)
WOE转换支持
加载包含WOE映射信息的规则后,可直接进行WOE转换:
>>> binner.load('binning_rules.json') >>> X_woe = binner.transform(X_test, metric='woe') # 直接使用,无需重新fit
- plot(feature, save=None, **kwargs)[源代码]
绘制分箱图.
- 参数:
feature (str) -- 特征名
save (str | None) -- 图片保存路径,默认为None
kwargs -- 其他绘图参数
注意
绘制内容包括: 1. 各分箱的样本数分布 2. 各分箱的坏样本率 3. 各分箱的WOE值
- 返回:
matplotlib Figure 对象
- 参数:
feature (str)
save (str | None)
- abstractmethod transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。 这是分箱器的核心方法,用于将新数据应用到已训练的分箱规则。
- 参数:
X (DataFrame | ndarray) -- 待转换的数据,shape (n_samples, n_features) - 支持DataFrame或numpy数组 - 列名必须与fit时的特征名一致
metric (str) --
转换类型,默认为'indices' - 'indices': 返回分箱索引 (0, 1, 2, ...)
用途: 后续处理、特征工程
示例: [0, 1, 2, 0, 1, ...]
- 'bins': 返回分箱标签字符串
用途: 可视化、报告展示
示例: ['(-inf, 25]', '(25, 35]', '(35, 45]', ...]
类别型: ['北京,上海', '广州,深圳', ...]
- 'woe': 返回WOE值
用途: 逻辑回归建模
示例: [0.234, -0.456, 0.123, ...]
kwargs -- 其他参数
- 返回:
转换后的数据,返回类型与输入类型一致
- 返回类型:
DataFrame | ndarray
重要说明
metric参数是枚举值,只能使用以下3个值之一: - 'indices' (不是'分箱'、'索引'等中文) - 'bins' (不是'分箱标签'等中文) - 'woe' (不是'分档WOE值'等中文)
中文列名出现在分箱结果表中: - 使用 binner.get_bin_table(feature) 查看 - 列名: '分箱', '样本总数', '坏样本率', '分档WOE值'等
参考样例
>>> binner = OptimalBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> print(X_binned.head()) >>> >>> # 获取分箱标签 >>> X_labels = binner.transform(X_test, metric='bins') >>> print(X_labels.head()) >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe') >>> print(X_woe.head()) >>> >>> # 错误示例 - 不要使用中文 >>> # X_error = binner.transform(X_test, metric='分档WOE值') # ❌ ValueError!
处理特殊值
transform方法会自动处理: 1. 缺失值: 如果missing_separate=True,分配到专门的缺失箱 (索引=-1) 2. 特殊值: 如果指定了special_codes,分配到专门的特殊值箱 (索引=-2) 3. 超出范围的值: 分配到最近的分箱
- update(splits_dict, X=None, y=None)[源代码]
手动更新特征的切分点并重新计算相关属性.
参考 toad.Combiner.update 方法,允许在分箱器训练完成后手工修改切分点。 更新后会自动重新计算
n_bins_、feature_types_、_cat_bins_ 等属性。 如果提供 X 和 y,还会重新计算bin_tables_分箱统计表。参数
- 参数:
splits_dict (Dict[str, List | List[List]]) -- 新的切分点字典,格式与 export_rules() 返回的相同 - 数值型: {'age': [25, 35, 45, 55]} - 类别型: {'city': [['北京', '上海'], ['广州', '深圳'], [np.nan]]}
X (DataFrame | ndarray | None) -- 可选,训练数据。如果提供,会重新计算分箱统计表
y (ndarray | Series | None) -- 可选,目标变量
- 返回类型:
返回
- 返回:
self,支持链式调用
- 参数:
splits_dict (Dict[str, List | List[List]])
X (DataFrame | ndarray | None)
y (ndarray | Series | None)
- 返回类型:
参考样例
>>> # 只更新切分点(不重新计算统计表) >>> binner.update({'age': [20, 30, 40, 50]})
>>> # 更新切分点并重新计算统计表 >>> binner.update({'age': [20, 30, 40, 50]}, X=X_train, y=y_train)
>>> # 批量更新多个特征 >>> binner.update({ ... 'age': [20, 30, 40], ... 'income': [5000, 10000, 20000], ... 'city': [['北京', '上海'], ['广州', '深圳']] ... })
>>> # 链式调用 >>> binner.update({'age': [20, 30, 40]}).transform(X_test)
- class hscredit.core.binning.UniformBinning(max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, left_clip=None, right_clip=None, force_numerical=False, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinning等距分箱.
将特征值的范围等分为指定数量的区间,每个区间宽度相同。 适用于数据分布相对均匀的场景。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 是否要求单调性,默认为False
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (List | None) -- 特殊值列表,默认为None,如[-999, -98]
left_clip (float | None) -- 左侧截断分位数,默认为None,如0.01表示截断1%分位数以下的值
right_clip (float | None) -- 右侧截断分位数,默认为None,如0.99表示截断99%分位数以上的值
force_numerical (bool) -- 是否强制作为数值型处理,默认为False(自动识别类别型) - True: 将所有特征视为数值型进行等距分箱(默认,因为等距分箱适用于数值型) - False: 自动检测特征类型(根据dtype判断)
random_state (int | None) -- 随机种子,默认为None
cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | Sequence[bool]] | None)
参考样例
>>> from hscredit.core.binning import UniformBinning >>> # 基础用法 >>> binner = UniformBinning(max_n_bins=5) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> >>> # 使用截断处理异常值 >>> binner = UniformBinning(max_n_bins=5, left_clip=0.01, right_clip=0.99) >>> binner.fit(X_train, y_train) >>> >>> # 指定特殊值 >>> binner = UniformBinning(max_n_bins=5, special_codes=[-999, -98]) >>> binner.fit(X_train, y_train)
注意
等距分箱的特点: 1. 每个分箱的区间宽度相同 2. 分箱边界由 (max - min) / n_bins 计算得出 3. 支持通过left_clip/right_clip截断异常值 4. 支持通过special_codes处理特殊值(如-999表示缺失) 5. 默认force_numerical=False,自动识别类别型;如需强制数值等距分箱可显式设为 True 6. 计算速度快,实现简单;为无监督方法,不使用标签
y决定切分 7. 对偏态分布或含极端值的特征不友好(可能某些箱样本极少),此时优先用等频分箱引用
等距(equal-width)离散化综述见 Dougherty, J., Kohavi, R., & Sahami, M. (1995). Supervised and Unsupervised Discretization of Continuous Features. ICML-95. https://ai.stanford.edu/~ronnyk/disc.pdf
- fit(X, y=None, **kwargs)[源代码]
拟合等距分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据
y (ndarray | Series | None) -- 目标变量
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = UniformBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.QuantileBinning(target='target', min_n_bins=2, max_n_bins=10, quantiles=None, force_numerical=False, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning等频分箱算法.
将特征值按照分位数切分成多个区间,确保每个区间的样本数大致相等。 适用于数据分布不均匀或存在异常值的场景。
- 参数:
min_n_bins (int) -- 最小分箱数,默认为2
max_n_bins (int) -- 最大分箱数,默认为10
quantiles (List[float] | None) --
自定义分位点列表,如[0, 0.2, 0.5, 0.8, 1.0],默认为None - 如果提供,将直接使用这些分位点进行分箱 - 首尾的 0 与 1 支持自动补齐:可传入完整的 [0, ..., 1],
也可只传中间分位点(如 [0.2, 0.5, 0.8]),缺失的 0 / 1 会自动补齐
force_numerical (bool) -- 是否强制作为数值型处理,默认为False(自动识别类别型) - True: 将所有特征视为数值型进行等频分箱 - False: 自动检测特征类型
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 是否要求坏样本率单调,默认为False
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表
参考样例
>>> from hscredit.core.binning import QuantileBinning >>> # 基础用法 >>> binner = QuantileBinning(max_n_bins=5) >>> binner.fit(X, y) >>> X_binned = binner.transform(X) >>> >>> # 使用自定义分位点 >>> binner = QuantileBinning(quantiles=[0, 0.1, 0.3, 0.7, 0.9, 1.0]) >>> binner.fit(X, y)
注意
等频分箱为无监督方法,仅依据特征自身分布切分、不使用标签
y``(``y仅用于 生成分箱统计表),因此对异常值稳健、各箱样本量均衡,常用作有监督分箱的预分箱。引用
等频(equal-frequency)离散化综述见 Dougherty, J., Kohavi, R., & Sahami, M. (1995). Supervised and Unsupervised Discretization of Continuous Features. ICML-95. https://ai.stanford.edu/~ronnyk/disc.pdf
- fit(X, y=None, **kwargs)[源代码]
拟合等频分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据,shape (n_samples, n_features)
y (ndarray | Series | None) -- 目标变量,二分类 (0/1)
kwargs -- 其他参数
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = QuantileBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.TreeBinning(target='target', max_depth=5, max_leaf_nodes=None, min_samples_leaf=0.05, min_n_bins=2, max_n_bins=10, force_numerical=False, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning决策树分箱算法.
以 sklearn
DecisionTreeClassifier对单特征拟合一棵决策树, 取其内部节点的分裂阈值作为切分点。分裂以基尼系数 / 信息增益最大化为准则,因而切分 天然贴合目标变量。支持最大深度、叶子节点数与单调性约束。- 参数:
max_depth (int) -- 决策树最大深度,默认为5(越大切分越细)
max_leaf_nodes (int | None) -- 最大叶子节点数(约等于最大分箱数上限),默认为None
min_samples_leaf (float | int) -- 叶子节点最小样本数(
<1为占比,>=1为绝对数),默认为0.05min_n_bins (int) -- 最小分箱数,默认为2
max_n_bins (int) -- 最大分箱数,默认为10
force_numerical (bool) -- 是否强制作为数值型处理,默认为False
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 是否要求坏样本率单调,默认为False
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表tree_models_: 每个特征的决策树模型
参考样例
>>> from hscredit.core.binning import TreeBinning >>> binner = TreeBinning(max_depth=5, monotonic=True) >>> binner.fit(X, y) >>> X_binned = binner.transform(X)
引用
决策树分裂准则参见 Breiman, L. et al. (1984). Classification and Regression Trees. Wadsworth;实现基于 sklearn https://scikit-learn.org/stable/modules/generated/sklearn.tree.DecisionTreeClassifier.html
- fit(X, y=None, **kwargs)[源代码]
拟合决策树分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据,shape (n_samples, n_features)
y (ndarray | Series | None) -- 目标变量,二分类 (0/1)
kwargs -- 其他参数
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = TreeBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.CartBinning(target='target', max_n_bins=10, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, min_event_rate_diff=0.0, max_pvalue=None, max_pvalue_policy='consecutive', monotonic=False, class_weight=None, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningCART 分箱算法.
基于决策树的分箱方法,参考 optbinning 的 CART 预分箱实现。 使用 sklearn 的 DecisionTreeClassifier/Regressor 提取最优分割点。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为10
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_event_rate_diff (float) -- 相邻箱最小坏样本率差异,默认为0 - 如果设置,会合并坏样本率差异过小的相邻箱
max_pvalue (float | None) -- 最大 p-value 阈值,默认为None - 如果设置,会进行统计检验,合并差异不显著的相邻箱
max_pvalue_policy (str) -- p-value 检验策略,默认为"consecutive" - "all": 检验所有箱对 - "consecutive": 只检验相邻箱
monotonic (bool | str) -- 是否要求单调性,默认为False - False: 不要求 - True 或 'auto': 自动判断单调方向 - 'ascending': 强制递增 - 'descending': 强制递减
class_weight (str | Dict | None) -- 类别权重,默认为None - None: 不调整 - "balanced": 自动根据类别频率调整 - dict: 自定义权重,如 {0: 1, 1: 2}
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
random_state (int | None) -- 随机种子,默认为None
target (str)
min_bad_rate (float)
cat_cutoff (int | float | None)
handle_unknown (int | str)
verbose (bool)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表tree_models_: 每个特征的决策树模型
参考样例
>>> from hscredit.core.binning import CartBinning >>> binner = CartBinning(max_n_bins=5, monotonic=True) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
注意
CART 分箱的特点: 1. 基于决策树的信息增益选择切分点 2. 支持分类(二分类/多分类)和回归目标变量 3. 可设置类别权重处理不平衡数据 4. 支持 p-value 检验确保分箱统计显著性 5. 支持单调性约束
与
TreeBinning的区别:CART 额外提供 p-value 显著性检验合并、相邻箱坏样本率 最小差异约束(min_event_rate_diff)及回归目标支持,预分箱流程对齐 optbinning。引用
Breiman, L., Friedman, J., Olshen, R., & Stone, C. (1984). Classification and Regression Trees. Wadsworth;预分箱实现参考 optbinning https://gnpalencia.org/optbinning/
- fit(X, y=None, **kwargs)[源代码]
拟合 CART 分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据,shape (n_samples, n_features)
y (ndarray | Series | None) -- 目标变量,可以是二分类、多分类或连续型
kwargs -- 其他参数
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = CARTBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.ChiMergeBinning(target='target', max_n_bins=10, min_n_bins=2, min_chi2_threshold=None, significance_level=0.05, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning卡方分箱算法 (ChiMerge)。
一种自底向上(bottom-up)的有监督分箱方法。其核心假设是:若相邻两箱的好坏样本 分布无显著差异(卡方值小),则可以合并。算法流程:
初始化:将每个唯一值(或预分位点)各作为一个箱;
迭代合并:对所有相邻箱对计算 2×2 列联表的卡方统计量,合并卡方值最小的一对;
停止:当最小卡方值超过阈值
min_chi2_threshold,或箱数降至max_n_bins、min_n_bins限制时停止。
卡方值越大表示相邻两箱坏样本率差异越显著、越不应合并。继承
BaseBinning, 完整的分箱通用参数、属性与转换语义见基类。参数(本算法特有及关键项)
- 参数:
target (str) -- 目标列名(scorecardpipeline 风格),默认为
'target'max_n_bins (int) -- 最大分箱数,默认为
10min_n_bins (int) -- 最小分箱数,默认为
2min_chi2_threshold (float | None) -- 卡方合并阈值(停止合并的下限),默认为
None。 为None时取自由度 1、显著性水平significance_level的卡方临界值 (如 0.05 对应约 3.841)。当相邻箱的最小卡方值大于该阈值即停止合并significance_level (float) -- 显著性水平,用于在
min_chi2_threshold为None时 换算卡方临界值,默认为 ``0.05``(值越小阈值越大、分箱越粗)min_bin_size (float | int) -- 每箱最小样本数(
>=1)或占比(<1),默认为0.01max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为
Nonemin_bad_rate (float) -- 每箱最小坏样本率,默认为
0.0monotonic (bool | str) -- 坏样本率单调性约束,取值见
BaseBinning,默认为Falsespecial_codes (List | None) -- 特殊值列表,单独成箱,默认为
Nonemissing_separate (bool) -- 是否将缺失值单独成箱,默认为
Truerandom_state (int | None) -- 随机种子,默认为
Noneverbose (bool | int) -- 是否输出合并过程日志,默认为
Falsedecimal (int) -- 数值切分点保留小数位,默认为
4cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表(中文列名,见BaseBinning)
参考样例
>>> from hscredit.core.binning import ChiMergeBinning >>> binner = ChiMergeBinning(max_n_bins=5, significance_level=0.05) >>> binner.fit(X, y) # sklearn 风格 >>> X_woe = binner.transform(X, metric='woe') >>> binner.get_bin_table('age') # 查看某特征分箱明细
指定卡方阈值并要求坏样本率单调递减:
>>> binner = ChiMergeBinning(min_chi2_threshold=6.635, monotonic='descending') >>> binner.fit(X, y)
引用
Kerber, R. (1992). ChiMerge: Discretization of Numeric Attributes. Proceedings of AAAI-92. https://www.aaai.org/Papers/AAAI/1992/AAAI92-019.pdf
- fit(X, y=None, **kwargs)[源代码]
拟合卡方分箱。
对每个特征执行 ChiMerge 合并,得到切分点与分箱统计表。支持 sklearn 风格
fit(X, y)与 scorecardpipeline 风格fit(df)``(目标列由 ``target指定), 详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features);可为 DataFrame 或 ndarrayy (ndarray | Series | None) -- 目标变量,二分类(0=好/1=坏);scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
参考样例
>>> ChiMergeBinning(max_n_bins=5).fit(X, y).transform(X, metric='woe')
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = ChiMergeBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.BestKSBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningBest KS 分箱.
基于最大化KS统计量的分箱方法,寻找能够最大化区分能力的分箱点。 使用贪心算法逐步优化。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 坏样本率单调性约束,默认为False - False: 不要求单调性 - True 或 'auto': 自动检测并应用最佳单调方向 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (List | None) -- 特殊值列表,默认为None
random_state (int | None) -- 随机种子,默认为None
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import BestKSBinning >>> binner = BestKSBinning(max_n_bins=5) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
注意
Best KS 分箱的特点: 1. 以最大化 KS(Kolmogorov–Smirnov)统计量为目标选择切分点 2. KS = max |累计好样本占比 - 累计坏样本占比|,衡量好坏样本累积分布的最大差异 3. 使用贪心算法逐步优化,支持单调性约束 4. 相比等频/等距计算复杂度较高,但区分度更优
引用
Kolmogorov–Smirnov 检验:https://en.wikipedia.org/wiki/Kolmogorov–Smirnov_test ; KS 统计量在信用风险中的应用见 Siddiqi, N. (2006). Credit Risk Scorecards. Wiley.
- fit(X, y=None, **kwargs)[源代码]
拟合 Best KS 分箱。
对每个特征预分割为细箱后,在单调性约束下贪心选择切分点以最大化 KS 统计量。 支持 sklearn 风格
fit(X, y)与 scorecardpipeline 风格fit(df), 详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏);scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = BestKSBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.BestIVBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningBest IV 分箱.
基于最大化IV的分箱方法,寻找能够最大化预测能力的分箱点。 IV是衡量特征预测能力的重要指标。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 坏样本率单调性约束,默认为False - False: 不要求单调性 - True 或 'auto': 自动检测并应用最佳单调方向 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (List | None) -- 特殊值列表,默认为None
random_state (int | None) -- 随机种子,默认为None
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import BestIVBinning >>> binner = BestIVBinning(max_n_bins=5) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
注意
Best IV 分箱的特点: 1. 以最大化 IV(Information Value,信息价值)为目标,逐步贪心优化切分点 2. IV < 0.02:几乎无预测能力 3. 0.02 ≤ IV < 0.1:弱预测能力 4. 0.1 ≤ IV < 0.3:中等预测能力 5. IV ≥ 0.3:强预测能力(过高时需警惕标签泄漏或过拟合)
其中
IV = Σ (好样本占比 - 坏样本占比) × WOE,WOE = ln(箱内好样本占比 / 箱内坏样本占比)。引用
Information Value / WOE 经典出处:Siddiqi, N. (2006). Credit Risk Scorecards: Developing and Implementing Intelligent Credit Scoring. Wiley. IV 阈值经验区间参考业界通行标准(见 scorecard / toad / optbinning 文档)。
- fit(X, y=None, **kwargs)[源代码]
拟合 Best IV 分箱。
对每个特征预分割为细箱后,在单调性约束下贪心合并以最大化 IV,得到切分点与分箱 统计表。支持 sklearn 风格
fit(X, y)与 scorecardpipeline 风格fit(df), 详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏);scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = BestIVBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.OptimalBinning(target='target', method='mdlp', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, missing_separate=True, user_splits=None, user_splits_fixed=None, prebinning=None, prebinning_params=None, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, woe_clip=None, n_jobs=-1, parallel_backend=None, parallel_config=None, **kwargs)[源代码]
基类:
BaseBinning统一分箱接口 - 整合所有分箱方法.
提供统一的 fit/transform 接口,支持所有分箱方法。 融合 MonotonicBinning 的单调性约束功能。 支持指定切割点 (user_splits) 和预分箱。
架构设计原则
OptimalBinning 作为统一入口:集成所有分箱方法,支持预分箱功能
独立分箱模块保持简单:各个具体分箱类(如BestIVBinning、MDLPBinning等) 只执行一次分箱,不包含预分箱逻辑
预分箱在 OptimalBinning 层面实现:通过 prebinning 参数在统一接口层实现 预分箱+二次分箱的两阶段分箱流程
- 参数:
target (str) -- 目标变量列名,默认为'target'
method (str) --
分箱方法,默认为
'mdlp'。可取以下枚举值(按类别):无监督(不使用标签决定切分)
'uniform':等距分箱,按数值范围等宽切分,快但对偏态敏感'quantile':等频分箱,各箱样本量均衡,对异常值稳健,常作预分箱'kmeans':K-Means 聚类分箱,按数值聚类结构切分,适合自然分组'kernel_density':核密度分箱,以分布谷值为边界,适合多峰分布
有监督(结合标签寻优)
'tree':决策树分箱,取决策树分裂点,贴合目标'cart':CART 分箱(对齐 optbinning 预分箱),支持 p-value 检验/回归目标'chi':卡方分箱(ChiMerge),合并分布无显著差异的相邻箱'mdlp':MDLP 信息论分箱,自动确定分箱数(默认)'best_ks':最大化 KS 统计量'best_iv':最大化 IV(信息价值),评分卡常用'best_lift':最大化头部箱提升度 Lift,偏策略拒绝场景'target_bad_rate':按目标坏样本率梯度切分'monotonic':单调最优分箱,强约束坏样本率/WOE 单调(含 U/倒U)'genetic':遗传算法全局寻优,约束复杂时使用'smooth':平滑分箱,对箱内坏样本率做平滑收缩,适合小样本
运筹规划(数学规划全局最优)
'or_tools':基于 Google OR-Tools 的整数规划分箱'cp_sat':基于 CP-SAT 求解器的约束规划分箱
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None(不限制)
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0。坏样本率低于该值的分箱将与相邻 分箱合并;无论该参数取值,坏样本率为 0/1 的退化分箱都会被合并以避免 WOE 异常 (等宽 uniform / 等频 quantile 为保持切分结构精确,不参与该约束)
monotonic (bool | str) -- 坏样本率单调性约束,默认为False - False: 不要求单调性 - True 或 'auto': 自动检测最佳趋势(允许单增、单减、正U、倒U) - 'auto_asc_desc': 自动检测,但只允许单增或单减(不允许U型) - 'auto_heuristic': 使用启发式方法自动检测 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减 - 'peak': 允许单峰形态(先升后降,倒U型) - 'valley': 允许单谷形态(先降后升,正U型) - 'peak_heuristic': 使用启发式方法检测峰值 - 'valley_heuristic': 使用启发式方法检测谷值
user_splits (Dict[str, List] | Callable | None) -- 用户指定的切分点,支持: - Dict[str, List]: 每个特征的切分点,如 {'age': [25, 35, 45]} - Callable: 函数返回切分点
user_splits_fixed (bool | Mapping[str, bool | Sequence[bool]] | None) -- 用户切分点固定配置。支持全局布尔值,或按字段配置布尔值/布尔列表
prebinning (str | BaseBinning | Dict | None) -- 预分箱方法,支持: - str: 预分箱方法名(所有VALID_METHODS中的方法都可作为预分箱方法) - BaseBinning: 预分箱器实例 - Dict: 预分箱配置,如 {'method': 'cart', 'max_n_bins': 20} 默认为None(不进行预分箱)
prebinning_params (Dict | None) -- 预分箱参数,当prebinning为str时使用
special_codes (List | None) -- 特殊值列表,默认为None
cat_cutoff (int | float | None) -- 类别型变量处理阈值,默认为None
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
decimal (int) -- 数值型切分点保留的小数位数,默认为4
woe_clip (float | None) -- WOE值截断阈值,默认为None 当某个分箱无坏样本或无好样本时,WOE可能变得极大(如±10以上), 这会导致评分卡中对应分箱的分数异常。 设置此参数可将WOE限制在[-woe_clip, woe_clip]范围内。
kwargs -- 其他分箱方法特定参数
missing_separate (bool)
category_order (Dict[str, Sequence[Any]] | Callable[[str, Series, Series], Sequence[Any]] | None)
handle_unknown (int | Literal['value', 'raise'])
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
参考样例
>>> from hscredit.core.binning import OptimalBinning >>> # 使用MDLP分箱(默认,直接分箱) >>> binner = OptimalBinning(method='mdlp', max_n_bins=5) >>> binner.fit(X, y) >>> # 使用最优IV分箱(直接分箱) >>> binner = OptimalBinning(method='best_iv', max_n_bins=5) >>> binner.fit(X, y) >>> # 使用CART分箱(直接分箱) >>> binner = OptimalBinning(method='cart', max_n_bins=5) >>> binner.fit(X, y) >>> # 使用预分箱(MDLP先进行CART预分箱成20箱,再优化为5箱) >>> binner = OptimalBinning(method='mdlp', prebinning='cart', prebinning_params={'max_n_bins': 20}) >>> binner.fit(X, y) >>> # 使用预分箱器实例 >>> pre_binner = OptimalBinning(method='cart', max_n_bins=20) >>> binner = OptimalBinning(method='best_iv', prebinning=pre_binner) >>> binner.fit(X, y) >>> # 使用quantile预分箱(先将数据分成20等份,再进行MDLP分箱) >>> binner = OptimalBinning(method='mdlp', prebinning='quantile', prebinning_params={'max_n_bins': 20}) >>> binner.fit(X, y) >>> # 自动为某特征选择最优分箱方法 >>> best = OptimalBinning.auto_select_method(X, y, 'age') >>> binner = OptimalBinning(method=best).fit(X, y)
引用
最优分箱(optimal binning)的两阶段(预分箱 + 二次合并)框架与单调/规划求解参考 optbinning:Navas-Palencia, G. (2020). Optimal binning: mathematical programming formulation. arXiv:2001.08025. https://arxiv.org/abs/2001.08025 ; 各子方法的具体出处见对应分箱类文档。
- VALID_METHODS = ['uniform', 'quantile', 'tree', 'chi', 'best_ks', 'best_iv', 'mdlp', 'or_tools', 'cp_sat', 'cart', 'kmeans', 'monotonic', 'genetic', 'smooth', 'kernel_density', 'best_lift', 'target_bad_rate']
- static auto_select_method(X, y, feature, methods=None, criterion='iv', n_jobs=-1, parallel_backend=None, parallel_config=None)[源代码]
自动选择最优分箱方法.
对指定特征遍历多种分箱方法,选择最优的一个。 适用于在不了解特征分布时自动选择最佳分箱策略。
- 参数:
X (DataFrame) -- 特征数据 DataFrame
y (Series) -- 目标变量 Series,二分类 (0/1)
feature (str) -- 待评估的特征名(必须是X中的列)
methods (List[str] | None) -- 待评估的方法列表,默认为 ['uniform', 'quantile', 'tree', 'chi', 'best_ks', 'best_iv', 'mdlp', 'cart', 'kmeans']
criterion (str) -- 选择标准,默认为 'iv' - 'iv': 选择IV值最大的方法 - 'ks': 选择KS值最大的方法
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
- 返回:
最优方法名(字符串)
- 抛出:
Warning -- 某个方法执行失败时输出警告但继续评估其他方法
- 返回类型:
str
参考样例
>>> binner = OptimalBinning() >>> best_method = OptimalBinning.auto_select_method(X, y, 'age') >>> print(f"最优方法: {best_method}") >>> >>> # 自定义方法列表 >>> best = OptimalBinning.auto_select_method( ... X, y, 'income', ... methods=['best_iv', 'cart', 'mdlp'], ... criterion='ks' ... ) >>> >>> # 使用最优方法进行分箱 >>> binner = OptimalBinning(method=best_method) >>> binner.fit(X[[feature]], y)
- fit(X, y=None, **kwargs)[源代码]
拟合分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据
y (ndarray | Series | None) -- 目标变量
kwargs -- 其他参数
- 返回:
拟合后的分箱器
- 返回类型:
- get_stats(feature=None)[源代码]
获取分箱统计信息.
返回各特征的IV值、KS值、分箱表等统计指标。
- 参数:
feature (str | None) -- 特征名,如果为None则返回所有特征的统计,默认为None
- 返回:
统计信息字典 - 如果指定了feature,返回 {'
n_bins_': int, 'bin_table': DataFrame, 'ks': float, 'iv': float, 'monotonic_trend': str} - 如果未指定feature,返回 {feature_name: stats, ...} 格式的字典- 抛出:
ValueError -- 如果分箱器尚未拟合
KeyError -- 如果指定特征不存在
- 返回类型:
Dict[str, Any]
参考样例
>>> binner = OptimalBinning(method='best_iv') >>> binner.fit(X, y) >>> >>> # 获取单个特征的统计 >>> stats = binner.get_stats('age') >>> print(stats['n_bins_']) # 分箱数 >>> print(stats['iv']) # IV值 >>> print(stats['ks']) # KS值 >>> print(stats['bin_table']) # 分箱统计表 >>> >>> # 获取所有特征的统计 >>> all_stats = binner.get_stats() >>> for feat, s in all_stats.items(): ... print(f"{feat}: IV={s.get('iv', 'N/A')}")
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = OptimalBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.MDLPBinning(target='target', max_n_bins=10, min_n_bins=2, min_samples_split=2, min_samples_leaf=2, max_candidates=32, min_iv_gain=0.0001, force_min_bins=True, mdlp_weight=0.7, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningMDLP 分箱算法.
基于最小描述长度原理的递归分箱方法,自动确定最优分箱数。 使用信息增益和 MDLP 准则决定是否继续分割。
优化版本V3特点(针对平滑分布): - 放宽终止条件,支持force_min_bins强制最小分箱数 - 改进候选切分点选择,结合IV值评估 - 更好的平滑分布处理
- 参数:
target (str) -- 目标变量列名,默认为'target'
max_n_bins (int) -- 最大分箱数,默认为10
min_n_bins (int) -- 最小分箱数,默认为2
min_samples_split (int) -- 分割内部节点所需的最小样本数,默认为2
min_samples_leaf (int) -- 叶子节点所需的最小样本数,默认为2
max_candidates (int) -- 每次评估的最大候选切分点数,默认为32
min_iv_gain (float) -- 最小IV增益阈值,默认为0.0001(降低以允许更多分箱)
force_min_bins (bool) -- 是否强制满足最小分箱数,默认为True
mdlp_weight (float) -- MDLP准则权重(0-1之间),默认为0.7(降低以放宽终止条件)
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
min_bin_size (float | int)
max_bin_size (int | float | None)
min_bad_rate (float)
monotonic (bool | str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import MDLPBinning >>> binner = MDLPBinning(max_n_bins=5, min_n_bins=2) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test)
引用
Fayyad, U. M., & Irani, K. B. (1993). Multi-interval discretization of continuous-valued attributes for classification learning. IJCAI-93. https://trs.jpl.nasa.gov/handle/2014/35171 ; MDLP(最小描述长度原理)参见 https://en.wikipedia.org/wiki/Minimum_description_length
- fit(X, y=None, **kwargs)[源代码]
拟合 MDLP 分箱.
- 参数:
X (DataFrame | ndarray) -- 特征数据
y (ndarray | Series | None) -- 目标变量
- 返回:
self
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = MDLPBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.ORBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic='auto', objective='iv', custom_objective=None, n_prebins=20, max_candidates=100, time_limit=60, use_cp_sat=False, num_workers=None, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningOR-Tools 运筹规划分箱.
基于 Google OR-Tools CP-SAT 求解器的最优化分箱方法。 支持多种优化目标和约束条件,能够找到全局最优分箱方案。 支持自定义目标函数,可实现复合指标优化。
参数
- 参数:
target (str) -- 目标变量列名,默认为'target'。在scorecardpipeline风格中使用, 当fit时只传入df且y为None时,从df中提取该列作为目标变量。
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (Union[float, int]) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (Optional[Union[float, int]]) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (Union[bool, str]) -- 坏样本率单调性约束,默认为auto - False: 不要求单调性 - True 或 'auto': 自动检测并应用最佳单调方向 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减
objective (str) -- 优化目标,默认为'iv' - 'iv': 最大化 IV 值 - 'ks': 最大化 KS 统计量 - 'gini': 最大化 Gini 系数 - 'entropy': 最小化熵(信息增益最大) - 'chi2': 最大化卡方统计量 - 'custom': 使用自定义目标函数(通过 custom_objective 参数传入)
custom_objective (Optional[callable]) -- 自定义目标函数,当 objective='custom' 时使用 - 类型: Callable[[List[Dict], int, int], float] - 参数: bin_stats(List[Dict]) 每个箱的统计信息, total_good(int) 总好样本数, total_bad(int) 总坏样本数 - 返回: float 目标函数值,越大越好(OR-Tools 求解器始终最大化) - 箱统计字典包含: 'count', 'good', 'bad', 'bad_rate', 'good_rate', 'lift', 'woe'
n_prebins (int) -- 预分箱数量(候选分割点数),默认为20 - 候选点越多,求解越精确,但计算时间越长
max_candidates (int) -- 最大候选分割点数,默认为100 - 如果唯一值超过此数,将使用分位数采样
time_limit (int) -- 求解时间限制(秒),默认为60 - 超过此时间将返回当前找到的最优解
use_cp_sat (bool) -- 是否使用真正的 CP-SAT 求解器,默认为False - False: 使用启发式+DP组合算法,速度快,结果接近最优 - True: 使用 CP-SAT 约束规划求解器,保证全局最优解
num_workers (Optional[int]) -- 原生求解器线程数;默认 None,继承统一 n_jobs 预算 - 可以设置为大于1以加速求解(仅在 use_cp_sat=True 时生效)
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (Optional[List]) -- 特殊值列表,默认为None
random_state (Optional[int]) -- 随机种子,默认为None
cat_cutoff (Optional[Union[float, int]])
handle_unknown (Union[int, str])
n_jobs (Union[int, float])
parallel_backend (Optional[str])
parallel_config (Optional[Dict[str, Any]])
user_splits (Optional[Dict[str, List]])
user_splits_fixed (Optional[Union[bool, Dict[str, Union[bool, List[bool]]]]])
参考样例
sklearn风格 (推荐):
>>> from hscredit.core.binning import ORBinning >>> # 最大化 IV >>> binner = ORBinning(max_n_bins=5, objective='iv', monotonic=True) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
scorecardpipeline风格 (目标列在DataFrame中):
>>> from hscredit.core.binning import ORBinning >>> # 初始化时指定目标列名,fit时传入完整DataFrame >>> binner = ORBinning(target='target', max_n_bins=5, objective='ks', time_limit=60) >>> binner.fit(df) # df包含特征列和目标列'target' >>> X_binned = binner.transform(df.drop(columns=['target']))
混合风格 (y参数优先):
>>> # 即使初始化时指定了target,fit时传入y会优先使用y >>> binner = ORBinning(target='target', objective='iv') >>> binner.fit(df, y=external_y) # 使用external_y,忽略df中的'target'列 >>> >>> # 自定义目标:最大化 LIFT + IV >>> def custom_obj(bin_stats, total_good, total_bad): ... total_iv = sum(stat.get('woe', 0) * (stat.get('bad_rate', 0) - stat.get('good_rate', 0)) ... for stat in bin_stats if 'woe' in stat) ... total_lift = sum(abs(stat.get('lift', 1) - 1) for stat in bin_stats) ... return total_iv + total_lift * 0.1 # IV + 0.1 * LIFT偏差 >>> >>> binner = ORBinning(objective='custom', custom_objective=custom_obj) >>> binner.fit(X_train, y_train)
使用 CP-SAT 求解器(全局最优)
>>> from hscredit.core.binning import ORBinning >>> # 使用真正的 CP-SAT 约束规划求解器 >>> binner = ORBinning( ... max_n_bins=5, ... objective='iv', ... monotonic='auto', ... use_cp_sat=True, # 启用 CP-SAT 求解器 ... time_limit=60, # 求解时间限制 ... num_workers=4 # 并行工作线程数 ... ) >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test)
注意
OR-Tools 分箱的特点: 1. 能够找到全局最优解(而非贪心算法的局部最优) 2. 支持复杂的约束条件组合 3. 支持自定义目标函数,实现复合指标优化 4. 计算时间较长,适合对分箱质量要求高的场景 5. 可以设置时间限制,在时间和精度之间权衡
自定义目标函数示例
最大 LIFT + IV:
def max_lift_iv(bin_stats, total_good, total_bad): total_iv = sum(stat['woe'] * (stat['bad_rate'] - stat['good_rate']) for stat in bin_stats) total_lift = sum(stat['lift'] for stat in bin_stats) return total_iv + total_lift * 0.01
最小 LIFT + IV(LIFT 越接近1越好):
def min_lift_iv(bin_stats, total_good, total_bad): total_iv = sum(stat['woe'] * (stat['bad_rate'] - stat['good_rate']) for stat in bin_stats) lift_penalty = sum(abs(stat['lift'] - 1) for stat in bin_stats) return total_iv - lift_penalty * 0.1 # 减去惩罚项
最大/最小 LIFT 离1的距离求和 + IV:
def lift_distance_iv(bin_stats, total_good, total_bad): total_iv = sum(stat['woe'] * (stat['bad_rate'] - stat['good_rate']) for stat in bin_stats) max_lift_dist = max(abs(stat['lift'] - 1) for stat in bin_stats) min_lift_dist = min(abs(stat['lift'] - 1) for stat in bin_stats) return total_iv + (max_lift_dist + min_lift_dist) * 0.1
引用
最优分箱的数学规划建模参考 optbinning:Navas-Palencia, G. (2020). Optimal binning: mathematical programming formulation. arXiv:2001.08025. https://arxiv.org/abs/2001.08025 ;求解器为 Google OR-Tools https://developers.google.com/optimization 。与
CPSATBinning相比, 本类额外支持自定义目标函数与启发式+DP 快速模式(use_cp_sat=False)。- fit(X, y=None, **kwargs)[源代码]
拟合 OR-Tools 运筹规划分箱.
支持两种API风格: 1. sklearn风格: fit(X, y) - X是特征矩阵,y是目标变量 2. scorecardpipeline风格: fit(df) - df是完整数据框,目标列名在初始化时通过target参数传入
优先级规则:如果y不是None,直接使用y(优先);否则从X中提取target列。
- 参数:
X (DataFrame | ndarray) -- 训练数据 - sklearn风格: 特征矩阵,shape (n_samples, n_features) - scorecardpipeline风格: 完整数据框,包含特征列和目标列
y (ndarray | Series | None) -- 目标变量(可选) - sklearn风格: 传入目标变量 - scorecardpipeline风格: 不传,从X中提取 - 如果传入y,优先使用y而忽略X中的target列
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = ORBinning(objective='iv') >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.CustomObjectives[源代码]
基类:
object常用自定义目标函数集合.
提供预定义的复合指标目标函数,可与 ORBinning 的 custom_objective 参数配合使用.
使用示例
>>> from hscredit.core.binning import ORBinning, CustomObjectives >>> >>> # 使用预定义的最大 LIFT + IV 目标 >>> binner = ORBinning( ... objective='custom', ... custom_objective=CustomObjectives.max_lift_iv(lift_weight=0.1) ... ) >>> binner.fit(X_train, y_train) >>> >>> # 使用自定义权重 >>> binner = ORBinning( ... objective='custom', ... custom_objective=CustomObjectives.min_lift_distance_iv( ... iv_weight=1.0, ... lift_weight=0.5 ... ) ... )
- static lift_distance_sum_iv(lift_weight=0.1, iv_weight=1.0)[源代码]
最大/最小LIFT离1的距离求和 + IV 目标函数.
目标:最大化(最大LIFT离1的距离 + 最小LIFT离1的距离)+ IV 值
- 参数:
lift_weight (float) -- LIFT距离和项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
原理
同时考虑最强和最弱分箱与基准线的偏离程度,平衡极端区分能力.
- static max_ks_iv(ks_weight=0.5, iv_weight=1.0)[源代码]
最大 KS + IV 复合目标函数.
同时考虑 KS 统计量和 IV 值。
- 参数:
ks_weight (float) -- KS 项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
- static max_lift_distance_iv(lift_weight=0.1, iv_weight=1.0)[源代码]
最大LIFT离1的距离 + IV 目标函数.
目标:最大化(最大LIFT离1的距离)+ IV 值
- 参数:
lift_weight (float) -- 最大LIFT距离项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
原理
鼓励产生至少一个与基准(LIFT=1)有明显偏离的强区分分箱.
- static max_lift_iv(lift_weight=0.1, iv_weight=1.0)[源代码]
最大 LIFT + IV 目标函数.
目标:最大化(所有分箱中LIFT最大的那一箱的LIFT值)+ IV 值
- 参数:
lift_weight (float) -- 最大LIFT项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
原理
LIFT = 箱内坏样本率 / 总体坏样本率 - LIFT > 1: 该箱坏样本率高于平均水平 - LIFT < 1: 该箱坏样本率低于平均水平
通过最大化最大LIFT,鼓励产生至少一个强区分能力的分箱.
- static max_min_lift_sum_iv(lift_weight=0.1, iv_weight=1.0)[源代码]
最大LIFT + 最小LIFT + IV 目标函数.
目标:最大化(最大LIFT值 + 最小LIFT值)+ IV 值
- 参数:
lift_weight (float) -- LIFT和项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
原理
同时考虑最强和最弱分箱的LIFT值,确保分箱既有强区分箱,整体区分度也较好.
- static min_lift_distance_iv(lift_weight=0.1, iv_weight=1.0)[源代码]
最小LIFT离1的距离 + IV 目标函数.
目标:最大化(最小LIFT离1的距离)+ IV 值
- 参数:
lift_weight (float) -- 最小LIFT距离项权重
iv_weight (float) -- IV 项权重
- 返回:
目标函数
原理
鼓励最弱分箱也有较好的区分能力,避免某些分箱过于接近基准线.
- class hscredit.core.binning.CPSATBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.02, max_bin_size=None, min_bad_rate=0.0, monotonic='auto', objective='iv', n_prebins=50, max_candidates=100, time_limit=30, num_workers=None, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningCP-SAT 运筹规划分箱.
基于 Google OR-Tools CP-SAT 求解器的最优化分箱方法。 将分箱问题建模为约束规划问题,通过 CP-SAT 求解器找到全局最优分箱方案。
参数
- 参数:
target (str) -- 目标变量列名,默认为'target'。在scorecardpipeline风格中使用, 当fit时只传入df且y为None时,从df中提取该列作为目标变量。
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (Union[float, int]) -- 每箱最小样本数或占比,默认为0.02 - 如果 < 1, 表示占比 (如 0.02 表示 2%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (Optional[Union[float, int]]) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (Union[bool, str]) -- 坏样本率单调性约束,默认为'auto' - False: 不要求单调性 - True 或 'auto': 自动检测并应用最佳单调方向 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减
objective (str) -- 优化目标,默认为'iv' - 'iv': 最大化 IV 值(Information Value) - 'ks': 最大化 KS 统计量 - 'gini': 最大化 Gini 系数
n_prebins (int) -- 预分箱数量(候选分割点数),默认为50 - 候选点越多,求解越精确,但计算时间越长
max_candidates (int) -- 最大候选分割点数,默认为100 - 如果唯一值超过此数,将使用分位数采样
time_limit (int) -- 求解时间限制(秒),默认为30 - 超过此时间将返回当前找到的最优解
num_workers (Optional[int]) -- 原生求解器线程数;默认 None,继承统一 n_jobs 预算 - 可以设置为大于1以加速求解
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (Optional[List]) -- 特殊值列表,默认为None
random_state (Optional[int]) -- 随机种子,默认为None
cat_cutoff (Optional[Union[float, int]])
handle_unknown (Union[int, str])
n_jobs (Union[int, float])
parallel_backend (Optional[str])
parallel_config (Optional[Dict[str, Any]])
user_splits (Optional[Dict[str, List]])
user_splits_fixed (Optional[Union[bool, Dict[str, Union[bool, List[bool]]]]])
参考样例
sklearn风格 (推荐):
>>> from hscredit.core.binning import CPSATBinning >>> # 最大化 IV >>> binner = CPSATBinning(max_n_bins=5, objective='iv', monotonic='auto') >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
scorecardpipeline风格 (目标列在DataFrame中):
>>> from hscredit.core.binning import CPSATBinning >>> binner = CPSATBinning(target='target', max_n_bins=5, objective='ks', time_limit=60) >>> binner.fit(df) >>> X_binned = binner.transform(df.drop(columns=['target']))
注意
CP-SAT 分箱的特点: 1. 能够找到全局最优解(而非贪心算法的局部最优) 2. 支持复杂的约束条件组合 3. 计算时间可控,可设置时间限制 4. 适合对分箱质量要求高的场景 5. 依赖可选包
ortools,未安装时实例化会抛出 ImportError引用
将最优分箱建模为数学规划问题参考 optbinning:Navas-Palencia, G. (2020). Optimal binning: mathematical programming formulation. arXiv:2001.08025. https://arxiv.org/abs/2001.08025 ;求解器为 Google OR-Tools CP-SAT https://developers.google.com/optimization/cp/cp_solver
- class hscredit.core.binning.KMeansBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, force_numerical=False, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_init=10, max_iter=300, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinningK-Means聚类分箱算法.
使用K-Means算法将特征值聚类成K个簇,每个簇作为一个分箱。 根据聚类中心排序确定分箱边界(相邻聚类中心的中点)。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 是否要求坏样本率单调,默认为False
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,用于K-Means初始化,默认为None
force_numerical (bool) -- 是否强制作为数值型处理,默认为False(自动识别类别型) - True: 将所有特征视为数值型进行K-Means聚类分箱 - False: 自动检测特征类型
n_init (int) -- K-Means初始化次数,默认为10
max_iter (int) -- K-Means最大迭代次数,默认为300
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表
参考样例
>>> from hscredit.core.binning import KMeansBinning >>> # 基础用法 >>> binner = KMeansBinning(max_n_bins=5, random_state=42) >>> binner.fit(X, y) >>> X_binned = binner.transform(X) >>> >>> # 查看分箱统计 >>> bin_table = binner.get_bin_table('feature_name')
注意
K-Means 为无监督分箱,依据特征数值的聚类结构切分、不使用标签
y决定边界 (切分点取相邻聚类中心的中点);对存在自然分组的特征效果好,对均匀分布的特征则 与等距分箱接近。引用
K-Means 聚类:MacQueen, J. (1967) 与 Lloyd, S. (1982); https://en.wikipedia.org/wiki/K-means_clustering
- fit(X, y=None, **kwargs)[源代码]
拟合 K-Means 分箱。
对每个数值特征做一维 K-Means 聚类,以相邻聚类中心的中点作为切分点;类别特征按 类别成箱。支持 sklearn 风格
fit(X, y)与 scorecardpipeline 风格fit(df), 详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏),仅用于生成分箱统计表; scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = KMeansBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.MonotonicBinning(target='target', monotonic='auto', init_method='quantile', init_n_bins=20, max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning单调性约束分箱算法 - 支持U型和倒U型.
通过初始分箱后合并相邻箱,确保坏样本率或WOE值满足指定的单调性约束。 支持多种单调性模式,包括递增、递减、峰值、谷值、凸函数、凹函数等。 参考optbinning的monotonic_trend参数实现。
- 参数:
monotonic (bool | str | None) -- 单调性约束类型,默认为'auto' - 'auto': 自动检测最佳趋势(允许单增、单减、正U、倒U) - 'auto_asc_desc': 自动检测,但只允许单增或单减 - 'auto_heuristic': 使用启发式方法自动检测 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减 - 'peak': 倒U型/峰值(先增后减) - 'valley': U型/谷值(先减后增) - 'convex': 凸函数(U型近似) - 'concave': 凹函数(倒U型近似) - 'peak_heuristic': 使用启发式方法检测峰值 - 'valley_heuristic': 使用启发式方法检测谷值 - False/None: 不强制单调性
init_method (str) -- 初始分箱方法,默认为'quantile' - 'quantile': 等频分箱 - 'uniform': 等距分箱
init_n_bins (int) -- 初始分箱数,默认为20
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
属性
splits_: 每个特征的分箱切分点n_bins_: 每个特征的实际分箱数bin_tables_: 每个特征的分箱统计表monotonic_trend_: 每个特征检测到的单调趋势
参考样例
>>> from hscredit.core.binning import MonotonicBinning >>> # 峰值模式(倒U型) >>> binner = MonotonicBinning(monotonic='peak', max_n_bins=5) >>> binner.fit(X, y) >>> >>> # 谷值模式(U型) >>> binner = MonotonicBinning(monotonic='valley', max_n_bins=5) >>> binner.fit(X, y) >>> >>> # 自动检测 >>> binner = MonotonicBinning(monotonic='auto', max_n_bins=5) >>> binner.fit(X, y) >>> print(f"检测到的模式: {binner.monotonic_trend_}")
引用
单调最优分箱(monotonic_trend:ascending/descending/peak/valley/convex/concave) 设计参考 optbinning:Navas-Palencia, G. (2020). Optimal binning: mathematical programming formulation. arXiv:2001.08025. https://arxiv.org/abs/2001.08025
- VALID_MONOTONIC_MODES = ['auto', 'auto_asc_desc', 'auto_heuristic', 'ascending', 'descending', 'peak', 'valley', 'convex', 'concave', 'peak_heuristic', 'valley_heuristic', None, False]
- fit(X, y=None, **kwargs)[源代码]
拟合单调性约束分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据,shape (n_samples, n_features)
y (ndarray | Series | None) -- 目标变量,二分类 (0/1)
kwargs -- 其他参数
- 返回:
拟合后的分箱器
- 返回类型:
- plot_binning(feature, metric='bad_rate', figsize=(10, 6), save_path=None)[源代码]
绘制分箱结果可视化.
- 参数:
feature (str) -- 特征名
metric (str) -- 绘制的指标,'bad_rate' 或 'woe'
figsize (Tuple[int, int]) -- 图形大小
save_path (str | None) -- 保存路径
- 返回:
matplotlib图形对象
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = MonotonicBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.GeneticBinning(target='target', population_size=50, generations=100, mutation_rate=0.1, crossover_rate=0.8, elitism_rate=0.1, objective='iv', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=False, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning遗传算法分箱.
使用遗传算法在候选切分点中搜索最优分箱方案,支持多种优化目标。 通过交叉、变异、选择等遗传操作,逐步逼近全局最优解。
- 参数:
population_size (int) -- 种群大小,默认为50
generations (int) -- 迭代代数,默认为100
mutation_rate (float) -- 变异率,默认为0.1
crossover_rate (float) -- 交叉率,默认为0.8
elitism_rate (float) -- 精英保留率(每代直接保留的最优个体比例),默认为0.1
objective (str) --
适应度(优化目标)函数,默认为
'iv'。可取以下枚举值:'iv':最大化 Information Value(信息价值),最常用,衡量整体预测力'ks':最大化 KS 统计量,衡量好坏样本累积分布的最大区分度'gini':最大化 Gini 系数(≈ 2×AUC−1),衡量排序区分能力
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
monotonic (bool | str) -- 是否要求坏样本率单调,默认为False
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import GeneticBinning >>> binner = GeneticBinning(objective='iv', max_n_bins=5, generations=100) >>> binner.fit(X, y) >>> X_binned = binner.transform(X)
注意
遗传算法为随机全局优化,结果依赖
random_state;相比贪心方法更可能跳出局部最优, 但计算开销随population_size × generations增长,适合约束复杂、对分箱质量要求高的场景。引用
遗传算法:Holland, J. H. (1975). Adaptation in Natural and Artificial Systems. https://en.wikipedia.org/wiki/Genetic_algorithm
- fit(X, y=None, **kwargs)[源代码]
拟合遗传算法分箱。
对每个特征以遗传算法(选择/交叉/变异/精英保留)在候选切分点中搜索使
objective最大化的分箱方案。支持 sklearn 与 scorecardpipeline 两种调用风格,详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏);scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签或WOE值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = GeneticBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe')
- class hscredit.core.binning.SmoothBinning(target='target', method='adaptive', smoothing_param=0.5, max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, prior_bad_rate=None, monotonic=None, n_prebins=100, merge_criterion='iv_chi2', chi2_threshold=3.84, min_iv_improvement=0.001, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning平滑/正则化分箱.
通过平滑技术和正则化约束防止分箱过拟合,提高模型泛化能力。 支持多种平滑方法:Laplace平滑、贝叶斯平滑、Beta平滑等。
优化版本V3特点(针对平滑分布): - 改进合并逻辑,避免过度合并 - 支持IV变化率检测,保留有价值的切分点 - 自适应平滑强度
- 参数:
method (str) --
坏样本率平滑方法,默认为
'adaptive'。可取以下枚举值:'laplace':拉普拉斯(加性)平滑,坏样本率 = (坏数 + k) / (总数 + 2k)'bayesian':贝叶斯平滑,以全局/先验坏样本率为先验做收缩'beta':Beta 分布共轭先验平滑'adaptive':自适应平滑,按各箱样本量动态调整平滑强度(样本越少收缩越强)
smoothing_param (float) -- 平滑强度参数(越大越向先验收缩),默认为0.5
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
min_bad_rate (float) -- 每箱最小坏样本率,默认为0.0
prior_bad_rate (float | None) -- 先验坏样本率,默认为None(使用全局坏样本率)
monotonic (str | None) -- 单调性约束,默认为None,可选
'ascending'/'descending'/'peak'/'valley'/ None,含义见BaseBinningn_prebins (int) -- 预分箱数量,默认为100(提高预分箱数以获得更多候选点)
merge_criterion (str) --
相邻箱合并准则,默认为
'iv_chi2'。可取以下枚举值:'iv':仅按合并前后 IV 损失最小决定合并'chi2':仅按相邻箱卡方值(分布差异显著性)决定合并'iv_chi2':综合 IV 损失与卡方显著性(推荐)
chi2_threshold (float) -- 卡方检验阈值,默认为3.84(自由度1、p=0.05)
min_iv_improvement (float) -- 最小IV改进阈值,默认为0.001
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import SmoothBinning >>> binner = SmoothBinning(method='adaptive', max_n_bins=5) >>> binner.fit(X, y) >>> X_binned = binner.transform(X)
注意
平滑分箱通过对各箱坏样本率做收缩(向先验靠拢)来抑制小样本箱的 WOE/IV 虚高, 适合样本量小或噪声大的场景,可显著降低分箱在跨期数据上的不稳定(PSI)。
引用
加性(拉普拉斯)平滑与贝叶斯收缩:https://en.wikipedia.org/wiki/Additive_smoothing ; 经验贝叶斯收缩思想参见 Efron & Morris (1975), James–Stein estimator。
- fit(X, y=None, **kwargs)[源代码]
拟合平滑分箱。
预分箱后按
merge_criterion合并相邻箱,并以method指定的平滑方法对各箱 坏样本率做收缩。支持 sklearn 与 scorecardpipeline 两种调用风格,详见BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏);scorecardpipeline 风格下可省略
kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- class hscredit.core.binning.KernelDensityBinning(target='target', kernel='gaussian', bandwidth='isj', min_peak_height=0.05, min_peak_distance=0.05, max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, monotonic=None, use_target=True, n_grid_points=1000, smooth_density=True, iv_weight=0.7, fallback_to_iv=True, special_codes=None, missing_separate=True, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, verbose=False, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None)[源代码]
基类:
BaseBinning核密度分箱.
使用核密度估计识别数据分布的局部极大值(峰)和极小值(谷), 以谷值作为分箱边界,使分箱反映数据的自然分布结构。
优化版本V3特点(针对平滑分布): - 当KDE峰谷检测失败时,自动切换到基于IV的切分策略 - 支持检测数据分布的平滑程度 - 改进的带宽自适应
- 参数:
bandwidth (str | float) --
核密度估计带宽(平滑程度),默认为
'isj'。可取以下枚举值或具体数值:'isj':Improved Sheather–Jones 法自适应选择(对多峰分布更稳健,推荐)'scott':Scott 经验法则n^(-1/5),计算快,适合近正态分布'silverman':Silverman 经验法则,与 Scott 类似、对长尾略保守'normal_reference':正态参考法则float:直接指定固定带宽(值越大曲线越平滑、峰越少)
min_peak_height (float) -- 最小峰高(相对于最大密度),默认为0.05
min_peak_distance (float) -- 峰之间的最小距离(相对于数据范围),默认为0.05
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
monotonic (str | None) -- 单调性约束,默认为None
use_target (bool) -- 是否结合目标变量优化切分点,默认为True
n_grid_points (int) -- 核密度估计的网格点数,默认为1000
smooth_density (bool) -- 是否对密度曲线进行平滑处理,默认为True
iv_weight (float) -- IV值在切分点选择中的权重,默认为0.7
fallback_to_iv (bool) -- 当KDE失败时是否回退到IV策略,默认为True
special_codes (List | None) -- 特殊值列表,默认为None
missing_separate (bool) -- 是否将缺失值单独分为一箱,默认为True
random_state (int | None) -- 随机种子,默认为None
verbose (bool | int) -- 是否输出详细信息,默认为False
target (str)
max_bin_size (int | float | None)
min_bad_rate (float)
cat_cutoff (int | float | None)
handle_unknown (int | str)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import KernelDensityBinning >>> binner = KernelDensityBinning(bandwidth='isj', max_n_bins=5) >>> binner.fit(X, y) >>> X_binned = binner.transform(X)
注意
核密度分箱以数据分布的"谷值"(密度局部极小处)作为切分点,使分箱边界落在自然的 低密度间隔上,适合明显多峰的特征;当
fallback_to_iv=True且峰谷检测失败时, 自动回退到基于 IV 的切分策略。引用
核密度估计(KDE):Rosenblatt (1956), Parzen (1962), https://en.wikipedia.org/wiki/Kernel_density_estimation ; 带宽选择 ISJ 见 Botev, Z. I. et al. (2010). Kernel density estimation via diffusion. Annals of Statistics.
- fit(X, y=None, **kwargs)[源代码]
拟合核密度分箱。
对每个特征做核密度估计,以密度曲线的谷值作为切分点(必要时回退到 IV 策略)。 支持 sklearn 与 scorecardpipeline 两种调用风格,详见
BaseBinning.fit()。- 参数:
X (DataFrame | ndarray) -- 训练数据,shape
(n_samples, n_features),DataFrame 或 ndarrayy (ndarray | Series | None) -- 二分类目标变量(0=好/1=坏);当
use_target=True时参与切分点优化, scorecardpipeline 风格下可省略kwargs -- 透传给基类的其他参数
- 返回:
拟合后的分箱器自身(便于链式调用)
- 返回类型:
- class hscredit.core.binning.BestLiftBinning(target='target', max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=0.5, min_bad_rate=0.0, min_lift=0.0, monotonic=True, n_prebins=50, optimization='extreme', missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinningBest Lift 分箱.
基于最大化 Lift 差异的分箱方法,特别关注头部或尾部的极端值。 Lift = 箱内坏样本率 / 总体坏样本率。
业务场景: - 高风险识别:寻找头部 Lift > 2 或尾部 Lift < 0.5 的分箱 - 风险分层:最大化不同分箱间的风险差异
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01 - 如果 < 1, 表示占比 (如 0.01 表示 1%) - 如果 >= 1, 表示绝对数量 (如 100 表示最少100个样本)
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为0.5
min_lift (float) -- 最小 Lift 阈值,默认为0(不限制) - 设为0:不限制,允许任何 Lift 值 - 设为0.5:过滤掉 Lift > 0.5 的箱(用于识别极低风险) - 设为1.5:只保留 Lift > 1.5 的箱(用于识别极高风险)
monotonic (bool | str) -- 坏样本率单调性约束,默认为True - False: 不要求单调性 - True 或 'auto': 自动检测并应用最佳单调方向 - 'ascending': 强制坏样本率递增 - 'descending': 强制坏样本率递减
n_prebins (int) -- 预分箱数量,默认为50 - 预分箱越细,结果越精确,但计算量越大
optimization (str) -- 优化目标,默认为'extreme' - 'extreme': 最大化极端箱的 Lift(头部最高或尾部最低) - 'spread': 最大化 Lift 分布范围(max - min) - 'iv': 最大化 IV 值
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (List | None) -- 特殊值列表,默认为None
random_state (int | None) -- 随机种子,默认为None
target (str)
min_bad_rate (float)
cat_cutoff (int | float | None)
handle_unknown (int | str)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
>>> from hscredit.core.binning import BestLiftBinning >>> # 识别高风险客群 >>> binner = BestLiftBinning(max_n_bins=5, optimization='extreme') >>> binner.fit(X_train, y_train) >>> X_binned = binner.transform(X_test) >>> bin_table = binner.get_bin_table('feature_name')
注意
Best Lift 分箱的特点: 1. 关注头部/尾部的极端风险识别 2. 支持单调性约束,保证业务可解释性 3. 自动确定最优单调方向 4. 高效的动态规划风格实现
其中
Lift(提升度)= 箱内坏样本率 / 总体坏样本率,Lift>1 表示该箱风险高于均值。引用
Lift / 提升度是响应模型与风险分层的标准评估口径,参见 Siddiqi, N. (2006). Credit Risk Scorecards. Wiley,以及营销响应模型中的 lift chart 概念 https://en.wikipedia.org/wiki/``Lift_``(data_mining)
- fit(X, y=None, **kwargs)[源代码]
拟合 Best Lift 分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据
y (ndarray | Series | None) -- 目标变量
- 返回:
拟合后的分箱器
- 返回类型:
- transform(X, metric='indices', **kwargs)[源代码]
应用分箱转换.
将原始特征值转换为分箱索引、分箱标签、WOE值或LIFT值。
- 参数:
X (DataFrame | ndarray) -- 待转换数据, DataFrame或数组格式
metric (str) -- 转换类型, 可选值: - 'indices': 返回分箱索引 (0, 1, 2, ...), 用于后续处理 - 'bins': 返回分箱标签字符串, 用于可视化或报告 - 'woe': 返回WOE值, 用于逻辑回归建模 - 'lift': 返回LIFT值, 用于评估分箱效果
kwargs -- 其他参数
- 返回:
转换后的数据, 格式与输入X相同
- Example:
- 返回类型:
DataFrame | ndarray
>>> binner = BestLiftBinning() >>> binner.fit(X_train, y_train) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取WOE编码 (用于建模) >>> X_woe = binner.transform(X_test, metric='woe') >>> >>> # 获取LIFT值 >>> X_lift = binner.transform(X_test, metric='lift')
- class hscredit.core.binning.TargetBadRateBinning(target='target', target_bad_rates=None, max_n_bins=5, min_n_bins=2, min_bin_size=0.01, max_bin_size=None, min_bad_rate=0.0, strict_mode=True, merge_empty_bins=True, monotonic=True, missing_separate=True, special_codes=None, cat_cutoff=None, category_order=None, handle_unknown=-3, random_state=None, decimal=4, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits=None, user_splits_fixed=None, **kwargs)[源代码]
基类:
BaseBinning目标坏样本率分箱.
支持两种分箱模式:
**模式1:严格边界模式**(指定 target_bad_rates) 按目标坏样本率边界严格划分,确保每箱的坏样本率在指定区间内。
- 参数:
target_bad_rates (List[float] | None) -- 目标坏样本率边界列表,例如 [0.05, 0.10, 0.20] - 会产生 len(target_bad_rates)+1 个分箱 - 第0箱:坏样本率 <= target_bad_rates[0] - 第1箱:target_bad_rates[0] < 坏样本率 <= target_bad_rates[1] - 依此类推
target (str)
max_n_bins (int)
min_n_bins (int)
min_bin_size (float | int)
max_bin_size (int | float | None)
min_bad_rate (float)
strict_mode (bool)
merge_empty_bins (bool)
monotonic (bool)
missing_separate (bool)
special_codes (List | None)
cat_cutoff (int | float | None)
handle_unknown (int | str)
random_state (int | None)
decimal (int)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
**模式2:自动模式**(不指定 target_bad_rates,指定 max_n_bins) 自动寻找使每箱之间坏样本率差异最大的划分。
- 参数:
max_n_bins (int) -- 最大分箱数,默认为5
min_n_bins (int) -- 最小分箱数,默认为2
min_bin_size (float | int) -- 每箱最小样本数或占比,默认为0.01
max_bin_size (int | float | None) -- 每箱最大样本数或占比,默认为None
strict_mode (bool) -- 是否严格模式(严格限制边界),默认为True - True: 严格按照目标坏样本率边界划分,可能产生空箱 - False: 在满足约束下尽量接近目标坏样本率
merge_empty_bins (bool) -- 是否合并空箱,默认为True
monotonic (bool) -- 是否要求单调性,默认为True
missing_separate (bool) -- 缺失值是否单独分箱,默认为True
special_codes (List | None) -- 特殊值列表,默认为None
decimal (int) -- 切分点小数点保留精度,默认为4
target (str)
target_bad_rates (List[float] | None)
min_bad_rate (float)
cat_cutoff (int | float | None)
handle_unknown (int | str)
random_state (int | None)
n_jobs (int | float)
parallel_backend (str | None)
parallel_config (Dict[str, Any] | None)
user_splits (Dict[str, List] | None)
user_splits_fixed (bool | Dict[str, bool | List[bool]] | None)
参考样例
严格边界模式:
>>> # 指定坏样本率边界:5%, 10%, 20% >>> binner = TargetBadRateBinning( ... target_bad_rates=[0.05, 0.10, 0.20], ... strict_mode=True ... ) >>> # 结果:4个分箱,坏样本率分别在 <=5%, 5%-10%, 10%-20%, >20%
自动模式:
>>> # 自动寻找最优划分 >>> binner = TargetBadRateBinning(max_n_bins=5) >>> # 结果:5个分箱,每箱间坏样本率差异最大
注意
本方法以"业务目标坏样本率"为切分依据,属业务驱动的风险分层分箱(risk-based segmentation),无单一学术出处;严格边界模式便于将分箱直接对齐既定的风险定价/ 准入档位。坏样本率(bad rate)即各箱内坏样本占比。
- fit(X, y=None, **kwargs)[源代码]
拟合目标坏样本率分箱.
- 参数:
X (DataFrame | ndarray) -- 训练数据
y (ndarray | Series | None) -- 目标变量
- 返回:
拟合后的分箱器
- 返回类型:
- class hscredit.core.binning.OptimalBinning2D(target='target', max_n_bins=5, min_bin_size=0.02, method='quantile', monotonic=False, max_n_bins_2d=None, max_n_bins_x=None, min_bin_size_x=None, method_x=None, monotonic_x=None, user_splits_x=None, special_codes_x=None, dtype_x='numerical', max_n_bins_y=None, min_bin_size_y=None, method_y=None, monotonic_y=None, user_splits_y=None, special_codes_y=None, dtype_y='numerical', x_params=None, y_params=None, missing_separate=True, missing_separate_x=None, missing_separate_y=None, random_state=None, decimal=4, woe_clip=None, verbose=False, n_jobs=-1, parallel_backend=None, parallel_config=None, user_splits_fixed_x=None, user_splits_fixed_y=None)[源代码]
基类:
ParallelizableMixin,ArtifactSerializableMixin,BaseEstimator,TransformerMixin二维分箱器.
对两个特征进行交叉分箱分析,生成二维分箱矩阵,用于揭示特征间的交互效应。 每个单元格包含该交叉区间的样本数、坏样本率、WOE、IV等统计指标。
接口与 OptimalBinning 保持一致,支持 sklearn 和 scorecardpipeline 两种调用风格。
参数
- 目标与分箱控制
- param target:
目标变量列名,默认为 'target'
- param max_n_bins:
两个特征的最大分箱数,默认 5
- param min_bin_size:
两个特征的每箱最小样本占比,默认 0.02
- param method:
分箱方法,默认 'quantile'(等频)
- param monotonic:
单调性约束,默认 False。设为 'ascending'/'descending'/True 时, 作为**硬约束**作用于二维合并:最终各轴向相邻分箱的坏样本率保证满足单调趋势 (通过持续合并违例相邻分箱实现,可能使二维分箱数低于 max_n_bins_2d)
ascending表示特征值越大坏样本率越高(越大越差),descending表示 特征值越大坏样本率越低(越大越好);自动模式复用内部一维分箱器识别的方向。- param max_n_bins_2d:
相邻格子合并后的最大二维分箱数,默认使用 max_n_bins
- 特征1 专用参数(以 _x 后缀区分)
- param max_n_bins_x:
特征1的最大分箱数
- param min_bin_size_x:
特征1的每箱最小样本占比
- param method_x:
特征1的分箱方法
- param monotonic_x:
特征1的单调性约束
- param user_splits_x:
特征1的自定义切分点,包含 np.nan/None 时显式预留缺失箱
- param special_codes_x:
特征1的特殊值列表
- param dtype_x:
特征1的数据类型
- 特征2 专用参数(以 _y 后缀区分)
- param max_n_bins_y:
特征2的最大分箱数
- param min_bin_size_y:
特征2的每箱最小样本占比
- param method_y:
特征2的分箱方法
- param monotonic_y:
特征2的单调性约束
- param user_splits_y:
特征2的自定义切分点,包含 np.nan/None 时显式预留缺失箱
- param special_codes_y:
特征2的特殊值列表
- param dtype_y:
特征2的数据类型
- 扩展参数
- param x_params:
额外参数仅传递给特征1的内部 OptimalBinning
- param y_params:
额外参数仅传递给特征2的内部 OptimalBinning 参数优先级统一为:显式
_x/_y参数 >x_params/y_params> 全局参数。 所有参数会在构造内部OptimalBinning前完成合并和校验。
- 其他参数
- param missing_separate:
是否将缺失值单独分箱,默认 True
- param missing_separate_x:
是否将特征1缺失值单独分箱,None 时继承 missing_separate
- param missing_separate_y:
是否将特征2缺失值单独分箱,None 时继承 missing_separate
- param random_state:
随机种子
- param decimal:
数值精度
- param woe_clip:
WOE截断阈值
- param verbose:
是否输出详细信息
属性
binner_x_: 特征1的分箱器binner_y_: 特征2的分箱器splits_x_: 特征1的切分点splits_y_: 特征2的切分点n_bins_x_: 特征1的分箱数n_bins_y_: 特征2的分箱数solution_: 预分箱网格到最终二维分箱索引的映射矩阵;存在缺失值时追加缺失行/列n_bins_2d_: 合并后的最终二维分箱数binning_table_: 合并后的二维分箱统计表cross_table_: 二维交叉分箱统计表iv_interaction_: 交互IV值
参考样例
sklearn 风格:
>>> binner = OptimalBinning2D(max_n_bins=5) >>> binner.fit(X_2d, y_array) # X_2d shape=(n, 2)
scorecardpipeline 风格:
>>> binner = OptimalBinning2D(max_n_bins=5) >>> binner.fit(df, y=df['target'], features=['age', 'income'])
获取统计:
>>> cross = binner.get_cross_table() # 交叉分箱表 >>> table_x = binner.get_bin_table('age') # 特征1独立分箱表 >>> stats = binner.get_stats() # 两特征统计 >>> splits = binner.get_splits() # 两特征切分点 >>> rules = binner.export_rules() # 分箱规则(末尾 np.nan 表示缺失箱)
引用
二维交互最优分箱接口与求解思路参考 optbinning 的
OptimalBinning2D: Navas-Palencia, G. (2020). Optimal binning: mathematical programming formulation. arXiv:2001.08025. https://arxiv.org/abs/2001.08025 ; 交互效应(feature interaction)背景见 https://gnpalencia.org/optbinning/binning_2d.html- 参数:
target (str)
max_n_bins (int)
min_bin_size (Union[float, int])
method (str)
monotonic (Union[bool, str])
max_n_bins_2d (Optional[int])
max_n_bins_x (Optional[int])
min_bin_size_x (Optional[Union[float, int]])
method_x (Optional[str])
monotonic_x (Optional[Union[bool, str]])
user_splits_x (Optional[List])
special_codes_x (Optional[List])
dtype_x (str)
max_n_bins_y (Optional[int])
min_bin_size_y (Optional[Union[float, int]])
method_y (Optional[str])
monotonic_y (Optional[Union[bool, str]])
user_splits_y (Optional[List])
special_codes_y (Optional[List])
dtype_y (str)
x_params (Optional[Dict])
y_params (Optional[Dict])
missing_separate (bool)
missing_separate_x (Optional[bool])
missing_separate_y (Optional[bool])
random_state (Optional[int])
decimal (int)
woe_clip (Optional[float])
verbose (Union[bool, int])
n_jobs (int | float | None)
parallel_backend (str | None)
parallel_config (Mapping[str, Any] | None)
user_splits_fixed_x (Optional[Union[bool, List[bool]]])
user_splits_fixed_y (Optional[Union[bool, List[bool]]])
- artifact_kind = '分箱器'
- export_rules()[源代码]
导出分箱规则.
与 OptimalBinning.export_rules 保持一致。数值规则中的 np.nan 位置只表示 缺失值归属的普通箱;独立 -1 缺失箱由
missing_separate配置表达。- 返回:
分箱规则字典,格式同 OptimalBinning.export_rules
- 返回类型:
Dict[str, List]
参考样例
>>> binner = OptimalBinning2D() >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> rules = binner.export_rules() >>> print(rules['age']) # [25, 35, 45] >>> print(rules['income']) # [5000, 10000, 20000]
- fit(X, y=None, features=None)[源代码]
在干净候选对象上完整拟合并于成功后一次提交。
- 参数:
X (DataFrame | ndarray)
y (ndarray | Series | None)
features (List[str] | None)
- 返回类型:
- get_bin_table(feature=None)[源代码]
获取分箱统计表.
与 OptimalBinning 的 get_bin_table 保持一致。 - 若指定特征名,返回该特征的独立分箱表(等同于 OptimalBinning.get_bin_table) - 若不指定(默认 None),返回合并后的二维分箱表
- 参数:
feature (str | None) -- 特征名,None 时返回交叉分箱表
- 返回:
分箱统计表
- 返回类型:
DataFrame
参考样例
>>> binner = OptimalBinning2D() >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> >>> # 获取交叉分箱表(默认) >>> cross = binner.get_bin_table() >>> >>> # 获取特征1的分箱表 >>> table_x = binner.get_bin_table(binner.feature_x_)
- get_cross_table()[源代码]
获取二维交叉分箱统计表.
- 返回:
交叉分箱统计表,包含以下列: - 分箱, 分箱标签: 最终二维分箱索引和标签 - 特征1名称, 特征2名称: 特征名 - 特征1分箱, 特征2分箱: 单特征分箱索引 - 特征1标签, 特征2标签: 单特征分箱标签 - 样本总数, 好样本数, 坏样本数: 样本统计 - 坏样本率: 坏样本占比 - 样本占比: 交叉区间样本占全量样本的比例 - 分档WOE值, 分档IV值: WOE/IV统计 - LIFT值: 提升度
- 返回类型:
DataFrame
- get_splits(feature=None)[源代码]
获取切分点.
与 OptimalBinning 的 get_splits 保持一致。
- 参数:
feature (str | None) -- 特征名,None 时返回两个特征的切分点字典
- 返回:
切分点数组或字典
- 返回类型:
ndarray | Dict[str, ndarray]
参考样例
>>> binner = OptimalBinning2D() >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> >>> # 获取两个特征的切分点 >>> splits = binner.get_splits() >>> print(splits['age']) >>> print(splits['income']) >>> >>> # 获取单个特征切分点 >>> splits_x = binner.get_splits(binner.feature_x_)
- get_stats(feature=None)[源代码]
获取分箱统计信息.
与 OptimalBinning 的 get_stats 保持一致。
- 参数:
feature (str | None) -- 特征名,None 时返回两个特征的统计字典
- 返回:
统计信息字典 - 'n_bins': 分箱数 - 'bin_table': 分箱统计表 - 'iv': IV值 - 'ks': KS值
- 返回类型:
Dict[str, Any]
参考样例
>>> binner = OptimalBinning2D() >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> >>> # 获取两个特征的统计 >>> stats = binner.get_stats() >>> for feat, s in stats.items(): ... print(f"{feat}: IV={s.get('iv', 'N/A'):.4f}") >>> >>> # 获取单个特征统计 >>> s = binner.get_stats(binner.feature_x_)
- import_rules(rules)[源代码]
导入分箱规则.
- 参数:
rules (Dict[str, List]) -- 分箱规则字典,格式同 export_rules
- 返回:
self
- 返回类型:
参考样例
>>> rules = {'age': [25, 35, 45], 'income': [5000, 10000]} >>> binner = OptimalBinning2D(user_splits_x=[25, 35, 45], ... user_splits_y=[5000, 10000]) >>> # 先 fit(用于初始化结构),再 import_rules 覆盖切分点 >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> binner.import_rules(rules)
- plot(metric='bad_rate', figsize=None, cmap=None, annot=True, fmt='.2%', title=None, xlabel=None, ylabel=None, save=None, ax=None, **kwargs)[源代码]
绘制二维分箱热力图.
- 参数:
metric (Literal['bad_rate', 'woe', 'iv', 'lift', 'count']) -- 显示指标,可选 'bad_rate'(默认)、'woe'、'iv'、'lift'、'count'
figsize (tuple | None) -- 图像尺寸
cmap (str | None) -- 配色方案
annot (bool) -- 是否在热力图中显示数值
fmt (str) -- 数值格式
title (str | None) -- 图表标题
xlabel (str | None) -- X轴标签
ylabel (str | None) -- Y轴标签
save (str | None) -- 保存路径
ax (Any | None) -- 可选的 matplotlib Axes 对象
kwargs -- 其他参数传递给 seaborn.heatmap
- 返回:
matplotlib Figure 或 Axes
- 返回类型:
Any
- plot2d(figsize=None, colors=None, title=None, annot=True, fontsize=10, save=None)[源代码]
快捷绘制二维分箱联合分析图.
该方法等价于
hscredit.core.viz.bin_2d_plot(self, ...)。- 参数:
figsize (tuple | None) -- 图像尺寸
colors (List[str] | None) -- 配色方案
title (str | None) -- 图表总标题
annot (bool) -- 热力图是否标注数值
fontsize (int) -- 单元格字体大小
save (str | None) -- 保存路径
- 返回:
matplotlib Figure
- 返回类型:
Any
- plot_3d(metric='bad_rate', figsize=None, title=None, save=None, **kwargs)[源代码]
绘制三维表面图展示交互效应.
- 参数:
metric (Literal['bad_rate', 'woe', 'lift'])
figsize (tuple | None)
title (str | None)
save (str | None)
- 返回类型:
Any
- transform(X, metric='indices')[源代码]
将新数据映射到二维分箱.
- 参数:
X (DataFrame | ndarray) -- 待转换的数据
metric (Literal['indices', 'bins', 'woe', 'event_rate']) -- 转换类型,可选值: - 'indices': 返回合并后的二维分箱索引 (0, 1, 2, ...),默认 - 'bins': 返回合并后的二维分箱标签 - 'woe': 返回合并后的 WOE 值 - 'event_rate': 返回合并后的坏样本率
- 返回:
转换后的数据
- 返回类型:
DataFrame
参考样例
>>> binner = OptimalBinning2D() >>> binner.fit(df, y=df['target'], features=['age', 'income']) >>> >>> # 获取分箱索引 >>> X_binned = binner.transform(X_test, metric='indices') >>> >>> # 获取分箱标签 >>> X_labels = binner.transform(X_test, metric='bins') >>> >>> # 获取 WOE 编码 >>> X_woe = binner.transform(X_test, metric='woe')