sparkmllib学习之线性回归

SparkDr SparkDr     2022-09-01     672

关键词:

SparkMLlib学习之线性回归

(一)回归的概念

  1,回归与分类的区别

   分类模型处理表示类别的离散变量,而回归模型则处理可以取任意实数的目标变量。但是二者基本的原则类似,都是通过确定一个模型,将输入特征映射到预测的输出。回归模型和分类模型都是监督学习的一种形式。

  2.回归分类

   线性回归模型:本质上和对应的线性分类模型一样,唯一的区别是线性回归使用的损失函数、相关连接函数和决策函数不同。MLlib提供了标准的最小二乘回归模型在MLlib中,标准的最小二乘回归不使用正则化。但是应用到错误预测值的损失函数会将错误做平方,从而放大损失。这也意味着最小平方回归对数据中的异常点和过拟合非常敏感。因此对于分类器,我们通常在实际中必须应用一定程度的正则化。正则化分为:应用L2正则化时通常称为岭回归(ridge regression),应用L1正则化是称为LASSO(Least Absolute Shrinkage and Selection Operator)。

   决策树模型:决策树同样可以通过改变不纯度的度量方法用于回归分析

(二)SparkMLlib线性回归的应用

  1,数据集的选择

    http://archive.ics.uci.edu/ml/datasets/Bike+Sharing+Dataset。

  2.数据集的描述

    此数据是根据一系列的特征预测每小时自行车租车次数,特征类型如下:

  3,数据处理及构建模型

    数据集中共有17 379个小时的记录。接下来的实验,我们会忽略记录中的 instant和 dteday 。忽略两个记录次数的变量 casual 和 registered ,只保留 cnt ( casual 和registered 的和)。最后就剩下12个变量,其中前8个是类型变量,后4个是归一化后的实数变量。对其中8个类型变量,我们使用之前提到的二元编码,剩下4个实数变量不做处理。另外一种二元变量化方法:http://blog.csdn.net/u010824591/article/details/50374904

import org.apache.log4j.{Level, Logger}
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.{LabeledPoint, LinearRegressionWithSGD}
import org.apache.spark.mllib.tree.DecisionTree
import org.apache.spark.rdd.RDD
import org.apache.spark.{SparkConf, SparkContext}

/**
  * Created by Damon on 17-5-22.
  */
object Regression {
  def main(args: Array[String]): Unit = {
    Logger.getLogger("org.apache.spark").setLevel(Level.WARN)
    Logger.getLogger("org.eclipse.jetty.server").setLevel(Level.OFF)
    val conf =new SparkConf().setAppName("regression").setMaster("local[4]")
    val sc =new SparkContext(conf)
    //文件名
    val file_bike="hour_nohead.csv"
    //调用二元向量化方法
    val labeled_file=labeledFile(file_bike,sc)
    /*/*对目标值取对数*/
    val labeled_file1=labeled_file.map(point => LabeledPoint(math.log(point.label),point.features))
    */
    //构建线性回归模型,注该方法在:spark2.1.0已经抛弃了。。。。
    val model_liner=LinearRegressionWithSGD.train(labeled_file,10,0.1)
    //val categoricalFeaturesInfo = Map[Int,Int]()
    //val model_DT=DecisionTree.trainRegressor(labeled_file,categoricalFeaturesInfo,"variance",5,32)
    val predict_vs_train=labeled_file.map{
      point => (model_liner.predict(point.features),point.label)
//对目标取对数后的,预测方法
     /* point => (math.exp(model_liner.predict(point.features)),math.exp(point.label))*/
    }
    predict_vs_train.take(5).foreach(println(_))
   /*
(135.94648455498356,16.0)
(134.38058174607252,40.0)
(134.1840793861374,32.0)
(133.88699144084515,13.0)
(133.77899037657548,1.0)
   */
  def labeledFile(originFile:String,sc:SparkContext):RDD[LabeledPoint]={
    val file_load=sc.textFile(originFile)
    val file_split=file_load.map(_.split(","))
    /*构建映射类函数的方法:mapping*/
    def mapping(rdd:RDD[Array[String]],index:Int)=
      rdd.map(x => x(index)).distinct.zipWithIndex().collect.toMap
    /*存储每列映射方法mapping的maps集合*/
    var maps:Map[Int,Map[String,Long]] = Map()
    /* 生成maps*/
    for(i <- 2 until 10)
      maps += (i -> mapping(file_split,i))
    /*max_size表示每列的特征之和*/
    val max_size=maps.map(x =>x._2.size).sum
    val file_label=file_split.map{
      x =>
        var num:Int=0
        var size:Int=0
        /*构建长度为max_size+4的特征数组,初始值全为0*/
        val arrayOfDim=Array.ofDim[Double](max_size+4)
        for(j<-2 until 10) {
          num = maps(j)(x(j)).toInt
          if(j==2) size=0 else size += maps(j-1).size
          /*为特征赋值*/
          arrayOfDim(size+num)=1.0
        }
        /*添加后面4列归一化的特征*/
        for(j<-10 until 14)
        arrayOfDim(max_size+(j-10))=x(j).toDouble
        /*生成LabeledPoint类型*/
        LabeledPoint(x(14).toDouble+x(15).toDouble,Vectors.dense(arrayOfDim))
    }
    file_label
  }
}

  4,模型性能评价

    (1) MSE是均方误差,是用作最小二乘回归的损失函数,表示所有样本预测值和实际值平方差的平均值。公式如下: 

                                 

    (2)RMSE是MSE的平方根    

    (3)平均绝对误差(MAE):预测值与实际值的绝对值差的平均值 

            

    (4) 均方根对数误差(RMSLE):预测值和目标值进行对数变换后的RMSE. 

代码如下:

/*MSE是均方误差*/
    val mse=predict_vs_train.map(x => math.pow(x._1-x._2,2)).mean()
   /* 平均绝对误差(MAE)*/
    val mae=predict_vs_train.map(x => math.abs(x._1-x._2)).mean()
    /*均方根对数误差(RMSLE)*/
    val rmsle=math.sqrt(predict_vs_train.map(x => math.pow(math.log(x._1+1)-math.log(x._2+1),2)).mean())
    println(s"mse is $mse and mae is $mae and rmsle is $rmsle")
/*
mse is 29897.34020145107 and mae is 130.53255991178477 and rmsle is 1.4803867063174845
*/

(三) 改进模型性能和参数调优

  1,变换目标变量  

   许多机器学习模型都会假设输入数据和目标变量的分布,比如线性模型的假设为正态分布,这里就将目标值取对数(还可以去sqrt处理)(将上文注释去掉)实现正态分布,结果如为:mse is 47024.572159822106 and mae is 149.28861881845546 and rmsle is 1.4525632598540426

  将上述结果和原始数据训练的模型性能比较,可以看到我们提升了RMSLE的性能,但是却没有提升MSE和MAE的性能。

  2.交叉验证

   1,创建训练集和测试集来评估参数

   2,调节参数来判断对线性模型的影响

迭代次数及步长的影响:

//划分训练集和测试集
    val labeled_orign = labeled_file.randomSplit(Array(0.8, 0.2), 11L)
    val train_file = labeled_orign(0)
    val test_file = labeled_orign(1)
    /*调节迭代次数*/
    val Iter_Results = Seq(1, 5, 10, 20, 50, 100).map { param =>
      val model = LinearRegressionWithSGD.train(test_file, param, 0.01)
      val scoreAndLabels = test_file.map { point =>
        (model.predict(point.features), point.label)
      }
      val rmsle = math.sqrt(scoreAndLabels.map(x => math.pow(math.log(x._1) - math.log(x._2), 2)).mean)
      (s"$param lambda", rmsle)
    }
    /*迭代次数的结果输出*/
    Iter_Results.foreach { case (param, rmsl) => println(f"$param, rmsle = ${rmsl}")}
    /*调节步长数的大小*/
    val Step_Results = Seq(0.01, 0.025, 0.05, 0.1, 1.0).map { param =>
        val model = LinearRegressionWithSGD.train(test_file, 20, param)
        val scoreAndLabels = test_file.map { point =>
          (model.predict(point.features), point.label)
        }
        val rmsle = math.sqrt(scoreAndLabels.map(x => math.pow(math.log(x._1) - math.log(x._2), 2)).mean)
        (s"$param lambda", rmsle)
      }
    /*步长的结果输出*/
    Step_Results.foreach { case (param, rmsl) => println(f"$param, rmsle = ${rmsl}")}
/*results
1 lambda, rmsle = 2.9033629718241167
5 lambda, rmsle = 2.0102924520366092
10 lambda, rmsle = 1.7548482896314488
20 lambda, rmsle = 1.5785106813100764
50 lambda, rmsle = 1.461748782192306
100 lambda, rmsle = 1.4462810196387068
步长
0.01 lambda, rmsle = 1.5785106813100764
0.025 lambda, rmsle = 1.4478358250917658
0.05 lambda, rmsle = 1.5152549319928832
0.1 lambda, rmsle = 1.5687431700715837
1.0 lambda, rmsle = NaN
*/

  结果表明,随着迭代次数的增加,误差确实有所下降(即性能提高),并且下降速率和预期一样越来越小。可以看出为什么不使用默认步长来训练线性模型。其中默认步长为1.0,得到的RMSLE结果为 nan 。这说明SGD模型收敛到了最差的局部最优解。这种情况在步长较大的时候容易出现,原因是算法收敛太快而不能得到最优解。另外,小步长与相对较小的迭代次数(比如上面的10次)对应的训练模型性能一般较差。而较小的步长与较大的迭代次数下通常可以收敛得到较好的解。通常来讲,步长和迭代次数的设定需要权衡。较小的步长意味着收敛速度慢,需要较大的迭代次数。但是较大的迭代次数更加耗时,特别是在大数据集上。

  还可以调节L1正则化和L2正则化参数。 MLlib目前支持两种正则化方法L1和L2。 L2正则化假设模型参数服从高斯分布,L2正则化函数比L1更光滑,所以更容易计算;L1假设模型参数服从拉普拉斯分布,L1正则化具备产生稀疏解的功能,从而具备Feature Selection的能力。(由于spark 2.1.0中的线性回归方法已经忽略了,就没去验证L1和L2对模型的影响)

 

 

 

    

机器学习之线性回归以及logistic回归

1、线性回归回归的目的是预测数值型数据的目标值。目标值的计算是通过一个线性方程得到的,这个方程称为回归方程,各未知量(特征)前的系数为回归系数,求这些系数的过程就是回归。对于普通线性回归使用的损失函数... 查看详情

机器学习之一元线性回归模型

一元线性回归模型样本数量m           输入变量x              输出变量y    &nb 查看详情

机器学习之线性回归(代码片段)

文章目录评价方法一元线性回归np.polyfit求解带入公式求解化简公式求解lstsq求解多元线性回归代码实现一元多项式回归代码实现参考评价方法回归问题有很多的评价方法。这里主要想写一下R^2的计算方法。需要计算R^2需要先弄清... 查看详情

机器学习之线性回归---logistic回归---softmax回归

1摘要     本报告是在学习斯坦福大学机器学习课程前四节加上配套的讲义后的总结与认识。前四节主要讲述了回归问题,回归属于有监督学习中的一种方法。该方法的核心思想是从连续型统计数据中得到数学... 查看详情

javascript机器学习之线性回归

译者按:AI时代,不会机器学习的JavaScript开发者不是好的前端工程师。原文:MachineLearningwithJavaScript:Part1译者:Fundebug为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。使用JavaScript做机器学... 查看详情

机器学习之线性回归

1.机器学习算法**监督学习:**已经知道类别的样本,通过一定的模型或者是特定的算法,可以预测出某种特定的结果,例如预测房价,最终可以预测出房价是什么,或者是预测肿瘤疾病,判断肿瘤是良... 查看详情

机器学习之线性回归

1.机器学习算法**监督学习:**已经知道类别的样本,通过一定的模型或者是特定的算法,可以预测出某种特定的结果,例如预测房价,最终可以预测出房价是什么,或者是预测肿瘤疾病,判断肿瘤是良... 查看详情

深度学习之线性回归+基础优化(代码片段)

线性回归可以看作一个最简单的神经网络模型损失函数在我们开始考虑如何用模型拟合(fit)数据之前,我们需要确定一个拟合程度的度量。损失函数(lossfunction)能够量化目标的实际值与预测值之间的差距... 查看详情

机器学习之线性回归(代码片段)

以kaggle上的HousePrices:AdvancedRegressionTechniques为例讲述线性回归fromsklearn.linear_modelimportLinearRegression,RidgeCV,LassoCV,ElasticNetCV1、回归模型(1)一般线性回归:LinearRegressionwithoutregularizationfromsklearn.linear_modelimportLinearRegressionlr=LinearRegression... 查看详情

20171028机器学习之线性回归过拟合问题的解决方案

在函数中加入一个正则项: 三种方式:一、Ridge回归(岭回归):  优点:具有较高的准确性、鲁棒性以及稳定性  缺点:求解速度慢二、Lasso回归:  优点:求解速度快(原理降维计算,把数据维度中存在的噪音和... 查看详情

机器学习之逻辑回归

1.用自己的话描述一下,什么是逻辑回归,与线性回归对比,有什么不同?逻辑回归又称逻辑回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域;与线性回归相比大致有两大不同:①... 查看详情

机器学习之线性回归(代码片段)

目录预测数值型数据:回归用线性回归找到最佳拟合直线程序8-1标准回归函数和数据导入函数程序8-2基于程序8-1绘图图片8-1ex0的数据集和它的最佳拟合直线局部加权线性回归图片8-2参数k与权重的关系程序8-3局部加权线性回归函... 查看详情

机器学习之线性回归概念总结速记

目录线性回归简介线性回归应用场景线性回归定义线性回归模型线性回归初步使用步骤分析代码过程线性回归的损失和优化损失函数优化算法正规方程梯度下降梯度的概念梯度下降和正规方程的对比算法选择依据欠拟合和过拟合... 查看详情

机器学习之线性回归算法

1.本节重点知识点用自己的话总结出来,可以配上图片,以及说明该知识点的重要性(1)、回归算法总结:  回归是统计学中最有力的工具之一。机器习监督学习算法分为分类算法和回归算法两种,其实就是根据类别标签分布... 查看详情

机器学习之linearregression线性回归(代码片段)

一、预测先来看看这样一个场景:假如你手头有一套房子要出售,你咨询了房产中介。中介跟你要了一系列的数据,例如房子面积、位置、楼层、年限等,然后进行一系列计算后,给出了建议的定价。房产中介是如何帮你定价的... 查看详情

机器学习之线性回归岭回归lasso回归(代码片段)

1、回归算法分类算法的目标值是标称型数据,而回归的目标变量是连续型数据,主要包括线性回归,岭回归,lasso回归,前向逐步回归。2、线性回归线性回归主要用于处理线性数据,结果易于理解,计算复杂度不高,但是处理... 查看详情

菜鸟之路——机器学习之非线性回归个人理解及python实现(代码片段)

关键词:梯度下降:就是让数据顺着梯度最大的方向,也就是函数导数最大的放下下降,使其快速的接近结果。Cost函数等公式太长,不在这打了。网上多得是。这个非线性回归说白了就是缩小版的神经网络。python实现:1importnump... 查看详情

sparkmllib聚类学习之kmeans聚类

SparkMLlib聚类学习之KMeans聚类(一),KMeans聚类 k均值算法的计算过程非常直观:     1、从D中随机取k个元素,作为k个簇的各自的中心。     2、分别计算剩下的元素到k个簇中心的相异度,... 查看详情