梯度下降法

梯度下降法

对于一个二元一次函数 y = ax + b,我们只需要知道两个 (x,y) 点即可获取到 ab 的值,我们称其为精确解,如下图:在这里插入图片描述
但是如果该函数中存在已知分布的噪声,那么又该如何求解:
在这里插入图片描述

我们可以假设 ab为任意值,则根据输入 x 有预测输出 y',实际的 y 值与预测的 y' 的差距我们称为损失,对于已知的若干 (x,y) 点的损失则为损失函数:
l o s s = 1 n ∑ i = 1 n ( y i − y ′ i ) 2 loss = \frac{1}{n} \sum_{i=1}^n (y_i - {y'}_i)^2 loss=n1i=1n(yiyi)2

我们最终的目的是求得ab使损失值最小,所以可以从当前的参数取值,一步步的按照损失函数下坡的方向下降,直到走到最低点。第一要保证 loss 是下降的,第二要使得下降的趋势尽可能的快。微积分的基础知识告诉我们:沿着梯度的反方向,是函数值下降最快的方向,所以只需要对损失函数求导,并且沿着导数的反方向逐步移动,则会找到最佳的 ab。我们称这种求解方法为梯度下降法,称该问题为线性回归问题。
在这里插入图片描述

代码实现

ab 分别求偏导数:
l o s s = 1 n ∑ i = 1 n ( a x i + b − y i ) 2 loss = \frac{1}{n} \sum_{i=1}^n (ax_i + b - y_i)^2 loss=n1i=1n(axi+byi)2
∂ l o s s ∂ a = 2 n ∑ i = 1 n [ ( a x i + b − y i ) x i ] {\partial loss \over \partial a} = {2\over n}\sum_{i=1}^n [(ax_i+b-y_i)x_i] aloss=n2i=1n[(axi+byi)xi]
∂ l o s s ∂ b = 2 n ∑ i = 1 n ( a x i + b − y i ) {\partial loss \over \partial b} = {2\over n}\sum_{i=1}^n (ax_i+b-y_i) bloss=n2i=1n(axi+byi)

# 线性回归模型

import numpy as np
import matplotlib.pyplot as plt


# 创建样本 y = ax+b,其中x = 1.72,b = 3.69
def create_sample():
    # 生成 0-100 之间 200 个随机数
    x = np.random.rand(200) * 10
    y = x * 1.72 + 3.69 + (np.random.normal(size=200))
    # 转换为 [[x1,y1],[x2,y2]...[xn,yn]] 的矩阵
    return np.array(list(zip(x, y)))


# 计算梯度,并更新 a,b 值
def gradient(a_cur, b_cur, points, learning_rate):
    a_gradient = 0
    b_gradient = 0
    points_length = len(points)
    # 计算梯度
    for i in range(0, points_length):
        x = points[i, 0]
        y = points[i, 1]
        a_gradient += (2 / points_length) * x * (a_cur * x + b_cur - y)
        b_gradient += (2 / points_length) * (a_cur * x + b_cur - y)

    # 更新 a、b 值
    new_a = a_cur - learning_rate * a_gradient
    new_b = b_cur - learning_rate * b_gradient
    return [new_a, new_b]


# 计算损失
def computer_loss(a, b, points):
    points_length = len(points)
    loss = 0
    for i in range(0, points_length):
        x = points[i, 0]
        y = points[i, 1]
        loss += (a * x + b - y) ** 2
    loss /= points_length
    return loss


points = create_sample()
print("points", points)
a = 0
b = 0
loss_list = list()
for i in range(0, 100000):
    [a, b] = gradient(a, b, points, 0.001)
    loss_list.append(computer_loss(a, b, points))

#求得 a = 1.7219045715547612 b = 3.6145089870651086
print("a = {} b = {}".format(a, b))

# 绘制损失函数
plt.plot(loss_list)
plt.show()

最终损失区域0
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值