深度学习 Pytorch 基本优化思想与最小二乘法

在正式开始进行神经网络建模之前,我们还需要掌握pytorch中最核心的基础数学工具——autograd(自动微分)模块。虽然对于任何一个通用的深度学习框架都会提供许多自动优化的算法和现成的loss function,但如果想更深入理解神经网络,对深度学习的建模不仅仅停留在调包和调参的层次,就必须掌握一些数学工具,在日后取得更好的建模效果。当然,要使用好微分工具,就首先要了解广泛应用于机器学习建模的优化思想。

所谓优化思想,指的是利用数学工具求解复杂问题的基本思想。在实际建模过程中,我们往往会给出待解决问题的数值评估指标,并在此基础上构建方程、采用数学工具、不断优化评估指标结果,以期达到可以达到的最优结果。

import numpy as np
import torch

21 简单线性回归的机器学习建模思路

在上一节末尾,我们曾简单提及线性方程建模问题,将方程组转化为矩阵表示形式,最终使用逆矩阵的方法解出线性方程系数。线性回归是较为基础且通用的模型,但使用矩阵方法求解不是通用方法。

接下来将进一步将简单线性回归的求解参数问题转化为最优化问题求解,这也是机器学习建模中最通用的思想。


21.1 回顾简单线性回归建模问题

import matplotlib as mpl
import matplotlib.pyplot as plt
A = torch.arange(1, 5).reshape(2, 2).float()
A
# output :
tensor([[1., 2.],[3., 4.]])
# 绘制点图查看两个点的位置
plt.plot(A[:, 0], A[:, 1], 'o')
# output :

在这里插入图片描述

如果更近一步,我们希望在二维空间中找到一条直线,来拟合这两个点,也就是所谓的构建以恶线性回归模型,我们可以设置线性回归方程如下:
y = a x + b y = ax + b y=ax+b

21.2 转化为优化问题

上述问题除了可以使用矩阵方法求解以外,还可以将其转化为最优化问题,然后通过求解最优化问题的方法对其进行求解。

最优化问题的转化分为两步,其一是确定优化数值指标,其二则是确定优化目标函数。在大多数问题中,这二者是相辅相成的,确定了优化的数值指标,也就确定了优化的目标函数。

如果我们希望通过一条直线拟合二维平面空间上分布的点,最核心的目标毫无疑问就是希望方程的预测值和真实值相差较小。假设真实的y值用y表示,预测值用ŷ表示,带入a、b参数,则表示如下:

x(i)y(i)ŷ(i)
12a+b
343a+b

y ^ 1 = 1 ∗ a + b = a + b ŷ_1 = 1*a + b = a + b y^1=1a+b=a+b

y ^ 2 = 3 ∗ a + b = 3 a + b ŷ_2 = 3*a + b = 3a + b y^2=3a+b=3a+b

而这两个预测值和真实值相差:
y 1 = 2 , y ^ 1 = a + b , y 1 − y ^ 1 = 2 − a − b y_1 = 2, ŷ_1 = a + b, y_1 - ŷ_1 = 2 - a - b y1=2,y^1=a+b,y1y^1=2ab

y 2 = 4 , y ^ 2 = 3 a + b , y 2 − y ^ 1 = 2 = 4 − 3 a − b y_2 = 4, ŷ_2 = 3a + b, y_2 - ŷ_1=2 = 4 - 3a - b y2=4,y^2=3a+b,y2y^1=2=43ab

我们希望yŷ尽可能接近,因此可以考虑计算上述误差总和,但为了避免正负相消,我们使用平方和来进行衡量两个点的误差总和,而不是简单的求和:
( y 1 − y ^ 1 ) 2 + ( y 2 − y ^ 2 ) 2 (y_1 - ŷ_1)^2 + (y_2 - ŷ_2)^2 (y1y^1)2+(y2y^2)2

= ( 2 − a − b ) 2 + ( 4 − 3 a − b ) 2 = (2 - a - b)^2 + (4 - 3a - b)^2 =(2ab)2+(43ab)2

上式也就是两个点的预测值和真实值间差值的平方和,也就是误差平方和(Sum of the Squared Errors)

此处只带入了(1,2)(3,4)两个点来计算SSE,也就是带入了两条数据来训练y = ax + b这个模型。

至此,我们已经将原问题转化为了一个最优化问题,接下来我们的问题是,当a、b取何值时,SSE取值最小?

值得注意的是,SSE方程就是我们优化的目标方程(求最小值),因此上述方程也被称为目标函数,同时,SSE代表着真实和预测之间的差值,因此也被称为损失函数

换言之,当SSE取值最小的时候,a、b的取值就是最终线性回归方程的系数取值。

注: 目标函数和损失函数并不完全等价,但大多数目标函数都由损失函数构成。


21.3 最优化问题的求解方法

在上述问题中,我们需要围绕SSE求最小值。SSE是一个关于ab的二元函数,要求其最小值,需要借助数学工具,也就是所谓的最优化方法。选择优化方法并执行相应计算,可以硕士整个建模过程中最核心也是相对较难的部分,很多时候这个过程会直接决定模型的性能。

图形展示目标函数

为了更好讨论目标函数(SSE)求最小值的过程,对于上述二元函数,我们可以将其展示在三维空间内。

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
x = np.arange(-1, 3, 0.05)
y = np.arange(-1, 3, 0.05)
a, b = np.meshgrid(x, y)	# 生成一个二维的网格点坐标矩阵a和b
SSE = (2 - a - b) ** 2 + (4 - 3 * a - b) ** 2
ax = plt.axes(projection = '3d')	# 创建了一个三维坐标轴对象ax
ax.plot_surface(a, b, SSE, cmap = 'rainbow')	# 在三维坐标轴上绘制曲面,cmap='rainbow'指定了颜色映射,使得曲面根据高度显示不同的颜色。
ax.contour(a, b, SSE, zdir = 'z', offset = 0, cmap = 'rainbow')
plt.show()	# 在三维视图中添加了等高线图
# output :

在这里插入图片描述


函数的凹凸性

不难看出目标函数是个整体“向下凸”的函数。

函数的凹凸性是函数的重要性质,首先我们给出凸函数的一般定义,对于任意一个函数,如果函数f(x)上存在任意两个点x1,x2,且
( f ( x 1 ) + f ( x 2 ) ) / 2 > = f ( ( x 1 + x 2 ) / 2 ) (f(x_1) + f(x_2))/2 >= f((x_1 + x_2)/2) (f(x1)+f(x2))/2>=f((x1+x2)/2)
我们就判定这个函数是凸函数。

典型的,例如y = x2,我们可以绘制函数图像如下:

x = np.arange(-10,10,0.1)
y = x ** 2
plt.plot(x, y, '-')
plt.show()
# output :

在这里插入图片描述

不难看出,函数上任意两个点y的取值的均值都不小于这两个点均值的y值。

# x1 = 1, x2 = 3
(1 ** 2 + 3 ** 2)/2
# output :
5.0
# x1 = 1, x2 = 3
((1+3)/2) ** 2
# output :
4.0

而对于一个凸函数来说,全域最小值明显存在,基于凸函数的数学定义,我们可以进一步给出求解上述SSE凸函数最小值的一般方法,也就是著名的最小二乘法。


凸函数的最小值

通过y = x2函数不难看出,最小值x = 0 唯一存在,并且最小值点对应的函数切线与x轴平行,也就是在最小值点,函数的导数为0。这其实也凸函数求解最小值的一般方法:

  1. 对于一元函数,如果存在导数为0的点,则该点就是最小值点;

  2. 对于多元函数,如果存在某一点,使得函数的各个自变量的偏导数都为0,则该点就是最小值点。

因此,对于凸函数的最小值求解,最基本的出发点就是寻找导数为0的点。而最小二乘法也是基于偏导函数取值为0联立的方程组进行的求解。

从更严格的意义上来说,凸函数的最小值点其实是根据边界点和驻点(导数为0的点)决定,如果没有边界点且没有驻点,则函数没有最小值(例如y = x),如果存在边界点,但没有驻点,则边界点的一侧就是最小值点。

如果存在驻点(且左右两边单调性相反),则驻点就是最小值点,例如,对于y = x2而言,y′ = 2x2x = 0x取值为0,也就是0点就是最小值点
值得注意的是,驻点也可以说是临界点,但不是拐点,拐点特指左右两边函数凹凸性发生变化的点,切勿和驻点混淆。

机器学习建模中的目标函数,大多数时候都是可导的函数,而凹凸性则是影响使用哪种最优化方法的最核心因素。正因如此,凸函数的最优化问题是优化方法的一类重要应用,甚至围绕凸函数,还衍生出了凸优化相关的一大类优化问题分支学科。

在机器学习中,我们经常听说的最小二乘法就是求解凸优化问题的重要工具。当然,很多本身不是针对凸函数设计的最优化方法,但鉴于凸函数在求最小值时的优异特性,我们也会在凸优化过程中应用,例如梯度下降、拟牛顿法等等等等,都是本次重点学习的内容。


SSE最小值

对于简单线性回归的损失函数,SSE是凸函数,因此,对于$ SSE(a,b) = (2 - a - b)^2 + (4 - 3a - b)^2 $而言,最小值点就是a、b两个参数求偏导等于0的点
S S E = ( y 1 − y ^ 1 ) 2 + ( y 2 − y ^ 2 ) 2 SSE = (y_1 - ŷ_1)^2 + (y_2 - ŷ_2)^2 SSE=(y1y^1)2+(y2y^2)2

= ( 2 − a − b ) 2 + ( 4 − 3 a − b ) 2 = (2 - a - b)^2 + (4 - 3a - b)^2 =(2ab)2+(43ab)2

∂ S S E ( a , b ) ∂ ( a ) = 0 \frac{\partial{SSE_(a,b)}}{\partial{(a)}} = 0 (a)SSE(a,b)=0

∂ S S E ( a , b ) ∂ ( b ) = 0 \frac{\partial{SSE_(a,b)}}{\partial{(b)}} = 0 (b)SSE(a,b)=0

其中:
∂ S S E ( a , b ) ∂ ( a ) = 2 ( 2 − a − b ) ∗ ( − 1 ) + 2 ( 4 − 3 a − b ) ∗ ( − 3 ) = 20 a + 8 b − 28 ( 1 ) = 0 \begin{align} \frac{\partial{SSE_{(a,b)}}}{\partial{(a)}} & = 2(2-a-b)*(-1) + 2(4-3a-b)*(-3)\\ & = 20a+8b-28(1)\\ & = 0 \end{align} (a)SSE(a,b)=2(2ab)(1)+2(43ab)(3)=20a+8b28(1)=0

∂ S S E ( a , b ) ∂ ( b ) = 2 ( 2 − a − b ) ∗ ( − 1 ) + 2 ( 4 − 3 a − b ) ∗ ( − 1 ) = 8 a + 4 b − 12 ( 2 ) = 0 \begin{align} \frac{\partial{SSE_{(a,b)}}}{\partial{(b)}} & = 2(2-a-b)*(-1) + 2(4-3a-b)*(-1)\\ & = 8a+4b-12(2) \\ & = 0 \end{align} (b)SSE(a,b)=2(2ab)(1)+2(43ab)(1)=8a+4b12(2)=0

( 1 ) 式 − ( 2 ) 式 ∗ 2 可得: 4 a − 4 = 0 , a = 1 (1)式 - (2)式*2 可得: 4a-4 = 0,a=1 (1)(2)2可得:4a4=0a=1

将 a = 1 带入 ( 2 ) 式可得: 4 b − 4 = 0 , b = 1 将a=1带入(2)式 可得: 4b-4 = 0,b=1 a=1带入(2)式可得:4b4=0b=1

y = x + 1 y = x + 1 y=x+1

利用偏导等于0得出的方程组求解线性回归方程参数,就是最小二乘法求解过程

此处我们求得a = 1,b = 1时,SSE(a,b)取得最小值,也就是(1,1)是目标函数的最小值点。


21.4 机器学习建模一般流程

至此,我们就完成了一个基本的简单线性回归建模过程。当然,对于线性回归来说,有很多种建模方式,哪怕是主流的统计学和机器学习,在利用线性回归进行建模时都有不一样的流程。

此处我们是通过一个简单的例子,来介绍机器学习、包括深度学习的利用优化方法建模的一般思想,我们可以将其总结如下:

  • Step 1:提出基本模型
      如本节中,我们试图利用一条直线(y=ax+b)去拟合二维平面空间中的点,这里我们所使用的这条直线,就是我们提出的基本模型。而在后续的深度学习的学习过程中,我们还将看到更为强大、同时也更加通用的神经网络模型。当然,不同的模型能够适用不同的场景,在提出模型时,我们往往会预设一些影响模型结构或者实际判别性能的参数,如简单线性回归中的a和b;

  • Step 2:确定损失函数和目标函数

    接下来,围绕建模的目标,我们需要合理设置损失函数,并在此基础之上设置目标函数,当然,在很多情况下,这二者是相同的。例如,在上述简单线性回归中,我们的建模目标就是希望y=ax+b这条直线能够尽可能的拟合(1,2)、(3,4)这两个点,或者说尽可能“穿过”这两个点,因此我们设置了SSE作为损失函数,也就是预测值和真实值的差值平方和。当然,在计算过程中不难发现,SSE是一个包含了a和b这两个变量的方程,因此SSE本身也是一个函数(a和b的二元函数),并且在线性回归中,SSE既是损失函数(用于衡量真实值和预测值差值的函数),同时也是我们的目标函数(接下来需要优化、或者说要求最小值的函数)。这里尤其需要注意的是,损失函数不是模型,而是模型参数所组成的一个函数。

  • Step 3:根据目标函数特性,选择优化方法,求解目标函数

    之前提到,目标函数既承载了我们优化的目标(让预测值和真实值尽可能接近),同时也是包含了模型参数的函数,因此完成建模需要确定参数、优化结果需要预测值尽可能接近真实值这两方面需求就统一到了求解目标函数最小值的过程中了,也就是说,当我们围绕目标函数求解最小值时,也就完成了模型参数的求解。当然,这个过程本质上就是一个数学的最优化过程,求解目标函数最小值本质上也就是一个最优化问题,而要解决这个问题,我们就需要灵活适用一些最优化方法。当然,在具体的最优化方法的选择上,函数本身的性质是重要影响因素,也就是说,不同类型、不同性质的函数会影响优化方法的选择。在简单线性回归中,由于目标函数是凸函数,我们根据凸函数性质,判断偏导函数取值为0的点就是最小值点,进而完成a、b的计算(也就是最小二乘法),其实就是通过函数本身的性质进行最优化方法的选取。


22 第一个优化算法:最小二乘法

前面提到,利用优化方法求解目标函数其实是机器学习建模过程中最为核心的环节,因此,我们有必要将围绕上述简单线性回归问题,进一步讨论最小二乘法背后的数学逻辑和优化思想,同时简单探讨数据的矩阵表示方法和基本矩阵运算。

虽然最小二乘法并不是主流的深度学习损失函数的优化算法,但从最小二乘法入手了解优化算法背后的数学逻辑,却是非常有必要,同时,线性方程也是构建神经网络模型的基础,因此,我们有必要深入探讨线性模型建模细节以及最基本的优化算法:最小二乘法。


最小二乘法的代数表示方法

从更加严格的数学角度出发,最小二乘法有两种表示形式,分别是代数法表示和矩阵表示。我们先看最小二乘法的代数表示方法。

首先,假设多元线性方程有如下形式:
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1x1+w2x2+...+wdxd+b
w = ( w 1 , w 2 , . . . w d ) w = (w_1,w_2,...w_d) w=(w1,w2,...wd) x = ( x 1 , x 2 , . . . x d ) x = (x_1,x_2,...x_d) x=(x1,x2,...xd),则上式可写为
f ( x ) = w T x + b f(x) = w^Tx+b f(x)=wTx+b

在机器学习领域,我们将线性回归自变量系数命名为w,其实是weight的简写,意为自变量的权重

多元线性回归的最小二乘法的代数法表示较为复杂,此处先考虑简单线性回归的最小二乘法表示形式。在简单线性回归中,w只包含一个分量,x也只包含一个分量,我们令此时的 x i x_i xi就是对应的自变量的取值,此时求解过程如下

优化目标可写为:
S S E = ∑ i = 1 m ( f ( x i ) − y i ) 2 = E ( w , b ) SSE = \sum^m_{i=1}(f(x_i)-y_i)^2 = E_(w,b) SSE=i=1m(f(xi)yi)2=E(w,b)
通过偏导为0求得最终结果的最小二乘法求解过程为:
∂ S S E ( w , b ) ∂ ( w ) = 2 ( w ∑ i = 1 m x i 2 − ∑ i = 1 m ( y i − b ) x i ) = 0 \begin{align} \frac{\partial{SSE_(w,b)}}{\partial{(w)}} & = 2(w\sum^m_{i=1}x^2_i - \sum^m_{i=1}(y_i-b)x_i) = 0 \end{align} (w)SSE(w,b)=2(wi=1mxi2i=1m(yib)xi)=0

∂ S S E ( w , b ) ∂ ( b ) = 2 ( m b − ∑ i = 1 m ( y i − w x i ) ) = 0 \begin{align} \frac{\partial{SSE_(w,b)}}{\partial{(b)}} & = 2(mb - \sum^m_{i=1}(y_i-wx_i)) = 0 \end{align} (b)SSE(w,b)=2(mbi=1m(yiwxi))=0

进而可得
w = ∑ i = 1 m y i ( x i − x ˉ ) ∑ i = 1 m x i 2 − 1 m ( ∑ i = 1 m x i ) 2 w = \frac{\sum^m_{i=1}y_i(x_i-\bar{x}) }{\sum^m_{i=1}x^2_i-\frac{1}{m}(\sum^m_{i=1}x_i)^2 } w=i=1mxi2m1(i=1mxi)2i=1myi(xixˉ)

b = 1 m ∑ i = 1 m ( y i − w x i ) b = \frac{1}{m}\sum^m_{i=1}(y_i-wx_i) b=m1i=1m(yiwxi)

其中, x ˉ = 1 m ∑ i = 1 m x i , x i \bar x = \frac{1}{m}\sum^m_{i=1}x_i,x_i xˉ=m1i=1mxixi为x的均值,并且 ( x i , y i ) (x_i,y_i) (xi,yi)代表二维空间中的点。


最小二乘法的矩阵表示形式

从上节的矩阵部分内容不难理解,对于线性方程组来说,矩阵表示是一种更加简洁的表示方式,并且对于支持数组运算的torch来说,线性方程组的矩阵表示也更贴近代码的实际书写形式。首先先回顾上节中提到的将上述方程转化为矩阵的过程。线性方程如下
1 ∗ a + b = 2 1*a + b = 2 1a+b=2

3 ∗ a + b = 4 3*a + b = 4 3a+b=4

在转化为矩阵表示的过程中,我们令
A = [ 1 1 3 1 ] A = \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right] A=[1311]

B = [ 2 4 ] B = \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] B=[24]

X T = [ a b ] X^T = \left [\begin{array}{cccc} a \\ b \\ \end{array}\right] XT=[ab]

则原方程组可表示为
A ∗ X T = B A * X^T = B AXT=B
更为一般的情况下,多元线性回归方程为
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1x1+w2x2+...+wdxd+b

w ^ = ( w 1 , w 2 , . . . , w d , b ) \hat w = (w_1,w_2,...,w_d,b) w^=(w1,w2,...,wd,b)

x ^ = ( x 1 , x 2 , . . . , x d , 1 ) \hat x = (x_1,x_2,...,x_d,1) x^=(x1,x2,...,xd,1)

  • w ^ \hat w w^:方程系数所组成的向量,并且我们将自变量系数和截距放到了一个向量中,此处 w ^ \hat w w^就相当于前例中的a、b组成的向量(a,b);
  • x ^ \hat x x^:方程自变量和1共同组成的向量;

因此,方程可表示为
f ( x ) = w ^ ∗ x ^ T f(x) = \hat w * \hat x^T f(x)=w^x^T
另外,我们将所有自变量的值放在一个矩阵中,并且和此前A矩阵类似,为了捕捉截距,添加一列全为1的列在矩阵的末尾,设总共有m组取值,则
X = [ x 11 x 12 . . . x 1 d 1 x 21 x 22 . . . x 2 d 1 . . . . . . . . . . . . 1 x m 1 x m 2 . . . x m d 1 ] X = \left [\begin{array}{cccc} x_{11} &x_{12} &... &x_{1d} &1 \\ x_{21} &x_{22} &... &x_{2d} &1 \\ ... &... &... &... &1 \\ x_{m1} &x_{m2} &... &x_{md} &1 \\ \end{array}\right] X= x11x21...xm1x12x22...xm2............x1dx2d...xmd1111
对应到前例中的A矩阵,A矩阵就是拥有一个自变量、两个取值的X矩阵。令y为因变量的取值,则有
y = [ y 1 y 2 . . . y m ] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] y= y1y2...ym
此时,SSE可表示为:
S S E = ∣ ∣ y − X w ^ T ∣ ∣ 2 2 = ( y − X w ^ T ) T ( y − X w ^ T ) = E ( w ^ ) SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w) SSE=∣∣yXw^T22=(yXw^T)T(yXw^T)=E(w^)
根据最小二乘法的求解过程,令 E ( w ^ ) E(\hat w) E(w^) w ^ \hat w w^求导方程取值为0,有
E ( w ^ ) ∂ w ^ = ∂ ∣ ∣ y − X w ^ T ∣ ∣ 2 2 ∂ w ^ = ∂ ( y − X w ^ T ) T ( y − X w ^ T ) ∂ w ^ ∵ ( A − B ) T = A T − B T 并且 ( A B ) T = B T ∗ A T ∴ 上式 = ∂ ( y T − w ^ X T ) ( y − X w ^ T ) ∂ w ^ = ∂ ( y T y − w ^ X T y − y T X w ^ T + w ^ X T X w ^ T ) ∂ w ^ = 0 − X T y − X T y + 2 X T X w ^ T = X T X w ^ T − X T y = 0 值得注意的是,在矩阵求导中, a 为常数,有如下规则: ∂ a ∂ A = 0 , ∂ A T B T C ∂ A = B T C , ∂ C T B A ∂ A = B T C , ∂ A T B A ∂ A = ( B + B T ) A \begin{aligned} \frac{E(\hat w)}{\partial{\boldsymbol{\hat w}}} &= \frac{\partial{||\boldsymbol{y} - \boldsymbol{X\hat w^T}||_2}^2}{\partial{\boldsymbol{\hat w}}} \\ &= \frac{\partial(\boldsymbol{y} - \boldsymbol{X\hat w^T})^T(\boldsymbol{y} - \boldsymbol{X\hat w^T})}{\partial{\boldsymbol{\hat w}}} \\ \\ \because &\ (A-B)^T = A^T - B^T并且(AB)^T = B^T*A^T \\ \\ \therefore& 上式=\frac{\partial(\boldsymbol{y}^T - \boldsymbol{\hat w X^T})(\boldsymbol{y} - \boldsymbol{X\hat w^T})}{\partial{\boldsymbol{\hat w}}} \\ &=\frac{\partial(\boldsymbol{y}^T\boldsymbol{y} - \boldsymbol{\hat w X^Ty}-\boldsymbol{y}^T\boldsymbol{X \hat w^T} +\boldsymbol{\hat wX^T}\boldsymbol{X\hat w^T})} {\partial{\boldsymbol{\hat w}}}\\ &= 0 - \boldsymbol{X^Ty} - \boldsymbol{X^Ty} + 2\boldsymbol{X^TX\hat w ^T}\\ &= \boldsymbol{X^TX\hat w^T} - \boldsymbol{X^Ty} = 0 \\ &值得注意的是,在矩阵求导中,a为常数,有如下规则: \begin{equation} \\\frac{\partial{a}}{\partial{A}} = 0, \ \ \ \frac{\partial{A^TB^TC}}{\partial{A}} = B^TC, \ \ \ \frac{\partial{C^TBA}}{\partial{A}} = B^TC, \ \ \ \frac{\partial{A^TBA}}{\partial{A}} = (B+B^T)A \end{equation} \end{aligned} w^E(w^)=w^∣∣yXw^T22=w^(yXw^T)T(yXw^T) (AB)T=ATBT并且(AB)T=BTAT上式=w^(yTw^XT)(yXw^T)=w^(yTyw^XTyyTXw^T+w^XTXw^T)=0XTyXTy+2XTXw^T=XTXw^TXTy=0值得注意的是,在矩阵求导中,a为常数,有如下规则:Aa=0,   AATBTC=BTC,   ACTBA=BTC,   AATBA=(B+BT)A
进一步可得
X T X w ^ T = X T y X^TX\hat w^T = X^Ty XTXw^T=XTy
要使得此式有解,等价于 X T X X^TX XTX(也被称为矩阵的交叉乘积crossprod存在逆矩阵,若存在,则可解出
w ^ T = ( X T X ) − 1 X T y \hat w ^T = (X^TX)^{-1}X^Ty w^T=(XTX)1XTy

最小二乘法的简单实现

回到最初的例子,不难发现,有如下对应关系:
X = A = [ 1 1 3 1 ] X = A = \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right] X=A=[1311]

y = B = [ 2 4 ] y = B = \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] y=B=[24]

w ^ T = X T = [ a b ] \hat w ^T = X^T = \left [\begin{array}{cccc} a \\ b \\ \end{array}\right] w^T=XT=[ab]

手动实现代码验证最小二乘法

X = A
X
# output :
tensor([[1., 1.],[3., 1.]])
y = B
y
# output :
tensor([[2.],[4.]])
X.t()
# output :
tensor([[1., 3.],[1., 1.]])
w = torch.mm(torch.mm(torch.inverse(torch.mm(X.t(),X)),X.t()),y)
w
# output :
tensor([[1.0000],[1.0000]])

和此前结果保持一致。当然,最小二乘法作为最优化问题的求解方法,我们可以这么理解w最终取值:当w取值为(1,1)时,自变量为w的SSE函数取得全域最小值。

当然,我们也可以直接调用最小二乘法函数torch.lstsq(B, A)进行求解

torch.lstsq(y, X)
# output :
torch.return_types.lstsq(
solution=tensor([[1.0000],[1.0000]]),
QR=tensor([[-3.1623, -1.2649],[ 0.7208, -0.6325]]))

对于lstsq函数来说,第一个参数是因变量张量,第二个参数是自变量张量,并且同时返回结果还包括QR矩阵分解的结果,QR分解也是一种矩阵分解方法,后续在涉及到QR分解内容时会详细进行讲解。

另外,在最小二乘法数学推导过程,涉及到矩阵范数的运算,在PyTorch中,我们使用linalg.norm函数求向量或矩阵的范数

在深度学习中,范数(Norm)是一个数学概念,用于衡量向量的大小或长度。它是一个非负值,可以用来表示向量在多维空间中的距离或幅度。范数在深度学习中被广泛应用于各种场景,例如正则化、梯度下降、损失函数等。

常见的范数有:

  1. L1范数(曼哈顿距离):向量各元素绝对值之和。
    ∥ x ∥ 1 = ∑ i = 1 n ∣ x i ∣ \|\mathbf{x}\|_1 = \sum_{i=1}^{n} |x_i| x1=i=1nxi
    L1范数在深度学习中常用于正则化,可以促进模型的稀疏性。

  2. L2范数(欧几里得距离):向量各元素平方和的平方根。
    ∥ x ∥ 2 = ∑ i = 1 n x i 2 \|\mathbf{x}\|_2 = \sqrt{\sum_{i=1}^{n} x_i^2} \ x2=i=1nxi2  

L2范数在深度学习中常用于正则化,可以防止模型过拟合。

注意,老版本教材会推荐使用norm函数进行求解,但实际上新版pytorch已经开始推荐使用linalg.norm替换norm进行范数运算,因此更推荐使用linalg.norm函数

t = torch.tensor([-1, 2.])
# 默认情况,求解L2范数,各元素的平方和开平方
torch.linalg.norm(t)
# output :
tensor(2.2361)
torch.sqrt(torch.tensor(5.))
# output :
tensor(2.2361)
# 输入参数,求解L1范数,各元素的绝对值之和
torch.linalg.norm(t, 1)
# output :
tensor(3.)

反向验证导数为零

当然,我们也可以反向验证,看下损失函数SSEa=1,b=1时偏导数是否都为0。此时就需要借助PyTorch中的autograd模块来进行偏导计算。严格意义上来讲,autograd模块是PyTorch中的自动微分模块,我们可以通过autograd模块中的函数进行微分运算,在神经网络模型中,通过自动微分运算求解梯度是模型优化的核心。关于微分计算梯度进而执行优化的相关方法我们会在后续逐步介绍,此处我们仅适用autograd模块来进行简单的微分计算尝试,也就是对SSE进行偏导计算,判断a、b同时取值为1时偏导是否为0

目前市面上流通的PyTorch教材有些会介绍Variable类,在进行微分运算时需提前将Tensor类转化为Variable类,但其实在PyTorch 0.4版本以后Tensor就已经不仅仅是一个纯计算的载体,而是可以支持微分运算,Variable的概念被逐渐弱化,可微分性也变成了Tensor的一个基本属性,我们只需要在创建Tensor时,通过设置requires_grad属性为True、规定张量可微分即可。

a = torch.tensor(1.,requires_grad = True)
a
# output :
tensor(1., requires_grad=True)

此时a就是一个可微分的张量,requires_grada的一个属性,可以查看可以修改。

# 查看可微分性
a.requires_grad
# output :
True
# 修改可微分性
a.requires_grad = False
a.requires_grad
# output :
False
a.requires_grad = True
b = torch.tensor(1.,requires_grad = True)
b
# output :
tensor(1., requires_grad=True)

然后创建损失函数
( y 1 − y ^ 1 ) 2 + ( y 2 − y ^ 2 ) 2 (y_1 - ŷ_1)^2 + (y_2 - ŷ_2)^2 (y1y^1)2+(y2y^2)2

= ( 2 − a − b ) 2 + ( 4 − 3 a − b ) 2 = (2 - a - b)^2 + (4 - 3a - b)^2 =(2ab)2+(43ab)2

sse = torch.pow((2 - a - b), 2) + torch.pow((4 - 3 * a - b), 2)

使用torch.autograd.grad进行偏导运算,并输出a=1、b=1时偏导数的值

torch.autograd.grad(sse,[a, b])
# output :
(tensor(-0.), tensor(-0.))

至此,也可验证(1,1)是损失函数的最小值点。


torch.autograd.grad函数

torch.autograd.grad是通用微分函数,当只输入一个自变量时计算结果就是导数,输入多个自变量时则会计算偏导数。

x = torch.tensor(1.,requires_grad = True)
y = x ** 2
# 导数计算结果
torch.autograd.grad(y, x)
# output :
(tensor(2.),)

当然,微分计算作为神经网络优化的核心,autograd模块的功能远不仅于此,更多的微分运算,我们将在下一节继续讲解。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/4140.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

word转pdf

依赖 先安装好MAVEN https://blog.csdn.net/m0_62214280/article/details/140643392 链接&#xff1a;https://pan.baidu.com/s/1jISO-TPEyLgC8RTmMJGRQw 提取码&#xff1a;9ju8 <dependency><groupId>com.aspose</groupId><artifactId>aspose-words…

【多线程】线程池

一、什么是线程池 线程池&#xff08;Thread Pool&#xff09;是一种多线程并发执行的设计模式&#xff0c;它通过维护一个线程集合来执行多个任务&#xff0c;避免频繁地创建和销毁线程&#xff0c;提高系统性能和响应速度。 就好比如你经营了一家餐饮店&#xff0c;你名下有…

【QT】: 初识 QWidget 控件 | QWidget 核心属性(API) | qrc 文件

&#x1f525; 目录 1. 控件概述 控件体系的发展阶段 2. QWidget 核心属性 2.1 核心属性概览2.2 用件可用&#xff08;Enabled&#xff09; 2.3 坐标系&#xff08;Geometry&#xff09; **实例 1: 控制按钮的位置**实例 2: 表白 程序 2.4 窗口标题&#xff08;windowTiltle&a…

CSS 合法颜色值

CSS 颜色 CSS 中的颜色可以通过以下方法指定&#xff1a; 十六进制颜色带透明度的十六进制颜色RGB 颜色RGBA 颜色HSL 颜色HSLA 颜色预定义/跨浏览器的颜色名称使用 currentcolor 关键字 十六进制颜色 用 #RRGGBB 规定十六进制颜色&#xff0c;其中 RR&#xff08;红色&…

C++第十五讲:异常

C第十五讲&#xff1a;异常 1.异常的概念和使用1.1异常的抛出和捕获1.2异常抛出和捕获的注意事项1.3异常的重新抛出1.4异常规范 2.标准库的异常 1.异常的概念和使用 1.1异常的抛出和捕获 异常的抛出和捕获的过程分为三个阶段&#xff1a; 1.异常的抛出&#xff1a; 使用throw对…

HTML<bdo>标签

例子 指定文本方向&#xff1a; <bdo dir"rtl"> This text will go right-to-left. </bdo> <!DOCTYPE html> <html> <body> <h1>The bdo element</h1> <p>This paragraph will go left-to-right.</p> …

Git:问题解决办法 及 Tips 总结

目录 查看历史记录及比较区别查看所有提交的历史记录查看提交的详细历史记录查看提交之间的差异点击文件操作历史&#xff0c;筛选出所有改动过此文件的提交任意两个提交之间的比较&#xff08;开发及查BUG常用&#xff09; 在需要版本回滚的情况下处理方法短时间内无法彻查BUG…

uniApp开通uniPush1.0个推,SpringBoot集成uniPush1.0个推

uniApp开通unipush1.0个推&#xff0c;SpringBoot程序集成 一、APP开通unipush1.0个推(商户App源码仅支持1.0个推) 1.app模块配置开通推送 2.应用开通推送 3.开通后点击消息推送菜单会看到如下页面 完成以上步骤后 此时android 仅支持在线推送。 4.配置各厂商离线推送 暂未…

[JavaScript] 深入理解流程控制结构

文章目录 1. **if-else 语句**基本语法&#xff1a;示例&#xff1a;扩展&#xff1a;else if 2. **switch-case 语句**基本语法&#xff1a;示例&#xff1a;注意事项&#xff1a; 3. **for 循环**基本语法&#xff1a;示例&#xff1a;扩展&#xff1a;for-in 和 for-of 4. *…

庄小焱——2024年博文总结与展望

摘要 大家好&#xff0c;我是庄小焱。岁末回首&#xff0c;2024 年是我在个人成长、博客创作以及生活平衡方面收获颇丰的一年。这一年的经历如同璀璨星辰&#xff0c;照亮了我前行的道路&#xff0c;也为未来的发展奠定了坚实基础。 1. 个人成长与突破 在 2024 年&#xff0c…

八大排序--冒泡排序

目录 什么是冒泡排序&#xff1f; 算法步骤 举例说明 代码实现&#xff08;java&#xff09; 什么是冒泡排序&#xff1f; 冒泡排序&#xff08;英语&#xff1a;Bubble sort&#xff09;是一种简单的排序算法。由于在算法的执行过程中&#xff0c;较小的元…

新阿里云买服务器配置需手动配置80端口

新买阿里云服务器需手动配置80&#xff0c;端口才可以访问nginx CentOS系统 安装nginx 1. 安装 Nginx yum install nginx 2. 启动 Nginx 服务 systemctl start nginx 3. 修改默认网页 cd /usr/share/nginx/ echo "666" >index.html cat index.html 访问ngin最后…

如何下载对应城市的地理json文件

这里采用的是阿里地图工具进行查找&#xff1a; DataV.GeoAtlas地理小工具系列 由阿里云DataV数据可视化团队出品,多年深耕数据可视化领域,数据大屏业务开拓者和领航者。致力用震撼而清晰的视觉语言,让更多人读懂大数据,受惠数据驱动的决策方式 第一步打开网站 &#xff1a; …

“libcudart,so.1 1.0“ loss解决方案

sudo find /usr/ -name libcudart.so.11.0 2 > /dev/null参考链接&#xff1a;1、https://stackoverflow.com/questions/70967651/could-not-load-dynamic-library-libcudart-so-11-0 2、https://blog.csdn.net/weixin_43786241/article/details/109203995

通过图形界面展现基于本地知识库构建RAG应用

1. 客户需求 快速完成概念验证(PoC)通过图形界面快速完成演示本地私有数据对比不同模型和成本&#xff0c;决定如何部署 2. 阿里云基于本地知识库构建RAG应用 参考方案&#xff1a; 百炼本地知识库方案 解决方案&#xff1a; FastAPI Gradio Llamaindex qwen-plus 主要三大…

安路FPGA开发工具TD:问题解决办法 及 Tips 总结

安路科技&#xff08;Anlogic&#xff09;是一家专注于高性能、低功耗可编程逻辑器件&#xff08;FPGA&#xff09;设计和生产的公司。其提供的开发工具TD&#xff08;TangDynasty&#xff09;是专门为安路FPGA系列产品设计的集成开发环境&#xff08;IDE&#xff09;。以下是对…

聚铭网络6款产品入选CCIA《网络安全专用产品指南》

近日&#xff0c;中国网络安全产业联盟CCIA正式发布《网络安全专用产品指南》&#xff08;第二版&#xff09;&#xff08;以下简称《指南》&#xff09;。聚铭网络凭借突出技术优势、创新能力以及市场积累&#xff0c;旗下安全产品成功入选防火墙、网络安全审计、日志分析、网…

渗透笔记1

第一天 工具&#xff1a;cs cobalt strike 4.9 / msf kali &#xff08;自带 Ubuntu&#xff09; cs cobalt strike 4.9&#xff1a;server-client server部署在云服务器上&#xff0c;client分别在各地&#xff0c;与server相连接&#xff1b;连接上后就可以共享上线主机。…

计算机网络 (51)鉴别

前言 计算机网络鉴别是信息安全领域中的一项关键技术&#xff0c;主要用于验证用户或信息的真实性&#xff0c;以及确保信息的完整性和来源的可靠性。 一、目的与重要性 鉴别的目的是验明用户或信息的正身&#xff0c;对实体声称的身份进行唯一识别&#xff0c;以便验证其访问请…

《Vue3 九》动画

Vue 提供了一些内置组件和对应的 API 来完成动画&#xff0c;利用它们可以方便地实现动画效果。 <transition> 内置组件&#xff1a; Vue 提供了 <transition> 内置组件&#xff0c;可以给任意元素或组件添加进入/离开时的动画效果。在条件渲染、动态组件、改变 …