Lettle
Lettle
发布于 2023-04-14 / 3 阅读
0

机器学习-梯度下降

梯度下降算法

梯度下降是一种优化算法,用于最小化各种机器学习算法中的成本函数。它主要用于更新学习模型的参数。

在求解损失函数的最小值时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数和模型参数值。

反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。在机器学习中,基于基本的梯度下降法发展了两种梯度下降方法,分别为随机梯度下降法批量梯度下降法

数学基础

梯度

一元函数里梯度就是表示某一函数在该点处的方向导数沿 着该方向取得较大值,即函数在当前位置的导数。如果函数为一元函数,梯度就是该函数的导数。

而多元函数中梯度为求偏导(其实一元函数同理)

例如 f(x,y) = x^2 + y^2 在点(1,2)处的梯度

grad(f) = (∂f/∂x , ∂f/∂y) = (2x , 2y) = (2,4)

cost

它可以帮助我们计算出一个算法的准确性

cost定义了一个算法的当前表现与期望之间的差距,以便帮助我们确定算法的有效性。也可以帮我们评价模型A和模型B哪个更好,若模型A的cost小于B的cost,那么我们说模型A优于模型B。

普通算法

附上全部代码,看一遍就懂了

# 普通算法
# 梯度下降是一种优化算法,用于最小化各种机器学习算法中的成本函数。它主要用于更新学习模型的参数。

# step 1 数据集
x_data = [1.0, 2.0, 3.0]    # 输入
y_data = [2.0, 4.0, 6.0]    # 输出

# 要被训练的参数
w = 1.0

# 训练的线性公式 y = wx
def forward(x):
    return x * w

# step 2 cost函数 
# 它可以帮助我们计算出一个算法的准确性
# 它定义了一个算法的当前表现与期望之间的差距,以便帮助我们确定算法的有效性。
# 参数:xs 和 ys 是一堆x和y的值,我们在算法中要成对使用。
# 
# 也可以帮我们评价模型A和模型B哪个更好
# 若模型A的cost小于B的cost,那么我们说模型A优于模型B
def cost(xs, ys):
    cost = 0
    for x,y in zip(xs,ys):
        y_pred = forward(x)             # 使用我们训练的 w 参数来计算一个 y 的预测值
        cost += (y_pred - y) ** 2       # Cost先对所有 delta y 的平方 进行求和
    return cost / len(xs)               # 随后根据有多少点求出平均 cost

# 梯度下降 Gradient Descent
# step 3 gradient函数
# 参数与cost函数同理

def gradient(xs,ys):
    grad = 0
    for x,y in zip(xs,ys):
        grad += 2 * x * (x * w - y)     # 计算的公式 2x(wx-y) 是 cost函数 对 w 的偏导数
    return grad / len(xs)               # 这里也是求出平均grad

print('Predict (before training)', 4 , forward(4))      # 首先输出训练前模型的表现

for epoch in range(100):                                # 训练100轮
    cost_val = cost(x_data, y_data)                     # 利用cost函数先计算本次循环的cost,用于评估训练效果
    grad_val = gradient(x_data, y_data)                 # 算出梯度
    w -= 0.01 * grad_val                                # 根据梯度对要训练的 w 进行相应调整
    print("Epoch:", epoch, 'w=', w, 'loss=', cost_val)  # 输出本轮训练信息

print('Predict (after training)', 4, forward(4))        # 输出经过训练后模型的表现

随机梯度下降

# 随机梯度下降
# 噪声能够帮助 cost 离开鞍点

# 批量随机梯度下降 (Mini-Batch)
# 折中的方法,性能中,时间复杂度中

# 相同的数据集
x_data = [1.0, 2.0, 3.0]
y_data = [2.0, 4.0, 6.0]

# 要被训练的参数
w = 1.0

# 线性模型 y = wx
def forward(x):
    return x * w

# Loss函数
# 仅计算一个 x 的预测y值与真实y之间的loss
# 与cost相比,loss是一个x的loss,cost是很多个x的loss的平均值
def loss(x, y):
    y_pred = forward(x)
    return (y_pred - y) ** 2

# 计算梯度,即求loss的偏导数
# loss = (wx - y)^2
# grad(loss) = 2x(wx-y)
def gradient(x,y):
    return 2 * x * (x * w - y)

print('Predict (before training)', 4 , forward(4))

for epoch in range(100):

    # 这次我们每个循环将每个点单独计算loss
    for x,y in zip(x_data, y_data):
        grad = gradient(x, y)           # 求出一个点的梯度
        w -= 0.01 * grad                # 对w进行调整
        print("\tgrad: ", x,y,grad)     # 输出这个点计算的梯度信息 此处y是真实值
        l = loss(x,y)                   # 算出当前loss
    print("progress:", epoch, "w=", w, "loss=", l)  # 将数据集中点用过一遍后 输出本次循环训练效果

print('Predict (after training)', 4, forward(4))