我的spark学习之路(三):利用spark做回归分析
spark的機器學習庫(MLlib)下有簡單的回歸分析方法,今天只說最簡單的線性回歸,spark提供有兩個回歸分析庫(mllib和ml),我學習的時候在網上也查了不少資料,有一個奇怪的現象是網上關于spark回歸分析的資料基本全是mllib,關于ml的基本沒見到,根據官方文檔我自己對兩個庫的方法都做了測試,發現mllib做出的結果不是很正確
6,15,7,8,1,21,16,45,45,33,22
11,31,12,15,1,44,34,88,90,67,54
上面是我用來測試的一組數據,用mllib計算得到的系數a=-6.977555728270526E260,而有ml得到的系數為0.44543491975396066,不知道是不是我數據量少的原因,很明顯mllib的結果是有問題的。此外,spark官網對于我們的學習給出這樣的建議
This page documents sections of the MLlib guide for the RDD-based API (the spark.mllib package). Please see the MLlib Main Guide for the DataFrame-based API (the spark.ml package), which is now the primary API for MLlib.
也就是說ml庫是spark目前主要支持的庫,基于這兩個原因,今天在這里主要說說ml庫如何實現回歸分析。
mllib回歸的資料網上有很多,這里有一些不錯的資料僅供參考:
spark官方文檔
http://cos.name/2015/04/spark-beginner-1/
http://blog.selfup.cn/747.html
下面進入正題,說說ml庫的回歸分析,下面是完整代碼
import org.apache.log4j.PropertyConfigurator import org.apache.spark.{SparkConf, SparkContext} import org.apache.spark.ml.regression.LinearRegression import org.apache.spark.rdd.RDD import org.apache.spark.sql.types.{DoubleType, StructField, StructType} import org.apache.spark.sql.{DataFrame, Row, SQLContext, types} import org.apache.spark.mllib.linalg.{VectorUDT, Vectors} import org.apache.spark.mllib.regression.LabeledPointimport scala.io.Source object Regression extends App{val conf=new SparkConf().setAppName("regression")val sc=new SparkContext(conf)val sqc=new SQLContext(sc)val date=Source.fromFile("data/data1.txt").getLines().map{line=>val parts=line.split(",")val a=Vectors.dense(parts(1).split(" ").map(_.toDouble))val b=parts(0).toDoubleLabeledPoint(b,a)//LabeledPoint(parts(0).toDouble,Vectors.dense(parts(1).split(" ").map(_.toDouble)))}//val df=sqc.createDataFrame(d,schema)val df=sqc.createDataFrame(sc.parallelize(date.toSeq))//val training=Source.fromFile("data/data.txt").getLines()val lr=new LinearRegression().setMaxIter(10)//set maximum number of iterations.setRegParam(0.3)//Set the regularization parameter..setElasticNetParam(0.8)//Set the ElasticNet mixing parameter.// Fit the modelval lrModel = lr.fit(df)// Print the coefficients and intercept for linear regressionprintln(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}")// Summarize the model over the training set and print out some metricsval trainingSummary = lrModel.summaryprintln(s"numIterations: ${trainingSummary.totalIterations}")println(s"objectiveHistory: ${trainingSummary.objectiveHistory.toList}")trainingSummary.residuals.show()println(s"RMSE: ${trainingSummary.rootMeanSquaredError}")println(s"r2: ${trainingSummary.r2}") }其實代碼很少,整個過程都很簡單,管方文檔已經寫的很清楚了,唯一的難點就是
val lrModel = lr.fit(df)這是的df是DataFrame格式,官方文檔是利用
val df=spark.read.format("libsvm").load("data/mllib/sample_linear_regression_data.txt")從文件中直接讀取數據,讀取后df就是DataFrame格式,但是實際使用時,我們的數據可能是其它函數計算的結果,因此,如何把格式的數據(比如數組,其它任何結果轉數組都是很容易的)轉為DataFrame就是問題的難點了(對于我這樣的初學都來說,對于熟悉scala的人來說可能都不是個事),翻啟遍了scala的文檔,終于找到一個函數sqc.createDataFrame(rdd: RDD[A]),SQLContext有一個方法createDataFrame可以把RDD 轉為DataFrame,那么接下來的問題就是如何把數組轉為我們需要的RDD格式了,那么我們需要的RDD到底是什么格式呢,調試跟蹤發現是LabeledPoint,它的定義如下:
case class LabeledPoint @Since("1.0.0") (@Since("0.8.0") label: Double,@Since("1.0.0") features: Vector) {override def toString: String = {s"($label,$features)"} }其中label是因變量,它是一個Double數據,而features則是自變量,它是一個Vector,知道了格式構造起來就簡單了,比如上面的代碼,它是這樣構造的:
val date=Source.fromFile("data/data1.txt").getLines().map{line=>val parts=line.split(",")val a=Vectors.dense(parts(1).split(" ").map(_.toDouble))val b=parts(0).toDoubleLabeledPoint(b,a)}這里雖然還是從文件中讀的數據,但和官方文檔的本質區別在于它是把讀得的數據分割成數組然后構造RDD,筆者這里要說的是如何把一個數據組造成DataFrame,如果我們要用到的數據都存在文件中當然不用這么麻煩,直接讀就可以了,但是筆者遇到的問題是,我的數據是其它函數計算得到 ,它是放在一個數組中的,所以才有了這篇博客。如果大家有更好的方法,歡迎探討
轉載于:https://www.cnblogs.com/xtfge/p/9949075.html
總結
以上是生活随笔為你收集整理的我的spark学习之路(三):利用spark做回归分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IC/RFID/NFC 关系与区别
- 下一篇: IO的生命周期