1. 程式人生 > >分類和迴歸(四)-線性迴歸

分類和迴歸(四)-線性迴歸

線性迴歸

迴歸問題的條件或者說前提是

  • 1) 收集的資料
  • 2) 假設的模型,即一個函式,這個函式裡含有未知的引數,通過學習,可以估計出引數。然後利用這個模型去預測/分類新的資料。
1   線性迴歸的概念 線性迴歸假設特徵和結果都滿足線性。即不大於一次方。收集的資料中,每一個分量,就可以看做一個特徵資料。每個特徵至少對應一個未知的引數。這樣就形成了一個線性模型函式,向量表示形式: 這個就是一個組合問題,已知一些資料,如何求裡面的未知引數,給出一個最優解。 一個線性矩陣方程,直接求解,很可能無法直接求解。有唯一解的資料集,微乎其微。
基本上都是解不存在的超定方程組。因此,需要退一步,將引數求解問題,轉化為求最小誤差問題,求出一個最接近的解,這就是一個鬆弛求解。
在迴歸問題中,線性最小二乘是最普遍的求最小誤差的形式。它的損失函式就是二乘損失。如下公式**(1)**所示: 根據使用的正則化型別的不同,迴歸演算法也會有不同。普通最小二乘和線性最小二乘迴歸不使用正則化方法。ridge迴歸使用L2正則化,lasso迴歸使用L1正則化。
2   線性迴歸原始碼分析 2.1   例項
importorg.apache.spark.ml.regression.LinearRegression// 載入資料valtraining= spark.read.format("libsvm")
  .load("data/mllib/sample_linear_regression_data.txt"
) vallr=newLinearRegression() .setMaxIter(10) .setRegParam(0.3) .setElasticNetParam(0.8) // 訓練模型vallrModel= lr.fit(training) // 列印線性迴歸的係數和截距 println(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}") // 列印統計資訊valtrainingSummary= 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}")
2.2 程式碼實現 2.2.1  引數配置 根據上面例子,我們先看看線性迴歸可以配置的引數
// 正則化引數,預設為0,對應於優化演算法中的lambdadefsetRegParam(value: Double):this.type = set(regParam, value)
setDefault(regParam ->0.0)

// 是否使用截距,預設使用defsetFitIntercept(value: Boolean):this.type = set(fitIntercept, value)
setDefault(fitIntercept ->true)

// 在訓練模型前,是否對訓練特徵進行標準化。預設使用。// 模型的相關係數總是會返回原來的空間(不是標準化後的標準空間),所以這個過程對使用者透明defsetStandardization(value: Boolean):this.type = set(standardization, value)
setDefault(standardization ->true)

// ElasticNet混合引數// 當改值為0時,使用L2懲罰;當該值為1時,使用L1懲罰;當值在(0,1)之間時,使用L1懲罰和L2懲罰的組合defsetElasticNetParam(value: Double):this.type = set(elasticNetParam, value)
setDefault(elasticNetParam ->0.0)

// 最大迭代次數,預設是100defsetMaxIter(value: Int):this.type = set(maxIter, value)
setDefault(maxIter ->100)

// 收斂閾值defsetTol(value: Double):this.type = set(tol, value)
setDefault(tol ->1E-6)

// 樣本權重列的列名。預設不設定。當不設定時,樣本權重為1defsetWeightCol(value: String):this.type = set(weightCol, value)

// 最優化求解方法。實際有l-bfgs和帶權最小二乘兩種求解方法。// 當特徵列數量超過4096時,預設使用l-bfgs求解,否則使用帶權最小二乘求解。defsetSolver(value: String):this.type = {
    require(Set("auto", "l-bfgs", "normal").contains(value),
      s"Solver $value was not supported. Supported options: auto, l-bfgs, normal")
    set(solver, value)
  }
setDefault(solver ->"auto")

// 設定treeAggregate的深度。預設情況下深度為2// 當特徵維度較大或者分割槽較多時,可以調大該深度defsetAggregationDepth(value: Int):this.type = set(aggregationDepth, value)
setDefault(aggregationDepth ->2)
2.2.2   訓練模型 train方法訓練模型並返回LinearRegressionModel。方法的開始是處理資料集,生成需要的RDD。
// Extract the number of features before deciding optimization solver.valnumFeatures= dataset.select(col($(featuresCol))).first().getAs[Vector](0).size
valw=if (!isDefined(weightCol) || $(weightCol).isEmpty) lit(1.0) else col($(weightCol))

valinstances:RDD[Instance] = dataset.select(
    col($(labelCol)), w, col($(featuresCol))).rdd.map {
    caseRow(label: Double, weight: Double, features: Vector) =>Instance(label, weight, features)  // 標籤,權重,特徵向量
}
2.2.2.1   帶權最小二乘 當樣本的特徵維度小於4096並且solver為auto或者solver為normal時,用WeightedLeastSquares求解,這是因為WeightedLeastSquares只需要處理一次資料, 求解效率更高。WeightedLeastSquares的介紹見帶權最小二乘。
if (($(solver) =="auto"&&
    numFeatures <=WeightedLeastSquares.MAX_NUM_FEATURES) || $(solver) =="normal") {
    
    valoptimizer=newWeightedLeastSquares($(fitIntercept), $(regParam),
        elasticNetParam = $(elasticNetParam), $(standardization), true,
        solverType =WeightedLeastSquares.Auto, maxIter = $(maxIter), tol = $(tol))
    valmodel= optimizer.fit(instances)
    // When it is trained by WeightedLeastSquares, training summary does not// attach returned model.vallrModel= copyValues(newLinearRegressionModel(uid, model.coefficients, model.intercept))
    val (summaryModel, predictionColName) = lrModel.findSummaryModelAndPredictionCol()
    valtrainingSummary=newLinearRegressionTrainingSummary(
        summaryModel.transform(dataset),
        predictionColName,
        $(labelCol),
        $(featuresCol),
        summaryModel,
        model.diagInvAtWA.toArray,
        model.objectiveHistory)

    return lrModel.setSummary(Some(trainingSummary))
}
2.2.2.2  擬牛頓法
  • 1  統計樣本指標
當樣本的特徵維度大於4096並且solver為auto或者solver為l-bfgs時,使用擬牛頓法求解最優解。使用擬牛頓法求解之前我們 需要先統計特徵和標籤的相關資訊。
val (featuresSummarizer, ySummarizer) = {
      valseqOp= (c: (MultivariateOnlineSummarizer, MultivariateOnlineSummarizer),
        instance: Instance) =>
          (c._1.add(instance.features, instance.weight),
            c._2.add(Vectors.dense(instance.label), instance.weight))

      valcombOp= (c1: (MultivariateOnlineSummarizer, MultivariateOnlineSummarizer),
        c2: (MultivariateOnlineSummarizer, MultivariateOnlineSummarizer)) =>
          (c1._1.merge(c2._1), c1._2.merge(c2._2))

      instances.treeAggregate(
        newMultivariateOnlineSummarizer,newMultivariateOnlineSummarizer
      )(seqOp, combOp, $(aggregationDepth))
}
這裡MultivariateOnlineSummarizer繼承自MultivariateStatisticalSummary,它使用線上(online)的方式統計樣本的均值、方差、最小值、最大值等指標。 具體的實現見MultivariateOnlineSummarizer。統計好指標之後,根據指標的不同選擇不同的處理方式。 如果標籤的方差為0,並且不管我們是否選擇使用偏置,係數均為0,此時並不需要訓練模型。
valcoefficients=Vectors.sparse(numFeatures, Seq())  // 係數為空valintercept= yMean
valmodel= copyValues(newLinearRegressionModel(uid, coefficients, intercept))
獲取標籤方差、特徵均值、特徵方差以及正則化項
// if y is constant (rawYStd is zero), then y cannot be scaled. In this case// setting yStd=abs(yMean) ensures that y is not scaled anymore in l-bfgs algorithm.valyStd=if (rawYStd >0) rawYStd else math.abs(yMean)
 valfeaturesMean= featuresSummarizer.mean.toArray
 valfeaturesStd= featuresSummarizer.variance.toArray.map(math.sqrt)
 valbcFeaturesMean= instances.context.broadcast(featuresMean)
 valbcFeaturesStd= instances.context.broadcast(featuresStd)
 
 valeffectiveRegParam= $(regParam) / yStd
 valeffectiveL1RegParam= $(elasticNetParam) * effectiveRegParam
 valeffectiveL2RegParam= (1.0- $(elasticNetParam)) * effectiveRegParam
  • 2   定義損失函式
valcostFun=newLeastSquaresCostFun(instances, yStd, yMean, $(fitIntercept),
      $(standardization), bcFeaturesStd, bcFeaturesMean, effectiveL2RegParam, $(aggregationDepth))
損失函式LeastSquaresCostFun繼承自DiffFunction[T],用於表示最小二乘損失。它返回一個點L2正則化後的損失和梯度。 它使用方法def calculate(coefficients: BDV[Double]): (Double, BDV[Double])計算損失和梯度。這裡coefficients表示一個特定的點。
overridedefcalculate(coefficients: BDV[Double]): (Double, BDV[Double]) = {
    valcoeffs=Vectors.fromBreeze(coefficients)
    valbcCoeffs= instances.context.broadcast(coeffs)
    vallocalFeaturesStd= bcFeaturesStd.value

    valleastSquaresAggregator= {
      valseqOp= (c: LeastSquaresAggregator, instance: Instance) => c.add(instance)
      valcombOp= (c1: LeastSquaresAggregator, c2: LeastSquaresAggregator) => c1.merge(c2)

      instances.treeAggregate(
        newLeastSquaresAggregator(bcCoeffs, labelStd, labelMean, fitIntercept, bcFeaturesStd,
          bcFeaturesMean))(seqOp, combOp, aggregationDepth)
    }

    valtotalGradientArray= leastSquaresAggregator.gradient.toArray //梯度
    bcCoeffs.destroy(blocking =false)

    valregVal=if (effectiveL2regParam ==0.0) {
      0.0
    } else {
      varsum=0.0
      coeffs.foreachActive { (index, value) =>// 下面的程式碼計算正則化項的損失和梯度,並將梯度新增到totalGradientArray中
        sum += {
          if (standardization) {
            totalGradientArray(index) += effectiveL2regParam * value
            value * value
          } else {
            if (localFeaturesStd(index) !=0.0) {
              // 如果`standardization`為false,我們仍然標準化資料加快收斂速度。獲得的結果,我們需要執行反標準化// ,來得到正確的目標函式valtemp= value / (localFeaturesStd(index) * localFeaturesStd(index))
              totalGradientArray(index) += effectiveL2regParam * temp
              value * temp
            } else {
              0.0
            }
          }
        }
      }
      0.5* effectiveL2regParam * sum
    }

    (leastSquaresAggregator.loss + regVal, newBDV(totalGradientArray))
  }

這裡LeastSquaresAggregator用來計算最小二乘損失函式的梯度和損失。為了在優化過程中提高收斂速度,防止大方差 的特徵在訓練時產生過大的影響,將特徵縮放到單元方差並且減去均值,可以減少條件數。當使用截距進行訓練時,處在縮放後空間的目標函式 如下:

$$ \begin{align} L &= 1/2N ||\sum_i w_i(x_i - \bar{x_i}) / \hat{x_i} - (y - \bar{y}) / \hat{y}||^2 \end{align} $$

  在這個公式中,$\bar{x_i}$是$x_i$的均值,$\hat{x_i}$是$x_i$的標準差,$\bar{y}$是標籤的均值,$\hat{y}$ 是標籤的標準差。

  如果不使用截距,我們可以使用同樣的公式。不同的是$\bar{y}$和$\bar{x_i}$分別用0代替。這個公式可以重寫為如下的形式。

$$ \begin{align} L &= 1/2N ||\sum_i (w_i/\hat{x_i})x_i - \sum_i (w_i/\hat{x_i})\bar{x_i} - y / \hat{y} + \bar{y} / \hat{y}||^2 \\ &= 1/2N ||\sum_i w_i^\prime x_i - y / \hat{y} + offset||^2 = 1/2N diff^2 \end{align} $$

  在這個公式中,$w_i^\prime$是有效的相關係數,通過$w_i/\hat{x_i}$計算。offset是$- \sum_i (w_i/\hat{x_i})\bar{x_i} + \bar{y} / \hat{y}$, 而diff是$\sum_i w_i^\prime x_i - y / \hat{y} + offset$。

  注意,相關係數和offset不依賴於訓練資料集,所以它們可以提前計算。

  現在,目標函式的一階導數如下所示:

$$ \begin{align} \frac{\partial L}{\partial w_i} &= diff/N (x_i - \bar{x_i}) / \hat{x_i} \end{align} $$

  然而,$(x_i - \bar{x_i})$是一個密集的計算,當訓練資料集是稀疏的格式時,這不是一個理想的公式。通過新增一個稠密項 $\bar{x_i} / \hat{x_i}$到 公式的末尾可以解決這個問題。目標函式的一階導數如下所示:

$$ \begin{align} \frac{\partial L}{\partial w_i} &=1/N \sum_j diff_j (x_{ij} - \bar{x_i}) / \hat{x_i} \\ &= 1/N ((\sum_j diff_j x_{ij} / \hat{x_i}) - diffSum \bar{x_i} / \hat{x_i}) \\ &= 1/N ((\sum_j diff_j x_{ij} / \hat{x_i}) + correction_i) \end{align} $$

  這裡,$correction_i = - diffSum \bar{x_i} / \hat{x_i}$。通過一個簡單的數學推導,我們就可以知道diffSum實際上為0。

$$ \begin{align} diffSum &= \sum_j (\sum_i w_i(x_{ij} - \bar{x_i}) / \hat{x_i} - (y_j - \bar{y}) / \hat{y}) \\ &= N * (\sum_i w_i(\bar{x_i} - \bar{x_i}) / \hat{x_i} - (\bar{y} - \bar{y}) / \hat{y}) \\ &= 0 \end{align} $$

  所以,目標函式的一階導數僅僅依賴於訓練資料集,我們可以簡單的通過分散式的方式來計算,並且對稀疏格式也很友好。

$$ \begin{align} \frac{\partial L}{\partial w_i} &= 1/N ((\sum_j diff_j x_{ij} / \hat{x_i}) \end{align} $$

  我們首先看有效係數$w_i/\hat{x_i}$和offset的實現。

@transient privatelazyvaleffectiveCoefAndOffset= {
    valcoefficientsArray= bcCoefficients.value.toArray.clone() //係數,表示公式中的wvalfeaturesMean= bcFeaturesMean.value
    varsum=0.0vari=0vallen= coefficientsArray.length
    while (i < len) {
      if (featuresStd(i) !=0.0) {
        coefficientsArray(i) /=  featuresStd(i)
        sum += coefficientsArray(i) * featuresMean(i)
      } else {
        coefficientsArray(i) =0.0
      }
      i +=1
    }
    valoffset=if (fitIntercept) labelMean / labelStd - sum 
            
           

相關推薦

分類迴歸()-線性迴歸

線性迴歸 迴歸問題的條件或者說前提是 1) 收集的資料2) 假設的模型,即一個函式,這個函式裡含有未知的引數,通過學習,可以估計出引數。然後利用這個模型去預測/分類新的資料。1   線性迴歸的

機器學習實戰——線性迴歸區域性加權線性迴歸(含python中複製的種情形!)

書籍:《機器學習實戰》中文版 IDE:PyCharm Edu 4.02 環境:Adaconda3  python3.6 注:本程式相比原書中的程式區別,主要區別在於函式驗證和繪圖部分。 一、一般線

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

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

機器學習筆記之——線性迴歸原理以及推導

一元線性迴歸:   對於樣本[(x1,y1),(x2,y2),……(xn,yn)],xi為特徵,yi為標籤。(字幕i代表下標)   假定y與x有:                 

LRSVM、線性迴歸的聯絡與區別

LR和SVM的聯絡:都是監督的分類演算法都是線性分類方法 (不考慮核函式時)都是判別模型 判別模型和生成模型是兩個相對應的模型。 判別模型是直接生成一個表示P(Y|X)P(Y|X)或者Y=f(X)Y=f(X)的判別函式(或預測模型) 生成模型是先計算聯合概率分佈P(Y,X)P

用 Scikit-Learn Pandas 學習線性迴歸

1. 獲取資料,定義問題 沒有資料,當然沒法研究機器學習啦。:) 這裡我們用UCI大學公開的機器學習資料來跑線性迴歸。 資料的介紹在這: http://archive.ics.uci.edu/ml/datasets/Combined+Cycle+Power+Plant 資料的下載地址在這: http://a

根據空間點座標擬合平面直線(線性迴歸svd分解)

根據一組點的座標擬合空間平面,有兩種方法第一種:如果在測量得到的資料中,x,y值都是確認沒有誤差的,而誤差只是出現在z值上,則可以使用線性迴歸的方法,此方法最小二乘的目標是在z方向上de殘差Matlab 程式碼% 隨機生成一組(x,y,z),這些點的座標離一個空間平面比較近x0=1,L1=2;y0=1,L2=

神經網路系列之--線性迴歸方法與原理

系列部落格,原文在筆者所維護的github上:https://aka.ms/beginnerAI, 點選star加星不要吝嗇,星越多筆者越努力 第4章 單入單出的單層神經網路 4.0 單變數線性迴歸問題 4.0.1 提出問題 在網際網路建設初期,各大運營商需要解決的問題就是保證伺服器所在的機房的溫度常年保持

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轉化成概率(

SparkML之迴歸(一)線性迴歸

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

邏輯迴歸線性迴歸、最小二乘、極大似然、梯度下降

轉自 http://www.zhihu.com/question/24900876 機器學習的基本框架大都是模型、目標和演算法! 重要的事情說三遍! 對於一個數據集,首先你要根據資料的特點和目的來選擇合適模型。 就你問的而言,選定的模型是Logistic Regressi

sklearn學習筆記之決策樹分類線性迴歸

decisoin tree: # -*- coding: utf-8 -*- import sklearn from sklearn import tree import matplotlib.pyplot as plt from sklearn.model_selection impor

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

線性迴歸, 邏輯迴歸線性分類

本文系轉載,原文地址:http://blog.csdn.net/weixin_35653315/article/details/54599771  線性迴歸, Linear Regression 邏輯迴歸, Logistic Regression 線性分類器, Linear Classifier 邏輯分

量價線性模型假設-基於Adaboost線性迴歸分類

     前兩篇的文章中我演示瞭如何進行預測,但是預測的準確率一直停留在50%上下,好一點的有60%,IR就不用說了,有多有少,可操作性比較差。今天從另一個角度解釋一下為什麼這麼難預測。先從一個有趣的題目來入手:任意開啟一張圖表,將價格走勢圖刪掉一部分,但是不要刪成交量的走

資料探勘領域中的分類迴歸區別是什麼?

先簡單的說下吧,下面給出實際例子 類和迴歸的區別在於輸出變數的型別。定量輸出稱為迴歸,或者說是連續變數預測;定性輸出稱為分類,或者說是離散變數預測。舉個例子:預測明天的氣溫是多少度,這是一個迴歸任務;預測明天是陰、晴還是雨,就是一個分類任務。  拿支援向量機舉個例子,分類問題

線性迴歸梯度下降講解與程式碼

本文也是根據吳恩達機器學習課程作業的答案。 迴歸:預測值是連續的; 分類:預測值是離散的; 建模誤差:預測值與實際值之間的差距; 目標:選擇模型引數,使得建模誤差的平方和能夠最小,即代價函式最小; 代價函式:選擇平方誤差函式,是解決迴歸問題最常用的手段;代價函式是幫助我們選擇最優

分類迴歸的區別(在CNN中)

兩者的本質相同,分類和迴歸的區別在於輸出變數的型別。 定量——連續——迴歸 定性——離散——分類 用於迴歸:最後一層有m個神經元,每個神經元輸出一個標量,m個神經元的輸出可以看作向量V,現全部連到一個神經元上,則這個神經元的輸出為wx+b,是一個連續值,可以處理迴歸問題 用於分類:現

資料學習(1)·線性迴歸Logistic迴歸

本系列是作者上課時記錄的筆記整理,同時有對應的作業習題,自學的同學參考部落格同步即可。郵箱聯絡[email protected] Preview: 監督學習(第一部分) 線性迴歸 Logistic迴歸 Softmax迴歸