美文网首页sparkMl
Spark Mllib中LinearRegression

Spark Mllib中LinearRegression

作者: LZhan | 来源:发表于2019-07-27 19:16 被阅读0次

1.相关参数设置:

<1> setMaxIter():设置最大迭代次数

<2> setRegParam(): 设置正则项的参数,控制损失函数与惩罚项的比例,防止整个训练过程过拟合

<3> setElasticNetParam():使用L1范数还是L2范数
setElasticNetParam=0.0 为L2正则化;
setElasticNetParam=1.0 为L1正则化;
setElasticNetParam=(0.0,1.0) 为L1,L2组合

<4> setFeaturesCol():指定特征列的列名,传入Array类型

<5>setLabelCol():指定标签列的列名,传入String类型

<6>setPredictionCol():指定预测列的列名

<7>setFitIntercept(value:Boolean):是否需要偏置,默认为true(即是否需要y=wx+b中的b)

<8>setStandardization(value:Boolean):模型训练时,是否对各特征值进行标准化处理,默认为true

<9>setSolver(value:String):设置用于优化求解器。线性回归支持的有l-bfgs(有限内存拟牛顿法),normal(加权最小二乘法)和auto(自动选择)。

<10>setTol(value:Double):设置迭代的收敛公差。值越小准确性越高但是迭代成本增加。默认值为1E-6。(即损失函数)

<11>setWeightCol(value:String):设置某特征列的权重值,如果不设置或者为空,默认所有实例的权重为1。

<12>setAggregationDepth:建议深度大于或等于2,默认为2。如果特征维度较大或者数据的分区量大的时候,可以调大该值。

<13>fit:基于训练街训练出模型

<14>transform:基于训练出的模型对测试集进行预测

2.demo

class LinearRegressionDemo {
  def train(): Unit = {
    val spark = SparkSession.builder()
      .master("local[2]")
      .appName("LinearRegression")
      .getOrCreate()


    //local模式下,加上file:/// 表示读取本地文件
    //header为true,表示要设置第一行为列名
    val file = spark.read.format("csv").option("header", "true")
      .option("sep", ";").load("src/main/resources/house.csv")

    file.show(false)

    import spark.implicits._

    //数据集是有序的,对训练效果不好,添加1列
    val random = new Random()

    //经过map操作变成DataSet[(Double,Double)]类型,要通过toDF转成DataFrame
    val data = file.select("square", "price").map(
      row => (row.getAs[String](0).toDouble, row.getAs[String](1).toDouble, random.nextDouble())
    ).toDF("square", "price", "random")
      .sort("random")

    data.show(false)

    //将多个列或单列合并成Vector
    val assembler = new VectorAssembler()
      .setInputCols(Array("square"))
      .setOutputCol("features")

    val dataset = assembler.transform(data)
    val Array(train, test) = dataset.randomSplit(Array(0.8, 0.2), 1234L)

    val regression = new LinearRegression()
      .setMaxIter(10)
      .setRegParam(0.3)
      .setElasticNetParam(0.8)

    //在train数据集上训练fit
    val model = regression.setLabelCol("price").setFeaturesCol("features").fit(train)
    //transform 预测
    model.transform(test).show(false)

  }
}

transform的结果:
会多一列预测值(prediction)


image.png

最终打印出训练模型的参数,就是w向量和b值:
println("Cofficients:"+model.coefficients)
println("Intercept:"+model.intercept)

image.png

例子中特征列只有1项,所以w向量也只有1个维度。

那么如何查看预测结果信息:

test_predict.select("features","price","prediction").collect().foreach{
      case Row(features:org.apache.spark.ml.linalg.Vector,label:Double,prediction:Double)=>

        println(s"($features,$label)-> prediction=$prediction")
    }
image.png

如何打印模型摘要:

 val trainingSummary=model.summary
    //每次迭代的目标值
    val objectiveHistory=trainingSummary.objectiveHistory
    //迭代次数
    println(s"numIterations:${trainingSummary.totalIterations}")
    //每次迭代的目标值,即损失函数+正则化项
    println(s"objectiveHistory:[${trainingSummary.objectiveHistory.mkString(",")}]")
    //每个样本的误差值(即label值减去预测值)
    trainingSummary.residuals.show(false)
    //均方误差
    println(s"RMSE:${trainingSummary.rootMeanSquaredError}")
    //最终的决定系数,0-1之间,值越大拟合程度越高
    println(s"r2:${trainingSummary.r2}")

结果显示:


image.png image.png

trainingSummary中还有许多别的参数,详细可以看源码。

最后一步,保存和加载训练模型:

 model.save("hdfs://")
 val load_model=LinearRegressionModel.load("hdfs://")

补充:

1.正则化(在特征较多时比较有效)

比如说下图,就是过拟合的情况


image.png

直观上来讲。解决这个例子中的过拟合问题,最好就是消除x4,x5,x^6的影响,也就是让theta4,theta5,theta6约等于0,一个简单的办法就是给原有的cost函数加上略大惩罚项,如:

image.png
这样在最小化cost函数的时候,theta4,theta5,theta6约等于0

=====》 加上正则化项的损失函数:


image.png

正则化项就是权重(即theta1或者theta2等)的L1或者L2范数乘以一个正则系数
正则系数的作用:用来控制损失函数和正则化项的比重

image.png

2.ElasticNet

被定义为L1和L2的正则化项的凸组合:


image.png

参数为0时,采用L2正则化参数,则训练的模型相当于ridge回归模型;参数为1时,采用L1正则化参数,相当于Lasso模型。

相关文章

网友评论

    本文标题:Spark Mllib中LinearRegression

    本文链接:https://www.haomeiwen.com/subject/oqvglctx.html