博客信息

xgboost on spark 稀疏向量的缺失值问题解决办法

发布时间:『 2019-12-23 16:40』  博客类别:Hadoop/Spark  阅读(2030) 评论(0)

最近在使用xgboost on spark过程中发现一个问题,发现对于标签型的稀疏变量(即有值就为1),得到的树节点如下:

0:[tag1<2.00000095] yes=1,no=2,missing=2

既然为1和0,为什么条件会是小于2呢?这样不是会导致所有值都满足条件吗?
于是,带着这个问题,查找了相关的资料。美团的技术团队遇到过xgboost on spark 的缺失值问题,我觉得可能就是这个问题导致的。
美团的解决办法:https://tech.meituan.com/2019/08/15/problems-caused-by-missing-xgboost-values-and-their-in-depth-analysis.html
文中描述:

在XGBoost on Spark场景下,默认将Float.NaN作为缺失值。如果数据集中的某一行存储结构是DenseVector,实际执行时,该行的缺失值是Float.NaN。而如果数据集中的某一行存储结构是SparseVector,由于XGBoost on Spark仅仅使用了SparseVector中的非0值,也就导致该行数据的缺失值是Float.NaN和0。

其实,看文章中的解决方案就是将Sparse Vector转为Dense Vector。

具体措施是修改dmlc的源码。

1、从github上下载xgboost on spark 0.72版本,地址:https://github.com/dmlc/xgboost/tree/release_0.72。并将源码复制到spark scala工程中。在pom.xml中去掉xgboost on spark的引用。后面直接在工程中使用源码;

2、修改两处代码。

(1)ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator  132行:

      val values = features match {
//        case v: SparseVector => (v.indices, v.values.map(_.toFloat))
        //SparseVector的数据,先转成Dense
        case v: SparseVector => v.toArray.map(_.toFloat)
        case v: DenseVector => v.values.map(_.toFloat)
      }
      XGBLabeledPoint(label.toFloat, null, values, baseMargin = baseMargin, weight = weight)

(2)ml.dmlc.xgboost4j.scala.spark.DataUtils 67行:

//        XGBLabeledPoint(0.0f, v.indices, v.values.map(_.toFloat))
        //SparseVector的数据,先转成Dense
        XGBLabeledPoint(0.0f, null, v.toArray.map(_.toFloat))


关键字:   xgboost     spark  
评论信息
暂无评论
发表评论
验证码: 
Powered by IMZHANGJIE.CN Copyright © 2015-2025 粤ICP备14056181号