评分卡
hscredit.core.models.ScoreCard 提供基于逻辑回归与 WOE 的标准评分卡。
- class hscredit.core.models.ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750, step=None, lower=None, upper=None, direction='descending', decimal=2, lr_model=None, lr_kwargs=None, binner=None, encoder=None, pipeline=None, calculate_stats=True, verbose=False, target='target', **kwargs)[源代码]
基类:
StandardScoreTransformer评分卡模型.
将逻辑回归模型转换为评分卡,支持评分卡输出、保存和导出等功能。 继承 StandardScoreTransformer 实现评分计算,统一参数命名。
参数
- 参数:
pdo (float) -- Point of Double Odds,odds增加rate倍时分数变化量,默认 60
rate (float) -- 倍率,默认 2 - odds增加的倍数
base_odds (float) -- 好坏比(好客户:坏客户),默认 35 - 当 base_odds >= 1 时,解释为好坏比。例如 35 表示 35:1,坏样本率 ≈ 2.8% - 当 base_odds < 1 时,解释为坏样本率或坏好比(P(bad)/P(good))
base_score (float) -- 基础 odds 对应的分数,默认 750
step (int | None) -- score_odds_reference的步长,默认None(自动计算为pdo/10)
direction (str) -- 评分方向,默认 'descending'(信用分模式) - 'descending': 概率越高分越低(信用分,分越高越好) - 'ascending': 概率越高分越高(欺诈分,分越高越差)
lr_model (Any | None) -- 预训练的逻辑回归模型,可选 - 如果传入,predict前不需要调用fit - 如果未传入,predict前必须先调用fit训练
lr_kwargs (Dict[str, Any] | None) -- 未传入 lr_model 时,通过 kwargs 传入 LR 参数进行训练,可选
binner (Any | None) -- 特征分箱器,可选。支持以下类型: - hscredit 分箱器:支持 transform(X, metric='woe') - toad/scorecardpipeline 分箱器:输出分箱索引
encoder (Any | None) -- WOE 转换器,可选。支持以下类型: - hscredit WOEEncoder:支持 transform(X) - toad WOETransformer
pipeline (Any | None) -- 已训练的 pipeline,支持以下类型: - 末端为 LR:从 pipeline 中提取 LR 模型 - 包含分箱器+WOE转换器+LR:提取所有组件
calculate_stats (bool) -- 是否计算统计信息,默认 True
verbose (bool) -- 是否输出详细信息,默认 False
target (str) -- 目标列名,默认'target'
lower (float | None)
upper (float | None)
decimal (int)
属性
- 变量:
A_ -- 刻度参数 A = base_score + B × ln(actual_odds),其中 actual_odds = 1/base_odds (当 base_odds >= 1)
B_ -- 补偿参数 B = pdo / ln(rate)
rules_ -- 评分卡规则字典,包含每个特征的分箱和对应分数
base_effect_ -- 每个特征的基础效应分数
- 参数:
pdo (float)
rate (float)
base_odds (float)
base_score (float)
step (int | None)
lower (float | None)
upper (float | None)
direction (str)
decimal (int)
lr_model (Any | None)
lr_kwargs (Dict[str, Any] | None)
binner (Any | None)
encoder (Any | None)
pipeline (Any | None)
calculate_stats (bool)
verbose (bool)
target (str)
继承方法
- 从 StandardScoreTransformer 继承的方法:
transform(proba): 将概率转换为评分
inverse_transform(scores): 将评分反向转换为概率
predict_score(X, proba): 通过概率预测评分
score_odds_reference: 评分与odds对应关系表
get_score_reference_by_prob(): 根据概率获取评分参考
评分公式
- 继承自 StandardScoreTransformer:
Score = A - B × ln(odds) 其中: odds = P(bad) / P(good)
B = pdo / ln(rate) A = base_score + B × ln(actual_odds) actual_odds = 1/base_odds (当 base_odds >= 1,好坏比) actual_odds = base_odds (当 base_odds < 1,坏样本率)
使用方式
方式1:从零开始训练(fit传入 WOE 数据,predict传入原始数据)
>>> from hscredit.core.models import ScoreCard >>> from hscredit.core.binning import OptimalBinning >>> >>> # 步骤1:分箱和 WOE 转换 >>> binner = OptimalBinning(method='best_iv', max_n_bins=5) >>> binner.fit(X_train, y_train) >>> X_train_woe = binner.transform(X_train, metric='woe') >>> >>> # 步骤2:训练评分卡(传入 WOE 数据) >>> scorecard = ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> scorecard.fit(X_train_woe, y_train) # 默认 input_type='woe' >>> >>> # 步骤3:预测(传入原始数据,自动转换) >>> scores = scorecard.predict(X_test) # 默认 input_type='raw'
方式2:fit传入原始数据(需要配置binner进行WOE转换)
>>> scorecard = ScoreCard(binner=binner) # 配置binner用于WOE转换 >>> scorecard.fit(X_train, y_train, input_type='raw') # 传入原始数据 >>> scores = scorecard.predict(X_test) # predict默认传入原始数据
方式3:使用预训练LR模型(无需fit,直接predict)
>>> lr = LogisticRegression() >>> lr.fit(X_train_woe, y_train) >>> scorecard = ScoreCard(lr_model=lr) # 传入预训练模型 >>> # 不需要调用fit,直接predict >>> scores = scorecard.predict(X_test, input_type='woe') # 传入WOE数据
引用
标准评分卡刻度公式 ``Score = A - B·ln(odds)``(A=offset、B=factor=pdo/ln(rate))出自 Siddiqi, N. (2006). Credit Risk Scorecards: Developing and Implementing Intelligent Credit Scoring. Wiley。API 设计对标 toad.ScoreCard、scorecardpipeline.ScoreCard 与 optbinning.Scorecard(https://gnpalencia.org/optbinning/scorecard.html)。
- property coef_: ndarray
获取逻辑回归系数.
- property intercept_: float
获取逻辑回归截距.
- property n_features_: int
获取非零系数特征数量.
- get_feature_importances(importance_type='coef')[源代码]
获取特征重要性.
基于底层逻辑回归模型的系数计算特征重要性。
- 参数:
importance_type (str) -- 重要性类型,默认'coef' - 'coef': 系数绝对值 - 'score_range': 评分范围(最大-最小分)
- 返回:
特征重要性Series
- 返回类型:
Series
- property feature_importances_: ndarray
特征重要性属性 (兼容sklearn风格).
- property feature_names_: list
获取特征名列表.
- fit(X, y=None, sample_weight=None, input_type='woe')[源代码]
训练评分卡模型.
支持两种调用方式: 1. 常规方式: fit(X, y) 2. scorecardpipeline风格: 在__init__中指定target,然后fit(X)
输入数据类型
fit 方法支持两种输入数据类型,通过 input_type 参数控制: - 'woe': WOE 转换后的数据(默认) - 'raw': 原始数据(需要配置 binner 进行 WOE 转换)
- 使用 WOE 数据(推荐):
>>> binner = OptimalBinning() >>> binner.fit(X_train, y_train) >>> X_train_woe = binner.transform(X_train, metric='woe') >>> scorecard.fit(X_train_woe, y_train) # 默认 input_type='woe'
- 使用原始数据:
>>> scorecard = ScoreCard(binner=binner) # 需要配置binner >>> scorecard.fit(X_train, y_train, input_type='raw')
- 参数:
X (DataFrame | ndarray) -- 训练数据(特征矩阵) 支持 numpy array 或 pandas DataFrame 如果是DataFrame且y为None,会尝试从X中提取target列作为y 数据类型由 input_type 参数决定(woe或raw)
y (ndarray | Series | None) -- 目标变量,可选 如果为None且init中指定了target,则从X中提取
sample_weight (ndarray | None) -- 样本权重,可选
input_type (str) -- 输入数据类型,默认为'woe' - 'woe': WOE 转换后的数据(默认,推荐) - 'raw': 原始数据(需要配置 binner 进行 WOE 转换)
- 返回:
self
- 返回类型:
- inverse_transform(scores)[源代码]
将评分反向转换为概率,要求评分卡已拟合或已加载.
- 参数:
scores (ndarray | Series)
- 返回类型:
ndarray
- predict_score(X=None, proba=None, input_type='auto')[源代码]
预测评分(通过LR模型概率)。
继承自 StandardScoreTransformer 的 predict_score 方法, 但使用 ScoreCard 内部的 LR 模型来预测概率。
可通过传入X或proba之一来获取评分。
- 参数:
X (DataFrame | ndarray | None) -- 特征矩阵,用于预测概率
proba (ndarray | Series | None) -- 直接传入预测概率(正类概率)
input_type (str) -- X 的输入类型,可选
'auto'/'raw'/'woe',默认'auto'
- 返回:
评分数组
- 返回类型:
ndarray
参考样例
>>> # 通过特征矩阵预测 >>> scores = scorecard.predict_score(X_test_woe)
>>> # 通过概率直接转换 >>> proba = scorecard.lr_model_.predict_proba(X_test_woe)[:, 1] >>> scores = scorecard.predict_score(proba=proba)
- predict(X, input_type='raw')[源代码]
预测评分(基于WOE特征的线性评分卡公式)。
与 predict_score 不同,此方法使用评分卡公式: Score =
A_-B_* (intercept + sum(coef_i * WOE_i))- 参数:
X (DataFrame | ndarray) -- 输入数据
input_type (str) -- 输入数据类型,可选: - 'raw': 原始数据,会进行 WOE 转换(默认) - 'woe': WOE 数据,直接使用 - 'auto': 自动检测,通过数据特征推断输入类型
- 返回类型:
ndarray
- input_type='auto' 时的判断逻辑:
数值范围检测:WOE数据通常取值范围在[-5, 5]之间,若所有数值列的min/max 都在[-10, 10]范围内且主要分布集中在[-5, 5],则判定为WOE数据
整数列检测:若存在int64/int32类型的列且唯一值数量>10,判定为原始数据 (原始数据常包含年龄、收入等整数特征)
默认策略:当无法明确判断时,为安全起见默认按原始数据处理
注意:auto检测基于启发式规则,对于边界情况(如原始数据本身就是小数值范围) 可能误判。生产环境建议显式指定input_type='raw'或'woe'。
- 返回:
评分数组
- 抛出:
NotFittedError -- 如果未传入lr_model且未调用fit方法
- 参数:
X (DataFrame | ndarray)
input_type (str)
- 返回类型:
ndarray
- predict_proba(X, input_type='auto')[源代码]
预测样本属于各类别的概率(使用底层 LR 模型)。
支持显式指定输入类型。若为原始数据则先经 binner/encoder 转为 WOE, 再交由逻辑回归模型输出概率。与 :meth:`predict`(输出分数)相对,本方法输出概率。
- 参数:
X (DataFrame | ndarray) -- 输入数据,原始特征或 WOE 数据,DataFrame 或 ndarray
input_type (str) -- 输入类型
'auto'/'raw'/'woe',默认'auto'
- 返回:
形状
(n_samples, 2)的概率数组,第 1 列为坏样本(正类)概率- 抛出:
NotFittedError -- 评分卡尚未拟合且未传入预训练 LR 模型时
- 返回类型:
ndarray
参考样例
>>> proba_bad = scorecard.predict_proba(X_test)[:, 1] # 坏样本概率
- scorecard_scale()[源代码]
输出评分卡基础配置(刻度参数).
- 返回:
DataFrame,包含 base_odds/base_score/rate/pdo 及推导出的 A、B 刻度参数
- 返回类型:
DataFrame
- score_formula(decimal=4)[源代码]
输出评分卡的评分转换公式(人类可读 + 可编程使用).
返回标准评分卡公式
Score = A - B × ln(odds)的各项参数与等价的 WOE 线性表达式,便于复核、文档化与离线部署。- 参数:
decimal (int) -- 公式中数值保留的小数位数,默认 4
- 返回:
包含公式字符串与参数的字典,键包括
公式/A/B/截距分数/base_odds/base_score/pdo/rate/direction/WOE线性公式- 返回类型:
Dict[str, Any]
- scorecard_points(feature_map=None, decimal=4)[源代码]
输出评分卡分箱信息及其对应的分数.
支持从分箱器获取完整的分箱信息,包括: - 基础分(截距项对应的分数) - 数值特征分箱(区间格式) - 类别特征分箱 - 缺失值分箱(标记为 'missing') - 特殊值分箱(标记为 'special')
参考 scorecardpipeline 的实现方式,确保与分箱器格式兼容。
- 参数:
feature_map (Dict[str, str] | None) -- 特征名到中文含义的映射字典
decimal (int) -- 分数保留小数位数,默认 2
- 返回类型:
DataFrame
- score_to_bad_rate_table(scores, y, n_bins=10, method='quantile', score_decimal=4)[源代码]
生成评分分箱对应坏样本率、Odds、KS 的对照表(评分卡校验/划档常用)。
将分数切成
n_bins档,逐档统计样本数、坏样本率、Odds,并累计计算 KS, 用于检查"分数越高坏率越低"的单调性与整体区分度。- 参数:
scores (ndarray) -- 模型输出的分数数组(如
predict()的结果)y (ndarray) -- 对应的真实标签数组(0=好/1=坏),与
scores等长n_bins (int) -- 分数分档数量,默认为
10method (str) --
分档方式,默认为
'quantile'。可取以下枚举值:'quantile':等频分档(每档样本量大致相等),用pd.qcut其他值(如
'uniform'):等距分档(按分数范围等宽),用pd.cut
score_decimal (int) -- 评分区间边界保留小数位数,默认
4,用于消除浮点显示尾差
- 返回:
DataFrame,列含
评分区间/样本数/坏样本数/坏样本率/好样本数/Odds/累计好样本占比/累计坏样本占比/KS- 返回类型:
DataFrame
参考样例
>>> s = scorecard.predict(X_test) >>> scorecard.score_to_bad_rate_table(s, y_test, n_bins=10)
- save_pickle(file, engine='joblib', compression=None, compression_level=None)[源代码]
保存模型.
使用 utils.io.save_pickle 进行持久化存储,支持多种序列化引擎和压缩格式。
- 参数:
file (str) -- 文件路径
engine (str) -- 序列化引擎,可选 'joblib'/'pickle'/'dill'/'cloudpickle',默认 'joblib'
compression (str | None) -- 压缩格式,可选 'gzip'/'bz2'/'xz'/'lz4'/'zstd',默认 None
compression_level (int | None) -- 压缩级别(1-9),默认 None
- 返回:
保存的文件路径
- 返回类型:
str
- classmethod load_pickle(file, engine='auto', compression=None)[源代码]
加载模型.
使用 utils.io.load_pickle 进行持久化读取,支持多种序列化引擎和压缩格式。
- 参数:
file (str) -- 文件路径
engine (str) -- 序列化引擎,可选 'auto'/'joblib'/'pickle'/'dill'/'cloudpickle',默认 'auto'
compression (str | None) -- 压缩格式,可选 'gzip'/'bz2'/'xz'/'lz4'/'zstd',默认 None(自动检测)
- 返回:
加载的 ScoreCard 模型实例
- 返回类型:
- export_pmml(pmml_file='scorecard.pmml', decimal=12, debug=False)[源代码]
导出 PMML 文件.
- 参数:
pmml_file (str) -- PMML 文件保存路径,默认 'scorecard.pmml'
decimal (int) -- 特征子分保留小数位数,默认 12,确保 PMML 与 predict 精度一致
debug (bool) -- 是否返回中间对象进行调试,默认 False
- 返回:
debug=True 时返回 PMMLPipeline,否则返回 None
- export_deployment_code(language='python', output_file=None, function_name='calculate_score', decimal=12)[源代码]
导出评分卡部署代码.
支持生成 SQL、Python、Java 格式的评分卡计算代码,可直接用于生产部署。
- 参数:
language (str) -- 目标语言,可选 'sql'/'python'/'java',默认 'python'
output_file (str | None) -- 输出文件路径,为 None 时仅返回字符串
function_name (str) -- 函数/存储过程名称,默认 'calculate_score'
decimal (int) -- 分数保留小数位数,默认 4
- 返回:
生成的部署代码字符串
- 返回类型:
str
参考样例
>>> sc = ScoreCard(...) >>> sc.fit(X_train, y_train) >>> # 生成 SQL >>> sql = sc.export_deployment_code(language='sql', output_file='scorecard.sql') >>> # 生成 Python >>> py = sc.export_deployment_code(language='python', output_file='scorecard.py')
- get_feature_importance()[源代码]
获取评分卡的特征重要性表(基于 LR 系数)。
以逻辑回归系数绝对值衡量重要性。与
get_feature_importances`(返回 Series, 支持 ``coef`()/score_range两种口径)不同,本方法返回明细 DataFrame。- 返回:
DataFrame,含
feature/coef/importance三列,按importance降序- 抛出:
NotFittedError -- 评分卡尚未拟合时
- 返回类型:
DataFrame
参考样例
>>> scorecard.get_feature_importance().head()
- get_reason_codes(X, keep=3, feature_map=None, reason_map=None)[源代码]
返回评分卡中真正拉低分数的不利原因码。
- 参数:
X (DataFrame | ndarray)
keep (int)
feature_map (Dict[str, str] | None)
reason_map (Dict[str, Dict[str, str]] | None)
- 返回类型:
DataFrame
- get_reason(X, keep=3)[源代码]
输出每个样本评分的主要驱动原因(reason codes / 拒绝原因)。
对每个样本,按"该特征得分相对其基准效应的偏离"排序,取偏离最负(最拉低分数)的 前
keep个特征作为不利原因,可用于授信拒绝理由说明(adverse action)与可解释性。- 参数:
X (DataFrame | ndarray) -- 输入数据,原始或 WOE 数据(自动识别),DataFrame 或 ndarray
keep (int) -- 每个样本保留的主要原因(特征)个数,默认为
3
- 返回:
DataFrame,每行对应一个样本,列为排序后的 Top-
keep不利特征及其影响- 抛出:
NotFittedError -- 评分卡尚未拟合时
- 返回类型:
DataFrame
参考样例
>>> scorecard.get_reason(X_test, keep=3)
- score_to_probability_table(scores=None, X=None, y=None, n_bins=10, method='quantile', score_bins=None)[源代码]
生成评分区间与理论逾期率(坏样本概率)对照表。
将分数分档后,依据评分卡刻度公式由各档分数中位数反推理论 odds 与坏样本概率 (
prob = odds/(1+odds),odds = exp((A - score)/B)),可叠加真实标签y对比理论与实际逾期率,用于评分卡校准核验与划档定价。- 参数:
scores (ndarray | None) -- 分数数组;若为
None则用X经predict()计算X (DataFrame | ndarray | None) -- 输入数据,当
scores未提供时用于预测分数y (ndarray | None) -- 可选真实标签,提供后表中追加各档实际坏样本率以对比理论值
n_bins (int) -- 分数分档数量,默认为
10method (str) --
分档方式,默认为
'quantile'。可取以下枚举值:'quantile':等频分档(pd.qcut)'uniform':等距分档(pd.cut)'custom':使用score_bins指定的自定义分档边界
score_bins (list | None) -- 自定义分档边界列表,仅当
method='custom'时生效
- 返回:
DataFrame,含评分区间及对应理论 odds / 理论坏样本概率(提供
y时含实际值)- 抛出:
ValueError --
scores与X均未提供时- 返回类型:
DataFrame
参考样例
>>> scorecard.score_to_probability_table(X=X_test, y=y_test, n_bins=10)
- get_detailed_score(X, sample_idx=None, include_reason=True)[源代码]
输出样本级评分明细:基础分 + 各特征贡献分 + 总分(可附主要原因)。
将总分拆解为截距基础分与每个特征的贡献分,便于逐样本审视分数构成、做可解释性展示。
- 参数:
X (DataFrame | ndarray) -- 输入数据,原始或 WOE 数据(自动识别),DataFrame 或 ndarray
sample_idx (int | list | None) -- 仅输出指定样本的明细,可为单个下标或下标列表;
None表示全部include_reason (bool) -- 是否附带主要驱动原因列(同
get_reason()),默认为True
- 返回:
DataFrame,每行一个样本,列含各特征贡献分、基础分与总分
- 抛出:
NotFittedError -- 评分卡尚未拟合时
- 返回类型:
DataFrame
参考样例
>>> scorecard.get_detailed_score(X_test, sample_idx=0)
- export(to_json=None, to_frame=False, decimal=12, include_meta=True, compatibility=None)[源代码]
导出评分卡规则,兼容 toad/scorecardpipeline 格式.
导出格式与 toad.ScoreCard.export() 和 scorecardpipeline.ScoreCard.export() 保持一致。
- 参数:
to_json (str | None) -- 可选,JSON 文件保存路径。如果提供,将规则保存到该文件
to_frame (bool) -- 是否返回 DataFrame 格式,默认为 False
decimal (int) -- 分数保留小数位数,默认为 12,确保规则往返与原模型一致
include_meta (bool) -- 是否额外导出重建评分所需元数据,默认为 True
compatibility (str | None) -- 外部兼容格式;设为
'toad'时等价于include_meta=False
- 返回:
评分卡规则字典或 DataFrame - 字典格式: {'feature': {'bin_label': score, ...}, ...} - DataFrame格式: columns=['name', 'value', 'score']
- 返回类型:
Dict | DataFrame
参考样例
>>> card = ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> card.fit(X_woe, y, binner=binner) >>> >>> # 导出为字典 >>> rules = card.export() >>> >>> # 导出并保存到 JSON 文件 >>> rules = card.export(to_json='scorecard_rules.json') >>> >>> # 导出为 DataFrame >>> df = card.export(to_frame=True)
与 toad/scorecardpipeline 的兼容性
导出的规则可以直接被 toad 和 scorecardpipeline 加载:
>>> # toad 加载(显式导出不含 hscredit 元数据的兼容格式) >>> import toad >>> toad_rules = card.export(compatibility='toad') >>> toad_card = toad.ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> toad_card.load(toad_rules) >>> >>> # scorecardpipeline 加载 >>> from scorecardpipeline import ScoreCard >>> scp_rules = card.export(compatibility='scorecardpipeline') >>> scp_card = ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> scp_card.load(scp_rules)
- load_rules(from_json, update=False, binner=None)[源代码]
加载评分卡规则,兼容 hscredit/toad/scorecardpipeline 格式.
从字典或 JSON 文件加载评分卡规则,支持 toad 和 scorecardpipeline 导出的格式。
- 参数:
from_json (str | PathLike | Dict) -- 评分卡规则字典或 JSON 文件路径 - 字典: {'feature': {'bin_label': score, ...}, ...} - 文件路径: 'scorecard_rules.json'
update (bool) -- 是否更新现有规则(而非替换),默认为 False
binner (Any | None) -- 可选的分箱器,用于对原始数据进行分箱后评分。 - 如果提供,将用于 predict(input_type='raw') 时的数据转换 - 如果不提供,将基于规则中的分箱信息进行转换
- 返回:
self,支持链式调用
- 返回类型:
参考样例
>>> card = ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> >>> # 从字典加载 >>> rules = {'age': {'[18, 25)': 50, '[25, 35)': 45}} >>> card.load(rules) >>> >>> # 从 JSON 文件加载 >>> card.load('scorecard_rules.json') >>> >>> # 更新现有规则 >>> card.load({'new_feature': {'bin1': 10, 'bin2': 20}}, update=True)
与 toad/scorecardpipeline 的兼容性
可以直接加载 toad 和 scorecardpipeline 导出的规则:
>>> # toad 导出 >>> import toad >>> toad_card = toad.ScoreCard() >>> toad_card.fit(X, y, combiner=combiner, transer=transformer) >>> rules = toad_card.export() >>> >>> # hscredit 加载 >>> from hscredit.core.models import ScoreCard >>> card = ScoreCard(pdo=60, rate=2, base_odds=35, base_score=750) >>> card.load(rules)
- load(engine='auto', **kwargs)
从持久化文件加载评分卡模型;在实例上调用 load(...) 时兼容加载评分规则。
- 参数:
file (str)
engine (str)