[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)

作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119978818


目录

前置文章

第1章 导数与偏导

1.1 一元简单函数求导

1.2 N元简单函数求偏导

1.3 一元复合函数链式求导

1.4 多元复合函数链式求偏导

1.5 多元复合函数线性相加函数的链式求偏导

第2章 用最小二乘法的损失函数进行曲线拟合

2.0 前置条件

2.1 步骤1: 构建样本

2.2 步骤2:构建拟合函数

2.3 步骤3:利用python库提供算法求拟合函数的参数 (仅供参考)

2.4 步骤3:利用自定义的梯度下降法计算拟合函数的参数

2.4.1 使用最小二乘定义损失函数(残差函数)

2.4.2 链式求导

2.4.3 梯度下降法求解最佳w,b参数值

2.4.4 可视化迭代过程

2.5 步骤4:利用获得的拟合函数进行数据预测 

2.6 步骤5:可视化拟合函数


前置文章

[数值计算-15]:函数近似值的线性与非线性拟合的原理与Python代码示例

https://blog.csdn.net/HiWangWenBing/article/details/119973082

[数值计算-16]:最小二乘的解法1 - 一元二次方程解析法求解

https://blog.csdn.net/HiWangWenBing/article/details/119978799

[数值计算-17]:最小二乘的解法2 - 二元二次线性方程组求解

https://blog.csdn.net/HiWangWenBing/article/details/119977443

第1章 导数与偏导

1.1 一元简单函数求导

一元函数:就是只有一个自变量的函数。

简单函数:就是初等函数的线性加减得到的函数。

导数(Derivative),也叫导函数值。又名微商,是微积分中的重要基础概念。当函数y=f(x)的自变量x在一点x0上产生一个增量Δx时,函数输出值的增量Δy与自变量增量Δx的比值在Δx趋于0时的极限a如果存在,a即为在x0处的导数,记作f'(x0)或df(x0)/dx。

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第1张图片

一元函数的切线和导数,有现成的公式求导数,如下图所示:

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第2张图片

例题1:

y = f(x) = 2x^{2} + 4x + 1   ; x为自变量

导数:f '(x) =  2*2x^1 + 4 = 4x^1 + 4 = 4x + 4

例题2:

y = f(x) = wx + b  ; x为自变量,w,b为常量

导数:f '(x) = w + 0   = w

1.2 N元简单函数求偏导

多元函数:所谓多元函数,求是有包含有多个自变量的初等函数。

简单函数:就是初等函数的线性加减得到的函数。

 那么,对于二元函数或多元函数,求导数,该如何计算呢?

这就需要用到偏导数的概念:通过临时固化其他维度分量的数值,用来求解多元函数在某个维度方向的导数或切线斜率。

然后,把所有维度方向的导数组成一个向量,就得到多元函数在空间中某一点处的导数或梯度P = {P1, P2, P3.....Pn}; 其中Pi是在i维度方向上的偏导数。

其中:

x1, x2,....Xi......表示的是维度方向,而不是指在单个维度方向上的数值序列. 

{x1.0, x1.1, x1.2.....x1.n..}  表示在x1的维度方向的序列

{x2.0, x2.1, x2.2.....x2.n..}  表示在x2的维度方向的序列

{xi.0,  xi.1, xi.2  .....xi.n..}  表示在x2的维度方向的序列

因此,多元简单函数与一元简单函数的导数基本是一致的,唯一的区别就是:每个变量都有各自的偏导数,在求解某个变量Xi的偏导数是,需要假定其他变量为常数。

例题1:z = f(x,y) = 3x^{2} + 2xy + 2y^{2} + 1  ; x,y为自变量

z对x的偏导数:\frac{\partial z}{\partial x} = 6x + 2y + 0 = 6x + 2y

z对y的偏导数:\frac{\partial z}{\partial y} = 0 + 2x + 4y + 0 = 2x + 4y

例题2:z = f(w,b) = wx + b  #变量为w和b

z对w的偏导数:\frac{\partial z}{\partial w} = x_{i}

z对b的偏导数:\frac{\partial z}{\partial b} = 1

1.3 一元复合函数链式求导

例题1:z = f(u)= u^{2}, u=f(x) = wx + b => z(w,b) = (wx + b)^2

z对x的导数:\frac{\partial z}{\partial x} = \frac{\partial z}{\partial u} * \frac{\partial u}{\partial x} = 2u * w = (wx+b) * w

1.4 多元复合函数链式求偏导

例题1:w,b为参数,(xi,yi为常数)

 z = f(u)= u^{2}, u=f(w,b) = wx_{i} + b - y_{i} => z(w,b) = (wx_{i} + b - y_{i})^2

z对w的偏导数:\frac{\partial z}{\partial w} = \frac{\partial z}{\partial u} * \frac{\partial u}{\partial w} = 2u * x_{i}= 2( wx_{i} + b - y_{i}) * x_{i}

z对b的偏导数:\frac{\partial z}{\partial b} = \frac{\partial z}{\partial u} * \frac{\partial u}{\partial b} = 2u * 1 = 2(wx_{i} + b - y_{i})

1.5 多元复合函数线性相加函数的链式求偏导

例题1:w,b为参数,(xi,yi)为常数

z =\frac{1}{N} \sum f(u)= \frac{1}{N}\sum u_{i}^{2}

u=f(w,b) = wx_{i} + b - y_{i}

 z(w,b) =\frac{1}{N} \sum (wx_{i} + b - y_{i})^2

(1) z对w的偏导数:

\frac{\partial z}{\partial w} = \frac{1}{N}\sum \frac{\partial z}{\partial u} * \frac{\partial u}{\partial w} = \frac{1}{N}\sum 2u * x_{i}= \frac{2}{N} \sum ( wx_{i} + b - y_{i}) * x_{i}

\frac{\partial z}{\partial w} = \frac{2}{N}*((\sum (x_{i} * x_{i}))*w + (\sum x_{i})*b - \sum (x_{i} * y_{i}))

\frac{\partial z}{\partial w} = (\frac{2}{N}\sum (x_{i} * x_{i}))*w + (\frac{2}{N}\sum (x_{i}))*b - \frac{2}{N}\sum (x_{i} * y_{i})

(2)z对b的偏导数:

\frac{\partial z}{\partial b} = \frac{1}{N}\sum \frac{\partial z}{\partial u} * \frac{\partial u}{\partial b} =\frac{1}{N} \sum 2u * 1 = \frac{2}{N}\sum (wx_{i} + b - y_{i})

\frac{\partial z}{\partial b} = \frac{2}{N}* ((\sum (x_{i})) * w + N *b - \sum y_{i})

 \frac{\partial z}{\partial b} = (\frac{2}{N}*\sum (x_{i})) * w + 2*b - \frac{2}{N}\sum y_{i}

第2章 用最小二乘法的损失函数进行曲线拟合

2.0 前置条件

#导入库
from math import *
import time
import numpy as np
import matplotlib.pyplot as plt #画图工具
from pylab import mpl           #中文字体
from scipy import optimize      #最小二乘算法的算法库

2.1 步骤1: 构建样本

#步骤1:构建样本

#(1) 采用np, 直接手工生成样本的输入:一组等距离的分布在[-1,1]之间的100个点
sample_numbers = 50

x_data = np.linspace(0, 1, sample_numbers)

#(2) 为这些数据手工打上理论输出值(标签值):y = 2x + 1
y_data_pure =  2 * x_data + 1.0

#(3)为了模拟现实情况,通过随机数来模拟数据噪声
noise_range = 0.4
np.random.seed(10) #设置随机种子, 确保不同时候,执行结果是相同的
#randn(n)生成的0为均值,1为标准差的正态分布的n个随机数。
y_noise = np.random.randn(*x_data.shape) * noise_range  # *x_data.shape:输入样本的维度或个数

#(4)人工生成样本的输出:理论值 + 噪声
y_data_noise = y_data_pure + y_noise

#(5) 显示样本数据
# 样本的散点图
plt.scatter(x_data, y_data_noise, label="sample", color="black")

# 内在的、理论的曲线图
plt.plot(x_data, y_data_pure, label="f_pure(x)", color="blue", linewidth = 4)

#设置属性
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.title("线性拟合")
plt.legend(loc="upper left")
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第3张图片

2.2 步骤2:构建拟合函数

#步骤2:构建拟合函数:二元一次拟合函数
def f_line_wb(x, w, b):
    return (w*x + b)

2.3 步骤3:利用python库提供算法求拟合函数的参数 (仅供参考)

#步骤3-1:利用python库提供的最小二乘算法来计算拟合函数的参数
print("使用无噪声数据:")
popt, pcov = optimize.curve_fit(f_line_wb, x_data, y_data_pure)
print(popt)
print(pcov)
w_scipy =  popt[0]
b_scipy =  popt[1]
print("参数w=", w_scipy)
print("参数b=", b_scipy)

print("\n使用有噪声数据:")
popt, pcov = optimize.curve_fit(f_line_wb, x_data, y_data_noise)
print(popt)
print(pcov)
w_scipy =  popt[0]
b_scipy =  popt[1]
print("参数w=", w_scipy)
print("参数b=", b_scipy)
使用无噪声数据:
[2. 1.]
[[ 0. -0.]
 [-0.  0.]]
参数w= 2.0
参数b= 1.0

使用有噪声数据:
[1.91826746 1.08186076]
[[ 0.0310567  -0.01552835]
 [-0.01552835  0.01045787]]
参数w= 1.9182674578022025
参数b= 1.0818607577986927

2.4 步骤3:利用自定义的梯度下降法计算拟合函数的参数

2.4.1 使用最小二乘定义损失函数(残差函数)

(1)定义损失函数

# 定义残差函数或损失
def f_loss(input_f, w, b, input_x_data, input_y_data_noise):    
    loss = np.mean((input_f(input_x_data, w, b) - input_y_data_noise)**2)
    return (loss)
(2)测试损失函数
# 测试残差函数或损失函数
err0 = f_loss(f_line_wb, 2, 1, x_data, y_data_pure)
print("Mean Err under Case0:",err0)

err1 = f_loss(f_line_wb, 2, 1, x_data, y_data_noise)
print("Mean Err under Case1:",err1)

err2 = f_loss(f_line_wb, 2, 1.1, x_data, y_data_noise)
print("Mean Err under Case2:",err2)

err3 = f_loss(f_line_wb, 2, 0.9, x_data, y_data_noise)
print("Mean Err under Case3:",err3)

err4 = f_loss(f_line_wb, 2.1, 1, x_data, y_data_noise)
print("Mean Err under Case4:",err4)

err5 = f_loss(f_line_wb, 1.9, 1, x_data, y_data_noise)
print("Mean Err under Case5:",err5)

err6 = f_loss(f_line_wb, 1, 2, x_data, y_data_noise)
print("Mean Err under Case6:",err6)

# 问题:w, b 为多少时?残差值最小呢?
Mean Err under Case0: 0.0
Mean Err under Case1: 0.1315572426174743
Mean Err under Case2: 0.13335834500408647
Mean Err under Case3: 0.14975614023086212
Mean Err under Case4: 0.1322429501791569
Mean Err under Case5: 0.13760622893334273
Mean Err under Case6: 0.41311935413207634

(3)可视化损失函数

  • 可视化空间线性图形:  z轴为恒定值1
# 可视化空间线性数据
w_line = np.linspace(-10, 10, 10)
b_line = np.linspace(-10, 10, 10)

# 假定z轴的loss数值恒定为: z = 1
loss = 1 

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line, b_line, loss, cmap='Blues')  #绘制三维散点图
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第4张图片

  • 可视化空间线性图形:  z轴为损失函数
#二元(w,b)残差函数的线性图形
w_line = np.linspace(-10, 10, 30)
b_line = np.linspace(-10, 10, 30)

size = len(w_line)
loss = []

# 假定z轴的loss数值来自残差函数: z = f_loss
for i in range(size):
    err = f_loss(f_line_wb, w_line[i], b_line[i], x_data, y_data_noise)
    loss.append(err)

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line, b_line, loss, cmap='Blues')  #绘制三维散点图
ax.plot3D(w_line , b_line, loss,'gray')               #绘制三维曲线图
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第5张图片

  •  可视化空间网格图形:  z轴为恒定值1
# 可视化空间线性数据到空间网格数据的转换
w_line = np.linspace(-10, 10, 10)
b_line = np.linspace(-10, 10, 10)

w_line_grid ,b_line_grid = np.meshgrid(w_line, b_line)      #空间的点序列转换成网格点

# 假定z轴的loss数值恒定为: z = 1
loss = 1

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line_grid, b_line_grid, loss, cmap='rainbow')  #绘制三维散点图
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第6张图片

  •  可视化空间网格图形:  z轴为二次函数-1
# 可视化空间图形
w_line = np.linspace(-10, 10, 20)
b_line = np.linspace(-10, 10, 20)

w_line_grid ,b_line_grid = np.meshgrid(w_line, b_line)      #空间的点序列转换成网格点

# 假定z轴的loss数值来自于 z = x^2 + y^2
loss = w_line_grid**2 + b_line_grid**2

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line_grid, b_line_grid, loss, cmap='rainbow')  #绘制三维散点图
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第7张图片

  • 可视化空间网格图形:  z轴为二次函数-2
# 可视化空间图形
w_line = np.linspace(-10, 10, 20)
b_line = np.linspace(-10, 10, 30)

w_line_grid ,b_line_grid = np.meshgrid(w_line, b_line)      #空间的点序列转换成网格点
print("w_line_grid shape", w_line_grid.shape)
print("b_line_grid shape", b_line_grid.shape)

# 假定z轴的loss数值来自于: z = 3*x^2 - y^2 + 1
loss = 3*w_line_grid**2 - b_line_grid**2 + 1
print("loss shape", loss.shape)

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line_grid, b_line_grid, loss, cmap='rainbow')  #绘制三维散点图
plt.show()
w_line_grid shape (30, 20)
b_line_grid shape (30, 20)
loss shape (30, 20)

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第8张图片

  • 可视化空间网格图形:  z轴为二次函数-3
# 可视化空间图形
w_line = np.linspace(-10, 10, 20)
b_line = np.linspace(-10, 10, 30)

w_line_grid ,b_line_grid = np.meshgrid(w_line, b_line)      #空间的点序列转换成网格点
print("w_line_grid shape", w_line_grid.shape)
print("b_line_grid shape", b_line_grid.shape)

# 假定z轴的loss数值来自于: z = (1/3) * x^2 + x * y + y^2 + 1
loss = (1/3)*w_line_grid**2 + w_line_grid * b_line_grid + b_line_grid**2 + 1
print("loss shape", loss.shape)

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line_grid, b_line_grid, loss, cmap='rainbow')  #绘制三维散点图
plt.show()

w_line_grid shape (30, 20)
b_line_grid shape (30, 20)
loss shape (30, 20)

 [数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第9张图片

  •  可视化空间网格图形:  z轴为损失函数
# 可视化空间图形
w_line = np.linspace(-10, 10, 20)
b_line = np.linspace(-10, 10, 30)
print("w_line len:" ,len(w_line))
print("b_Line len:", len(b_line))

w_line_grid ,b_line_grid = np.meshgrid(w_line, b_line)      #空间的点序列转换成网格点
print("w_line_grid shape", w_line_grid.shape)
print("b_line_grid shape", b_line_grid.shape)

# 假定z轴的loss数值来自于残差函数: z = f_loss
loss = np.zeros((len(w_line_grid),len(w_line_grid[0])))
print("loss shape:", loss.shape)

for i in range (len(w_line_grid)):
    for j in range (len(w_line_grid[0])):
        loss[i][j] =  f_loss(f_line_wb, w_line_grid[i][j], b_line_grid[i][j], x_data, y_data_noise)
        
fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_line_grid, b_line_grid, loss, label="loss", cmap='rainbow')  #绘制三维散点图
plt.show()
w_line len: 20
b_Line len: 30
w_line_grid shape (30, 20)
b_line_grid shape (30, 20)
loss shape: (30, 20)

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第10张图片

2.4.2 链式求导

(1)一元线性函数求导

# 原函数yi=f(xi) = w*xi + b
# 对x的导函数: x为参数,w,b为常量
def fv1(xi, w, b):
    num = len(xi)
    rst = np.ones(num) * w
    return (rst)

#显示上述函数图形
x_line = np.linspace(0, 1, 30)
y_fv1 = fv1(x_line, 2, 1)

#对w的偏导函数
plt.scatter(x_line, y_fv1, label="sample", color="black")
plt.plot   (x_line, y_fv1, label="curve", color="blue", linewidth = 4)

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第11张图片

(2)二元线性求偏导 

# 残差:err = f(w,b, xi, yi) = w*xi + b - yi
# 对w求偏导数:w为变量,xi为常量, b为常量
def fv1_w(w, b, xi, yi):
    num = len(w)
    rst = np.ones(num) * xi  #对w偏导,其值为xi
    return (rst)

# 对b求偏导数:w为常量,xi为常量, b为变量
def fv1_b(w, b, xi, yi):
    num = len(b)
    rst = np.ones(num)  #对w偏导,其值恒定为1
    return (rst)

#显示上述函数图形
x_line = np.linspace(0, 1, 30)
y_fv1_w = fv1_w(x_line, 0, 2, 3)   #在点(2,2)的偏导函数
y_fv1_b = fv1_b(0, x_line, 2, 3)   #在点(2,2)的偏导函数

# 在b=0, (xi=0, yi=0)处对w的偏导函数
plt.scatter(x_line, y_fv1_w, label="w sample", color="black")
plt.plot   (x_line, y_fv1_w, label="w cruve", color="blue", linewidth = 4)

# 在w=0, (xi=0, yi=0)处对b的偏导函数
# 在b=0, (xi=0, yi=0)处对w的偏导函数
plt.scatter(x_line, y_fv1_b, label="b sample", color="black")
plt.plot   (x_line, y_fv1_b, label="b curve", color="blue", linewidth = 4)

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第12张图片

 (3)二元二次非线性函数求偏导

# loss = np.mean( w * xdata + b - y_data_noise)**2)
# 残差函数对 w 的一阶偏导数
def f_loss_fv1_w(w, b, input_x_data, input_y_data_noise):
    loss_fv = 2 * np.mean(input_x_data * input_x_data) * w + 2 * np.mean(input_x_data) * b -  2 * np.mean(input_x_data * input_y_data_noise)
    return (loss_fv)

# 残差函数对 b 的一阶偏导数
def f_loss_fv1_b(w, b, input_x_data, input_y_data_noise):
    loss_fv = 2 * np.mean(input_x_data) * w  + 2 * b - 2 * np.mean(input_y_data_noise)
    return (loss_fv)

(4)通过偏导求在某一点的梯度
# 计算指定(w,b)点的梯度
gradient_w = f_loss_fv1_w(2,1, x_data, y_data_pure)
print(gradient_w)

gradient_b = f_loss_fv1_b(2,1, x_data, y_data_pure)
print(gradient_b)

gradient_w = f_loss_fv1_w(2,1, x_data, y_data_noise)
print(gradient_w)

gradient_b = f_loss_fv1_b(2,1, x_data, y_data_noise)
print(gradient_b)
4.440892098500626e-16
4.440892098500626e-16
-0.026816393770928926
-0.08198897613387857

备注:当w=2,b=1时,梯度接近为0

2.4.3 梯度下降法求解最佳w,b参数值

(1)定义梯度下降法的迭代函数

# 用梯度下降法求w,b的值
#自定义最小二乘求解拟合函数参数:偏导 + 梯度下降法    
def usr_gradient_descent_fit(input_f, input_x_data, input_y_data_noise, learning_rate = 0.1, max_loop = 300):
    w_data  = []   #存放w值的迭代序列
    b_data  = []   #存放b值的迭代序列
    z_data  = []   #存放loss值的迭代序列
    w_diff_data  = []
    b_diff_data  = []
    
    w_k  = 0.
    b_k  = 0.
    z_k  = 0.
    
    #保存初始信息
    w_data.append(w_k)
    b_data.append(b_k)
    
    z_k = f_loss(input_f, w_k, b_k, input_x_data, input_y_data_noise)
    z_data.append(z_k)

    w_diff_data.append(w_k)
    b_diff_data.append(b_k)
    
    for k in range(max_loop):
        # (1)学习率与计算梯度!!!
        step_x = learning_rate * f_loss_fv1_w(w_k, b_k , input_x_data, input_y_data_noise)
        step_y = learning_rate * f_loss_fv1_b(w_k, b_k , input_x_data, input_y_data_noise)
        
        # (2)最重要的梯度下降迭代!!!
        w_k1 = w_k - step_x
        b_k1 = b_k - step_y

        # (3)计算迭代后的残差 !!!
        z_k1 = f_loss(input_f, w_k1, b_k1, input_x_data, input_y_data_noise)
        
        
        # (4)记录中间迭代过程
        
        # 计算迭代前后w,b的差(作为x的偏差)
        w_diff = step_x
        b_diff = step_y
        z_diff = z_k1 - z_k
        
        # 保存当前的迭代点信息
        w_data.append(w_k1)
        b_data.append(b_k1)
        z_data.append(z_k1)
        
        w_diff_data.append(w_diff)
        b_diff_data.append(b_diff)
        
        # (5)为新一轮迭代做准备
        w_k = w_k1
        b_k = b_k1
        z_k = z_k1
    
    #返回 w,b值以及中间迭代过程的数据
    return ((w_k, b_k, z_k), (w_data, b_data, z_data), (w_diff_data, b_diff_data))

(2)调用迭代函数接近w和b的最佳值

print("使用无噪声数据:")
rst = usr_gradient_descent_fit(f_line_wb, x_data, y_data_pure)
w_grad, b_grad, e_grad = rst[0]
print("参数w=", w_grad)
print("参数b=", b_grad)
print("残差e=", e_grad)

print("\n使用有噪声数据:")
rst = usr_gradient_descent_fit(f_line_wb, x_data, y_data_noise)
w_grad, b_grad, e_grad = rst[0]
print("参数w=", w_grad)
print("参数b=", b_grad)
print("残差e=", e_grad)
使用无噪声数据:
参数w= 1.9817535011137024
参数b= 1.0097929273554476
残差e= 2.9325459666068766e-05

使用有噪声数据:
参数w= 1.9015879580969595
参数b= 1.0908126753128762
残差e= 0.12932179354125223

备注:

对于无噪声样本,残差值接近于0,: 2.9325459666068766e-05

对于有噪声样本,残差值不可能为0,一定有一定的残差值:0.12932179354125223

2.4.4 可视化迭代过程

(1) w,b,残差的并发收敛过程

# w,b,残差的并发收敛过程
w_data, b_data, e_data = rst[1]
w_diff, b_diff = rst[2]

fig = plt.figure()
ax = plt.axes(projection='3d')        #使用matplotlib.pyplot创建坐标系
ax.scatter3D(w_data, b_data, e_data, label="loss", cmap='rainbow')  #绘制三维散点图
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第13张图片

 (2)w参数的迭代过程:反映的是w值本身数值的变化过程

print("w参数的迭代过程")
print("参数w=", w_grad)
num = len(w_data)
x_seq = np.array(range(0,num))

plt.scatter(x_seq, w_data, label="sample", color="blue")

 [数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第14张图片

 (3)w的偏差变化过程:反映的是相邻两次w值之间的迭代步长的变化。

print("w的偏差变化过程")
print("final w_diff = ", w_diff[-1])

num = len(w_diff)
x_seq = np.array(range(0, num))

plt.scatter(x_seq, w_diff, label="sample", color="blue")
w的偏差变化过程
final w_diff =  -0.00023128483534975432

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第15张图片

(4)b参数的迭代过程:反映的是b值本身数值的变化过程

print("b参数的迭代过程")
print("参数b=", b_grad)

num = len(w_data)
x_seq = np.array(range(0,num))

plt.scatter(x_seq, b_data, label="sample", color="blue")
b参数的迭代过程
参数b= 1.0908126753128762

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第16张图片

 (5)b的偏差变化过程:反映的是相邻两次b值之间的迭代步长的变化。

print("b的偏差变化过程")
print("final b_diff = ", b_diff[-1])

num = len(b_diff)
x_seq = np.array(range(0, num))

plt.scatter(x_seq, b_diff, label="sample", color="blue")
b的偏差变化过程
final b_diff =  0.0001241309691854653

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第17张图片

 (5)残差的变化过程

print("残差的变化过程")
print("残差e=", e_grad)

num = len(w_data)
x_seq = np.array(range(0,num))

plt.scatter(x_seq, e_data, label="sample", color="blue")

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第18张图片

2.5 步骤4:利用获得的拟合函数进行数据预测 

# 步骤4:利用获得的拟合函数进行数据预测
print("scipy:", w_scipy,b_scipy)
print("user :", w_usr, b_usr)
print("grad :", w_grad, b_grad)

# scipy算法的拟合数据
y_data_scipy = f_line_wb(x_data, w_scipy, b_scipy)

# 线性方程组求解的拟合数据
# y_data_usr  = f_line_wb(x_data, w_usr, b_usr)

# 最小二乘+梯度下降算法的拟合数据
y_data_grad = f_line_wb(x_data, w_grad, b_grad)
scipy: 1.9182674578022025 1.0818607577986927
grad : 1.9015879580969595 1.0908126753128762

2.6 步骤5:可视化拟合函数

#步骤5: 图形化展示
#(1) 显示样本数据曲线
plt.scatter(x_data, y_data_noise, label="sample", color="black")

#(2) 显示理论数据曲线
plt.plot(x_data, y_data_pure, label="intrinsic", color="blue", linewidth = 2)

#(3-1) 显示预测数据曲线 -  scipy库实现
plt.plot(x_data, y_data_scipy,  label="predict",  color="red",  linewidth = 2)

#(3-2) 显示预测数据曲线 -  自定义实现
# plt.plot(x_data, y_data_usr,  label="predict",  color="green",  linewidth = 2)

#(3-3) 显示预测数据曲线 -  自定义梯度下降法
plt.plot(x_data, y_data_grad,  label="predict",  color="green",  linewidth = 2)

#设置属性
mpl.rcParams['font.sans-serif'] = ['SimHei']
mpl.rcParams['axes.unicode_minus'] = False
plt.title("线性拟合")
plt.legend(loc="upper left")
plt.show()

[数值计算-18]:最小二乘的求解法3 - 链式求导与梯度下降法求解loss函数的最优化参数(Python, 超详细、可视化)_第19张图片

 备注:

  • scipy库提供的拟合结果(红色red)与自定义的梯度下降法拟合的结果(绿色blue),基本重合。


作者主页(文火冰糖的硅基工坊):https://blog.csdn.net/HiWangWenBing

本文网址:https://blog.csdn.net/HiWangWenBing/article/details/119978818

你可能感兴趣的:(人工智能-深度学习,数值计算,人工智能-数学基础,梯度下降法,最小二乘,深度学习,Python实现,线性拟合)