机器学习|梯度下降法

640?wx_fmt=png

  Spark推荐系统,干货,心得 

  点击上方蓝字关注~

 


在之前两章讲了线性回归,并定义损失函数使用直接求导法进行求解模型参数θ,这章使用梯度下降法进行求解并进行详细介绍~

往期回顾:

机器学习-线性回归(一)

机器学习-线性回归(二)




梯度下降法:

  • (英文:Gradientdescent)是一个一阶最优化算法,通常也称为最速下降法。

  • 梯度下降算法是一种求局部最优解的方法,对于F(x),在a点的梯度是F(x)增长最快的方向,那么它的相反方向则是该点下降最快的方向则是该点下降最快的方向

  • 原理:将函数比作一座山,站在某个上坡上,往四周看,从哪个方向向下走一小步,能够下降的最快

步骤:

  • 初始化theta

  • 沿着负梯度方向迭代,更新后的theta使得J(theta)更小

640?wx_fmt=png

   其中a表示学习率



梯度下降实现

在线性回归中,目标函数收敛而且为凸函数,是一个极值点,所以局部最小值就是全局最小值

640?wx_fmt=png

640?wx_fmt=png




批量梯度下降法BGD

批量梯度下降BatchGradient Descent——BGD

对所有数据点,上述损失函数的偏导(累和)为

640?wx_fmt=png

在最小化损失函数的过程中,需要不断反复更新weights(也就是下面代码里面的theta)使得误差函数(MSE)减小,更新过程如下:

640?wx_fmt=png

代码实现1(少量维度实现,易于理解)

# -*- coding: utf-8 -*-
# 5行3列,相当于5条样本,3特征(2个实际特征+1个截距项)
x_train = [(1, 0., 3), (1, 1., 3), (1, 2., 3), (1, 3., 2), (1, 4., 4)]
# 5个lable值
y_train = [95.364, 97.217205, 75.195834, 60.105519, 49.342380]

# 初始化thea(因为是3个特征,所以有3个theta)
theta0, theta1, theta2 = 0, 0, 0

# 设置学习率
alpha = 0.0001
# 样本数
m = len(x_train)
# 存放差值
error1, error2 = 0.0, 0.0
# 设置误差结束的阈值
epsilon = 0.00001
cnt = 0
# 根据更新后的theta 计算每一条样本的预测值y_hat
def hx(x):
return theta0 * x[0] + theta1 * x[1] + theta2 * x[2]

while True:
cnt += 1
# 计算梯度
diff = [0, 0, 0]
for i in range(m):
diff[0] += (y_train[i] - hx(x_train[i])) * 1
diff[1] += float((y_train[i] - hx(x_train[i])) * x_train[i][1])
diff[2] += float((y_train[i] - hx(x_train[i])) * x_train[i][2])
# 更新theta
theta0 = theta0 + alpha * diff[0] / m
theta1 = theta1 + alpha * diff[1] / m
theta2 = theta2 + alpha * diff[2] / m
print("theta0:", theta0, " theta1:", theta1, " theta2:", theta2)
# 计算MSE
for i in range(m):
error1 += (y_train[i] - hx(x_train[i])) ** 2
error1 /= m
# 判断结束条件
if abs(error1 - error2) < epsilon:
break
else:
error2 = error1
error1 = 0.0

求解结果

theta0: 92.56879079366635  theta1: -12.989587163127105  theta2: 2.8807162746286443


代码实现2(矩阵通用形式表达)

import numpy as np

np.random.seed(10)
x = np.random.rand(100, 4) # 随机生成100行4列矩阵(相当于100条样本,4个特征)
x_train = np.c_[np.ones((100, 1)), x] # 添加截距项

y_train = x_train @ np.random.randn(5, 1) # 生成100行1列的label值
print(x_train)
print(y_train)

# 初始化thea
theta = np.zeros((5, 1))

# 设置学习率
alpha = 0.001

# 存放差值
error1, error2 = 0.0, 0.0
# 设置误差结束的阈值
epsilon = 0.00000000001

while True:
# 求梯度
diff = 1 / m * x_train.T @ (x_train @ theta - y_train)
# 更新theta
theta = theta - alpha * diff
print("theta:", theta)

# 计算MSE
error1 = np.sum((x_train @ theta - y_train) ** 2)
error1 /= m
# 判断结束条件
if abs(error1 - error2) < epsilon:
break
else:
error2 = error1
error1 = 0.0

求解结果:

theta: [[ 0.75540004]
[-0.72832989]
[ 1.21532026]
[ 1.00850685]
[ 0.07384045]]




随机梯度下降SGD(实际项目中使用最多)

由于批量梯度下降每更新一个theta参数的时候,要用到所有的样本数据,所有训练速度会随着样本数量的增加而变得非常缓慢。随机梯度下降正是为了解决这个办法而提出的。它是利用每个样本的损失函数对θ求偏导得到对应的梯度,来更新θ:

640?wx_fmt=png

代码实现

import numpy as np

np.random.seed(10)
x = np.random.rand(100, 4) # 随机生成100行4列矩阵(相当于100条样本,4个特征)
x_train = np.c_[np.ones((100, 1)), x] # 添加截距项

y_train = x_train @ np.random.randn(5, 1) # 生成100行1列的label值
print(x_train)
print(y_train)

# 初始化thea
theta = np.zeros((5, 1))

# 设置学习率
alpha = 0.001

# 存放差值
error1, error2 = 0.0, 0.0
# 设置误差结束的阈值
epsilon = 0.000000001
m = len(x_train)

while True:
# 在x_train,y_train样本中随机选取一条数据
random_index = np.random.randint(m)
xi = x_train[random_index:random_index + 1]
yi = y_train[random_index:random_index + 1]

# 求梯度
diff = xi.T @ (xi @ theta - yi)
# 更新theta
theta = theta - alpha * diff
print("theta:", theta)

# 计算MSE
error1 = np.sum((x_train @ theta - y_train) ** 2)
error1 /= m
# 判断结束条件
if abs(error1 - error2) < epsilon:
break
else:
error2 = error1
error1 = 0.0


theta: [[ 0.75329149]
[-0.7250897 ]
[ 1.21542624]
[ 1.00817401]
[ 0.0749319 ]]

缺点:SGD伴随的一个问题是噪音较BGD要多,使得SGD并不是每次迭代都向着整体最优化方向。

解决方案:

1.动态更改学习速率a的大小,可以增大或者减小

2.随机选样本进行学习



小批量梯度下降MBGD

小批量梯度下降Mini-BathGradient Descent,简称MBGD解决BGD和SGD的缺点,使得算法的训练过程比较快,使得每次迭代也基本朝着整体最优化方向

代码实现

import numpy as np

np.random.seed(10)
x = np.random.rand(100, 4) # 随机生成100行4列矩阵(相当于100条样本,4个特征)
x_train = np.c_[np.ones((100, 1)), x] # 添加截距项

y_train = x_train @ np.random.randn(5, 1) # 生成100行1列的label值
print(x_train)
print(y_train)

# 初始化thea
theta = np.zeros((5, 1))

# 设置学习率
alpha = 0.001

# 存放差值
error1, error2 = 0.0, 0.0
# 设置误差结束的阈值
epsilon = 0.00000000001
m = len(x_train)

while True:
# 在x_train,y_train样本中随机选取一条数据
random_index = np.random.randint(m)
xi = x_train[random_index:random_index + 1]
yi = y_train[random_index:random_index + 1]

# 求梯度
diff = xi.T @ (xi @ theta - yi)
# 更新theta
theta = theta - alpha * diff
print("theta:", theta)

# 计算MSE
error1 = np.sum((x_train @ theta - y_train) ** 2)
error1 /= m
# 判断结束条件
if abs(error1 - error2) < epsilon:
break
else:
error2 = error1
error1 = 0.0


theta: [[ 0.72819422]
[-0.0236637 ]
[ 0.69902268]
[ 0.59513736]
[ 0.26477262]]


总结:本文主要引入求解线性回归的loss函数最优解,来学习了梯度下降法,该方法被广泛使用在机器学习,深度学习求解最优解问题中~


640?wx_fmt=jpeg

推荐阅读:

学习人工智能你需要了解的基本概念

机器学习中一些基础的数学

Spark梯度下降法

spark协同过滤

Spark特征工程

Spark推荐系统

640?wx_fmt=jpeg

长按识别二维码关注我们



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值