spark Ml 機器學習之 線性迴歸

zhangshoutian發表於2018-01-18

本文版本選自spark 2.1.0

寫這篇文章之前已閱讀過官網api,演算法本身自認為自己手動寫,應該可以搞定(進一步優化不提);但是官網卻看的我迷迷糊糊的,引數選擇和結果獲取,描述不夠清晰,寫這篇文字的目的就是為了理清所有官網沒有解答的謎團;

演算法本身比較簡單,網上文章也很多,本人自身也提不出更高大上的解決方案,所以演算法不再詳解;重點就是解讀官網的不足;

上程式碼:

val training = spark.read.format("libsvm")
      .load(pathFile+"data/mllib/linearRegression.txt")
    val lr = new LinearRegression()
      .setMaxIter(10)
      .setRegParam(0)
      .setElasticNetParam(0)
解讀:關於setElasticNetParam的原始碼描述有:
* This supports multiple types of regularization:
*  - none (a.k.a. ordinary least squares)
*  - L2 (ridge regression)
*  - L1 (Lasso)
*  - L2 + L1 (elastic net)
意思就是說:這支援多種型別的正則化操作。
具體方法描述為:
/**
 * Set the ElasticNet mixing parameter.
 * For alpha = 0, the penalty is an L2 penalty.
 * For alpha = 1, it is an L1 penalty.
 * For alpha in (0,1), the penalty is a combination of L1 and L2.
 * Default is 0.0 which is an L2 penalty.
 *
 * @group setParam
 */
@Since("1.4.0")
def setElasticNetParam(value: Double): this.type = set(elasticNetParam, value)
setDefault(elasticNetParam -> 0.0)
可以發現這個引數設定是用來設定L1,、L2的。
L1與L2規範是用來幹嘛的呢?簡單來說是為了處理過擬合的(後面有具體測試),下圖是一個形象描述;

L1正則化和L2正則化可以看做是損失函式的懲罰項。對於線性迴歸模型,使用L1正則化的模型建叫做Lasso迴歸,使用L2正則化的模型叫做Ridge迴歸(嶺迴歸)。下圖是Python中Lasso迴歸的損失函式,式中加號後面一項α||w||1即為L1正則化項。

下圖是Python中Ridge迴歸的損失函式,式中加號後面一項α||w||22即為L2正則化項。

結合setRegParam(),該函式為設定正則化引數,結合以上描述
推測spark ml的線性規劃完整函式為:min(1/2n||coefficients*x -y||^2^ +(elasticNetParam*L1-(1-elasticNetParam)*L2))
也就是說:正則化引數設定為0時,elasticNetParam的設定無意義。
下面繼續程式碼驗證,及其測試結果
 val lrModel = lr.fit(training)
    //Y=w*x+b 迴歸係數(w) and 截距(b)
    println(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}")
    //總結訓練集上的模型並列印出一些指標
    val trainingSummary = lrModel.summary
    println(s"numIterations: ${trainingSummary.totalIterations}")
    println(s"objectiveHistory: [${trainingSummary.objectiveHistory.mkString(",")}]")
    trainingSummary.residuals.show()//殘差
    println(s"RMSE: ${trainingSummary.rootMeanSquaredError}")//均方根誤差
    println(s"r2: ${trainingSummary.r2}")//判定係數,也稱為擬合優度,越接近1越好
測試資料為:【選擇最直觀的資料,不裝逼】,引數如上文所示
1 1:0
    2 1:1
    3 1:2
    4 1:3
    5 1:4
結果為:
Coefficients: [0.9999999999999993] Intercept: 1.000000000000001
numIterations: 1
objectiveHistory: [0.0]
測試資料為:正則化引數設定為0.1
    1 1:0.2
	2 1:1.1
	3  1:2.1
	4  1:2.9
	5  1:4
結果為:
Coefficients: [1.0619069136918209] Intercept: 0.8124717577948491
numIterations: 1
objectiveHistory: [0.0]
正則化引數設定為:0.1,elasticNetParam為0.2
結果為:
Coefficients: [0.9908261029681737] Intercept: 0.9588982278855623
numIterations: 3
objectiveHistory: [0.5,0.4037043811427782,0.040903518280319406]
正則化引數設定為:0.1,elasticNetParam為0.8
結果為:
Coefficients: [0.9878122500298612] Intercept: 0.9651067649384861
numIterations: 3
objectiveHistory: [0.5,0.4116133463948107,0.06201518671563113]
根據結果分析公式min(1/2n||coefficients*x -y||^2^ +(elasticNetParam*L1-(1-elasticNetParam)*L2)),結論不坑
複雜的沒有測試,歡迎批評指正

相關文章