原文:Predicting Loan Credit Risk using Apache Spark Machine Learning Random Forests
做者:Carol McDonald,MapR解决方案架构师
翻译:KK4SBB
责编:周建丁(zhoujd@csdn.net)javascript
在本文中,我将向你们介绍如何使用Apache Spark的spark.ml库中的随机森林算法来对银行信用贷款的风险作分类预测。Spark的spark.ml库基于DataFrame,它提供了大量的接口,帮助用户建立和调优机器学习工做流。结合dataframe使用spark.ml,可以实现模型的智能优化,从而提高模型效果。html
分类算法是一类监督式机器学习算法,它根据已知标签的样本(如已经明确交易是否存在欺诈)来预测其它样本所属的类别(如是否属于欺诈性的交易)。分类问题须要一个已经标记过的数据集和预先设计好的特征,而后基于这些信息来学习给新样本打标签。所谓的特征便是一些“是与否”的问题。标签就是这些问题的答案。在下面这个例子里,若是某个动物的行走姿态、游泳姿式和叫声都像鸭子,那么就给它打上“鸭子”的标签。java
咱们来看一个银行信贷的信用风险例子:git
决策树是一种基于输入特征来预测类别或是标签的分类模型。决策树的工做原理是这样的,它在每一个节点都须要计算特征在该节点的表达式值,而后基于运算结果选择一个分支通往下一个节点。下图展现了一种用来预测信用风险的决策树模型。每一个决策问题就是模型的一个节点,“是”或者“否”的答案是通往子节点的分支。github
融合学习算法结合了多个机器学习的算法,从而获得了效果更好的模型。随机森林是分类和回归问题中一类经常使用的融合学习方法。此算法基于训练数据的不一样子集构建多棵决策树,组合成一个新的模型。预测结果是全部决策树输出的组合,这样可以减小波动,而且提升预测的准确度。对于随机森林分类模型,每棵树的预测结果都视为一张投票。得到投票数最多的类别就是预测的类别。算法
咱们使用德国人信用度数据集,它按照一系列特征属性将人分为信用风险好和坏两类。咱们能够得到每一个银行贷款申请者的如下信息:sql
存放德国人信用数据的csv文件格式以下:shell
1,1,18,4,2,1049,1,2,4,2,1,4,2,21,3,1,1,3,1,1,1 1,1,9,4,0,2799,1,3,2,3,1,2,1,36,3,1,2,3,2,1,1 1,2,12,2,9,841,2,4,2,2,1,4,1,23,3,1,1,2,1,1,1
在这个背景下,咱们会构建一个由决策树组成的随机森林模型来预测是否守信用的标签/类别,基于如下特征:apache
本教程将使用Spark 1.6.1数组
按照教程指示,登陆MapR沙箱,用户名为user01,密码为mapr。将样本数据文件复制到你的沙箱主目录下/user/user01 using scp。(注意,你可能须要先更新Spark的版本)打开spark shell:
$spark-shell --master local[1]
首先,咱们须要引入机器学习相关的包。
import org.apache.spark.ml.classification.RandomForestClassifier import org.apache.spark.ml.evaluation.BinaryClassificationEvaluator import org.apache.spark.ml.feature.StringIndexer import org.apache.spark.ml.feature.VectorAssembler import sqlContext.implicits._ import sqlContext._ import org.apache.spark.ml.tuning.{ ParamGridBuilder, CrossValidator } import org.apache.spark.ml.{ Pipeline, PipelineStage }
咱们用一个Scala的case类来定义Credit的属性,对应于csv文件中的一行。
// define the Credit Schema case class Credit( creditability: Double, balance: Double, duration: Double, history: Double, purpose: Double, amount: Double, savings: Double, employment: Double, instPercent: Double, sexMarried: Double, guarantors: Double, residenceDuration: Double, assets: Double, age: Double, concCredit: Double, apartment: Double, credits: Double, occupation: Double, dependents: Double, hasPhone: Double, foreign: Double )
下面的函数解析一行数据文件,将值存入Credit类中。类别的索引值减去了1,所以起始索引值为0.
// function to create a Credit class from an Array of Double def parseCredit(line: Array[Double]): Credit = { Credit( line(0), line(1) - 1, line(2), line(3), line(4) , line(5), line(6) - 1, line(7) - 1, line(8), line(9) - 1, line(10) - 1, line(11) - 1, line(12) - 1, line(13), line(14) - 1, line(15) - 1, line(16) - 1, line(17) - 1, line(18) - 1, line(19) - 1, line(20) - 1 ) } // function to transform an RDD of Strings into an RDD of Double def parseRDD(rdd: RDD[String]): RDD[Array[Double]] = { rdd.map(_.split(",")).map(_.map(_.toDouble)) }
接下去,咱们导入germancredit.csv文件中的数据,存为一个String类型的RDD。而后咱们对RDD作map操做,将RDD中的每一个字符串通过ParseRDDR函数的映射,转换为一个Double类型的数组。紧接着是另外一个map操做,使用ParseCredit函数,将每一个Double类型的RDD转换为Credit对象。toDF()函数将Array[[Credit]]类型的RDD转为一个Credit类的Dataframe。
// load the data into a RDD val creditDF= parseRDD(sc.textFile("germancredit.csv")).map(parseCredit).toDF().cache() creditDF.registerTempTable("credit") DataFrame的printSchema()函数将各个字段含义以树状的形式打印到控制台输出。 // Return the schema of this DataFrame creditDF.printSchema root |-- creditability: double (nullable = false) |-- balance: double (nullable = false) |-- duration: double (nullable = false) |-- history: double (nullable = false) |-- purpose: double (nullable = false) |-- amount: double (nullable = false) |-- savings: double (nullable = false) |-- employment: double (nullable = false) |-- instPercent: double (nullable = false) |-- sexMarried: double (nullable = false) |-- guarantors: double (nullable = false) |-- residenceDuration: double (nullable = false) |-- assets: double (nullable = false) |-- age: double (nullable = false) |-- concCredit: double (nullable = false) |-- apartment: double (nullable = false) |-- credits: double (nullable = false) |-- occupation: double (nullable = false) |-- dependents: double (nullable = false) |-- hasPhone: double (nullable = false) |-- foreign: double (nullable = false) // Display the top 20 rows of DataFrame creditDF.show +-------------+-------+--------+-------+-------+------+-------+----------+-----------+----------+----------+-----------------+------+----+----------+---------+-------+----------+----------+--------+-------+ |creditability|balance|duration|history|purpose|amount|savings|employment|instPercent|sexMarried|guarantors|residenceDuration|assets| age|concCredit|apartment|credits|occupation|dependents|hasPhone|foreign| +-------------+-------+--------+-------+-------+------+-------+----------+-----------+----------+----------+-----------------+------+----+----------+---------+-------+----------+----------+--------+-------+ | 1.0| 0.0| 18.0| 4.0| 2.0|1049.0| 0.0| 1.0| 4.0| 1.0| 0.0| 3.0| 1.0|21.0| 2.0| 0.0| 0.0| 2.0| 0.0| 0.0| 0.0| | 1.0| 0.0| 9.0| 4.0| 0.0|2799.0| 0.0| 2.0| 2.0| 2.0| 0.0| 1.0| 0.0|36.0| 2.0| 0.0| 1.0| 2.0| 1.0| 0.0| 0.0| | 1.0| 1.0| 12.0| 2.0| 9.0| 841.0| 1.0| 3.0| 2.0| 1.0| 0.0| 3.0| 0.0|23.0| 2.0| 0.0| 0.0| 1.0| 0.0| 0.0| 0.0| | 1.0| 0.0| 12.0| 4.0| 0.0|2122.0| 0.0| 2.0| 3.0| 2.0| 0.0| 1.0| 0.0|39.0| 2.0| 0.0| 1.0| 1.0| 1.0| 0.0| 1.0| | 1.0| 0.0| 12.0| 4.0| 0.0|2171.0| 0.0| 2.0| 4.0| 2.0| 0.0| 3.0| 1.0|38.0| 0.0| 1.0| 1.0| 1.0| 0.0| 0.0| 1.0| | 1.0| 0.0| 10.0| 4.0| 0.0|2241.0| 0.0| 1.0| 1.0| 2.0| 0.0| 2.0| 0.0|48.0| 2.0| 0.0| 1.0| 1.0| 1.0| 0.0| 1.0| | 1.0| 0.0| 8.0| 4.0| 0.0|3398.0| 0.0| 3.0| 1.0| 2.0| 0.0| 3.0| 0.0|39.0| 2.0| 1.0| 1.0| 1.0| 0.0| 0.0| 1.0| | 1.0| 0.0| 6.0| 4.0| 0.0|1361.0| 0.0| 1.0| 2.0| 2.0| 0.0| 3.0| 0.0|40.0| 2.0| 1.0| 0.0| 1.0| 1.0| 0.0| 1.0| | 1.0| 3.0| 18.0| 4.0| 3.0|1098.0| 0.0| 0.0| 4.0| 1.0| 0.0| 3.0| 2.0|65.0| 2.0| 1.0| 1.0| 0.0| 0.0| 0.0| 0.0| | 1.0| 1.0| 24.0| 2.0|