神经网络之梯度更新

  • tensorflow 2.2
    本文主要讲解的是线性模型的梯度更新示例,主要包含有:数据采集、误差累计、梯度计算以及梯度更新四个部分。

–1 数据准备部分
使用的数据集是随机点生成,主要实现的是模拟y=wx+b函数的参数回归计算。

data = []   # 数据集的列表
for i in range(1000):    # 循环采样1000个点
    x = np.random.uniform(-10., 10.)    # 随机采集样本数据,范围[-10., 10.]
    # 在采样时,为了规避数据的准确无误差,尽量采用有误差的项,加入采样高斯噪声
    AWGN= np.random.normal(0., 0.1)
    # 得到模型的输出
    y = 1.915*x + 0.915 + AWGN
    data.append([x, y])

data = np.array(data)   # 将列表转换为Numpy数组

–2 误差计算部分
采用MSE均方误差作为误差计算函数

def mse(b, w, points):
    # 根据当前传入的权重w,偏置b参数计算均方差损失
    total_loss = 0
    for i in range(0, len(points)): # 循环迭代所有样本点
        x = points[i, 0]    # 获得第i个点的输入点x
        y = points[i, 1]    # 获得第i个点的输出y
        # 计算并累加
        total_loss += (y - (w * x + b))**2
    # 将累加的误差求平均,得到均方差
    return total_loss / float(len(points))

–3 梯度计算
可以简单计算一下,MSE = ((w*x+b)-y)**2,那么w和b的偏导数分别别为:

神经网络参数更新原理 神经网络梯度更新_MSE
神经网络参数更新原理 神经网络梯度更新_数据_02

def step_gradient(b_current, w_current, points, lr):
    # 计算误差函数在所有点上的导数,并更新参数 w,b
    b_gradient = 0
    w_gradient = 0
    M = float(len(points)) # 总样本数
    for i in range(0, len(points)):
        x = points[i, 0]
        y = points[i, 1]
        # 误差函数对 b 的导数:grad_b = 2(wx+b-y)
        b_gradient += (2/M) * ((w_current * x + b_current) - y)
        # 误差函数对 w 的导数:grad_w = 2(wx+b-y)*x
        w_gradient += (2/M) * x * ((w_current * x + b_current) - y)
    # 根据梯度下降算法更新 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) # 计算当前的均方差,用于监控训练进度
            if step%50 == 0: # 打印误差和实时的 w,b 值
                print(f"iteration:{step}, loss:{loss}, w:{w}, b:{b}")
    return [b, w]   # 返回最后一次的 w,b

最后是main函数的调用

if __name__=="__main__":
# 加载训练集数据,这些数据是通过真实模型添加观测误差采样得到的
    lr = 0.01  # 学习率
    initial_b = 0  # 初始化 b 为 0
    initial_w = 0  # 初始化 w 为 0
    num_iterations = 1000
    # 训练优化 1000 次,返回最优 w*,b*和训练 Loss 的下降过程
    temp = gradient_descent(data, initial_b, initial_w, lr, num_iterations)
    [b, w] = temp
    loss = mse(b, w, data)  # 计算最优数值解 w,b 上的均方差
    print(f'Final loss:{loss}, w:{w}, b:{b}')

最终的结果如下图所示

神经网络参数更新原理 神经网络梯度更新_数据_03