上一篇通俗理解-梯度下降法(一)说明梯度下降的数学原理,这一篇讲讲具体的实现。分为spark(scala)实现和python版本具体实现批量梯度下降(Batch gradient descent)。最后引出下一篇的问题。
spark版本
假设目标函数y=θx, spark模拟梯度下降法求解参数θ的值。
直接上代码:
import scala.collection.mutable.HashMap
object bgd{
val data = HashMap[Int,Int]()
//创建100个数据集
def getData():HashMap[Int,Int] = {
for(i <- 1 to 100){
//写入公式y=12x
data += (i -> (12*i))
}
data
}
//第一步假设θ为0
var θ:Double = 10
//设置步进系数
var α:Double = 0.1
//设置迭代公式
def bgd(x:Double,y:Double) = {
θ = θ - α * ( (θ*x) - y)
}
def main(args: Array[String]): Unit = {
val dataSource = getData()
//开始迭代
dataSource.foreach(myMap => {
bgd(myMap._1, myMap._2)
println("θ: ", θ)
})
println("最终θ值为:" + θ)
}
}
python版本
增加点难度。假设目标函数 y = a x + b, 实现python版本的批量梯度下降求解参数a和参数b
#coding=utf-8
import random
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
def data():
x = range(10)
y = [(2*s+4) for s in x]
return x, y
def BGD(x,y):
flag = True
a = 0
b = 0
m = len(x)
arf = 0.05 #学习率
n = 0
sum1 = 0
sum2 = 0
exp = 0.000001
error0 = 0
error1 = 0
while flag:
for i in range(m):
#计算对应的偏导数
sum1 = a*x[i]+b-y[i]
sum2 = (a*x[i]+b-y[i])*x[i]
error1 = (a*x[i]+b-y[i])**2
a = a - sum2*arf/m #对a,b进行更新
b = b - sum1*arf/m
if abs(error1-error0)<exp: #计算误差
break
error0 = error1
print('a=%f,b=%f,error=%f' % (a, b, error1))
if n > 1000:
break
n += 1
if n % 10 == 0:
print('第%d次迭代:a=%f,b=%f' % (n, a, b))
return a,b
if __name__ == '__main__':
x,y = data()
a,b = BGD(x,y)
print('梯度下降BGD: y=%fX+%f'%(a,b))
部分结果如下:
a=2.413752,b=0.268195,error=0.000186
a=2.414114,b=0.268235,error=0.000065
a=2.414327,b=0.268259,error=0.000022
a=2.414453,b=0.268273,error=0.000008
a=2.414527,b=0.268281,error=0.000003
a=2.414571,b=0.268286,error=0.000001
第20次迭代:a=2.414571,b=0.268286
梯度下降BGD: y=2.414597X+0.268289
到此,简单实现了批量梯度下降(BGD)的两个版本。我们一般总听说随机梯度下降(Stochastic gradient descent),这两者有什么关系和区别呢。另起一篇讨论。