模型训练通过pandas一次分组计算多个标签的KS

模型训练通过pandas一次分组计算多个标签的KS

  1. 模型训练通常是一堆特征X和一个标签y,但是模型经常需要再多个不同的y标签上去看效果,进行综合评估,如信贷领域中需要看在不同的mob的表现
  2. 下面会使用pandas计算多个y标签效果

准备数据

  1. 生成模拟数据

    python 复制代码
    import numpy as np
    import pandas as pd
    from sklearn import metrics
    
    np.random.seed(2025)
    def gen_data(labels=['y1', 'y2', 'y3'], nums=1000):
        data = dict(
            # 模拟分组月份
            month=np.random.choice(range(1, 6), nums),
            pred=np.random.rand(nums)
        )
        df = pd.DataFrame(data)
        for y in labels:
            df[y] = np.random.choice([0, 1, np.nan], nums)
        return df
    df=gen_data(nums=10)
    print(df)
    # 输出如下
    # 
    #    month      pred   y1   y2   y3
    # 0      3  0.964238  1.0  1.0  1.0
    # 1      5  0.800984  1.0  NaN  NaN
    # 2      1  0.455205  NaN  0.0  0.0
    # 3      4  0.801058  1.0  0.0  0.0
    # 4      4  0.041718  NaN  1.0  NaN
    # 5      5  0.769458  0.0  1.0  0.0
    # 6      1  0.003171  0.0  1.0  1.0
    # 7      1  0.292809  NaN  0.0  0.0
    # 8      3  0.610914  NaN  0.0  NaN
    # 9      2  0.913027  1.0  1.0  0.0
  2. 创建计算单列ks的函数,注意处理模型打分或者标签为空的情况

    python 复制代码
    # 计算单个标签的ks
    def calc_one_ks(y_true, y_pred):
        # 去掉标签为空的
        y_true = y_true.reset_index(drop=True)
        idx = y_true[y_true.notna()].index
        # 去掉打分为空的
        y_pred = pd.Series(y_pred).reset_index(drop=True)
        idx2 = y_pred[y_pred.notna()].index
        # 取模型打分和标签都不为空的
        idx_uni = list(set(idx) & set(idx2))
        y_true = y_true[idx_uni]
        y_pred = y_pred[idx_uni]
        if len(y_true) == 0:
            return None
        tpr, fpr, _ = metrics.roc_curve(y_true, y_pred)
        ks = max(abs(tpr - fpr))
        return ks
  3. 使用pandas的groupBy和apply分组计算多个标签的ks值,同时输出主标签的数量和正样本率

    python 复制代码
        def get_ks(s: pd.Series, labels, y_main=None, score='pred'):
            cnt = len(s)
            y_main = y_main or labels[0]
            pos_cnt = s[y_main].sum()
            pos_pct = round(pos_cnt / cnt, 4)
            res = dict(cnt=cnt, pos_cnt=pos_cnt, pos_pct=pos_pct)
            for y in labels:
                res[f'{y}_ks'] = calc_one_ks(s[y], s[score])
            return pd.Series(res)
        

完整代码

python 复制代码
import numpy as np
import pandas as pd
from sklearn import metrics

np.random.seed(2025)


def gen_data(labels=['y1', 'y2', 'y3'], nums=1000):
    data = dict(
        # 模拟分组月份
        month=np.random.choice(range(1, 6), nums),
        pred=np.random.rand(nums)
    )
    df = pd.DataFrame(data)
    for y in labels:
        df[y] = np.random.choice([0, 1, np.nan], nums)
    return df


# 计算单个标签的ks
def calc_one_ks(y_true, y_pred):
    # 去掉标签为空的
    y_true = y_true.reset_index(drop=True)
    idx = y_true[y_true.notna()].index
    # 去掉打分为空的
    y_pred = pd.Series(y_pred).reset_index(drop=True)
    idx2 = y_pred[y_pred.notna()].index
    # 取模型打分和标签都不为空的
    idx_uni = list(set(idx) & set(idx2))
    y_true = y_true[idx_uni]
    y_pred = y_pred[idx_uni]
    if len(y_true) == 0:
        return None
    tpr, fpr, _ = metrics.roc_curve(y_true, y_pred)
    ks = max(abs(tpr - fpr))
    return ks


def get_ks(s: pd.Series, labels, y_main=None, score='pred'):
    cnt = len(s)
    y_main = y_main or labels[0]
    pos_cnt = s[y_main].sum()
    pos_pct = round(pos_cnt / cnt, 4)
    res = dict(cnt=cnt, pos_cnt=pos_cnt, pos_pct=pos_pct)
    for y in labels:
        res[f'{y}_ks'] = calc_one_ks(s[y], s[score])
    return pd.Series(res)


if __name__ == '__main__':
    labels = ['y1', 'y2', 'y3']
    df = gen_data(labels)
    g_cols = ['month']
    df_res = df.groupby(g_cols).apply(lambda s: get_ks(s, labels))
    print(df_res)
# 输出
#          cnt  pos_cnt  pos_pct     y1_ks     y2_ks     y3_ks
# month                                                       
# 1      212.0     55.0   0.2594  0.206674  0.270109  0.101449
# 2      183.0     66.0   0.3607  0.138675  0.088418  0.135717
# 3      188.0     63.0   0.3351  0.139406  0.120635  0.125490
# 4      196.0     63.0   0.3214  0.104762  0.192693  0.148323
# 5      221.0     80.0   0.3620  0.120833  0.092691  0.073430

注意,使用pandas直接计算的方式仅适用于样本量较小的情况下,如果样本量较大可以使用sql或者spark进行计算,后续会再进行更新

相关推荐
Rocky Ding*1 小时前
Latent Consistency Models:一篇读懂扩散模型的少步生成核心基础知识
人工智能·深度学习·机器学习·ai作画·stable diffusion·aigc·ai-native
学术头条1 小时前
清华团队开源SCAIL-2:角色动画告别骨骼依赖,端到端还原视频中动作细节
人工智能·科技·机器学习·ai·开源·音视频·agi
Black蜡笔小新2 小时前
制造业AI质检工作站/企业AI算力工作站DLTM助力制造业质检智能化升级
人工智能·深度学习·机器学习
大C聊AI4 小时前
通用大模型纷纷收费,垂直场景AI工具的价值正在被重估
大数据·人工智能·机器学习·办公效率·ai 工具·智标领航·ai 辅助办公
苏州邦恩精密4 小时前
2026江苏GOM三维扫描仪定制厂家找哪家?企业数字化转型视角
人工智能·机器学习·3d·自动化·制造
王小王-1235 小时前
基于机器学习算法的恶意软件行为分析与检测系统设计与实现
机器学习·pyqt5·检测系统·恶意软件行为检测
Godspeed Zhao5 小时前
Level 4自动驾驶系统设计0——功能与场景0
人工智能·机器学习·自动驾驶
CCC:CarCrazeCurator6 小时前
大模型核心注意力机制技术深度报告:MHA、MQA、GQA 与 MLA 技术原理、性能对比与场景适配
人工智能·机器学习·自动驾驶·transformer
炎武丶航6 小时前
LeNet-5深度学习详解:从手写数字识别到代码实战
人工智能·python·深度学习·机器学习·ai·cnn·lenet