三种下降梯度算法代码实现及优化

263 阅读3分钟

梯度下降算法分为三种主要类型:

批量梯度下降、随机梯度下降和小批量梯度下降。

1.全量梯度下降 :

原理:在每一次迭代中,使用所有训练样本来计算损失函数的梯度。

优点:收敛稳定,能够保证收敛到全局最优解(在凸函数的情况下)。

缺点:计算成本高,特别是在大型数据集上。

2.随机梯度下降:

原理:在每一次迭代中,随机选择一个样本来计算损失函数的梯度。

优点:计算速度快,尤其适用于大型数据集。

缺点:由于随机性,收敛路径不稳定,可能在局部最优解附近震荡。

3.小批量梯度下降:

原理:结合了批量梯度下降和随机梯度下降的优点,每次迭代使用一小部分样本来计算损失函数的梯度。

优点:在计算效率和收敛稳定性之间取得了平衡。

缺点:需要调节批量大小,可能需要一些调参工作。

全量梯度下降代码实现:

import numpy as np
#创建数据集X,y
X=np.random.rand(100,1)
y=4+3*X+np.random.randn(100,1)
X_b=np.c_[np.ones((100,1)),X]
#创建超参数
learning_rate=0.001
n_iterations=100000

#1,初始化θ,Wθ...Wn,标准正太分布创建W
theta=np.random.randn(2,1)
# 4,判断是否收敛,一般不会去设定阈值,而是直接采用设置相对大的迭代次数保证可以收敛
for _ in range(n_iterations):
    #2,求梯度,计算gradient
    gradients=X_b.T.dot(X_b.dot(theta)-y)
    #3,应用梯度下降法的公式去调整θ值  θt+1=θt-η*gradient
    theta=theta -learning_rate * gradients
print(theta)

随机梯度下降代码实现

import numpy as np
X=2*np.random.rand(100,1)
y= 4 + 3*X+np.random.randn(100,1)
X_b=np.c_[np.ones((100,1)),X]
n_epochs=10000
m=100
learning_rate=0.001
theta=np.random.randn(2,1)
for epoch in range(n_epochs):
    for _ in range(m):
        random_index=np.random.randint(m)
        xi=X_b[random_index:random_index+1]
        yi=y[random_index:random_index+1]
        gradints=xi.T.dot(xi.dot(theta)-yi)
        theta=theta - learning_rate *gradints
print(theta)

小批量梯度代码实现:

import numpy as np
X=2*np.random.rand(100,1)
y=4+3*X+np.random.randn(100,1)
X_b=np.c_[np.ones((100,1)),X]
learning_rate=0.0001
n_epochs=10000
m=100
batch_size=10
num_batches=int(m/batch_size)
theta=np.random.randn(2,1)
for epoch in range(n_epochs):
    for _ in range(num_batches):
        random_index = np.random.randint(m)
        x_batch=X_b[random_index:random_index+batch_size]
        y_batch = y[random_index:random_index+batch_size]
        gradients=x_batch.T.dot(x_batch.dot(theta)-y_batch)
        theta=theta-learning_rate*gradients
print(theta)

代码优化:

  • 保证训练数据全都能被随机取到
  • 动态调整学习率
import numpy as np
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
n_epochs = 10000
m = 100
t0, t1 = 5, 500

# 定义一个函数来调整学习率
def learning_rate_schedule(t):
    return t0 / (t + t1)

theta = np.random.randn(2, 1)

for epoch in range(n_epochs):
    arr = np.arange(len(X_b))
    np.random.shuffle(arr)
    X_b = X_b[arr]
    y = y[arr]
    for i in range(m):
        xi = X_b[i:i + 1]
        yi = y[i:i + 1]
        gradients = xi.T.dot(xi.dot(theta) - yi)
        learning_rate = learning_rate_schedule(epoch * m + i)
        theta = theta - learning_rate * gradients

print(theta)