梯度下降过程全都露 -- 视觉化

前言

『梯度下降』是神经网路(Neural Network)优化求解的关键,有时候在解说『梯度下降』时,怎么讲都讲不清楚,这时候如果有个动画展示,一图胜过千言万语,看了就一目了然了,所以,笔者就来写个小程式实践这个构想。以下就以简单的线性迴归为例,视觉化整个梯度下降的过程。

梯度下降概念

我们先複习一下神经网路求解的流程,参考下图:

先随机指定权重(Weights)及偏差(Bias)。依模型逐层求出预测值(Y hat)。计算损失函数,若与前一次的损失函数比较,如无明显差异,就认为目前的权重及偏差就是最佳解了,否则就继续进行第4步骤。依预测与训练资料实际值的误差及学习率,更新权重,回到第2步骤,重複计算,直到损失函数与前一次的损失函数比较,无明显差异为止。
http://img2.58codes.com/2024/20001976zsaI93lw3n.png
图. Neural Network 求解流程

线性迴归求解

我们现在就以简单线性迴归(即单层神经网路,无启动函数)为例,撰写程式求解。

y=b1x+b0

下图是一个简单线性迴归的图解:
http://img2.58codes.com/2024/20001976x5SKN08Zhp.jpg
图片来源:『Machine-Learning-with-Python』

目标就是以梯度下降法求解 (b1, b0),程式码如下。

import matplotlib.pyplot as pltfrom matplotlib.pyplot import figurefrom sklearn.datasets import make_regressionimport numpy as np# 学习率LEARNING_RATE=0.005# 损失函数与前一次的差异设定值,小于设定值,就停止ERROR_TOLERENCE=0.01# 图形更新的频率PAUSE_INTERVAL=0.5# 产生图形大小fig, ax = plt.subplots()fig.set_size_inches(14, 8)# 产生随机资料X, y= make_regression(n_samples=100, n_features=1, noise=5, bias=50)X=X.ravel()# print(X, y)            plt.scatter(X,y)line, = ax.plot(X, [0] * len(X), 'g')# 随机指定权重(Weights)及偏差(Bias)b0 = np.random.rand()b1 = np.random.rand()# 求预测值(Y hat)def calc_forecast(b0, b1, x):    return b0 + (b1*x) # 计算损失函数 MSEdef calc_loss(b0, b1, X, y):    lossValue = 0    # MSE       for (xi, yi) in zip(X, y):        # print(type(b0), type(b1), type(xi))                lossValue += 0.5 * ((calc_forecast(b0, b1, xi) - yi)**2)    return lossValue# 偏微分,求梯度def derivatives(b0, b1, X, y):    b0_offset = 0    b1_offset = 0    for (xi, yi) in zip(X, y):        b0_offset += calc_forecast(b0, b1, xi) - yi        b1_offset += (calc_forecast(b0, b1, xi) - yi)*xi    b0_offset /= len(X)    b1_offset /= len(X)    return b0_offset, b1_offset# 更新权重def updateParameters(b0, b1, X, y, alpha):    b0_offset, b1_offset = derivatives(b0, b1, X, y)    b0 = b0 - (alpha * b0_offset)    b1 = b1 - (alpha * b1_offset)    return b0, b1 # 主程式i=0prev_loss = 999999999999.while True:    if i % 100 == 0:        # 更新图形Y轴资料        y_new = [b0 + b1 * xplot for xplot in X]        line.set_data(X, y_new)  # update the data.        #ax.cla()        plt.pause(PAUSE_INTERVAL)    current_loss = calc_loss(b0, b1, X, y)    # print('current_loss=',current_loss)    # print(prev_loss - current_loss)    if prev_loss - current_loss > ERROR_TOLERENCE:        b0, b1 = updateParameters(b0, b1, X, y, LEARNING_RATE)        prev_loss = current_loss        # print('prev_loss=',prev_loss)    else:        print(b0, b1)        break    i+=1plt.show()

结语

输出结果如下,显示控制的参数可调整『学习率』、『损失函数与前一次的差异设定值』、『图形更新的频率等变数』。读者也可以轻鬆改为一元多次迴归试试看。
http://img2.58codes.com/2024/20001976isKK1oGiH6.png

点我观看动画 !!

透过 MatPlotLib 套件的 Pause 及更新Y轴资料,让我们很容易製作动画,太感谢套件发明人了。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章