spark|SCALA下的GBDT与LR融合实现
admin
2023-08-16 15:45:36
0次

我们直接使用的ML的包对GBDT/LR进行融合
首先我们需要导入的包如下所示:

import org.apache.spark.sql. Row import scala.collection.mutable import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS import org.apache.spark.mllib.evaluation.MulticlassMetrics import org.apache.spark.mllib.linalg.DenseVector import org.apache.spark.mllib.regression.LabeledPoint import org.apache.spark.mllib.tree.GradientBoostedTrees import org.apache.spark.mllib.tree.configuration.{BoostingStrategy, FeatureType, Strategy} import org.apache.spark.mllib.tree.model.Node import com.suning.aps.util.handle_data.deleteHDFS import com.suning.aps.utils.StringUtil.getSign import org.apache.spark.rdd.RDD import org.apache.spark.sql.SparkSession import org.apache.spark.mllib.linalg.Vectors import org.apache.spark.sql.types._

其次,由于ml的数据需要LabeledPoint格式,而我们从hive里面提取的数据格式是DataFrame ,所以我们需要做数据转化
val spark = SparkSession.builder().appName("wap_cpc_searchApp_v") .enableHiveSupport().getOrCreate() import spark.implicits._ val instance = "yuntu/cpc_ctr/hotmai_02&20" val statis_day = "20191207" val statis_day_before = "20191205" val parallels =50deleteHDFS(instance + "/wap_cpc_searchApp_v/" + statis_day, spark.sparkContext)val pv_click_searchApp1 = spark.sql( s"""select |case when length(ta.query)=0 then '-' else ta.query end as query, |case when length(ta.ideaid)=0 then '00000000000000000-' |when ta.ideaid is NULL then '00000000000000000-' |else lpad(ta.ideaid,18,'0') end as ideaid, |case when length(ta.terminal)=0 then '-' else ta.terminal end as terminal,""".stripMargin) .select("is_click","query","terminal","query_brand_name","query_third_categ","userid" ,"ideaid","idea_first_categ","idea_second_categ", "idea_third_categ","idea_brand_name").rdd.map(l=>{Row( l(0).toString.toDouble, getSign(l(1).toString).toString.toDouble, getSign(l(3).toString).toString.toDouble, getSign(l(4).toString).toString.toDouble, getSign(l(5).toString).toString.toDouble, getSign(l(6).toString).toString.toDouble, getSign(l(7).toString).toString.toDouble, getSign(l(8).toString).toString.toDouble, getSign(l(9).toString).toString.toDouble, getSign(l(10).toString).toString.toDouble)}) //由于使用MAP转化了数据(原先数据很多是离散变量,我们需要进行哈希编码)所以我们先转化为DATAFRAME val ScoreSchema=StructType(mutable.ArraySeq( StructField("y",DoubleType,nullable=false), StructField("x1",DoubleType,nullable=false),StructField("x2",DoubleType,nullable=false), StructField("x3",DoubleType,nullable=false),StructField("x4",DoubleType,nullable=false), StructField("x5",DoubleType,nullable=false),StructField("x6",DoubleType,nullable=false), StructField("x7",DoubleType,nullable=false),StructField("x8",DoubleType,nullable=false), StructField("x9",DoubleType,nullable=false) )) val df=spark.createDataFrame(pv_click_searchApp1,ScoreSchema) val ignored = List("y") val featInd = df.columns.diff(ignored).map(df.columns.indexOf(_))// Get index of target val targetInd = df.columns.indexOf("y")val ds=df.rdd.map(r => LabeledPoint( r.getDouble(targetInd), // Get target value // Map feature indices to values Vectors.dense(featInd.map(r.getDouble(_)).toArray) ))

上文DS即为转化后的数据,下文将介绍GBDT
//训练GBDT val numTrees = 2 // Train a GradientBoostedTrees model. val boostingStrategy = BoostingStrategy.defaultParams("Classification") boostingStrategy.numIterations = 10 boostingStrategy.treeStrategy.numClasses = 2 boostingStrategy.treeStrategy.maxDepth = 3 boostingStrategy.learningRate = 0.3 boostingStrategy.setNumIterations(numTrees) // Empty categoricalFeaturesInfo indicates all features are continuous. boostingStrategy.treeStrategy.categoricalFeaturesInfo = Map[Int, Int]()val model = GradientBoostedTrees.train(ds, boostingStrategy)

训练完GBDT后,我们需要从GBDT中探查树模型的结构,如下
val treeLeafArray = new Array[Array[Int]](numTrees)for (i <- 0.until(numTrees)) { treeLeafArray(i) = getLeafNodes(model.trees(i).topNode) } for (i <- 0.until(numTrees)) { println("正在打印第%d 棵树的 topnode 叶子节点", i) for (j <- 0.until(treeLeafArray(i).length)) { println(j) }}

【spark|SCALA下的GBDT与LR融合实现】其中,我们定义了两个函数,如下所示:
def getLeafNodes(node: Node): Array[Int] = { var treeLeafNodes = new Array[Int](0) if (node.isLeaf) { treeLeafNodes = treeLeafNodes.:+(node.id) } else { treeLeafNodes = treeLeafNodes ++ getLeafNodes(node.leftNode.get) treeLeafNodes = treeLeafNodes ++ getLeafNodes(node.rightNode.get) } treeLeafNodes }// predict decision tree leaf's node value def predictModify(node: Node, features: DenseVector): Int = { val split = node.split if (node.isLeaf) { node.id } else { if (split.get.featureType == FeatureType.Continuous) { if (features(split.get.feature) <= split.get.threshold) { //println("Continuous left node") predictModify(node.leftNode.get, features) } else { //println("Continuous right node") predictModify(node.rightNode.get, features) } } else { if (split.get.categories.contains(features(split.get.feature))) { //println("Categorical left node") predictModify(node.leftNode.get, features) } else { //println("Categorical right node") predictModify(node.rightNode.get, features) } } } }

下文将利用上文训练的GBDT构造新特征并用LR训练
//gbdt 构造新特征 val newFeatureDataSet = df.rdd.map { x => (x(0).toString().toDouble, new DenseVector(Array(x(1).toString().toDouble, x(2).toString().toDouble, x(3).toString().toDouble, x(4).toString().toDouble, x(5).toString().toDouble, x(6).toString().toDouble , x(7).toString().toDouble, x(8).toString().toDouble, x(9).toString().toDouble))) }.map { x => var newFeature = new Array[Double](0) for (i <- 0.until(numTrees)) { val treePredict = predictModify(model.trees(i).topNode, x._2) //gbdt tree is binary tree val treeArray = new Array[Double]((model.trees(i).numNodes + 1) / 2) treeArray(treeLeafArray(i).indexOf(treePredict)) = 1 newFeature = newFeature ++ treeArray } (x._1, newFeature) }newFeatureDataSet.take(2).foreach(println)val newData = https://www.it610.com/article/newFeatureDataSet.map(x => LabeledPoint(x._1, new DenseVector(x._2)))newData.take(2).foreach(println) val splits2 = newData.randomSplit(Array(0.8, 0.2)) val train2 = splits2(0) val test2 = splits2(1)var predictions = ds.map(lp => model.predict(lp.features)) predictions.take(10).foreach(println) var predictionAndLabel = predictions.zip( ds.map(_.label)) var accuracy = 1.0 * predictionAndLabel.filter(x => x._1 == x._2 ).count/ds.count println("GBTR accuracy " + accuracy)val model1 = new LogisticRegressionWithLBFGS().setNumClasses(2).run(train2).setThreshold(0.01) model1.weights val predictionAndLabels = test2.map { case LabeledPoint(label, features) => val prediction = model1.predict(features) (prediction, label) } val metrics = new MulticlassMetrics(predictionAndLabels) val precision = metrics.accuracy println("Precision = " + precision)

相关内容

热门资讯

大浪淘金APP黑幕揭秘:内盘操...   大浪淘金APP平台最隐蔽的黑幕,在于其完全封闭的内盘交易系统。这个看似与国际市场接轨的交易平台,...
告别固定工资实现财富自由?一品...   普通投资者被广告宣传诱导,注册就送现金,充值返现金券等等这些宣传方式,都是在引流到平台开户,不怕...
哈易购APP打着现货交易幌子搞...   网络上各类白银、铂金等贵金属投资广告铺天盖地,不少平台以"现货交易"为名,暗中却从事着非法期货交...
5元起投!高额收益?中国白银、...   上海华通白银国际交易中心有限公司(以下简称“华通白银国际”)打着“白银、铂金现货订购”的旗号,实...
"九州订购APP、起...   近年来,贵金属投资热度持续攀升,但乱象也随之而来。一些不法分子趁机搭建虚假交易平台,打着"低门槛...
坚锅淘金APP投资者频繁爆仓亏...   坚锅淘金APP对外宣称是贵金属现货交易平台,日常出入金看似畅通无阻,给人一种合规运营的假象。但事...
斗金订购APP“5元订购现货”...   斗金订购APP“5元订购现货”骗局揭秘:充值易、回本难,越陷越深!  许多投资人在未核实平台合规...
贵金属APP乱象曝光:&quo...   当前市场上部分贵金属类APP未取得正规交易资质,涉嫌误导消费者参与白银、铂金等商品的非合规交易!...
华通白银、银宝街APP被指虚假...   警惕现货白银投资陷阱:上海华通白银背后的平台涉嫌非法期货交易  近年来,各类现货白银交易平台以“...
充值送300,月入过万?别被量...   如今,网络上充斥着大量未经批准的贵金属及其他产品订购交易平台。这些平台普遍缺乏合法经营资质,却将...
鑫汇智投APP贵金属非法期货、...   鑫汇智投APP贵金属非法期货、人为控盘,大量投资者遭恶意收割  鑫汇智投APP长期以“低门槛、高...
矅光智策APP非法贵金属交易骗...   不少投资人在矅光智策APP上进行贵金属交易后出现了严重亏损。许多人在下载该平台时,根本不清楚其是...
飞鸽订购APP非法期货交易骗局...   飞鸽订购APP非法期货交易骗局,很多投资者根本没搞懂规则就盲目充值,买涨买跌跟买cai票一样!平...
天龙白银APP被操控的非法期货...   中小投资者在网络平台参与商品现货订购交易,表面看似合规合法,实则暗藏诸多难以察觉的风险。商品现货...
下载送试玩金?千万别碰!带你揭...   当前,许多贵金属APP交易平台正采用欺诈性营销手段。它们通过抖音等短视频平台,以“5元起投”“充...
泡泡淘金APP骗局:打着&qu...   泡泡淘金APP骗局:打着"商品订购"幌子,实则非法期货收割投资者!投资需谨慎,切勿轻信“高额回报...
南商云购APP虚假电子盘背后的...   南商云购是虚假电子盘吗?它是否具备合规的交易资质?这个曾经的"现货电子盘"如今摇身一变,披上了"...
警惕"祥龙订购&qu...   祥龙订购APP、掌上银牛APP等平台背后的运营方——四川禄宏商品现货市场有限公司,仅具备现货交易...
中国白银、华银:虚假宣传、后台...   中国白银APP宣称是上市公司“中国白银集团”与“上海华通白银国际交易中心”旗下的现货交易平台,提...
起底“优品订购”APP非法期货...   “优品订购”APP根本不具备任何合法的交易资质。其背后的运营方仅凭随便注册一家公司、开发一款交易...