spark aggregate函数使用方法(SparkMllib如何解决回归问题)

1-问题引入

我们都参加过高考,据统计,高考的物理成绩确实与数学成绩有一定关系,但除此之外,还存在很多影响物理成绩的因素,例如:是否喜欢物理,用在物理上的时间等。而当我们主要考虑数学成绩对物理的影响时,就是要考察这两者之间的相关关系。

现实生活中还有很多的相关关系,如

1.商品销售输入与广告支出经费之间的关系,销售输入与广告支出有着密切的关系,但是还与商品质量、居民收入等因素有关。

2.粮食产量与施肥量之间的关系。在一定范围内,施肥量越大,粮食生产就越高。除此之外,粮食产量还受到土壤质量、降雨量等的影响。

3.人体内脂肪的含量与年龄之间的关系。在一定年龄段内,随着年龄的增长,人体内的脂肪含量会增加,但人体内的脂肪含量还和饮食习惯,体育锻炼有关系,可能还与先天

体质有关系。

对于上述两个变量之间的关系,应该说都可以根据经验做出相应的判断,因为“经验当中有规律”,但是,不管你经验多么丰富,如果只凭借经验办事,还是很容易出错。因此在分析两个变量之间的相关关系时,我们需要一些说服力的办法。

在寻找变量之间的相关关系中,统计同样发挥着非常重要的作用。因为上面提到的这种关系,并不像匀速直线运动中时间与速度的关系那样是完全确定的,而是带有不确定性,这就需要通过收集大量的数据(有时候通过调查、或实验),在对数据进行统计分析的基础上,发现其中的规律,才能让他们之间的关系做出判断。

2-脂肪含量和年龄相关吗?

两个变量的线性相关:

如下表中描述了人体的脂肪百分比和年龄的关系图表:

年龄脂肪含量

239.5

2717.8

3921.2

4125.9

4527.5

4926.3

5028.2

5329.6

5430.2

5631.4

5730.8

5833.5

6035.2

6134.6

问题:根据上述数据,人体的脂肪含量与年龄之间有怎么样的关系呢?

对问题的描述:

一般地,对于某个人来说,他的体内脂肪不一定随年龄增长而增加或减少,但是如果把很多个体放在一起,这时就可能表现出一定的规律性,各年龄对应的脂肪数据是这个年龄人群脂肪含量的样本平均值。观察上述表数据,从大体上看,随着年龄的增加,人体中脂肪的百分比也在增加。为了确定这一细节,我们需要进行数据的分析,与以前一样,我们可以做统计图、表,通过做统计图、表,可以使我们对两个变量之间的关系有一个直观的印象和判断。

下面我们做一个散点图,如图,假设人的年龄影响体内脂肪含量,于是,按照习惯,以x轴表示年龄,y轴表示脂肪含量,得到下图:

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(1)

这些散分布的位置也是值得注意的,他们散布在从左上角到右下角的区域。对于两个变量的这种相关关系,我们称为正相关。还有一些变量,例如汽车的重量和汽车每消耗1L汽油所行驶的平均路程,是负相关,也就是汽车越重,每消耗1L汽油所行驶的平均路程就越短,这时的点如果绘制在画布上 将会从左上角到右下角的区域内。

接下来,需要进一步考虑的问题是,当人的年龄增加时,体内脂肪含量到底是以什么方式增加的呢?

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(2)

从散点图可以看出,这些点大致分布在通过散点图中心的一条直线附近,如果散点图中的点分布从整体上看大致是在一条直线附近,我们就称这两个变量之间具有线性相关关系,这条直线叫做回归直线(regression line)。

如果能求出这条回归直线的方程,那么我们就可以清晰的了解年龄与体内脂肪含量的相关性,就像平均值可以作为一个变量的数据的代表一样,这条直线可以作为两个变量具有线性相关性的代表。

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(3)

当你拿到这样一个任务的时候,你可能会采用测量的做法,先画出一条直线,测量各点与它的距离,然后移动直线,到达一个使得距离的和最小的位置,测量出此时的斜率和截距,既可以得到回归方程了。

也可能会采用平均方法,也就是在散点图中多取几组点,确定出几条直线的方程,再分别求出各条直线的斜率、截距的平均数,将这两个平均数作为回归方程的斜率和截距。

3-问题的求解

上面方法虽然有一定道理,但是总让人感觉可靠性不强。实际上,求回归方程的关键是如何用数学的方法来刻画“从整体上,各点与此直线的距离最小”。

假设我们已经得到两个具有线性相关关系的变量的一组数据

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(4)

且所求的回归方程设为

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(5)

它与实际数据的偏差是

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(6)

在坐标轴中表示如下

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(7)

这样,用这n个偏差的和来刻画“各点与此直线的整体偏差”比较合适的,由于

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(8)

可正可负,为了避免互相抵消,可以考虑用

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(9)

代替,但由于它含有绝对这,运算不方便,所以改用

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(10)

即:

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(11)

这样,问题就归结为:当a和b取什么值时Q最小,即总体偏差最小,经过数学上的最小值运算,a和b的值由下面式子给出

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(12)

其中b是回归方程的斜率,a是截距。

总结:这种通过求解Q关系式的最小值而得到回归直线的方法,即求回归直线,使得样本数据的点到它的距离的平方和最小的方法,叫做最小二乘法(Least square)。

4-Execl绘制相关图形

Execl画回归拟合直线如下方法:

(1)准备数据,首先绘制散点图

(2)在散点图基础上点”趋势预测”即可看到拟合的直线。

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(13)

(3)在图示区域显示拟合直线的方程

spark aggregate函数使用方法(SparkMllib如何解决回归问题)(14)

5-SparkMl代码实战

这里采用基于DataFrame的SparkMl完成实验,并与Execl的结果进行对比分析:

代码部分:

import org.apache.spark.ml.linalg.Vectors import org.apache.spark.ml.regression.{LinearRegression, LinearRegressionModel} import org.apache.spark.sql.SparkSession object testFat { def main(args: Array[String]): Unit = { val spark: SparkSession = SparkSession.builder().master("local[*]").appName("traintestSplitTest").getOrCreate() spark.sparkContext.setLogLevel("WARN") val data = spark.createDataFrame(Seq( (9.5, Vectors.dense(23)), (17.8, Vectors.dense(27)), (21.2, Vectors.dense(39)), (25.9, Vectors.dense(41)), (27.5, Vectors.dense(45)), (26.3, Vectors.dense(49)), (28.2, Vectors.dense(50)), (29.6, Vectors.dense(53)), (30.2, Vectors.dense(54)), (31.4, Vectors.dense(56)), (30.8, Vectors.dense(57)), (33.5, Vectors.dense(58)), (35.2, Vectors.dense(60)), (34.6, Vectors.dense(61)) )).toDF("label", "features") //1-data split val Array(train, test): Array[Dataset[Row]] = data.randomSplit(Array(0.9, 0.1), seed = 120L) //2-training model val lr: LinearRegression = new LinearRegression() val lrModel: LinearRegressionModel = lr.fit(data) //3- Print the coefficients and intercept for linear regression println(s"Coefficients: ${lrModel.coefficients} Intercept: ${lrModel.intercept}") // 4-Summarize the model over the training set and print out some metrics 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}") // Coefficients: [0.5764772505370067] Intercept: -0.44779925795753567 // numIterations: 1 // objectiveHistory: [0.0] // --------------------------------------------- // | residuals| // -------------------------------------------- // | -3.311177504393619| // | 2.682913493458356| // ............................. // RMSE: 1.629890205389517 // r2: 0.9423379190667397 } }

这里得到的R2是回归问题的考量标准,越接近于1效果越好,这里r2为0.94效果能够达到预期,因此能够证明随着年龄的增长脂肪含量会随着增长,在回归问题中此类问题常称之为一元线性回归或简单线性回归,当然可以考虑更多的变量因素存在对脂肪含量的影响,这里不再一一列举。

6-总结

通过对脂肪含量和年龄的关系问题猜想、定义、Execl绘图分析、SparkMl建模分析得到我们猜测和数学上可证明的结论,同学们可以借助SparkMl技术解决更多的回归问题。加油!

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页