人工智能
人工智能是一个宽泛概念 , 它只是计算机科学的分支之一 .目前我们认为只要在应用中嵌入一个智能模块 , 我们就可以把他定义为人工智能 .
目前它的实际应用包含机器视觉,指纹识别,人脸识别,视网膜识别,虹膜识别,掌纹识别,专家系统,自动规划,智能搜索,定理证明,博弈,自动程序设计,智能控制,机器人学,语言和图像理解,遗传编程等。
我们将人工智能划分为三个阶段: 弱人工智能, 中度人工智能, 强人工智能 . 强人工智能是指机器能够实现真正意义上的自我学习 , 类似电影终结者 . 例如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();
}
}
结果图示: