梯度下降法
梯度下降法通过数值解(多次迭代),最后收敛于真实解。很多模型底层都是通过梯度下降法来求解系数。比如:
逻辑回归模型
BP神经网络做误差反馈
所以梯度下降法的应用比二乘法更广泛(因为二乘法只使用模型方程存在解析解的情况,而在生成环境的下的模型方程较为复杂,很多都是不存在解析解的)
梯度的概念:
梯度从几何意义上,就是函数变化最快的方向,
如果沿着梯度方向,可以最快速度找到函数的极大值。->梯度上升法如果沿着梯度负方向,可以最快速度找到函数的极小值。->梯度下降法
我们常用的是梯度下降法,原因:
利用梯度下降法,找出损失函数的极小值(RSS),得到min RSS对应的系数
上述过程,有两个关键要素:
①步长,
②损失函数的梯度
针对上式的系数更新表达式,多次迭代
1次迭代RSS=100
2次迭代 RSS=65
3次迭代―RSS=35
…
99次迭代RSS=10.99
100次迭代 RSS=10.989
会发现迭代再多次,RSS几乎变化,此时可以算法收敛了,收敛于函数的极小值点,从而得到极小值点对应的最优解。
练习
案例数据
1,0 1
2,0 2
3,0 3
5,1 4
7,6 1
9,4 5
6,3 3
package cn.com.sgd
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.regression.LinearRegressionWithSGD
//梯度下降法
/*
*
1,0 1
2,0 2
3,0 3
5,1 4
7,6 1
9,4 5
6,3 3
第一列是Y,第二列和第三列是X1,X2。目的是建立Y和X1,X2的多元线性回归模型
Y=θ1X1+θ2X2
//[0.9900358102235034,1.0029315901669955]
Y=0.99X1+1.002X2
*
底层是通过梯度下降法来解出θ1和θ2
*/
object Driver {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("sgd")
val sc=new SparkContext(conf)
val data=sc.textFile("D://data/ml/testSGD.txt")
//第一步:转换-RDD[string :line]->RDD[LabeledPoint]
val pareData=data.map { line =>
val info=line.split(",")
val Y=info(0).toDouble
val X1=info(1).split(" ")(0).toDouble
val X2=info(1).split(" ")(1).toDouble
LabeledPoint(Y,Vectors.dense(X1, X2))
}
//建模
//①参:数据集②参:最大的迭代次数③参:步长
//1.迭代次数,如果过少,可能会导致还未收敛就结束了,误差很大。
//如果过多,会浪费cpu,导致计算代价过大
//2.步长,如果过小,会导致跌代很多次仍不收敛
//如果过大,会导致围绕真实解来回震荡而不收敛
//综上,建议∶迭代次数多一点,步长小一点(经验:0.5~0.5)
val model=LinearRegressionWithSGD.train(pareData, 25,0.05)
//提取模型的自变量系数
val coef=model.weights
// println(coef)
//第三步,通过模型实现预测
//回代样本集预测。要求传入的数据类型RDD[vector(x1,x2,...)]
val predict=model.predict(pareData.map { x => x.features })
predict.foreach { println }
}
}
展示
1.0029315901669955
2.005863180333991
3.0087947705009865
5.001762170891485
6.943146451508016
8.974801191728991
5.978902201171497
梯度下降法的补充
1.如果损失函数是非凸的,用梯度下降法得到的解可能是局部最优解,而不是全局最优解。因为算法中θ的初始位置是随机选择的
如果要得到全局最优解,多做几次,从中选择RSS最小的那一次。
2.如果损失函数是凸函数,用梯度下降法得到的解一定是全局最优解
3.梯度下降法的种类有三种:
①批量梯度下降法(BGD)B->Batch
每次更新系数时,是所有的样本都需要参与计算
优点:需要很少的迭代次数就可以收敛
缺点:如果样本量很大,迭代一次时间很长。所以生产环境下,不用这种,因为数据量都是很大的
②随机梯度下降法(SGD)S->随机
每次更新系数时,是从所有的样本中随机选取一个样本参与更新
优点:每次更新系数用时很短
缺点:需要更多的迭代次数才能收敛所以目前生产环境都是用这种来解技术
③小批量梯度下降法(MBDG)
这种算法相当于综合了①和②,选取一小批数据参与样本更新
=======================================
逻辑回归模型
逻辑回归模型可以对离散型数据响应,所以这种模型应用于二分类问越。
而之前学习线性回归模型,是对连续型数据响应,不能对离散型数据响应。
基本概念:
①连续型数据,给定一区间,可以去区间内任意的一实数值
[1,5]->1 2 3 4 5 1.1 2. 2 3.0
②离散型数据,给定一区间,只能取区间内有限个的实数值
[1,5]->只能取区间内的整数 1 2 3 4 5
生活中,哪些是离散型的:
性别男(0)或女(1)
疾病的阴性(1)或阳性(0)
人的年龄0~120
生活中,哪些数据是连续的:薪资收入
当前我们的目标是针对下面的数据,建模
================================
Sigmoid函数
此函数的作用:可以将任意的一实数值,映射到0或1。即把任意的一连续型数据离散化成0或1
上图中,其中e是一个超越数,约等于2.718
比如去银行存钱,本金1,年利率是100%,问存1年,一年后的本息和1(1+1)=2
一年发两次利息,一年之后的本息和1(1+1/2)^2=2.25
如果银行每天都发利息,问一年之后是否会成百万富翁1(1+1/365)^365~2.718
e=(1+1/n) n ,当n趋近于无穷时,得到的值就是超越数e
一般的,就可以把看做一个常数(2.718)
拟牛顿法图解
案例模板数据
17 1 1 1
44 0 0 1
48 1 0 1
55 0 0 1
75 1 1 1
35 0 1 0
42 1 1 0
57 0 0 0
28 0 1 0
20 0 1 0
38 1 0 0
45 0 1 0
47 1 1 0
52 0 0 0
55 0 1 0
68 1 0 1
18 1 0 1
68 0 0 1
48 1 1 1
17 0 0 1
测试数据
18 0 0
35 1 1
40 0 1
22 1 0
代码
package cn.com.logistic
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.mllib.regression.LabeledPoint
import org.apache.spark.mllib.linalg.Vectors
import org.apache.spark.mllib.classification.LogisticRegressionWithSGD
import org.apache.spark.mllib.classification.LogisticRegressionWithLBFGS
/*
* 建立逻辑回归模型,应用场景:用于二分类问题
* 因变量Y(离散的,取值情况有两种,1 or o)
* */
object Driver {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("logistic")
val sc=new SparkContext(conf)
val data=sc.textFile("D://data/ml/logistic.txt")
//--第一步,为了满足建模需要,需要做数据转换
// --RDD[String]->RDD[LabeledPoint]
val parseData=data.map { line =>
val info=line.split(" ")
val Y=info.last.toDouble
//获取由自变量组成的数组
val featuresArray=info.take(3).map { num => num.toDouble }
LabeledPoint(Y,Vectors.dense(featuresArray))
}
// parseData.foreach { println}
//第二步,建立逻辑回归模型,底层用的是随机梯度下降法来结解出系数
//方式1---不好使
// val model=LogisticRegressionWithSGD.train(parseData, 50 ,1)
//方式2
//建立逻辑回归模型,底层用的是拟牛顿法来解出系数
//这种算法属于通过数值解逼近真实解(迭代算法),属于快速迭代法,并且不需要指定步长
//优点:迭代次数少,而且不需要指定步长
//缺点:每迭代一次,计算量较大。所以如果数据量较大,还是建议使用SGDl
val model=new LogisticRegressionWithLBFGS().run(parseData)
//提取模型系数
val coef=model.weights
// println(coef)
//第三步,回代样本,做预测(分类)
val predict=model.predict(parseData.map{x=> x.features})
// predict.foreach{println}
val testData=sc.textFile("D://data/ml/testLogistic.txt")
val testParseData=testData.map { line =>
val info=line.split(" ")
//获取由自变量组成的数组
val testFeaturesArray=info.take(3).map { num => num.toDouble }
// LabeledPoint(0,Vectors.dense(testFeaturesArray))
Vectors.dense(testFeaturesArray)
}
val testPredict=model.predict(testParseData)
testPredict.foreach{println}
}
}
展示
1.0
0.0
0.0
1.0
=============================================
机器学习中模型及算法的梳理
建立模型后,需要求解出系数,可以用一些算法来解决,比如:
1.最小二乘法
2.随机梯度下降法
3.批量梯度下降法
4.牛顿法
5.ID3算法
6.C4.5
7.模拟退火算法
8.贝叶斯算法
======================================
推荐系统模型
实现推荐系统模型,内在思想是协同过滤的思想->利用大量已有的用户的偏好数据,来预测用户对其未接触过的物品的喜好程度。所以协同过滤思想实际上就是计算相似度。
计算相似度的常用手段(相关系数,向量之间的夹角余弦(主流),欧式距离)
推荐系统的推荐方式有两种:
1.基于用户的推荐
上图描述的就是基于用户推荐的思想,核心是计算出用户和用户之间的相似度,然后完成推荐
如果是基于物品的推荐,核心是计算物品和物品之间的其他类似的电影相似度,然后完成推荐。
比如现在的京东,天猫等,大多数是基于物品的推荐,即根据用户买过或浏览过的商品实现推荐
生产环境下,建立推荐系统模型,首先需要有:用户-物品的偏好矩阵数据
比如下表:
但是生产环境下的用户偏好矩阵往往是稀疏的,比如下表
所以如果直接对这个稀疏矩阵建模,结果肯定是不准确的,针对空缺数据,不能简单的置为0。所以我们需要通过某种算法将空缺数据预测出来,然后再计算相似度
我们可以通过矩阵分解法,设定用户的偏好矩阵:UI
然后需要找到一个低阶的K(K要小于U或I),比如上表中U=5,I=5,所以在定义K时,K要<5
在这里,我们令K=3,下一步则是将UI分解成两个因子矩阵
===========================================
ALS算法
交替最小二乘法
ALS算法的实现思想:
迭代式(多次)求解一系列最小二乘回归,每次迭代时,固定用户因子矩阵或物品因子矩阵其中的一个,然后用评级矩阵和固定的矩阵更新另一矩阵。这里固定指的是随机化生成数据。因为最初的矩阵分解成两个因子矩阵,数据是空的,所以需要通过随机化的方法来生成
每一次迭代,都会计算当前这一次的已知打分的重构误差,经过多次迭代,误差越来越小,当误差不怎么变化时,则算法收敛。比如:
1次跌代﹒已知打分的重构误差=100
2次跌代﹑己知打分的重构误差=65
99次跌代﹑已知打分的重构误差=12
100次跌代﹒已知打分的重构误差=11.998
此时算法收敛,收敛时对应的解就是我们要找到的最优解
这种随机算法靠谱吗?
比如玩猜数字游戏,比如我心里想的数字是75
1次90
2次40
经过多次迭代,最后肯定会收敛于75的真实解
案例:
数据
1 11 2
1 12 3
1 13 1
1 14 0
1 15 1
2 11 1
2 12 2
2 13 2
2 14 1
2 15 4
3 11 2
3 12 3
3 14 0
3 15 1
4 11 1
4 12 2
4 14 1
4 15 4
5 11 1
5 12 2
5 13 2
5 14 1
代码
package cn.com.als
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import org.apache.spark.mllib.recommendation.Rating
import org.apache.spark.mllib.recommendation.ALS
object Driver {
def main(args: Array[String]): Unit = {
val conf = new SparkConf().setMaster("local").setAppName("alx")
val sc=new SparkContext(conf)
val data=sc.textFile("D://data/ml/alx.txt")
//第一步,为了满足建立推荐系统模型的要求,需要做数据转换
//RDD[String]->RDD[Rating(userid,itemId, score)]
val ratings=data.map { line =>
val info=line.split(" ")
val userId=info(0).toInt//用户id
val itemId=info(1).toInt//商品id
val score=info(2).toDouble//分数
Rating(userId,itemId,score)
}
//第二步,建立推荐系统模型,底层是通过ALS算法来求解系数
//-①参∶数据集②参∶隐藏因子数(K),低阶,小于u和i ③参∶最大的迭代次数
//④参:λ 正则化参数,防止模型过拟合,可以不加。如果加,也是一个很小的值
val model=ALS.train(ratings, 3, 10, 0.01)
//下面表示为2号用户推荐一个商品
val r1=model.recommendProducts(2, 1)
//下面表示为1号用户推荐3个商品
val r2=model.recommendProducts(1, 3)
//下面表示为11号商品推荐两个用户
val r3=model.recommendUsers(11, 2)
r3.foreach{println}
//表面表示预测2号用户对13号商品的打分
val r4=model.predict(2, 13)
println(r4)
}
}
详细说明
====================================
求解机器学习算法的模型参数,即无约束优化问题时,梯度下降法是最常采用的方法之一,另一种常用的方法是最小二乘法。这里对梯度下降法做简要介绍。
最小二乘法法适用于模型方程存在解析解的情况。如果说一个函数不存在解析解,是不能用最小二乘法的,此时,只能通过数值解(迭代式的)去逼近真实解。
上面的方程就不存在解析解,每个系数无法用变量表达式表达。梯度下降法要比最小二乘法的适用性更强
什么是梯度
概述
Sigmoid函数起初是一个在生物学中常见的S型函数,也称为S型生长曲线。后来由于其单增以及反函数单增等性质,Sigmoid函数常被用作神经网络的阈值函数,将变量映射到0,1之间。
超越数e
概念介绍
e是一个无限不循环的数字,其值约等于2718281828.….,它是一个超越数.
以e为底的对数称为自然对数(Natural logarithm ),数学中使用自然( Natural )这个词的还有自然数( Natural number )。这里的“自然"并不是现代人所习惯的“大自然”,而是有点儿“天然存在,非人为"的意思。
利息与e的关系
e等于:当n->oo时,(1+1/n)^n的极限值
e的应用
对数中最常用的底数是10、2和e
为什么自然界中存在这么多的对数螺线呢?
因为对数螺线具有等角性,受环境影响,很多直线运动会转变为等角螺线运动。
我们以飞蛾扑火为例
亿万年来,夜晚活动的蛾子等昆虫都是靠月光和星光来导航,因为天体距离很远,这些光都是平行光,可以作为参照来做直线飞行。如下图所示,注意蛾子只要按照固定夹角飞行,就可以飞成直线,这样飞才最节省能量。
协同过滤
概述
协同过滤是一种借助众包智慧的途径。它利用大量已有的用户偏好来估计用户对其未接触过的物品的喜好程度。
其
内在思想是相似度的定义。
在基于用户的方法的中,如果两个用户表现出相似的偏好(即对相同物品的偏好大体相同),
那就认为他们的兴趣类似。要对他们中的一个用户推荐一个未知物品,便可选取若干与其类似的
用户并根据他们的喜好计算出对各个物品的综合得分,再以得分来推荐物品。其整体的逻辑是,
如果其他用户也偏好某些物品,那这些物品很可能值得推荐。
ALS算法与显式矩阵分解
概述
我们在实现推荐系统时,当要处理的那些数据是由用户所提供的自身的偏好数据,这些数据
被称作显式偏好数据,由显示偏好数据建立的矩阵称为显式矩阵。这类数据包括如物品评
级、赞、喜欢等用户对物品的评价。
这些数据可以转换为以用户为行、物品为列的二维矩阵。矩阵的每一个数据表示某个用户对
特定物品的偏好。大部分情况下单个用户只会和少部分物品接触,所以该矩阵只有少部分数
据非零(即该矩阵很稀疏)。在生产环境下,偏好矩阵—般的是稀疏的。
===========================================