梯度下降Python实现

如何让孩子爱上机器学习?

1. 梯度

gradient f : ▽f = (  ∂f/∂x,  ∂f/∂x,  ∂f/∂x )

a) 这是一个向量

b) 偏导和普通导数的区别就在于对x求偏导的时候,把y z 看成是常数  (对y求偏导就把x z 看成是常数)

梯度方向其实就是函数增长方向最快的地方,梯度的大小代表了这个速率究竟有多大,因此在迭代的过程中,我们有两种选择:

向着梯度方向前进->梯度上升

向着梯度反方向前进->梯度下降

需要注意的是,梯度本身是一个极限的局部概念,所以我们在更新的时候应该要较小范围的进行更新,否则可能会因为步长太大的原因并没有得到我们想要的下降结果,所以我们一般会引入一个学习率参数 α 来控制更新的速度

2. 参数解释

Andrew NG 在第一讲里引入了一些参数的约定,在这里写一下

1. 训练样本(training example)数m: 在后来的代码实现里通常也是DataMatrix的行数(m个样本)

2. 特征(feature)数n:每个样本所拥有的特征的数量。 例如一个房子拥有:面积,卧室数两个特征,我们说 n = 2

3.我们约定指数是样本次序,而右下角的脚标是样本的特征次序

4. 假设函数hθ (X)表示以x为变量,θ为参数的函数,是我们学习得到的一个预测函数

5. 为了度量参数好坏,引入损失函数,这个函数只有一个极小值点,所以这个点也是全局最小值


3. 梯度下降

梯度下降可以分成随机梯度下降和批梯度下降两种。

批梯度下降每次更新参数的时候都用到了训练集中所有的样本,这样使得每一次更新迭代进行的计算量很大,特别是当m:特别大的时候,更新的速度会很慢,以前用matlab实现的时候代码写的不是很好,每一个循环里还有符号计算,导致迭代速度非常慢,所以个人其实不是很喜欢批梯度下降...

直接上两个实现的例子,随机梯度是以前从csdn文章里大概抄下来的实现程序,然后我修改了一下改成了批梯度下降

# _*_ coding: utf-8 _*_  
# 批梯度下降
x = [(1, 0., 3), (1, 1., 3), (1, 3., 2), (1, 4., 4)]
#y = [95.364, 97.217205, 75.195834, 60.105519, 49.342380]
y = [10, 12, 13, 21]
eps = 0.00000001

alpha = 0.01
diff = [0, 0, 0]
max_itor = 1000
error1 = 0
error0 = 0
count = 0
m = len(x)


theta0 = 0
theta1 = 0
theta2 = 0

	
while True:
	count += 1
	# 更新梯度	
	diff[0] = diff[1] = diff[2] = 0
	for i in range(m):	# += 是因为这是对所有样本进行一次更新,J(θ)和随机梯度下降是不一样的
		diff[0] += ((theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]) * 1
		diff[1] += ((theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]) * x[i][1]
		diff[2] += ((theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]) * x[i][2]

	# 更新梯度 for all j simultaneously
	theta0 -= alpha * diff[0]
	theta1 -= alpha * diff[1]
	theta2 -= alpha * diff[2]

	error1 = 0
	for i in range(m):
		error1 += 1/2 *(y[i] - theta0 - theta1 * x[i][1] - theta2 * x[i][2]) ** 2
	if abs(error1 - error0) < eps:
		break
	else:
		error0 = error1

	print(' theta0 : %f, theta1 : %f, theta2 : %f, error1 : %f' % (theta0, theta1, theta2, error1))  
	print('Done: theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2))
	print('迭代次数: %d' % count)

# _*_ coding: utf-8 _*_  
#随机梯度下降

x = [(1, 0., 3), (1, 1., 3), (1, 3., 2), (1, 4., 4)]
#y = [95.364, 97.217205, 75.195834, 60.105519, 49.342380]
y = [10, 12, 13, 21]
eps = 0.0000000001

alpha = 0.001
diff = [0, 0]
max_itor = 1000
error1 = 0
error0 = 0
count = 0
m = len(x)


theta0 = 0
theta1 = 0
theta2 = 0
	
while True:
	count += 1

	for i in range(m):
		diff[0] = (theta0 + theta1 * x[i][1] + theta2 * x[i][2]) - y[i]

		theta0 -= alpha * diff[0]
		theta1 -= alpha * diff[0] * x[i][1]
		theta2 -= alpha * diff[0] * x[i][2]
	error1 = 0
	for lp in range(m):
		error1 += (y[lp]-(theta0 + theta1 * x[lp][1] + theta2 * x[lp][2]))**2/2  
	if abs(error1 - error0) < eps:
		break
	else:
		error0 = error1
	print(' theta0 : %f, theta1 : %f, theta2 : %f, error1 : %f' % (theta0, theta1, theta2, error1))  
	print('Done: theta0 : %f, theta1 : %f, theta2 : %f' % (theta0, theta1, theta2))
	print('迭代次数: %d' % count) 


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值