作者:杰少

Null Importance特征筛选

简介

目前数据量越来越大,数据特征维度也越来越高,这不仅对我们的计算存储带来了较大的挑战,与此同时,还会对模型的效果带来较大的损益。

  • 如何既能节省内存计算资源,同时能拿到模型的提效是我们非常关心的一个问题。

本文我们介绍一种特征筛选策略 -- Null Importance 特征筛选策略,该策略在95%的数据竞赛中基本都可以拿到效果,带来不错的提升。

Null Importance

1. 核心思想

Null Importance的核心思想在于:

  1. 计算不靠谱的特征重要性;

  • 我们对标签进行随机shuffle,并计算特征重要性,这些特征重要性是“错误的”;

  • 计算靠谱的特征重要性;

    • 对原始数据进行训练并得到特征重要性,这些特征重要性是“正确的”;

    1. 计算靠谱的特征重要性和不靠谱的特征重要性的差距/偏离度(自行设计Score函数);

    2. 按照计算得到的Score进行批量的特征筛选,并计算线下验证分数;

    3. 选用线下分数最好的一些特征作为最终的特征;

    2. 实现步骤

    Null Importance算法的实现步骤为:

    1. 在原始数据集上运行模型并且记录每个特征重要性。以此作为基准;

    2. 构建Null importances分布:对我们的标签进行随机Shuffle,并且计算shuffle之后的特征的重要性;

    3. 对2进行多循环操作,得到多个不同shuffle之后的特征重要性;

    4. 设计score函数,得到未shuffle的特征重要性与shuffle之后特征重要性的偏离度,并以此设计特征筛选策略;

    5. 计算不同筛选情况下的模型的分数,并进行记录;

    6. 将分数最好的几个分数对应的特征进行返回。

    代码

    代码摘自:https://www.kaggle.com/ogrellier/feature-selection-with-null-importances。

    1. 特征重要性获取函数

    def get_feature_importances(data, shuffle, seed=None):# Gather real featurestrain_features = [f for f in data if f not in ['TARGET', 'SK_ID_CURR']]# Go over fold and keep track of CV score (train and valid) and feature importances# Shuffle target if requiredy = data['TARGET'].copy()if shuffle:# Here you could as well use a binomial distributiony = data['TARGET'].copy().sample(frac=1.0)# Fit LightGBM in RF mode, yes it's quicker than sklearn RandomForestdtrain = lgb.Dataset(data[train_features], y, free_raw_data=False, silent=True)lgb_params = {'objective': 'binary','boosting_type': 'rf','subsample': 0.623,'colsample_bytree': 0.7,'num_leaves': 127,'max_depth': 8,'seed': seed,'bagging_freq': 1,'n_jobs': 4}# Fit the modelclf = lgb.train(params=lgb_params, train_set=dtrain, num_boost_round=200, categorical_feature=categorical_feats)# Get feature importancesimp_df = pd.DataFrame()imp_df["feature"] = list(train_features)imp_df["importance_gain"] = clf.feature_importance(importance_type='gain')imp_df["importance_split"] = clf.feature_importance(importance_type='split')imp_df['trn_score'] = roc_auc_score(y, clf.predict(data[train_features]))return imp_df
    

    2.获取原始版本的特征重要性

    # Seed the unexpected randomness of this world
    np.random.seed(123)
    # Get the actual importance, i.e. without shuffling
    actual_imp_df = get_feature_importances(data=data, shuffle=False)
    

    3.获取多个target shuffle版本的特征重要性

    null_imp_df = pd.DataFrame()
    nb_runs = 80
    import time
    start = time.time()
    dsp = ''
    for i in range(nb_runs):# Get current run importancesimp_df = get_feature_importances(data=data, shuffle=True)imp_df['run'] = i + 1 # Concat the latest importances with the old onesnull_imp_df = pd.concat([null_imp_df, imp_df], axis=0)# Erase previous messagefor l in range(len(dsp)):print('\b', end='', flush=True)# Display current run and time usedspent = (time.time() - start) / 60dsp = 'Done with %4d of %4d (Spent %5.1f min)' % (i + 1, nb_runs, spent)print(dsp, end='', flush=True)
    

    4.计算Score

    4.1 Score计算方式1

    • 以未进行特征shuffle的特征重要性除以shuffle之后的0.75分位数作为我们的score;

    feature_scores = []
    for _f in actual_imp_df['feature'].unique():f_null_imps_gain = null_imp_df.loc[null_imp_df['feature'] == _f, 'importance_gain'].valuesf_act_imps_gain = actual_imp_df.loc[actual_imp_df['feature'] == _f, 'importance_gain'].mean()gain_score = np.log(1e-10 + f_act_imps_gain / (1 + np.percentile(f_null_imps_gain, 75)))  # Avoid didvide by zerof_null_imps_split = null_imp_df.loc[null_imp_df['feature'] == _f, 'importance_split'].valuesf_act_imps_split = actual_imp_df.loc[actual_imp_df['feature'] == _f, 'importance_split'].mean()split_score = np.log(1e-10 + f_act_imps_split / (1 + np.percentile(f_null_imps_split, 75)))  # Avoid didvide by zerofeature_scores.append((_f, split_score, gain_score))scores_df = pd.DataFrame(feature_scores, columns=['feature', 'split_score', 'gain_score'])

    4.2 计算方式2

    • shuffle target之后特征重要性低于实际target对应特征的重要性0.25分位数的次数百分比。

    correlation_scores = []
    for _f in actual_imp_df['feature'].unique():f_null_imps = null_imp_df.loc[null_imp_df['feature'] == _f, 'importance_gain'].valuesf_act_imps = actual_imp_df.loc[actual_imp_df['feature'] == _f, 'importance_gain'].valuesgain_score = 100 * (f_null_imps < np.percentile(f_act_imps, 25)).sum() / f_null_imps.sizef_null_imps = null_imp_df.loc[null_imp_df['feature'] == _f, 'importance_split'].valuesf_act_imps = actual_imp_df.loc[actual_imp_df['feature'] == _f, 'importance_split'].valuessplit_score = 100 * (f_null_imps < np.percentile(f_act_imps, 25)).sum() / f_null_imps.sizecorrelation_scores.append((_f, split_score, gain_score))corr_scores_df = pd.DataFrame(correlation_scores, columns=['feature', 'split_score', 'gain_score'])

    5. 计算特征筛选之后的最佳分数并记录相应特征

    • 选用筛选之后分数最好的特征作为最终特征即可。

    def score_feature_selection(df=None, train_features=None, cat_feats=None, target=None):# Fit LightGBM dtrain = lgb.Dataset(df[train_features], target, free_raw_data=False, silent=True)lgb_params = {'objective': 'binary','boosting_type': 'gbdt','learning_rate': .1,'subsample': 0.8,'colsample_bytree': 0.8,'num_leaves': 31,'max_depth': -1,'seed': 13,'n_jobs': 4,'min_split_gain': .00001,'reg_alpha': .00001,'reg_lambda': .00001,'metric': 'auc'}# Fit the modelhist = lgb.cv(params=lgb_params, train_set=dtrain, num_boost_round=2000,categorical_feature=cat_feats,nfold=5,stratified=True,shuffle=True,early_stopping_rounds=50,verbose_eval=0,seed=17)# Return the last mean / std values return hist['auc-mean'][-1], hist['auc-stdv'][-1]# features = [f for f in data.columns if f not in ['SK_ID_CURR', 'TARGET']]
    # score_feature_selection(df=data[features], train_features=features, target=data['TARGET'])for threshold in [0, 10, 20, 30 , 40, 50 ,60 , 70, 80 , 90, 95, 99]:split_feats     = [_f for _f, _score, _ in correlation_scores if _score >= threshold]split_cat_feats = [_f for _f, _score, _ in correlation_scores if (_score >= threshold) & (_f in categorical_feats)]gain_feats     = [_f for _f, _, _score in correlation_scores if _score >= threshold]gain_cat_feats = [_f for _f, _, _score in correlation_scores if (_score >= threshold) & (_f in categorical_feats)]print('Results for threshold %3d' % threshold)split_results = score_feature_selection(df=data, train_features=split_feats, cat_feats=split_cat_feats, target=data['TARGET'])print('\t SPLIT : %.6f +/- %.6f' % (split_results[0], split_results[1]))gain_results = score_feature_selection(df=data, train_features=gain_feats, cat_feats=gain_cat_feats, target=data['TARGET'])print('\t GAIN  : %.6f +/- %.6f' % (gain_results[0], gain_results[1]))

    适用问题

    Null Importance特征筛选策略是数据实践中必备的技能之一,该方法基本可以在95%以上的数据竞赛或者实践项目中都能取得一定的收益。

    参考文献

    1. https://www.kaggle.com/ogrellier/feature-selection-with-null-importances

    2. https://academic.oup.com/bioinformatics/article/26/10/1340/193348

    
    往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
    AI基础下载机器学习的数学基础专辑黄海广老师《机器学习课程》课件合集
    本站qq群851320808,加入微信群请扫码:

【数据竞赛】99%情况下都有效的特征筛选策略--Null Importance。相关推荐

  1. smarty_modifier_truncate,无或者有md_substr的情况下都能正确截取字符串的php函数,可用于smarty。...

    smarty_modifier_truncate,无或者有md_substr的情况下都能正确截取字符串的php函数,可用于smarty. function smarty_modifier_trunca ...

  2. 在数据仓储的情况下进一步封装数据库基础操作,此版本为异步版本

    1 /// <summary> 2 /// 在数据仓储的情况下进一步封装数据库基础操作,此版本为异步版本 Created by ZhangQC 2016.08.17 3 /// </ ...

  3. 百面机器学习 -- No.2 特征工程 -- 训练数据不足的情况下会带来什么问题,如何缓解?

    训练数据不足的情况下会带来什么问题,如何缓解? 数据不足会带来什么问题 如何解决 ? 数据不足会带来什么问题 机器学习任务的问题,可以简单的理解成寻找最佳的拟合函数和最佳的泛化函数,拟合函数是用来学习 ...

  4. java流处理为什么快_“任何情况下,都不可以堕胎”是道德普遍主义的观点。

    [判断题]两个可能性之间可以彼此独立. [多选题]全球化正改变着我们的工作方式和生活方式,原因是我们首先必须处理( )和( )这两个问题. [判断题]"只许州官放火"体现了双重标准 ...

  5. java mail smtps,使用javamail发SMTPS邮件,javamailsmtps邮件,Java通常情况下都不会

    使用javamail发SMTPS邮件,javamailsmtps邮件,Java通常情况下都不会 Java 通常情况下都不会对smtp发邮件加密,但是gmail做了加密. 首先需要引用 Javamail ...

  6. 在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的。但是在通过了Apache,Squi...

    在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr() ,这种方法在大部分情况下都是有效的.但是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实 ...

  7. 【数据竞赛】五大100%奏效的特征筛选策略

    作者:杰少 五大100%奏效的特征筛选策略 简 介 在一些问题中,我们拿到的数据特征列是几千甚至上万的,这个时候如果我们直接使用模型训练,会非常耗时间,如果我们知道有些特征100%对于后期的模型训练不 ...

  8. 数据科学家们更换工作都有哪些特征(上)?

    前面有文章数据分析之探索性数据分析,里面详细阐述了何为EDA,以及一些常用的分析方法,感兴趣的小伙伴们可以参考下. 本文分析数据科学家更换工作情况数据集,运用常见EDA方法分析每个特征情况及他们与目标 ...

  9. 数据随机丢失情况下多传感器多速率鲁棒融合估计

    问题描述 存在N个传感器进行观测,观测数据有一定概率丢失 简而言之,其中γ\gammaγ是一个随机数(非0即1),0代表数据丢失,1代表数据存在.其他的多传感器多速率表示与上篇文章一致. 下面同样对多 ...

最新文章

  1. C++ with STL(一)
  2. CodeForces - 1337E Kaavi and Magic Spell(dp)
  3. 保留3位 python_Python基础(六)
  4. Asp.net2.0实现Word转换Html,同时分享系列笑话
  5. js与c语言效率_JavaScript控制流及关键字与C语言之比较
  6. java实现数据库内容修改_数据库更改到Java环境中实现可持续和平
  7. 更改VS的运行主窗体
  8. [css] 如何使用CSS绘制一个汉堡式菜单
  9. 【youcans 的 OpenCV 例程 200 篇】103. 陷波带阻滤波器消除周期噪声干扰
  10. Qt程序等待/睡眠的正确方法
  11. 一文带你彻底了解大数据处理引擎Flink内存管理
  12. iPhone 12系列重新上架苹果天猫旗舰店,5499元的iPhone 12今晚开订!
  13. 中芯国际A股最终确定发行价27.46元 发行规模超50亿
  14. 打印倍数_英语精读:3d打印的速度有望提高到100倍
  15. 这台计算机的rsa密匙如下怎解决,win10系统使用计划任务提示账户密钥集不存在错误代码0x80090016怎么办...
  16. 翻译:如何理解K-means的缺点
  17. Vue项目实例(一)------背景
  18. 计算百分比的分析函数
  19. 【阿里云镜像】更新阿里巴巴开源镜像站镜像——Ubuntu镜像
  20. 2023年NOC加码未来编程(小码王赛道)初赛-Scratch(小学低年级组-卷1)

热门文章

  1. 【old】简单易用的鹰眼类源代码下载
  2. 手工将python程序发布为exe执行程序 [转]
  3. Selenium3 + Python3自动化测试系列一——安装Python+selenium及selenium3 浏览器驱动
  4. Python单元测试框架之pytest 3 -- fixtures
  5. 文件上传api——MultipartFile
  6. mycat 编辑schema.xml
  7. 云计算学习(2-4)云计算的案例
  8. python字符串,列表,字典的常用方法
  9. MyBatis在insert插入操作时返回主键ID的配置
  10. [转贴]IT外包服务商如何构建高效率的服务台运营机制