线性回归

定义:用于预测输入变量(自变量)和输出变量(因变量)之间的关系

简单来说,就是选择一条函数曲线使其能很好地拟合已知数据且很好地预测未知数据(预测值是连续的实数范围)

最常用的损失函数:平方损失函数

\[L=\frac{1}{n}\sum_{i=0}^{n}{(wx^{(i)}+b-y^{(i)})}^{2} \]

需要优化的模型参数是 w 和 b,可按照下面方式更新参数:

\[w^{'}=w-\eta \frac{𝜕L}{𝜕w} \]

\[b^{'}=b-\eta \frac{𝜕L}{𝜕b} \]

代码实现

import numpy as np

# 1.采样数据
# 保存样本集列表
data = []
# 循环采样 100 个样本点
for i in range(100):
    # 从[-10,10] 里随机均匀分布采样
    x = np.random.uniform(-10., 10.)
    # 采样高斯噪声 服从高斯分布(正态分布)均值为 0 ,方差为 0.01
    eps = np.random.normal(0., 0.1)
    # 得到模型的输出
    y = 1.477 * x + 0.089 + eps
    data.append([x, y])
# 将样本转换为二维 numpy 数组形式
data = np.array(data)


# 2.计算误差
def mse(b, w, points):
    totalError = 0
    # 循环迭代所有样本点
    for j in range(0, len(points)):
        # 获得 j 号点上的输入 x
        x = points[j, 0]
        # 获得 j 号点上的输出 y
        y = points[j, 1]
        # 计算差的平方,并累加
        totalError += (y - (w * x + b)) ** 2
    # 求均方差
    return totalError / float(len(points))


# 3.计算梯度
def step_gradient(b_current, w_current, points, lr):
    # 计算误差函数在所有点上的导数,并更新 w b
    b_gradient = 0
    w_gradient = 0
    M = float(len(points))
    for k in range(0, len(points)):
        x = points[k, 0]
        y = points[k, 1]
        # 误差函数对 b 的导数
        b_gradient += (2 / M) * (w_current * x + b_current - y)
        # 误差函数对 w 的导数
        w_gradient += (2 / M) * (w_current * x + b_current - y) * x
    # 根据梯度下降算法更新 w b, lr 为学习率
    new_b = b_current - lr * b_gradient
    new_w = w_current - lr * w_gradient
    return [new_b, new_w]


# 4.梯度更新
def gradient_descent(points, starting_b, starting_w, lr, num_iterations):
    # 循环更新 w b 的值
    b = starting_b  # b 的初始值
    w = starting_w  # w 的初始值
    # 更加梯度下降算法更新多次
    for step in range(num_iterations):
        b, w = step_gradient(b, w, np.array(points), lr)
        # 计算当前均方差
        loss = mse(b, w, points)
        # 每 50 个 epoch 打印一次
        if step % 50 == 0:
            print(f"iterations:{step}, loss:{loss}, w:{w}, b:{b}")
    return [b, w]


if __name__ == '__main__':
    lr = 0.01  # 学习率
    initial_b = 0  # 初始化 b 为 0
    initial_w = 0  # 初始化 w 为 0
    num_iterations = 1000
    # 训练优化 1000 次,返回最优 w*,b*和训练 Loss 的下降过程
    [b, w] = gradient_descent(data, initial_b, initial_w, lr, num_iterations)
    loss = mse(b, w, data)  # 计算最优数值解 w,b 上的均方差
    print(f'Final loss:{loss}, w:{w}, b:{b}')

可以看到求解到的 w 和 b 是很接近于真实数值的

但对于复杂的非线性模型,通过梯度下降算法求解到的 w 和 b 可能是局部极小值而非全局最小值解,这是由模型函数的非凸性决定的。

posted @ 2020-03-07 20:45  -费费  阅读(161)  评论(0编辑  收藏  举报