机器学习_线性回归

人工智能

人工智能是一个宽泛概念 , 它只是计算机科学的分支之一 .目前我们认为只要在应用中嵌入一个智能模块 , 我们就可以把他定义为人工智能 .

目前它的实际应用包含机器视觉,指纹识别,人脸识别,视网膜识别,虹膜识别,掌纹识别,专家系统,自动规划,智能搜索,定理证明,博弈,自动程序设计,智能控制,机器人学,语言和图像理解,遗传编程等。
我们将人工智能划分为三个阶段: 弱人工智能, 中度人工智能, 强人工智能 . 强人工智能是指机器能够实现真正意义上的自我学习 , 类似电影终结者 . 例如AlphaGo就属于弱人工智能 , 它只能在围棋这一单一领域中实现人工智能 .

涉及学科:哲学和认知科学,数学,神经生理学,心理学,计算机科学,信息论,控制论,不定性论
(来自百度百科)


机器学习

机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科 . 它又属于人工智能的分支之一 , 机器学习的分支又有深度学习,神经网络等 .
机器学习,意味着我们不再需要编写那些纷繁复杂的特定传统代码,机器运用一套通用的算法 —泛型算法,就能告诉我们关于一组数据的有趣之处。不需要写代码、编程序,只要把数据交给泛型算法,它就能自动建立起数据逻辑。
机器学习的关键是算法 , 我们在开发中并不需要去深入的推导算法, 只需要大概了解 , 算法都是现成的 , 人工智能大部分使用python的原因就在于python已经把一些成熟的算法集成了.
机器学习的常用算法有:线性回归 ,逻辑回归 ,随机森林算法 , SVM ,朴素贝叶斯 ,K 最近邻算法 ,K 均值算法 ,神经网络 ,马尔可夫 ,Adaboost 算法 .

Spark的MLlib库也集成了大部分算法 , 我们只需要调用即可 .


MLlib

spark的MLlib是机器学习库,简化机器学习的工程实践工作,并方便扩展到更大规模。MLlib 由一些通用的学习算法和工具组成,包括分类、回归、聚类、协同过滤、降维等,同时还包括底层的优化原语和高层的管道 API。

MLlib又包括两个package: spark.ml,spark.mllib.
saprk.mllib包含 , 包含基于RDD的原始算法API , 实在spark1.0版本前就包含的.
spark.ml,提供基于DataFrames的高层次的API(写SQL),用来构建机器学习工作流 .
ML Pipeline弥补了MLLib库的不足 , 向用户提供了基于DataFrame的ML工作流式API套件 .


基于大数据的机器学习

传统的机器学习算法,由于技术和单机存储的限制,只能在少量数据上使用。
即以前的统计/机器学习依赖于数据抽样。而实际中样本往往很难做好随机,导致学习模型不是很准确,在测试数据上效果也可能不太好。随着 HDFS 等分布式文件系统出现,存储海量数据成为可能。在全量数据上进行学习也成为可能,这解决了统计随机性的问题。然而,由于 MR 自身的限制,使用 MR 来实现分布式机器学习算法非常耗时和消耗磁盘 IO。这是因为,机器学习算法参数学习的过程基本都是迭代的,如果使用 MR,只能把中间结果存储磁盘,然后在下一次计算的时候重新读取,这对多次迭代的算法而言是性能瓶颈。
在大数据上,进行全量数据的大量迭代计算,这要求 ML 平台具备强大的处理能力。Spark 立足内存计算,适合迭代计算。并且,Spark 提供了一个基于海量数据的 ML 库(MLLib),MLLib 提供了常用机器学习算法的分布式实现。开发者只需要有 Spark 基础,且了解机器学习算法的原理,以及方法相关参数的含义,就可以通过调用相应的 API 来实现机遇海量数据的 ML 过程。其次,Spark-Shell 的即席查询也是一个关键。算法工程师可以边写代码,边运行,边看结果。 Spark 提供的各种高效的工具正使得 ML 过程更加直观便捷。比如,通过sample 函数,可以非常方便的进行抽样。随着发展,Spark 拥有了实时批计算、批处理、算法库、SQL、流计算等模块,可以看成是一个全平台系统。


基本数据类型

MLLib 提供了一序列基本数据类型以支持底层的机器学习算法。主要的数据内心包括:本地向量、标注点(Labeled Point)、本地矩阵、分布式矩阵等。


线性回归

线性回归 , 一般用于预测 , 例如预测股票,预测房价,哈哈.本质是使用历史数据来寻找规律预测未来.
例如y=ax+b . y是唯一的因变量,代表结果 , x是自变量 ,代表特征,可以有多个,好比皮肤颜色,眼睛颜色等特征判断对象是何种人 .
比如我们建立一个多元线性回归模型 , y=ax1+bx2+cx3 , 我们就可以通过大量的数据训练模型,来让a,b,c的值接近于事实,来提高判断和预测的准确度.

说明:
模型公式: y=ax
建模训练模型: 求y=ax的过程, 通过大量数据来训练模型,求出a的值 . 在求a值过程中采用梯度下降发: 先确定a的初始值 , 将训练数据代入损失函数,得到因因变量.对因变量进行求导,导数如果是正数a减小,负数a增大,在不断训练中让a接近于事实.
训练集: 参与求出y=ax公式过程的数据,假设有100万
测试集: 用于检测模型准确度的数据, 数据是训练集中不包含的数据 .
在这里插入图片描述
以上是一条数据格式, 分为因变量和向量两部分 , 向量部分包含了9个特征值.



案例,九个维度的多元线性回归案例

package com.spark

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

/**
  * Created by Administrator on 2019/3/25.
  */
object LinearRegression {
  def main(args: Array[String]): Unit = {
    //创建spark对象
    val conf = new SparkConf().setMaster("local").setAppName("LinearRegressionWithSGD")
    val sc = new SparkContext(conf)

    //打印日志,日志级别
    Logger.getRootLogger.setLevel(Level.WARN)

    //读取数据 , 训练模型
    val data_path1 = "F:\\code02\\sparkLearn\\src\\lpsa.data"
    val data: RDD[String] = sc.textFile(data_path1)
    val examples: RDD[LabeledPoint] = data.map(line => {
      val parts = line.split(",");
      //LabeledPoint:标注点,带标签的本地向量;  Vectors: 向量.
      //Vectors.dense():稠密向量,所谓稠密向量就是指即使特征值为0或null也会被写入;
      //Vectors.sparse(int,Array1,Array2);稀疏向量, int是特征的数量,Array1是通过索引指定了哪些具体的特征,Array2是Array1中指定特征的值 , 其余的特征值均为0 . 稀疏向量可以通过toDense方法转换成稠密向量
      //例如: Vectors.sparse(10000,Array(0,2,5),Array(1.0,3.0,8.0))  ==> 共有10000个特征, 其中索引为0,2,5的向量值为1.0,3.0,8.0 , 其余特征值为0
      LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(" ").map(_.toDouble))) // parts(0): 因变量y值,  Vectors.dense(parts(1).split(" ").map(_.toDouble)):向量
    }).cache()

    // 随机的将数据切成2部分 , 一部分0.8 , 一部分0.2 ,  1是随机种子 => 一部分数据用于训练模型 , 一部分数据用于测试模型
    val train2TestData: Array[RDD[LabeledPoint]] = examples.randomSplit(Array(0.8,0.2),1)

    // 迭代次数
    val numIterations = 200

    // 在每次迭代过程中 , 梯度下降算法的下降步长. 也就是模型预测因变量和训练数据因变量不同时,修正的步长大小.
    val stepSize = 0.1

    //每一次梯度下降后,是不是要计算所有样本的误差值
    val miniBatchFraction = 1.0
    val lrs = new LinearRegressionWithSGD()

    //设置模型是否要有截距,例如:y=ax1+bx2+c , 要不要有c
    lrs.setIntercept(true)
    //设置梯度下降步长
    lrs.optimizer.setStepSize(stepSize)
    //设置迭代次数
    lrs.optimizer.setNumIterations(numIterations)
    //设置批次
    lrs.optimizer.setMiniBatchFraction(miniBatchFraction)

    //开始用80%的数据训练模型 , 返回一个线性回归模型对象
    val model: LinearRegressionModel = lrs.run(train2TestData(0))

    //打印权重 , y=ax1+bx2+cx3 ==>a,b,c就是权重,也就是不同特征或者说自变量对于预测结果的影响程度
    println(model.weights)
    //打印推算的截距
    println(model.intercept)

    /**
      * 2 . 训练完模型之后, 我们开始对模型进行测试
      */

    // 使用剩余20%的数据按照模型进行预测结果 ,   .features是将LabeledPoint自变量转换为具体的特征值
    val prediction: RDD[Double] = model.predict(train2TestData(1).map(_.features))
    // 将LabeledPoint中的y值也就是因变量提取出来 , .label是将LabeledPoint因变量转换为具体值的函数
    // 返回的RDD中的第一个Double值是预测因变量的值, 第二个Double是实际因变量的值
    val predictionAndLabel: RDD[(Double, Double)] = prediction.zip(train2TestData(1).map(_.label))
    // 预测结果我们只取前100条即可
    val print_predict: Array[(Double, Double)] = predictionAndLabel.take(100)

    // 将这100条数据的预测结果和实际结果打印
    println("prediction"+"\t"+"label")
    for(i <- 0 to print_predict.length - 1 ){
      println(print_predict(i)._1+"\t"+print_predict(i)._2)
    }

    /**
      * 计算测试结果的误差
       */
    //使用误差绝对值相加的方式计算总误差
    val loss = predictionAndLabel.map {
      case (p, v) =>
        //误差=预测值减去实际值
        val err = p - v
        //取误差值的绝对值
        Math.abs(err)
    }.reduce(_ + _)    //将所有的误差值相加
    // 平均误差 = 总误差/测试集个数
    val error = loss / train2TestData(1).count()
    // 打印平均误差
    println("平均误差值:" + error)

    /**
      *  将训练后的模型保存
      */
    //保存路径
    val ModelPath = "model"
    model.save(sc,ModelPath)

    // 使用的时候如何加载模型? 使用线性回归模型对象的load方法
    //val sameModel: LinearRegressionModel = LinearRegressionModel.load(sc,ModelPath)

    sc.stop();

  }
}


结果图示:

在这里插入图片描述

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值