High-performance Risk Modeling Toolkit powered by Polars
Project description
MARS
面向信贷风控分析与建模的 Polars-first 高性能工具库
项目简介 · 设计理念 · 能力地图 · 性能对比 · 安装 · 快速开始 · 核心-api-约定 · Modeling Pipeline · 报表导出 · FAQ
项目简介
MARS 覆盖数据画像、分箱评估、特征分析、特征筛选、Modeling Pipeline、特征/模型监控指标计算和 Excel/HTML 报表导出。它以宽表特征为主线,串联训练前分析、建模期调参与评估、特征与模型分稳定性观察和报表导出,让日常风控建模流程更容易复用、审计和交付。
MARS 将数据质量、分箱规则、指标评估、特征筛选、模型调参与评估结果、导出产物组织在同一套结构化报告体系中。使用者既可以直接生成 Excel/HTML 报表,也可以读取各模块返回的多粒度数据,继续做特征复盘、基于结构化表定制监控规则、内部看板数据接入或定制化分析。
设计理念
- 性能优先:面向宽表、大样本、多特征风控场景,核心计算优先使用 Polars,减少不必要的数据复制和跨框架转换。
- sklearn 风格:底层算法对象保持
fit/transform/evaluate等熟悉范式,便于接入现有建模实验和 Pipeline。 - Pandas/Polars 兼容:核心计算优先走 Polars,同时兼容 Pandas 和 Polars 的输入与输出;需要保持原类型的链路尽量减少无意义转换。
- 风控全链路:围绕数据画像、分箱评估、特征分析、特征筛选、Modeling Pipeline、特征/模型监控指标计算、报表导出组织能力。
- 模块可串联:分箱规则、指标明细、筛选结果、模型结果和 report 对象可在模块间复用,减少 Notebook、Excel 和零散脚本中的重复加工。
- 监控边界清晰:模型分、prob、score 可以作为特殊特征进入同一套监控指标计算;MARS 输出结构化指标和默认报警摘要,监控窗口、基准样本、模型版本、调度方式、阈值策略、看板和业务处置流程由使用者定义。
- 补齐开源空白:聚焦通用开源工具通常覆盖不足的信贷风控宽表分析、通用监控指标计算、报表交付和可复盘 report 对象。
- 可审计与可二次加工:各模块 report 保留多粒度结构化表,支持 Excel/HTML 导出、内部看板接入,以及借助 Agent 做定制化摘要和报告重排。
能力地图
模块链路:数据画像 -> 分箱评估 -> 特征分析 -> 特征筛选 -> Modeling Pipeline -> 特征/模型监控 -> Excel/HTML 报表导出。
| 模块 | 主 API | 典型问题 | 主要产出 |
|---|---|---|---|
| 数据画像 | MarsDataProfiler / profile_stats |
缺失率、零值、均值/分布、PSI、时间趋势、特征来源分组 | MarsProfileReport |
| 分箱评估 | MarsNativeBinner / MarsOptimalBinner / MarsBinEvaluator / profile_risk |
连续/类别分箱、IV、KS、AUC、Lift、分箱规则复用、部署转换、SQL 生成 | MarsRiskProfile、MarsEvaluationReport、分箱规则 |
| 特征分析 | MarsDataProfiler / profile_stats / profile_risk |
特征质量、单变量风险、稳定性、分布变化、业务特殊值影响 | 画像表、指标明细、趋势表 |
| 特征筛选 | MarsStatsSelector / MarsLinearSelector / MarsImportanceSelector |
质量筛选、稳定性、相关性、模型重要性 | selected_features_、筛选报告 |
| Modeling Pipeline | MarsModelingSession / MarsModelTuner / MarsModelReplayRunner / MarsModelEvaluator |
train/val/oot 切分、模型调参、benchmark 对比、Top-K replay、重要性表、建模评估报告 | MarsModelTuningResult、MarsModelReplayResult、MarsModelingReport |
| 特征/模型监控 | MarsMonitor / generate_monitoring_alert |
支持前端监控、后端监控的通用指标计算、PSI、缺失趋势、分箱占比趋势、分箱统计量趋势、target 表现覆盖率、默认报警摘要 | MarsMonitoringReport、监控报警摘要 |
| Excel/HTML 报表导出 | write_excel / write_html / build_scorecard |
画像报表、风险评估报表、建模评估报表、评分卡映射、部署 SQL | Excel、HTML、MarsScorecard |
性能对比
面向宽表分箱场景,MARS 重点优化大样本、多特征下的分箱拟合、规则转换和报表链路衔接。可用以下命令复现测试结果:
conda run -n mars python benchmarks/benchmark_binning_speed.py native --rows 200000 --features 3000 --repeats 1
conda run -n mars python benchmarks/benchmark_binning_speed.py optimal --rows 50000 --features 1000 --repeats 3
- 计时范围:数据生成 + fit + transform + 本轮清理
- 内存口径:主进程及其子进程的 RSS;结束增量为本轮结束 RSS - 起始 RSS,峰值增量为采样峰值 RSS - 起始 RSS
- Python:
3.10.19;系统:Windows-10-10.0.26200-SP0 - 结束增量会受 Python、Polars、NumPy 内存分配器缓存影响;比较峰值压力时优先看“峰值增量”
原生分箱:toad vs MarsNativeBinner
- 数据规模:
200,000行 ×3,000个数值特征 - 重复次数:
1;随机种子:2026
| 场景 | 方法 | 平均耗时(s) | 最快(s) | 最慢(s) | 平均结束增量(MB) | 峰值增量(MB) | 相对基准 | 备注 |
|---|---|---|---|---|---|---|---|---|
| 等频分箱 | toad Combiner + WOETransformer | 126.083 | 126.083 | 126.083 | 30.7 | 20516.1 | 1.60x | |
| 等频分箱 | MarsNativeBinner | 78.768 | 78.768 | 78.768 | 3348.2 | 6768.8 | 1.00x | method=quantile |
| 等宽分箱 | toad Combiner + WOETransformer | 105.859 | 105.859 | 105.859 | 6.7 | 20468.4 | 1.31x | |
| 等宽分箱 | MarsNativeBinner | 81.058 | 81.058 | 81.058 | -7.8 | 6727.7 | 1.00x | method=uniform |
原生等频/等宽的额外能力
MARS 的原生等频/等宽分箱不只是生成切点。围绕风控特征分析和监控指标计算,这些处理统一沉淀在同一套规则对象中,便于后续分析、监控和导出复用:
- 缺失值、
NaN、自定义missing_values和业务特殊值special_values会独立隔离,不挤占正常分箱数量。 merge_small_bins可在等频/等宽后自动合并低占比碎片箱,减少极端宽表中的不稳定分箱。remove_empty_bins可在等宽场景自动清理空箱,适配长尾、零膨胀和稀疏分布。- 原生分箱支持处理类别特征,最优分箱支持类别合并,用于降低高基数类别带来的不稳定性。
- 分箱规则可以继续进入特征分析、特征/模型监控指标计算、Modeling Pipeline 结果和后续报表链路,减少从探索到部署之间的规则重写。
最优分箱:MarsOptimalBinner vs optbinning
- 数据规模:
50,000行 ×1,000个数值特征 - 重复次数:
3;随机种子:2026
| 场景 | 方法 | 平均耗时(s) | 最快(s) | 最慢(s) | 平均结束增量(MB) | 峰值增量(MB) | 相对基准 | 备注 |
|---|---|---|---|---|---|---|---|---|
| 最优分箱 | MarsOptimalBinner | 28.011 | 26.627 | 29.189 | 282.0 | 5531.5 | 1.00x | 单特征 time_limit=1s |
| 最优分箱 | optbinning.BinningProcess | 125.826 | 124.474 | 126.538 | 17.0 | 628.4 | 4.49x | 单特征 time_limit=1s |
安装
MARS 支持 Python >= 3.10。
pip install mars-risk
| 场景 | 安装命令 |
|---|---|
| 基础能力(含画像、分箱、筛选、Excel/HTML 报表和图表报告) | pip install mars-risk |
| Notebook 交互 | pip install "mars-risk[notebook]" |
| 树模型与调参 | pip install "mars-risk[ml,tuning]" |
| 本地开发 | pip install -e ".[dev,ml,tuning]" |
git clone https://github.com/leeesq/mars-risk.git
cd mars-risk
pip install -e ".[dev,ml,tuning]"
快速开始
下面的示例保持短小,展示主链路的新 API 约定。
准备样本
import polars as pl
df = pl.DataFrame(
{
"apply_dt": [
"2024-01-03", "2024-01-10", "2024-01-17", "2024-01-24",
"2024-02-03", "2024-02-10", "2024-02-17", "2024-02-24",
"2024-03-03", "2024-03-10", "2024-03-17", "2024-03-24",
],
"month": [
"2024-01", "2024-01", "2024-01", "2024-01",
"2024-02", "2024-02", "2024-02", "2024-02",
"2024-03", "2024-03", "2024-03", "2024-03",
],
"income": [3200, 3600, -999, None, 3300, 4200, -999, 5800, 3400, 4300, None, 6100],
"utilization": [0.12, 0.18, 0.52, 0.61, 0.14, 0.29, 0.54, 0.58, 0.16, 0.31, 0.56, 0.63],
"segment": ["new", "repeat", "vip", "vip", "new", "repeat", "vip", "vip", "new", "repeat", "vip", "vip"],
"target": [0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1],
}
)
数据画像
from mars.analysis import MarsDataProfiler, profile_stats
profiler = MarsDataProfiler(missing_values=[-999])
profile_report = profiler.generate_profile(
df,
group_col="month",
config_overrides={
"enable_sparkline": False,
"dq_metrics": ["missing", "zeros"],
"stat_metrics": ["mean", "psi"],
},
)
quick_report = profile_stats(
df,
metrics=["missing", "mean"],
features=["income", "utilization"],
group_col="month",
missing_values=[-999],
)
分箱评估
from mars.analysis import profile_risk
risk_profile = profile_risk(
df,
target="target",
features=["income", "utilization", "segment"],
group_col="month",
binning_type="native",
binner_params={"method": "quantile", "n_bins": 4},
plot=False,
)
eval_report = risk_profile.report
binner = risk_profile.binner
summary = eval_report.summary_table
profile_risk() 返回 MarsRiskProfile(report, binner, targets, metadata)。report 用于查看和导出分箱评估报表,binner 用于复用本次分箱规则。
分箱器
from mars.feature import MarsNativeBinner
X = df.select(["income", "utilization", "segment"])
y = df.get_column("target")
binner = MarsNativeBinner(method="quantile", n_bins=4, special_values=[-999])
binner.fit(X, y, cat_features=["segment"])
X_bin = binner.transform(X, return_type="index")
X_woe = binner.transform(X, return_type="woe")
income_mapping = binner.get_bin_mapping("income")
特征筛选
from mars.feature import MarsStatsSelector
selector = MarsStatsSelector(
missing_thr=0.9,
iv_thr=0.01,
psi_thr=0.25,
skip_fine_scan=True,
)
selector.fit(
df,
target="target",
features=["income", "utilization", "segment"],
group_col="month",
)
selected_features = selector.selected_features_
selection_report = selector.get_eval_report(df)
特征/模型监控
mars.monitoring 的定位是监控指标计算层,MarsMonitor 提供特征与模型分的通用监控指标计算能力。无标签场景可以使用 target=None 做分布监控;target 成熟后可以继续计算坏账率、IV、KS、AUC、Lift 等标签指标。模型分、prob 或 score 只需要作为一个普通字段放入 features。
from mars.monitoring import MarsMonitor, generate_monitoring_alert
monitor_df = df.with_columns((pl.col("utilization") * 100).alias("model_score"))
monitor_report = MarsMonitor(
binner_params={"method": "quantile", "n_bins": 4},
).monitor(
monitor_df,
features=["model_score", "income", "utilization"],
target="target",
group_col="month",
trend_column_order="desc",
)
monitor_summary = monitor_report.summary_table
bin_stat_trends = monitor_report.bin_stat_trend_tables
target_observation = monitor_report.target_observation_table
alert_text = generate_monitoring_alert(
monitor_report,
score_key="model_score",
model_features=["income", "utilization"],
)
监控链路只接受 0/1/True/False/null target;null 表示样本尚未到表现期。target=None 时只输出无标签分布监控;传入 target 时,PSI、缺失率和分箱占比使用全量样本,坏账率、IV、KS、AUC、Lift 等标签指标只使用已表现样本。PSI 默认不包含缺失箱和特殊值箱,缺失率会单独进入趋势监控。trend_column_order 控制趋势宽表取值列的展示顺序,默认 "asc" 保持从早到晚;需要最新月份靠前时可设为 "desc",报警摘要会按 report 记录的趋势列顺序识别基准期和最新期。generate_monitoring_alert 是基于 MarsMonitoringReport 的默认摘要工具,不替代业务方自己的报警规则、阈值策略和处置流程。
Modeling Pipeline
建模调参需要安装 ml 和 tuning 可选依赖。
from mars.modeling import MarsModelingSession
from mars.modeling.tuning import MarsModelReplayRunner
session = MarsModelingSession(
model_type="xgb",
features=["income", "utilization", "segment"],
target="target",
categorical_features=["segment"],
optimize_metric="ks",
seed=1206,
)
modeling_df = session.slice(
df,
time_col="apply_dt",
split_ratios={"train": 0.6, "val": 0.2, "oot": 0.2},
)
tuning_result = session.tune(
modeling_df,
n_trials=20,
history_path=None,
)
replay_result = MarsModelReplayRunner().run(
tuning_result,
modeling_df,
top_k=3,
sort_metric="ks",
)
核心 API 约定
| 场景 | 约定 |
|---|---|
| 高层风控工作流 | 使用 df, target,例如 profile_risk(df, target="y") |
| 底层算法对象 | 使用 X, y,例如 MarsNativeBinner().fit(X, y) |
| 构造函数 | 放稳定策略、阈值、模型规格,不放本次样本数据 |
| 方法入参 | 放数据、列名、特征范围、分组、时间、输出路径 |
| 分组命名 | group_col 是已有分组列,time_col 是原始日期列,time_grain 是聚合粒度 |
| 建模切片 | dataset_flag_col 只表示 train/val/oot 等建模样本切片 |
| 文件输出 | 路径参数支持 `str |
Modeling Pipeline
Modeling Pipeline 仍在快速迭代中,可能不稳定;后续接口约定、结果对象和调参参数都可能发生较大变动。
当前支持 XGBoost(xgb)、LightGBM(lgb)、CatBoost(cbt / cat / catboost)和 Logistic Regression(lr / logistic)。逻辑回归支持 numeric 与 WOE 两种特征模式。
| API | 职责 | 返回值 |
|---|---|---|
MarsModelDataSplitter |
无状态样本切分工具 | 与输入类型一致的 DataFrame |
MarsModelingSession |
组织切分、调参、replay 和增量特征调参 | 会话对象 |
MarsModelTuner |
对单个模型后端执行 Optuna 调参 | MarsModelTuningResult |
MarsModelReplayRunner |
从调优结果中读取规格并回放 Top-K trial | MarsModelReplayResult |
MarsModelEvaluator |
对已打分样本构建建模评估报告 | MarsModelingReport |
MarsFeatureIncrementalTuner |
按特征数量逐步扩展调参 | MarsFeatureGrowthResult |
MarsModelTuningResult 会保存最佳模型、调参历史、特征重要性、训练配置和 artifact 元数据。MarsModelReplayResult 会保存 replay leaderboard、模型字典、打分数据、评估报告和重要性表。
模型分可以被视为一个特殊特征进入稳定性观察。当前 MarsModelEvaluator 是建模评估器,已输出 Score PSI 和 score_psi 明细,用于建模评估阶段观察模型分在 train/val/oot 或业务切片之间的分布漂移。需要按自定义时间或业务切片观察模型分时,使用者可以将模型分加入 MarsMonitor 的 features,得到 PSI、缺失率、分箱占比、分箱统计量和已表现样本风险指标等结构化结果。
Excel/HTML 报表导出与二次加工
画像、风险评估、建模评估和评分卡结果都以对象形式返回。MarsProfileReport、MarsEvaluationReport、MarsModelingReport 等 report 对象会保留 summary_table、detail_table / detail_tables、trend_tables、metadata / report_meta 等结构化数据,使用者可以按模块、特征、分组、时间或样本切片继续加工。
这些多粒度表格适合继续做特征复盘、基于结构化表继续定制监控规则、接入内部看板和定制化分析,也便于借助 Agent 基于明细表进行摘要、筛选、解释和报告重排。需要交付给业务或评审时,可以直接导出 Excel/HTML:
profile_report.write_excel("mars_profile.xlsx")
eval_report.write_excel("mars_evaluation.xlsx", engine="openpyxl")
eval_report.write_html("mars_evaluation.html")
评分卡链路支持从逻辑回归模型和 WOE 分箱结果生成分数映射,并导出 SQL 规则。
公开 API 概览
| 导入位置 | 公开对象 |
|---|---|
mars.analysis |
MarsDataProfiler、MarsBinEvaluator、MarsRiskProfile、profile_stats、profile_risk |
mars.feature |
MarsNativeBinner、MarsOptimalBinner、MarsStatsSelector、MarsLinearSelector、MarsImportanceSelector |
mars.modeling |
MarsModelingSession |
mars.modeling.tuning |
MarsModelTuner、MarsModelReplayRunner |
mars.modeling.slicing |
MarsModelDataSplitter |
mars.modeling.results |
MarsModelTuningResult、MarsModelReplayResult |
mars.modeling.feature_growth |
MarsFeatureGrowthResult、MarsFeatureIncrementalTuner |
mars.monitoring |
MarsMonitor、MarsMonitoringReport、MarsMonitoringData、MarsMonitoringAlerter、MarsMonitoringAlertConfig、generate_monitoring_alert |
mars.scoring |
MarsScorecard、build_scorecard |
可选依赖
mars-risk基础安装已包含 Excel/HTML 报表导出和绘图报告依赖。notebook:Notebook 交互展示。ml:XGBoost、LightGBM、CatBoost、SHAP、statsmodels。tuning:Optuna 调参。
测试与开发
python -m ruff check src tests benchmarks scripts
python -m mypy src/mars
pydoclint src/mars
python scripts/check_private_docstrings.py src/mars
MPLBACKEND=Agg python -m pytest -q --basetemp .pytest-tmp
本仓库使用 src/ 包结构,并声明 mars/py.typed。提交 Python 代码时,请保持类型注解、NumPy 风格 docstring、中文自然语言注释和 README 同步。public API 的参数、返回值和异常变更必须同步 docstring,CI 会通过 ruff 和 pydoclint 阻断漏改;复杂私有方法缺少中文短 docstring 时,会由 scripts/check_private_docstrings.py 阻断。
FAQ
profile_risk() 返回什么?
返回 MarsRiskProfile(report, binner, targets, metadata)。其中 report 是风险评估报告,binner 是本次拟合或复用的分箱器,targets 是目标列列表,metadata 保存运行上下文。
为什么高层 API 用 target,底层对象用 y?
高层 API 面向完整业务表,目标变量是某个列名,所以使用 df, target。底层算法对象面向特征矩阵和标签向量,所以使用 X, y。这样可以避免同一个方法里同时出现列名和标签向量两种语义。
MarsModelTuner.tune(history_path=None) 会写文件吗?
不会。history_path=None 时调参历史只保存在返回对象中。传入路径时才写 CSV;如果路径已存在且 overwrite=False,会抛出 FileExistsError。
Pandas 和 Polars 都能用吗?
可以。核心计算优先走 Polars;Pandas 输入会在需要时转换或保持原类型返回。建模切分器会根据输入类型选择对应实现,避免不必要的跨框架转换。
路线图
- 继续扩展模型评估、特征/模型监控指标计算、报警摘要和报表导出的测试覆盖。
- 增强评分卡 SQL 和 artifact 回放能力。
- 持续收敛 public API 命名和类型注解。
参与方式
欢迎提交 issue、测试用例、文档修正和真实建模场景反馈。PR 请附上最小复现、测试命令和对 public API 的影响说明。
许可证
本项目使用 LICENSE 中声明的开源许可证。
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mars_risk-0.0.16.tar.gz.
File metadata
- Download URL: mars_risk-0.0.16.tar.gz
- Upload date:
- Size: 359.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4aff8bb3447d3482310a521d7393c1a2dd085066c3fd85ba79e1a54676c2af90
|
|
| MD5 |
b36fc3e4cf8a605aa0fd934a76c6a44f
|
|
| BLAKE2b-256 |
d7626f25d37ad2cd1cdb27bebf6db5f8828e9813cc0e10798a95d8756c645f25
|
Provenance
The following attestation bundles were made for mars_risk-0.0.16.tar.gz:
Publisher:
publish.yml on leeesq/mars-risk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mars_risk-0.0.16.tar.gz -
Subject digest:
4aff8bb3447d3482310a521d7393c1a2dd085066c3fd85ba79e1a54676c2af90 - Sigstore transparency entry: 1740464754
- Sigstore integration time:
-
Permalink:
leeesq/mars-risk@6b349ecbaa860ed535ef6baa8d99c3d3bd2b6941 -
Branch / Tag:
refs/tags/0.0.16 - Owner: https://github.com/leeesq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b349ecbaa860ed535ef6baa8d99c3d3bd2b6941 -
Trigger Event:
release
-
Statement type:
File details
Details for the file mars_risk-0.0.16-py3-none-any.whl.
File metadata
- Download URL: mars_risk-0.0.16-py3-none-any.whl
- Upload date:
- Size: 351.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
da1e8405f76c877ab3849f777ab10f2b9c073157ecd5362ddeeff4102130b00e
|
|
| MD5 |
8f846479736a2e79fb184b740643d045
|
|
| BLAKE2b-256 |
2d3bc6e8943cd56b51d031adb5678d3d4253330729cfd986345997269a891b58
|
Provenance
The following attestation bundles were made for mars_risk-0.0.16-py3-none-any.whl:
Publisher:
publish.yml on leeesq/mars-risk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mars_risk-0.0.16-py3-none-any.whl -
Subject digest:
da1e8405f76c877ab3849f777ab10f2b9c073157ecd5362ddeeff4102130b00e - Sigstore transparency entry: 1740464814
- Sigstore integration time:
-
Permalink:
leeesq/mars-risk@6b349ecbaa860ed535ef6baa8d99c3d3bd2b6941 -
Branch / Tag:
refs/tags/0.0.16 - Owner: https://github.com/leeesq
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@6b349ecbaa860ed535ef6baa8d99c3d3bd2b6941 -
Trigger Event:
release
-
Statement type: