SuperModelingFactory 0.6.3__tar.gz → 0.6.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/Model_Eval_Tool.py +10 -1
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/evaluate_model.py +172 -18
- supermodelingfactory-0.6.5/Modeling_Tool/Feature/ODPS_Distribution_Tool.py +602 -0
- supermodelingfactory-0.6.5/Modeling_Tool/Feature/ODPS_Distribution_Tool.pyi +23 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/__init__.py +2 -1
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/_common.py +43 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/credit_model.py +275 -21
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/feature_validation.py +26 -2
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/field_meta.py +10 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Monotone_Binner.py +8 -5
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/__init__.py +3 -1
- {supermodelingfactory-0.6.3/SuperModelingFactory.egg-info → supermodelingfactory-0.6.5}/PKG-INFO +2 -2
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/README.md +1 -1
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5/SuperModelingFactory.egg-info}/PKG-INFO +2 -2
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/SuperModelingFactory.egg-info/SOURCES.txt +2 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/pyproject.toml +1 -1
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/setup.py +1 -1
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/ExcelMaster/ExcelFormatTool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/ExcelMaster/ExcelMaster.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/ExcelMaster/Template.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/ExcelMaster/Utility.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/ExcelMaster/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/LICENSE +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/MANIFEST.in +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Binning_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Binning_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Check_DuckDB_Compatibility.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Json_Data_Converter.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Model_Registry_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/ODPS_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Parallel_Engine.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Parallel_ODPS_Manager.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Proc_Compare.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Slope_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/Slope_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/XOR_Encryptor.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/XOR_Encryptor.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/kDataFrame.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/kDataFrame.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/sample_weight_utils.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Core/utils.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/Evaluation_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/Evaluation_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/Model_Eval_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/evaluate_model.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/weighted_eval_utils.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Explainability/Coalition_Structure.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Explainability/Model_Explainer.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Explainability/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Distribution_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Distribution_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Feature_Insights.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Feature_Insights.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Feature_Screen.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/PSI_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/PSI_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/WOE_Engine_Feature_Patch.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Feature/Weighted_Screen.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/Backward_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/Backward_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/GBM_Search_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/GBM_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/GBM_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/LRM_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/LRM_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Model/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/mock_sample.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/orchestrator.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/reject_inference.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/sample_analysis.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/score_comparison.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/score_consistency_uat.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Pipeline/screening_artifact.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Distribution_Adaptation.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Distribution_Adaptation.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Reject_Infer.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Reject_Infer.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Sample_Split.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/Sample_Split.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Sample/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/UAT/UAT_Consistency_Checker.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/UAT/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Adapter.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Adapter.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Master.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Master.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Monotone_Binner.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Plot_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Plot_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Report_Builder.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Report_Builder.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/WOE_Tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/plot_woe_tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/WOE/plot_woe_tool.pyi +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/_utils/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/_utils/nan_guard.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/_utils/robust.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/_utils/sentinels.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/ref_font/KaiTi.ttf +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/ref_font/WeiRuanYaHei.ttf +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/ref_font/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/ref_font/simsun.ttc +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Report/Report_Tool.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Report/__init__.py +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/SuperModelingFactory.egg-info/dependency_links.txt +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/SuperModelingFactory.egg-info/not-zip-safe +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/SuperModelingFactory.egg-info/requires.txt +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/SuperModelingFactory.egg-info/top_level.txt +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/requirements.txt +0 -0
- {supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/setup.cfg +0 -0
{supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/Model_Eval_Tool.py
RENAMED
|
@@ -2362,15 +2362,24 @@ class PerformanceEvaluator:
|
|
|
2362
2362
|
for name, data in self.datasets.items():
|
|
2363
2363
|
if data is None:
|
|
2364
2364
|
continue
|
|
2365
|
+
wc = self.dataset_weight_cols.get(name) or active_weight_col
|
|
2365
2366
|
work_data = data.copy()
|
|
2366
2367
|
scr_name = self.scr_name
|
|
2367
2368
|
if scr_name is None:
|
|
2368
2369
|
scr_name = "_mdl_scr"
|
|
2369
2370
|
work_data[scr_name] = self.model.predict_proba(work_data.loc[:, self.feature_cols])[:, 1]
|
|
2370
|
-
|
|
2371
|
+
payload = {
|
|
2371
2372
|
"y_true": work_data[self.tgt_name],
|
|
2372
2373
|
"y_score": work_data[scr_name],
|
|
2373
2374
|
}
|
|
2375
|
+
resolved_weight = _weighted_eval.resolve_weights(
|
|
2376
|
+
work_data,
|
|
2377
|
+
weight_col=wc,
|
|
2378
|
+
expected_len=len(work_data),
|
|
2379
|
+
)
|
|
2380
|
+
if resolved_weight is not None:
|
|
2381
|
+
payload["sample_weight"] = resolved_weight
|
|
2382
|
+
eval_datasets[name] = payload
|
|
2374
2383
|
if eval_datasets:
|
|
2375
2384
|
evaluate_performance(
|
|
2376
2385
|
datasets=eval_datasets,
|
{supermodelingfactory-0.6.3 → supermodelingfactory-0.6.5}/Modeling_Tool/Eval/evaluate_model.py
RENAMED
|
@@ -554,7 +554,49 @@ def __plot_kde_axes_base(ax, fontdicts):
|
|
|
554
554
|
ax.set_ylabel('Density', fontdict=fontdicts['axislabel'])
|
|
555
555
|
|
|
556
556
|
|
|
557
|
-
def
|
|
557
|
+
def _plot_weighted_kde_line(values, weights, ax, color, label):
|
|
558
|
+
values = np.asarray(values, dtype=float)
|
|
559
|
+
weights = np.asarray(weights, dtype=float)
|
|
560
|
+
mask = np.isfinite(values) & np.isfinite(weights) & (weights > 0)
|
|
561
|
+
values = values[mask]
|
|
562
|
+
weights = weights[mask]
|
|
563
|
+
if values.size == 0:
|
|
564
|
+
return
|
|
565
|
+
if values.size < 2 or np.unique(values).size < 2:
|
|
566
|
+
ax.axvline(
|
|
567
|
+
np.average(values, weights=weights),
|
|
568
|
+
color=color,
|
|
569
|
+
linewidth=1.5,
|
|
570
|
+
label=label,
|
|
571
|
+
)
|
|
572
|
+
return
|
|
573
|
+
|
|
574
|
+
try:
|
|
575
|
+
sns.kdeplot(
|
|
576
|
+
x=values,
|
|
577
|
+
weights=weights,
|
|
578
|
+
ax=ax,
|
|
579
|
+
color=color,
|
|
580
|
+
label=label,
|
|
581
|
+
bw_adjust=0.5,
|
|
582
|
+
common_norm=False,
|
|
583
|
+
warn_singular=False,
|
|
584
|
+
)
|
|
585
|
+
except (TypeError, ValueError, np.linalg.LinAlgError):
|
|
586
|
+
# Older seaborn/scipy combinations may reject weighted KDE. A
|
|
587
|
+
# weighted density line still preserves the intended population.
|
|
588
|
+
n_bins = max(5, min(50, int(np.sqrt(values.size))))
|
|
589
|
+
density, edges = np.histogram(
|
|
590
|
+
values,
|
|
591
|
+
bins=n_bins,
|
|
592
|
+
weights=weights,
|
|
593
|
+
density=True,
|
|
594
|
+
)
|
|
595
|
+
centers = (edges[:-1] + edges[1:]) / 2.0
|
|
596
|
+
ax.plot(centers, density, color=color, linewidth=1.5, label=label)
|
|
597
|
+
|
|
598
|
+
|
|
599
|
+
def __plot_single_kde_axes(y_true, y_score, bins, ax, fontdicts, sample_weight=None):
|
|
558
600
|
"""在axes上绘制单个kde图.
|
|
559
601
|
|
|
560
602
|
Parameters
|
|
@@ -572,16 +614,56 @@ def __plot_single_kde_axes(y_true, y_score, bins, ax, fontdicts):
|
|
|
572
614
|
"""
|
|
573
615
|
__plot_kde_axes_base(ax, fontdicts)
|
|
574
616
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
617
|
+
if sample_weight is None:
|
|
618
|
+
sns.distplot(y_score, bins=bins, hist=True, kde=False, ax=ax,
|
|
619
|
+
hist_kws={'density': True, 'rwidth': 0.95, 'color': palette['ClassicBlueRedGrey'][2], 'alpha': 1, 'label': 'Total'}, )
|
|
620
|
+
sns.distplot(y_score[np.where(y_true==0)], bins=bins, hist=False, kde=True,
|
|
621
|
+
kde_kws={'bw': 1/bins/2, 'color': palette['ClassicBlueRedGrey'][0], 'label': 'Neg KDE'}, )
|
|
622
|
+
sns.distplot(y_score[np.where(y_true==1)], hist=False, kde=True,
|
|
623
|
+
kde_kws={'bw': 1/bins/2, 'color': palette['ClassicBlueRedGrey'][1], 'label': 'Pos KDE'}, )
|
|
624
|
+
true_mean = np.mean(y_true)
|
|
625
|
+
score_mean = np.mean(y_score)
|
|
626
|
+
title = 'N={0:,} True={1:.2%} Score={2:.2%}'.format(
|
|
627
|
+
len(y_true), true_mean, score_mean
|
|
628
|
+
)
|
|
629
|
+
else:
|
|
630
|
+
sample_weight = np.asarray(sample_weight, dtype=float)
|
|
631
|
+
ax.hist(
|
|
632
|
+
y_score,
|
|
633
|
+
bins=bins,
|
|
634
|
+
weights=sample_weight,
|
|
635
|
+
density=True,
|
|
636
|
+
rwidth=0.95,
|
|
637
|
+
color=palette['ClassicBlueRedGrey'][2],
|
|
638
|
+
alpha=1,
|
|
639
|
+
label='Total (Weighted)',
|
|
640
|
+
)
|
|
641
|
+
neg_mask = y_true == 0
|
|
642
|
+
pos_mask = y_true == 1
|
|
643
|
+
_plot_weighted_kde_line(
|
|
644
|
+
y_score[neg_mask],
|
|
645
|
+
sample_weight[neg_mask],
|
|
646
|
+
ax,
|
|
647
|
+
palette['ClassicBlueRedGrey'][0],
|
|
648
|
+
'Neg KDE (Weighted)',
|
|
649
|
+
)
|
|
650
|
+
_plot_weighted_kde_line(
|
|
651
|
+
y_score[pos_mask],
|
|
652
|
+
sample_weight[pos_mask],
|
|
653
|
+
ax,
|
|
654
|
+
palette['ClassicBlueRedGrey'][1],
|
|
655
|
+
'Pos KDE (Weighted)',
|
|
656
|
+
)
|
|
657
|
+
true_mean = _weighted_eval.safe_weighted_average(y_true, sample_weight)
|
|
658
|
+
score_mean = _weighted_eval.safe_weighted_average(y_score, sample_weight)
|
|
659
|
+
title = 'N={0:,.2f} Raw={1:,} True={2:.2%} Score={3:.2%}'.format(
|
|
660
|
+
np.sum(sample_weight), len(y_true), true_mean, score_mean
|
|
661
|
+
)
|
|
662
|
+
|
|
663
|
+
ax.axvline(x=true_mean, linestyle='-', linewidth=1, color=palette['ClassicGreyRed'][0],label='True')
|
|
664
|
+
ax.axvline(x=score_mean, linestyle='--', linewidth=1, color=palette['ClassicGreyRed'][1], label='Score')
|
|
583
665
|
|
|
584
|
-
ax.set_title(
|
|
666
|
+
ax.set_title(title, fontdict=fontdicts['subtitle'])
|
|
585
667
|
ax.legend(loc=1, fontsize=fontdicts['legend']['size'])
|
|
586
668
|
|
|
587
669
|
|
|
@@ -1553,6 +1635,66 @@ def __plot_multi_gain_axes(pct_dfs, ax, fontdicts):
|
|
|
1553
1635
|
Y = np.insert(Y, 0, 0)
|
|
1554
1636
|
ax.plot(X, Y, color=palette['MorandiDark'][i], linewidth=2, marker='.', markersize=5, label='{0} avgTrue'.format(md))
|
|
1555
1637
|
|
|
1638
|
+
|
|
1639
|
+
def _weighted_gains_to_plot_frames(weighted_gains):
|
|
1640
|
+
"""Convert weighted gains output into the plotting helpers' long schema."""
|
|
1641
|
+
if weighted_gains is None or weighted_gains.empty:
|
|
1642
|
+
return pd.DataFrame(), pd.DataFrame()
|
|
1643
|
+
|
|
1644
|
+
required = {"N", "N_BAD", "AVG_SCORE", "AVG_BAD", "PROP"}
|
|
1645
|
+
missing = sorted(required.difference(weighted_gains.columns))
|
|
1646
|
+
if missing:
|
|
1647
|
+
raise KeyError(f"Weighted gains table missing plotting columns: {missing}")
|
|
1648
|
+
|
|
1649
|
+
descending = weighted_gains.reset_index(drop=True).copy()
|
|
1650
|
+
total_bad = float(descending["N_BAD"].sum())
|
|
1651
|
+
|
|
1652
|
+
def _convert(source):
|
|
1653
|
+
source = source.reset_index(drop=True)
|
|
1654
|
+
n = source["N"].to_numpy(dtype=float)
|
|
1655
|
+
n_bad = source["N_BAD"].to_numpy(dtype=float)
|
|
1656
|
+
proportion = source["PROP"].to_numpy(dtype=float)
|
|
1657
|
+
capture_rate = np.divide(
|
|
1658
|
+
n_bad,
|
|
1659
|
+
total_bad,
|
|
1660
|
+
out=np.zeros_like(n_bad, dtype=float),
|
|
1661
|
+
where=total_bad != 0,
|
|
1662
|
+
)
|
|
1663
|
+
cumulative_n = np.cumsum(n)
|
|
1664
|
+
cumulative_bad = np.cumsum(n_bad)
|
|
1665
|
+
return pd.DataFrame(
|
|
1666
|
+
{
|
|
1667
|
+
"thresholds": np.cumsum(proportion) * 100.0,
|
|
1668
|
+
"avg_score": source["AVG_SCORE"].to_numpy(dtype=float),
|
|
1669
|
+
"avg_true": source["AVG_BAD"].to_numpy(dtype=float),
|
|
1670
|
+
"proportion": proportion,
|
|
1671
|
+
"capture_rate": capture_rate,
|
|
1672
|
+
"cumsum_n": cumulative_n,
|
|
1673
|
+
"cumavg_true": np.divide(
|
|
1674
|
+
cumulative_bad,
|
|
1675
|
+
cumulative_n,
|
|
1676
|
+
out=np.full_like(cumulative_bad, np.nan, dtype=float),
|
|
1677
|
+
where=cumulative_n != 0,
|
|
1678
|
+
),
|
|
1679
|
+
"gain": np.cumsum(capture_rate),
|
|
1680
|
+
}
|
|
1681
|
+
)
|
|
1682
|
+
|
|
1683
|
+
# Percentile charts historically run from low score to high score, while
|
|
1684
|
+
# gain charts run from the highest score downward.
|
|
1685
|
+
percentile_frame = _convert(descending.iloc[::-1])
|
|
1686
|
+
gain_frame = _convert(descending)
|
|
1687
|
+
return percentile_frame, gain_frame
|
|
1688
|
+
|
|
1689
|
+
|
|
1690
|
+
def _set_weighted_axis_title(ax, fontdicts):
|
|
1691
|
+
subtitle_size = fontdicts.get("subtitle", {}).get("size", 12)
|
|
1692
|
+
ax.set_title(
|
|
1693
|
+
f"Weighted\n{ax.get_title()}",
|
|
1694
|
+
fontsize=max(9, subtitle_size - 2),
|
|
1695
|
+
)
|
|
1696
|
+
|
|
1697
|
+
|
|
1556
1698
|
@timeit_decorator
|
|
1557
1699
|
def evaluate_performance(datasets, dist_bins=20, pct_bins=10, square_figsize=5, fontdicts=fontdicts['sub'], to_show=True, save_path=None, gains_table = True, equal_freq = True, pct_bin_edges = None, sample_weight=None):
|
|
1558
1700
|
"""绘制单模型预测效果评价图.
|
|
@@ -1706,15 +1848,14 @@ def __evaluate_performance(y_true, y_score, nrow, ncol, i, dist_bins, pct_bins,
|
|
|
1706
1848
|
nbins=bin_count,
|
|
1707
1849
|
weight_col="w",
|
|
1708
1850
|
)
|
|
1709
|
-
pct_df = weighted_gains
|
|
1710
|
-
pct_desc_df = weighted_gains.iloc[::-1].reset_index(drop=True)
|
|
1851
|
+
pct_df, pct_desc_df = _weighted_gains_to_plot_frames(weighted_gains)
|
|
1711
1852
|
if gains_table:
|
|
1712
1853
|
y_gains = weighted_gains
|
|
1713
1854
|
pct_info = {
|
|
1714
1855
|
"pct_bins": weighted_gains.shape[0],
|
|
1715
1856
|
"pct_interval": 100.0 / weighted_gains.shape[0] if weighted_gains.shape[0] else np.nan,
|
|
1716
|
-
"pct_top_avgTrue": float(weighted_gains["AVG_BAD"].iloc[
|
|
1717
|
-
"pct_btm_avgTrue": float(weighted_gains["AVG_BAD"].iloc[
|
|
1857
|
+
"pct_top_avgTrue": float(weighted_gains["AVG_BAD"].iloc[0]) if len(weighted_gains) else np.nan,
|
|
1858
|
+
"pct_btm_avgTrue": float(weighted_gains["AVG_BAD"].iloc[-1]) if len(weighted_gains) else np.nan,
|
|
1718
1859
|
}
|
|
1719
1860
|
else:
|
|
1720
1861
|
if pct_bin_edges is not None:
|
|
@@ -1747,16 +1888,29 @@ def __evaluate_performance(y_true, y_score, nrow, ncol, i, dist_bins, pct_bins,
|
|
|
1747
1888
|
else:
|
|
1748
1889
|
pct_desc_df = calc_equid_pct(y_true, y_score, None, bins=pct_bins, ascending=False, sample_weight=sample_weight)
|
|
1749
1890
|
|
|
1750
|
-
|
|
1751
|
-
|
|
1891
|
+
ax_roc = plt.subplot(nrow, ncol, i*ncol+1)
|
|
1892
|
+
__plot_single_roc_axes(roc_df, ax_roc, fontdicts)
|
|
1893
|
+
ax_kde = plt.subplot(nrow, ncol, i*ncol+2)
|
|
1894
|
+
__plot_single_kde_axes(
|
|
1895
|
+
y_true,
|
|
1896
|
+
y_score,
|
|
1897
|
+
dist_bins,
|
|
1898
|
+
ax_kde,
|
|
1899
|
+
fontdicts,
|
|
1900
|
+
sample_weight=sample_weight,
|
|
1901
|
+
)
|
|
1752
1902
|
if sample_weight is None:
|
|
1753
1903
|
__plot_single_pct_axes(pct_df, plt.subplot(nrow, ncol, i*ncol+3), fontdicts)
|
|
1754
1904
|
__plot_single_gain_axes(pct_desc_df, plt.subplot(nrow, ncol, i*ncol+4), fontdicts)
|
|
1755
1905
|
else:
|
|
1906
|
+
_set_weighted_axis_title(ax_roc, fontdicts)
|
|
1907
|
+
_set_weighted_axis_title(ax_kde, fontdicts)
|
|
1756
1908
|
ax_pct = plt.subplot(nrow, ncol, i * ncol + 3)
|
|
1757
|
-
|
|
1909
|
+
__plot_single_pct_axes(pct_df, ax_pct, fontdicts)
|
|
1910
|
+
_set_weighted_axis_title(ax_pct, fontdicts)
|
|
1758
1911
|
ax_gain = plt.subplot(nrow, ncol, i * ncol + 4)
|
|
1759
|
-
|
|
1912
|
+
__plot_single_gain_axes(pct_desc_df, ax_gain, fontdicts)
|
|
1913
|
+
_set_weighted_axis_title(ax_gain, fontdicts)
|
|
1760
1914
|
|
|
1761
1915
|
info = {
|
|
1762
1916
|
'N': float(np.sum(sample_weight)) if sample_weight is not None else len(y_true),
|