1. 程式人生 > >SparkML之迴歸(一)線性迴歸

SparkML之迴歸(一)線性迴歸

----------------------------目錄-----------------------------------------------------------------------

線性迴歸理論

spark原始碼

Spark實驗

-------------------------------------------------------一元線性迴歸-------------------------------------------------------------------------

模型

反應一個因變數與一個自變數之間的線性關係,一元線性迴歸模型如下:

                                                         (1)

其中:

迴歸係數

自變數

因變數

隨機誤差,一般假設服從

那麼可以得到結論就是:服從

若我們之前對 (,)進行了 n次觀測,那麼就可以得到如下,一系列的資料

  為(1,2,...n)

那麼把這些數值,帶入(1)公式,那麼就有 n個包含方程,大家知道當要確定n個引數的時候,滿秩的情況下,只要n個方程就就可以確定了,那麼如何根據歷史的觀測資料來選擇,來選擇最佳的只要把確定了,那麼我們隨便輸入一個就可以得到一個,那麼選擇一個"未來"的,就可以計算一個"未來"的,那麼就達到了預測效果

普通最小二乘法

那麼什麼才是最佳的 最小二乘法的思想就是把決定後的方程,代入引數使得方差最小,就是最佳的。

我們把全部的方差記為:

                             

那麼現在就是計算關於引數的極小值,當關於引數的偏導為0的時候,那麼取到極值

           

對其進行整理,得到如下:

              

那麼可以直接計算出:


當自變數x多的時候,就很難直接計算、....、,那麼就必須用克拉姆法則(Cramer's Rule)計算,

其中、、、、....、的最小二乘估計。

擬合效果分析

1、殘差的樣本方差

殘差: (i = 1,2,...n)

殘差的樣本均值:

那麼殘差的樣本方差:

其中n-2是自由度,因為有約束,所以自由度減2(殘差之間相互獨立,殘差和自變數x相互獨立),如果我們的擬合方程:

解釋因變數越強,那麼MSE是越小。你會發現:

這個MSE就是總體迴歸模型中方差的無偏估計量。

那麼它的標準差:

2、判定係數(R)

我們從新考慮我們的樣本回歸函式:


因為我們的解釋變數的平均值,一定會經過我們的樣本回歸函式,下面證明:


兩邊進行平方之後再加總,然後除以樣本容量n:


其中,,得到:

下面結合影象進行說明:

結合影象,我們可以得到下面方程:

兩邊平方之後,進行加總,得到:


:樣本觀測值和其平均值的離差平方和,自由度為n-1

:擬合直線可解釋部分的平方和,自由度為1

:樣本的觀測值和估計值之差的平方,既殘差平方和,自由度為n-2

縮寫全拼(採用國外教材的縮寫方式):

Total sum of squares(SST):總離差平方和

Residual sum of squares (SSR):殘差平方和

explained sum of squares(SSE):迴歸平方和(國人根據實際意義自己命名的?)

所以我們有:

那麼對於我們真正解釋了的部分和總體的比值(用表示):



時,也就是SSR = SSE,那麼就是說原始資料完全可以擬合值來解釋,此時SSR = 0,那麼擬合非常完美

一般

SSR很好計算,就是樣本的實際觀察值與估計值差的平方,所以用SSR去計算R

顯著性檢驗

當你擬合好引數的時候,你要去評定一個這樣的一個模型對於我們想要解釋的問題是否顯著(只有R是不夠的),

如果不顯著那麼就需要換其他模型方法了。對於其中檢驗的方法有F檢驗和T檢驗,本文重點是SparkMlib下的線性迴歸,本節只是一個鋪墊,所以具體如何檢驗,就不贅述了。

-------------------------------------------------------多元線性迴歸----------------------------------------------------------------------------

模型

反應多個因變數與一個自變數之間的線性關係,多元線性迴歸模型如下:

 (2)

其中:都是與無關的未知引數,是迴歸係數。

現在得到n個樣本資料(),=1,....,n,其中,那麼(2)得到:

3)

我們可以把(3)寫成如下模式:

(4)

其中:

,,,

求解過程和一元線性迴歸一樣,可以得到:


判定係數(R)還是按照一元迴歸那樣求解,當R大於0.8才認為線性關係明顯

===================================最小二乘法的缺陷============================

1、只有當X滿秩的時候,才可以用最小二乘法。因為在求解的時候的條件:X是滿秩的,也就是在決定多個因變數

必須是相互獨立的,當如果有關聯,可以用表示,那麼X就不是滿秩的

此時用最小二乘法就是錯誤的,因為X是不可逆的

2、最小二乘的複雜度高,在處理大規模資料的時候,耗時長。

--------------------------------------------------------------------梯度下降法-------------------------------------------------------------------

由於最小二乘法在求解時,存在侷限,所以在計算機領域一般採用梯度下降法,來近似求解

為了與文獻2的符號一致,所以放棄前面用過的符號,採用文獻2中的符號。現在直接從多元線性迴歸開始

線性方程:

我們讓,那麼方程變為:


若我們之前對 (,)進行了 m次觀測,那麼就可以得到如下,一系列的資料

  為(1,2,...m),按照前面的思路,我們來計算“相差”多少,既所說的cost function:


(小插曲:不知道為什麼有很多人把上面的m給省略了,在andrew NG課程中和Spark原始碼理解中都有這個m

其實加上m更能體現問題)

也就說讓最小。如果用之前的最小二乘法,那麼就是,求偏導,讓等式都等於0,建立方程,聯合求解


我們知道最小二乘法的弊端,所以採用梯度下降法來求解最優的:


其中是學習效率,而且迭代的初始值設定為n+1列的零向量,然後一直迭代,直到收斂為止。

當樣本很大的時候,如果迭代次數很大,那麼我們會選擇一部分樣本進行對的更新計算。

更多細節,請看:http://blog.csdn.net/legotime/article/details/51277141

-------------------------------------------------------------------------------------------------------------------------------------------------

Spark原始碼

package org.apache.spark.mllib.regression包含了兩個部分:LinearRegressionModel和LinearRegressionWithSGD

1、迴歸的模型(class和object),class 的引數是繼承GeneralizedLinearModel廣義迴歸模型,之後形成一個完整的

性回歸模型,object上面的方法用於匯出已經儲存的模型進行迴歸

2、LinearRegressionWithSGD:隨機梯度下降法,cost  function:f(weights) = 1/n ||A weights-y||^2也就是前面


記住這個還是加上m更能體現問題,(除以m表示均方誤差)

LinearRegressionWithSGD是繼承GeneralizedLinearAlgorithm[LinearRegressionModel]廣義迴歸類

1、迴歸模型原始碼如下

/**
 * Regression model trained using LinearRegression.
 *
 * @param weights Weights computed for every feature.(每個特徵的權重向量)
 * @param intercept Intercept computed for this model.(此模型的偏置或殘差)
 *
 */
@Since("0.8.0")
class LinearRegressionModel @Since("1.1.0") (
    @Since("1.0.0") override val weights: Vector,
@Since("0.8.0") override val intercept: Double)
  extends GeneralizedLinearModel(weights, intercept) with RegressionModel with Serializable
  with Saveable with PMMLExportable {

  //進行預測:Y = W*X+intercept
override protected def predictPoint(
      dataMatrix: Vector,
weightMatrix: Vector,
intercept: Double): Double = {
    weightMatrix.toBreeze.dot(dataMatrix.toBreeze) + intercept
  }
  //模型儲存包含:儲存的位置,名字,權重和偏置
@Since("1.3.0")
  override def save(sc: SparkContext, path: String): Unit = {
    GLMRegressionModel.SaveLoadV1_0.save(sc, path, this.getClass.getName, weights, intercept)
  }

  override protected def formatVersion: String = "1.0"
}
//載入上面儲存和的模型,用load(sc,儲存路徑)
@Since("1.3.0")
object LinearRegressionModel extends Loader[LinearRegressionModel] {

  @Since("1.3.0")
  override def load(sc: SparkContext, path: String): LinearRegressionModel = {
    val (loadedClassName, version, metadata) = Loader.loadMetadata(sc, path)
    // Hard-code class name string in case it changes in the future
val classNameV1_0 = "org.apache.spark.mllib.regression.LinearRegressionModel"
(loadedClassName, version) match {
      case (className, "1.0") if className == classNameV1_0 =>
        val numFeatures = RegressionModel.getNumFeatures(metadata)
        val data = GLMRegressionModel.SaveLoadV1_0.loadData(sc, path, classNameV1_0, numFeatures)
        new LinearRegressionModel(data.weights, data.intercept)
      case _ => throw new Exception(
        s"LinearRegressionModel.load did not recognize model with (className, format version):" +
        s"($loadedClassName, $version).  Supported:\n" +
        s"  ($classNameV1_0, 1.0)")
    }
  }
}

2、LinearRegressionWithSGD類,該類是基於無正規化的隨機梯度下降,而且是繼承GeneralizedLinearAlgorithm[LinearRegressionModel]廣義迴歸類

/**
 * Train a linear regression model with no regularization using Stochastic Gradient Descent.
 * This solves the least squares regression formulation
 *              f(weights) = 1/n ||A weights-y||^2^
* (which is the mean squared error).
 * Here the data matrix has n rows, and the input RDD holds the set of rows of A, each with
 * its corresponding right hand side label y.
 * See also the documentation for the precise formulation.
 */
@Since("0.8.0")
class LinearRegressionWithSGD private[mllib] (
    private var stepSize: Double,//步長
private var numIterations: Int,//迭代次數
private var miniBatchFraction: Double)//參與迭代樣本的比列
extends GeneralizedLinearAlgorithm[LinearRegressionModel] with Serializable {

  private val gradient = new LeastSquaresGradient()  //閱讀:3
  private val updater = new SimpleUpdater()  //閱讀:4
  @Since("0.8.0")
  override val optimizer = new GradientDescent(gradient, updater) //閱讀:5
    .setStepSize(stepSize)
    .setNumIterations(numIterations)
    .setMiniBatchFraction(miniBatchFraction)

  /**
   * Construct a LinearRegression object with default parameters: {stepSize: 1.0,
   * numIterations: 100, miniBatchFraction: 1.0}.
   */
@Since("0.8.0")
  def this() = this(1.0, 100, 1.0) 

  override protected[mllib] def createModel(weights: Vector, intercept: Double) = {
    new LinearRegressionModel(weights, intercept)
  }
}

/**
 * Top-level methods for calling LinearRegression.
 *
 */
@Since("0.8.0")
object LinearRegressionWithSGD {

  /**
   * Train a Linear Regression model given an RDD of (label, features) pairs. We run a fixed number
   * of iterations of gradient descent using the specified step size. Each iteration uses
   * `miniBatchFraction` fraction of the data to calculate a stochastic gradient. The weights used
   * in gradient descent are initialized using the initial weights provided.
   *
   * @param input RDD of (label, array of features) pairs. Each pair describes a row of the data
   *              matrix A as well as the corresponding right hand side label y
   * @param numIterations Number of iterations of gradient descent to run.
   * @param stepSize Step size to be used for each iteration of gradient descent.
   * @param miniBatchFraction Fraction of data to be used per iteration.
   * @param initialWeights Initial set of weights to be used. Array should be equal in size to
   *        the number of features in the data.
   *
   */
@Since("1.0.0")
  def train(
      input: RDD[LabeledPoint],
numIterations: Int,
stepSize: Double,
miniBatchFraction: Double,
initialWeights: Vector): LinearRegressionModel = {
    new LinearRegressionWithSGD(stepSize, numIterations, miniBatchFraction)
      .run(input, initialWeights)
  }

  /**
   * Train a LinearRegression model given an RDD of (label, features) pairs. We run a fixed number
   * of iterations of gradient descent using the specified step size. Each iteration uses
   * `miniBatchFraction` fraction of the data to calculate a stochastic gradient.
   *
   * @param input RDD of (label, array of features) pairs. Each pair describes a row of the data
   *              matrix A as well as the corresponding right hand side label y
   * @param numIterations Number of iterations of gradient descent to run.
   * @param stepSize Step size to be used for each iteration of gradient descent.
   * @param miniBatchFraction Fraction of data to be used per iteration.
   *
   */
@Since("0.8.0")
  def train(
      input: RDD[LabeledPoint],
numIterations: Int,
stepSize: Double,
miniBatchFraction: Double): LinearRegressionModel = {
    new LinearRegressionWithSGD(stepSize, numIterations, miniBatchFraction).run(input)
  }

  /**
   * Train a LinearRegression model given an RDD of (label, features) pairs. We run a fixed number
   * of iterations of gradient descent using the specified step size. We use the entire data set to
   * compute the true gradient in each iteration.
   *
   * @param input RDD of (label, array of features) pairs. Each pair describes a row of the data
   *              matrix A as well as the corresponding right hand side label y
   * @param stepSize Step size to be used for each iteration of Gradient Descent.
   * @param numIterations Number of iterations of gradient descent to run.
   * @return a LinearRegressionModel which has the weights and offset from training.
   *
   */
@Since("0.8.0")
  def train(
      input: RDD[LabeledPoint],
numIterations: Int,
stepSize: Double): LinearRegressionModel = {
    train(input, numIterations, stepSize, 1.0)
  }

  /**
   * Train a LinearRegression model given an RDD of (label, features) pairs. We run a fixed number
   * of iterations of gradient descent using a step size of 1.0. We use the entire data set to
   * compute the true gradient in each iteration.
   *
   * @param input RDD of (label, array of features) pairs. Each pair describes a row of the data
   *              matrix A as well as the corresponding right hand side label y
   * @param numIterations Number of iterations of gradient descent to run.
   * @return a LinearRegressionModel which has the weights and offset from training.
   *
   */
@Since("0.8.0")
  def train(
      input: RDD[LabeledPoint],
numIterations: Int): LinearRegressionModel = {
    train(input, numIterations, 1.0, 1.0)
  }
}

3、最小平方梯度,首先聯絡我們的代價(損失)函式,如下:


損失函式原始碼標記為:L = 1/2n ||A weights-y||^2

每個樣本的梯度值:

每個樣本的誤差值:

第一個compute返回的是 ,第二個compute返回的是

class LeastSquaresGradient extends Gradient {
  override def compute(data: Vector, label: Double, weights: Vector): (Vector, Double) = {
    val diff = dot(data, weights) - label
    val loss = diff * diff / 2.0//誤差
val gradient = data.copy
    scal(diff, gradient)////梯度值x*(y-h(x))
(gradient, loss)
  }

  override def compute(
      data: Vector,
label: Double,
weights: Vector,
cumGradient: Vector): Double = {
    val diff = dot(data, weights) - label//h(x)-y
axpy(diff, data, cumGradient)//y = x*(h(x)-y)+cumGradient
/**axpy用法:
      * Computes y += x * a, possibly doing less work than actually doing that operation
      *  def axpy[A, X, Y](a: A, x: X, y: Y)(implicit axpy: CanAxpy[A, X, Y]) { axpy(a,x,y) }
      */
diff * diff / 2.0
}
}

4、權重更新(SimpleUpdater),更新公式如下:


返回的時候偏置項設定為0了

class SimpleUpdater extends Updater {
  override def compute(
      weightsOld: Vector,//上一次計算後的權重向量
gradient: Vector,//本次迭代的權重向量
stepSize: Double,//步長
iter: Int,//當前迭代次數
regParam: Double): (Vector, Double) = {
    val thisIterStepSize = stepSize / math.sqrt(iter)//學習速率  a
val brzWeights: BV[Double] = weightsOld.toBreeze.toDenseVector
    brzAxpy(-thisIterStepSize, gradient.toBreeze, brzWeights)
    //brzWeights + = gradient.toBreeze-thisIterStepSize
(Vectors.fromBreeze(brzWeights), 0)
  }
}

5權重優化

權重優化採用的是隨機梯度降,但是預設的是miniBatchFraction= 1.0。

/**
 * Class used to solve an optimization problem using Gradient Descent.
 * @param gradient Gradient function to be used.
 * @param updater Updater to be used to update weights after every iteration.
 */
class GradientDescent private[spark] (private var gradient: Gradient, private var updater: Updater)
  extends Optimizer with Logging {

  private var stepSize: Double = 1.0
private var numIterations: 
            
           

相關推薦

SparkML迴歸()線性迴歸

----------------------------目錄----------------------------------------------------------------------- 線性迴歸理論 spark原始碼 Spark實驗 -----------

機器學習優雅落地線性迴歸

在統計學中,線性迴歸(Linear regression)是利用稱為線性迴歸方程的最小二乘函式對一個或多個自變數和因變數之間關係進行建模的一種迴歸分析維基百科。 簡單線性迴歸 當只有一個自變數的時候,成為簡單線性迴歸。 簡單線性迴歸模型的思路 為了得到一個簡單線性迴歸模型,假設存在以房屋面積為特徵

【機器學習經典演算法梳理】.線性迴歸

【機器學習經典演算法梳理】是一個專門梳理幾大經典機器學習演算法的部落格。我在這個系列部落格中,爭取用最簡練的語言、較簡潔的數學公式,和清晰成體系的提綱,來盡我所能,對於演算法進行詳盡的梳理。【機器學習經典演算法梳理】系列部落格對於機器學習演算法的梳理,將從“基本思想”、“基本形式”、“過程推導”、“

機器學習實踐(十四)—sklearn迴歸線性迴歸的改進)

帶有 L2 正則化的線性迴歸就是嶺迴歸。 嶺迴歸,其實也是一種線性迴歸。 只不過在演算法建立迴歸方程時候,加上正則化的限制,從而達到解決過擬合的效果。 加上正則化,也就是使權重滿足劃分正確結果的同時儘量的小 一、嶺迴歸 - API 嶺迴歸 - API

吳恩達機器學習多變數線性迴歸實現部分

C++實現梯度下降法 “linear_regression.h” //多變數線性迴歸模型 struct elem_var2 { double y; double* x; //用陣列傳入自變數資料(x[0]=1,便於之後的計算) }; class var2

吳恩達機器學習多變數線性迴歸理論部分

本部落格主要參考此部落格:戀雨心 一.Multiple Features — 多維特徵 相對於單變數線性迴歸模型,多變數線性迴歸模型適用於處理多個變數/特徵。 對比: 以之前我們介紹的單變數線性迴歸模型為例: 用房屋面積x預測房子價格y。 現在我們對房價模型增加更多的特徵,例如房間

吳恩達機器學習單變數線性迴歸實現部分

C++實現 程式碼實現 “linear_regression.h” //單變數線性迴歸模型 struct elem_var1 { double x, y; //訓練集元素資料:自變數、因變數 }; class var1_lin_reg { p

吳恩達機器學習單變數線性迴歸理論部分

理論部分 1.方程形式 在進行資料處理過程中,有時資料影象可擬合成單變數線性函式,即 2.如何擬合 此時,我們雖知道擬合函式的形式,但如何擬合仍是個問題,怎樣擬合可以最接近實際資料情況呢? 最小二乘法 此時我們引入代價函式這個概念 代價函式 接下來我們來分析如何

機器學習經典演算法總結 .線性迴歸

一.基本形式 hθ(x)=θ0+θ1x1+θ2x2+....+θnxn=θTxh_θ(x)=θ_0+θ_1x_1+θ_2x_2+....+θ_nx_n=θ^Txhθ​(x)=θ0​+θ1​x1​+θ2​x2​+....+θn​xn​=θTx 二.損失函式 最常用

skleran 學習路徑 線性迴歸模型預測

使用sklearn 裡面的datasets 內建資料集波士頓的房價 來測試這個模型 首先匯入 from sklearn import datasets loaded_data = datasets.load_boston()#波士頓房價預測 data_x =

動手學深度學習()——線性迴歸從零開始

文章作者:Tyan 部落格:noahsnail.com  |  CSDN  |  簡書 注:本文為李沐大神的《動手學深度學習》的課程筆記! 參考資料 # 匯入mxnet的ndarra

動手學深度學習()——線性迴歸(gluon)

文章作者:Tyan 部落格:noahsnail.com  |  CSDN  |  簡書 注:本文為李沐大神的《動手學深度學習》的課程筆記! 建立資料集 # 匯入mxnet import

機器學習——多變數線性迴歸

在之前的部落格中,描述過單變數線性迴歸(Linear Regression with One Variables)的模型,這次來分享一下多變數線性迴歸模型(Linear Regression wit

機器學習單變數線性迴歸(Linear Regression with One Variable)

1. 模型表達(Model Representation) 我們的第一個學習演算法是線性迴歸演算法,讓我們通過一個例子來開始。這個例子用來預測住房價格,我們使用一個數據集,該資料集包含俄勒岡州波特蘭市的住房價格。在這裡,我要根據不同房屋尺寸所售出的價格,畫出我的資料集: 我們來看這個資料集,如果你有一個朋

機器學習入門單變數線性迴歸(上)——梯度下降法

  在統計學中,線性迴歸(英語:linear regression)是利用稱為線性迴歸方程的最小二乘函式對一個或多個自變數和因變數之間關係進行建模的一種迴歸分析。這種函式是一個或多個稱為迴歸係數的模型引數的線性組合。只有一個自變數的情況稱為簡單迴歸,大於一個自變數情況的叫做多元迴歸(multi

【機器學習】演算法原理詳細推導與實現():線性迴歸

【機器學習】演算法原理詳細推導與實現(一):線性迴歸 今天我們這裡要講第一個有監督學習演算法,他可以用於一個迴歸任務,這個演算法叫做 線性迴歸 房價預測 假設存在如下 m 組房價資料: 面積(m^2) 價格(萬元) 82.35 193 65.00 213 114.20 255 75.

Logistics迴歸線性迴歸

1. Logistics迴歸與線性迴歸 線性迴歸就是給定n個變數x,經過一些線性組合後得到一個預測值y,而Logistics迴歸實際則是一個二分類問題,將線性迴歸預測的值通過一個sigmod函式,程式設計了(0,1)之間的概率,然後規定大於0.5的分為1類,小於0.5的歸為0類。 sig

機器學習4:邏輯迴歸線性迴歸

邏輯迴歸與線性迴歸求解過程: 總體來說,迴歸過程都分三步: 1、Model 2、Loss Fuction 3、Gradient Decent 分析: 1、Model:線性迴歸中,模型為線性方程,取值範圍無窮大;邏輯迴歸中,通過sigmod函式函式將線性方程z轉化成概率(

Machine Learning--week3 邏輯迴歸函式(分類)、決策邊界、邏輯迴歸代價函式、多分類與(邏輯迴歸線性迴歸的)正則化

Classification It's not a good idea to use linear regression for classification problem. We can use logistic regression algorism, which is a classificati

邏輯迴歸線性迴歸區別

1)線性迴歸要求變數服從正態分佈,logistic迴歸對變數分佈沒有要求。 2)線性迴歸要求因變數是連續性數值變數,而logistic迴歸要求因變數是分型別變數。 3)線性迴歸要求自變數和因變數呈線