zoukankan      html  css  js  c++  java
  • toad

    本文主要记录一下toad有关的学习资料,以及操作过程

    先把连接放上:

    github主页: https://github.com/amphibian-dev/toad

    文档:https://toad.readthedocs.io

    演示:https://toad.readthedocs.io/en/latest/tutorial.html

    whl 下载地址: https://pypi.org/simple/toad/

    报错地址:https://github.com/amphibian-dev/toad/issues

    中文教程:https://toad.readthedocs.io/en/dev/tutorial_chinese.html

    0.0.60更新内容:https://github.com/amphibian-dev/toad/blob/master/CHANGELOG.md

    链接: https://pan.baidu.com/s/1rIaQm0XunlBU_5YXt6CXBw 提取码: fma6

    操作过程

    # -*- coding: utf-8 -*-
    """
    Created on Thu Aug  5 10:43:34 2021
    
    @author: L
    """
    #%%导入模块
    import pandas as pd
    import numpy as np
    import toad
    
    
    #%%导入数据
    data = pd.read_csv('D:/xxx/toad/train.csv')
    print('Shape:',data.shape)
    data.head(10)
    
    
    #%%数据包含2019年5月 - 7月的数据。其中我们将用3月和4月数据用于训练样本,5月、6月、7月数据作为时间外样本(OOT)
    train = data.loc[data.month.isin(['2019-03','2019-04'])==True,:]
    OOT = data.loc[data.month.isin(['2019-03','2019-04'])==False,:]
    
    print('train size:',train.shape,'
    OOT size:',OOT.shape)
    '''
    train size: (43576, 167) 
    OOT size: (65364, 167)
    '''
    
    
    
    #%%EDA
    
    #%%1.描述性统计,可展示数值型也可以展示类别型,类别型的分位数使用频数替代
    toad.detect(train)
    
    #展示的字段有
    toad.detect(train).columns
    '''
    ['type', 'size', 'missing', 'unique', 'mean_or_top1', 'std_or_top2',
           'min_or_top3', '1%_or_top4', '10%_or_top5', '50%_or_bottom5',
           '75%_or_bottom4', '90%_or_bottom3', '99%_or_bottom2', 'max_or_bottom1']
    '''
    
    #%%2.计算变量iV , toad.quality
    
    '''
    toad.quality(dataframe, target=’target’, iv_only=False)
    
    输出每个变量的iv值,gini,entropy,和unique values,结果以iv值排序。”target”为目标列,”iv_only”决定是否只输出iv值。
    
    注意:
    1. 对于数据量大或高维度数据,建议使用iv_only=True 
    2. 要去掉主键,日期等高unique values且不用于建模的特征
    '''
    to_drop = ['APP_ID_C','month'] # 去掉ID列和month列
    toad.quality(data.drop(to_drop,axis=1),'target',iv_only=True)[:15]
    
    
    #%%特征筛选
    
    '''
    3. toad.selection.select(dataframe, target=’target’, empty=0.9, iv=0.02, corr=0.7, return_drop=False, exclude=None):
    根据缺失值占比,iv值,和高相关性进行变量筛选,赋值为:
    
    (1)empyt=0.9: 若变量的缺失值大于0.9被删除
    
    (2)iv=0.02: 若变量的iv值小于0.02被删除
    
    (3)corr=0.7: 若两个相关性高于0.7时,iv值低的变量被删除
    
    (4)return_drop=False: 若为True,function将返回被删去的变量列
    
    (5)exclude=None: 明确不被删去的列名,输入为list格式
    
    如下面的cell,没有变量由于缺失值高被删除,大量变量因为低iv值被删除,部分相关性高的变量被删除。从165个特征中选出了32个变量。
    '''
    
    train_selected, dropped = toad.selection.select(train,target = 'target', empty = 0.5, iv = 0.05, corr = 0.7, return_drop=True, exclude=['APP_ID_C','month'])
    print(dropped)
    print(train_selected.shape)  #(43576, 34)
    
    
    #%%分箱
    
    '''
    toad的分箱功能支持数值型数据和离散型分箱,默认分箱方法使用 卡方分箱。
    
    toad.transform.Combiner 是用来分箱的class,分箱步骤如下:
    
    (1) c = toad.transform.Combiner()
    (2) *训练分箱*: c.fit(dataframe, y = ‘target’, method = ‘chi’, min_samples = None, n_bins = None, empty_separate = False)
        y: 目标列
        method: 分箱方法,支持’chi’ (卡方分箱), ‘dt’ (决策树分箱), ‘kmean’ , ‘quantile’ (等频分箱), ‘step’ (等步长分箱)
        min_samples: 每箱至少包含样本量,可以是数字或者占比
        n_bins: 箱数,若无法分出这么多箱数,则会分出最多的箱数
        empty_separate: 是否将空箱单独分开
    (3) *查看分箱节点*:c.export()
    (4) *手动调整分箱*: c.load(dict)
    (5) *apply分箱结果*: c.transform(dataframe, labels=False):
        labels: 是否将分箱结果转化成箱标签。False时输出0,1,2…(离散变量根据占比高低排序),True输出(-inf, 0], (0,10], (10, inf)。
    
    注意:1. 注意删去不需要分箱的列,特别是ID列和时间列
    '''
    
    
    c = toad.transform.Combiner()
    
    # 使用特征筛选后的数据进行训练:使用稳定的卡方分箱,规定每箱至少有5%数据, 空值将自动被归到最佳箱。
    c.fit(train_selected.drop(to_drop, axis=1), y = 'target', method = 'chi', min_samples = 0.05) #empty_separate = False
    
    # 为了演示,仅展示部分分箱
    # 注意c.export() 的结果是一个字典
    print('var_d2:',c.export()['var_d2'])
    print('var_d5:',c.export()['var_d5'])
    print('var_d6:',c.export()['var_d6'])
    
    
    #%%观察分箱
    #toad.plot的module提供了一部分的可视化功能,帮助调整分箱节点
    
    '''
    1.*时间内观察*: toad.plot.bin_plot(dataframe, x = None, target = ‘target),bar代表了样本量占比,红线代表了正样本占比(e.g. 坏账率)
      x: 需要观察的特征
      target: 目标列
    
    '''
    from toad.plot import bin_plot
    
    # 看'var_d2'在时间内的分箱
    col = 'var_d2'
    
    bin_plot(c.transform(train_selected[[col,'target']], labels=True), x=col, target='target')
    
    
    '''
    2. *跨时间观察:* toad.plot.badrate_plot(dataframe, target = ‘target’, x = None, by = None)
       输出不同时间段中每箱的正样本占比
    
    - target: 目标列
    
    - x: 时间列, string格式
    
    - by: 需要观察的特征
    
    注意:时间列需要预先分好并设成string,不支持timestampe
    
    '''
    from toad.plot import badrate_plot
    
    col = 'var_d2'
    
    # 观察 'var_d2' 分别在时间内和OOT中的稳定性
    badrate_plot(c.transform(train[[col,'target','month']], labels=True), target='target', x='month', by=col)
    badrate_plot(c.transform(OOT[[col,'target','month']], labels=True), target='target', x='month', by=col)
    
    badrate_plot(c.transform(data[[col,'target','month']], labels=True), target='target', x='month', by=col)
    '''
    敞口随时间变化而增大为优,代表了变量在更新的时间区分度更强。线之前没有交叉为优,代表分箱稳定。
    '''
    
    # 看'var_d5'在时间内的分箱
    col = 'var_d5'
    
    #观察单个变量分箱结果时,建议设置'labels = True'
    bin_plot(c.transform(train_selected[[col,'target']], labels=True), x=col, target='target')
    
    
    #%%调整分箱  c.set_rules(dict)
    
    #set_rules 后会更新被修改的箱
    
    # iv值较低,假设我们要 'F' 淡出分出一组来提高iv
    
    #设置分组
    rule = {'var_d5':[['O', 'nan'],['F'], ['M']]}
    
    #调整分箱
    c.set_rules(rule)
    
    #查看手动分箱稳定性
    bin_plot(c.transform(train_selected[['var_d5','target']], labels=True), x='var_d5', target='target')
    badrate_plot(c.transform(OOT[['var_d5','target','month']], labels=True), target='target', x='month', by='var_d5')
    
    
    #%%WOE转化
    
    '''
    WOE转化在分箱调整好之后进行,步骤如下:
    
    1. *用调整好的Combiner转化数据:* c.transform(dataframe, labels=False)只会转化被分箱的变量
    
    2. *初始化woe transer:* transer = toad.transform.WOETransformer()
    
    3. *fit_transform:* transer.fit_transform(dataframe, target, exclude = None)
    
       训练并输出woe转化的数据,用于转化train/时间内数据
    
       target:目标列数据(非列名)
       exclude: 不需要被WOE转化的列 注意:会转化所有列,包括未被分箱transform的列,通过 ‘exclude’ 删去不要WOE转化的列,特别是target列
    4. *根据训练好的transer,转化test/OOT数据:*transer.transform(dataframe)
    
    '''
    
    #根据训练好的transer输出woe转化的数据,用于转化test/OOT数据。
    # 初始化
    transer = toad.transform.WOETransformer()
    
    # combiner.transform() & transer.fit_transform() 转化训练数据,并去掉target列
    train_woe = transer.fit_transform(c.transform(train_selected), train_selected['target'], exclude=to_drop+['target'])
    OOT_woe = transer.transform(c.transform(OOT))
    
    print(train_woe.head(3))
    
    
    #%%逐步回归特征刷选 
    
    toad.selection.stepwise(dataframe, target=’target’, estimator=’ols’, direction=’both’, criterion=’aic’, max_iter=None, return_drop=False, exclude=None): *
    '''
    逐步回归特征筛选,支持向前,向后和双向(推荐)
    - estimator: 用于拟合的模型,支持'ols', 'lr', 'lasso', 'ridge'
    
    - direction: 逐步回归的方向,支持'forward', 'backward', 'both' (推荐)
    
    - criterion: 评判标准,支持'aic', 'bic', 'ks', 'auc'
    
    - max_iter: 最大循环次数
    
    - return_drop: 是否返回被剔除的列名
    
    - exclude: 不需要被训练的列名,比如ID列和时间列
    
    *tip: 经验证,direction = ‘both’效果最好。
    estimator = ‘ols’以及criterion = ‘aic’运行速度快且结果对逻辑回归建模有较好的代表性*
    '''
    # 将woe转化后的数据做逐步回归
    final_data = toad.selection.stepwise(train_woe,target = 'target', estimator='ols', direction = 'both', criterion = 'aic', exclude = to_drop)
    
    # 将选出的变量应用于test/OOT数据
    final_OOT = OOT_woe[final_data.columns]
    
    print(final_data.shape) # 逐步回归从31个变量中选出了10个
    
    # 确定建模要用的变量
    col = list(final_data.drop(to_drop+['target'],axis=1).columns)
    
    
    #%%计算PSI  *toad.metrics.PSI(df_train, df_test):*
    
    #输出每列特征的PSI,可以用于检验WOE转化后的特征稳定性
    
    toad.metrics.PSI(final_data[col], final_OOT[col])
    
    
    #%%常用模型评分标准  toad. metrics. KS, F1, AUC
    
    # 用逻辑回归建模
    from sklearn.linear_model import LogisticRegression
    
    lr = LogisticRegression()
    lr.fit(final_data[col], final_data['target'])
    
    # 预测训练和隔月的OOT
    pred_train = lr.predict_proba(final_data[col])[:,1]
    
    pred_OOT_may =lr.predict_proba(final_OOT.loc[final_OOT.month == '2019-05',col])[:,1]
    pred_OOT_june =lr.predict_proba(final_OOT.loc[final_OOT.month == '2019-06',col])[:,1]
    pred_OOT_july =lr.predict_proba(final_OOT.loc[final_OOT.month == '2019-07',col])[:,1]
    
    
    from toad.metrics import KS, AUC
    print('train KS',KS(pred_train, final_data['target']))
    print('train AUC',AUC(pred_train, final_data['target']))
    print('OOT结果')
    print('5月 KS',KS(pred_OOT_may, final_OOT.loc[final_OOT.month == '2019-05','target']))
    print('6月 KS',KS(pred_OOT_june, final_OOT.loc[final_OOT.month == '2019-06','target']))
    print('7月 KS',KS(pred_OOT_july, final_OOT.loc[final_OOT.month == '2019-07','target']))
    
    '''
    train KS 0.37042196076166667
    train AUC 0.7506045637676994
    OOT结果
    5月 KS 0.36857480763524153
    6月 KS 0.34764230892681874
    7月 KS 0.3786493041720077
    '''
    #*PSI 同样可以用于验证分数的稳定性*
    print(toad.metrics.PSI(pred_train,pred_OOT_may))
    print(toad.metrics.PSI(pred_train,pred_OOT_june))
    print(toad.metrics.PSI(pred_train,pred_OOT_june))
    
    
    #%%计算ks 
    
    '''
    *toad.metrics.KS_bucket(predicted_proba, y_true, bucket=10, method = ‘quantile’):*
    KS bucket输出模型预测分箱后评判信息,包括每组的分数区间,样本量,坏账率,KS等
       - bucket:分箱的数量
    
       - method:分箱方法,建议用'quantile'(等人数),或'step' (等分数步长)
    
    bad\_rate为每组坏账率:
    (1)组之间的坏账率差距越大越好
    (2)可以用于观察是否有跳点
    (3)可以用与找最佳切点
    (4)可以对比
    '''
    # 将预测等频分箱,观测每组的区别
    toad.metrics.KS_bucket(pred_train, final_data['target'], bucket=10, method = 'quantile')
    
    
    #%%转为评分卡
    
    '''
    toad.ScoreCard( combiner = {}, transer = None, pdo = 60, rate = 2, base_odds = 20, base_score = 750, card = None, C=0.1,kwargs):
    逻辑回归模型转标准评分卡,支持传入逻辑回归参数,进行调参。
    
    - combiner: 传入训练好的 toad.Combiner 对象
    
    - transer: 传入先前训练的 toad.WOETransformer 对象
    
    - pdo、rate、base_odds、base_score:
      e.g. pdo=60, rate=2, base_odds=20,base_score=750
          实际意义为当比率为1/20,输出基准评分750,当比率为基准比率2倍时,基准分下降60分
    
    - card: 支持传入专家评分卡
    
    - **kwargs: 支持传入逻辑回归参数(参数详见 sklearn.linear_model.LogisticRegression)
    '''
    
    card = toad.ScoreCard(
        combiner = c,
        transer = transer,
        #class_weight = 'balanced',
        #C=0.1,
        #base_score = 600,
        #base_odds = 35 ,
        #pdo = 60,
        #rate = 2
    )
    
    card.fit(final_data[col], final_data['target'])
    
    #评分卡在 fit 时使用 WOE 转换后的数据来计算最终的分数,分数一旦计算完成,便无需 WOE 值,可以直接使用 原始数据 进行评分。
    
    # 直接使用原始数据进行评分
    card.predict(train)
    
    #输出标准评分卡
    card.export()
    View Code
  • 相关阅读:
    aspnetpager 详解
    删除sql数据库日志的方法
    Asp.Net 自带的分布式事务(TransactionScope)的代码块
    VS2010项目放到VS2008下的方法
    SQL Server 2005中的SSIS维护计划
    XML格式与DataTable、DataSet、DataView格式的转换
    .NET公共执行类
    C#学习BackgroundWork
    <winform>源代码
    C#学习Thread
  • 原文地址:https://www.cnblogs.com/cgmcoding/p/15117263.html
Copyright © 2011-2022 走看看