Lesson 2. 矩阵运算基础、矩阵求导与最小二乘法

news2024/11/24 4:49:52

文章目录

  • 一、NumPy 矩阵运算基础
    • 1. NumPy 中的矩阵表示
    • 2. NumPy 中特殊矩阵构造方法
    • 3. NumPy 中矩阵基本运算
    • 4. NumPy 中矩阵代数运算
  • 二、矩阵方程与向量求导方法
    • 1. 方程组求解与矩阵方程求解
    • 2. 向量求导运算
      • 2.1 向量求导基本方法
      • 2.2 常见向量求导公式
  • 三、最小二乘法的推导过程及使用方法
    • 1. 模型及方程组的矩阵形式改写
    • 2. 构造损失函数
    • 3. 最小二乘法求解损失函数的一般过程
    • 4. 最小二乘法的简单实现

  • 在 Lesson 1 中,我们在基本没有数学公式和代码的情况下,简单介绍了关于线性回归的一般实现形式。不过这只是在初学阶段、为了不增加基础概念理解难度所采取的方法,但所有的技术最终都是为了解决实际问题的。
  • 因此,接下来,我们就在之前的基础上更进一步,从一个更加严谨的理论体系出发、来尝试进行一种更加贴合实际应用所采用的一般方法的建模方法的学习。
import numpy as np
import pandas as pd

一、NumPy 矩阵运算基础

  • 在机器学习基础阶段,需要掌握的矩阵及线性代数基本理论包括:
  • (1) 矩阵的形变及特殊矩阵的构造方法:包括矩阵的转置、对角矩阵的创建、单位矩阵的创建、上/下三角矩阵的创建等;
  • (2) 矩阵的基本运算:包括矩阵乘法、向量内积、矩阵和向量的乘法等;
  • (3) 矩阵的线性代数运算:包括矩阵的迹、矩阵的秩、逆矩阵的求解、伴随矩阵和广义逆矩阵等;
  • (4) 矩阵分解运算:特征分解、奇异值分解和 SVD 分解等。

1. NumPy 中的矩阵表示

  • 在 NumPy 中,二维数组(array)和 matrix 类型对象都可以用于表示矩阵,并且也都具备矩阵的代数学方法。
  • 利用数组创建矩阵。
A = np.array([[1, 2], [1, 1]])
A
#array([[1, 2],
#       [1, 1]])

type(A) #查看对象类型
#numpy.ndarray
  • 利用 mat 创建矩阵。
AM = np.mat(A)
AM
#matrix([[1, 2],
#        [1, 1]])

type(AM) #查看对象类型
#numpy.matrix
  • 关于两种对象类型的选取,此处进行简单说明:
  • (1) NumPy 中的 matrix 类型对象和 MATLAB 中的 matrix 类型等价,和 NumPy 中数组类型对象底层基本结构不同;
  • (2) 在 NumPy 中,针对大规模数据,数组类型对象的计算速度要快于矩阵类型对象
  • (3) 矩阵类型对象可以通过运算符直接进行矩阵乘法,而二维数组要进行矩阵乘法(及其他矩阵运算),则必须要使用包括 linalg(线性代数运算)模块在内的相关函数。
AM * AM
#matrix([[3, 4],
#        [2, 3]])

A.dot(A)
#array([[3, 4],
#       [2, 3]])

# 新版NumPy也支持使用符号进行矩阵乘法
A @ A
#array([[3, 4],
#       [2, 3]])
  • 在上述代码当中,A.dot(A) 表示矩阵 A 与矩阵 A 乘积。
  • 为了执行更高效的计算、以及确保代码整体基本对象类型统一,如无说明,将统一使用二维数组表示矩阵。

2. NumPy 中特殊矩阵构造方法

  • 在实际线性代数运算过程中,经常涉及一些特殊矩阵,如单位矩阵、对角矩阵等,相关创建方法如下:
函数描述
a.T数组a转置
np.eye(n)创建包含n个分量的单位矩阵
np.diag(a1)以a1中各元素,创建对角矩阵
np.triu(a)取矩阵a中的上三角矩阵
np.tril(a)取矩阵a中的下三角矩阵
# 创建一个2*3的矩阵
a1 = np.arange(1, 7).reshape(2, 3)
a1
#array([[1, 2, 3],
#       [4, 5, 6]])

# 转置
a1.T
#array([[1, 4],
#       [2, 5],
#       [3, 6]])
  • 矩阵的转置就是每个元素行列位置互换。
  • 在上述代码当中:
  • np.arange 函数共有三个参数,第一个参数是 start 表示起点,第二个参数是 stop 表示终点,第三个参数是 step 表示步长。
  • (1) 一个参数时,参数值为终点,起点取默认值 0,步长取默认值 1。
  • (2) 两个参数时,第一个参数为起点,第二个参数为终点,步长取默认值 1。
  • (3) 当有三个参数时,第一个参数为起点,第二个参数为终点,第三个参数为步长,步长可以是小数。
  • np.reshape 函数用于矩阵规格变换,将矩阵转换为特定的行和列的矩阵。
  • (1) 若是 np.reshape(x, -1) 则是将矩阵变成行数为 x,列数不规定的矩阵,具体列数按照总元素个数除行数,均分得到。
  • (2) 若是 np.reshape(-1, x) 则是将矩阵变成列数为 x,行数不规定的矩阵,具体行数按照总元素个数除列数,均分得到。
# 创建单位矩阵
np.eye(3)
#array([[1., 0., 0.],
#       [0., 1., 0.],
#       [0., 0., 1.]])
  • 单位矩阵之所以被称为单位,核心原因在于单位矩阵和任何矩阵相乘,都将返回原矩阵。
a = np.arange(5)
a
#array([0, 1, 2, 3, 4])

np.diag(a)
#array([[0, 0, 0, 0, 0],
#       [0, 1, 0, 0, 0],
#       [0, 0, 2, 0, 0],
#       [0, 0, 0, 3, 0],
#       [0, 0, 0, 0, 4]])

# 对角线向上偏移一位
np.diag(a, 1)
#array([[0, 0, 0, 0, 0, 0],
#       [0, 0, 1, 0, 0, 0],
#       [0, 0, 0, 2, 0, 0],
#       [0, 0, 0, 0, 3, 0],
#       [0, 0, 0, 0, 0, 4],
#       [0, 0, 0, 0, 0, 0]])

# 对角线向下偏移一位
np.diag(a, -1)
#array([[0, 0, 0, 0, 0, 0],
#       [0, 0, 0, 0, 0, 0],
#       [0, 1, 0, 0, 0, 0],
#       [0, 0, 2, 0, 0, 0],
#       [0, 0, 0, 3, 0, 0],
#       [0, 0, 0, 0, 4, 0]])

a1 = np.arange(9).reshape(3, 3)
a1
#array([[0, 1, 2],
#       [3, 4, 5],
#       [6, 7, 8]])

# 取上三角矩阵
np.triu(a1)
#array([[0, 1, 2],
#       [0, 4, 5],
#       [0, 0, 8]])

# 上三角矩阵向左下偏移一位
np.triu(a1, -1)
#array([[0, 1, 2],
#       [3, 4, 5],
#       [0, 7, 8]])

# 上三角矩阵向右上偏移一位
np.triu(a1, 1)
#array([[0, 1, 2],
#       [0, 0, 5],
#       [0, 0, 0]])

# 下三角矩阵
np.tril(a1)
#array([[0, 0, 0],
#       [3, 4, 0],
#       [6, 7, 8]])

3. NumPy 中矩阵基本运算

  • 由于 NumPy 中我们使用二维数组来表述矩阵,因此二维数组也就具备了数组和矩阵的两重属性。
  • 其中数组属性决定的基本运算相对简单,基础运算(如加减乘除)就是对应位置元素进行逐元素计算。
  • 矩阵属性决定的运算则稍显复杂,当然矩阵的相关线性代数运算将在下一小节讨论,在基础运算上,矩阵和数组核心的区别在于乘法运算。
  • 从另一个角度考虑,其实对于向量和矩阵这种具备一定结构的对象,有很多种容易混淆的计算规则。对于常用的计算规则,我们通过将其划分成三类以帮助大家理解:
描述解释/函数
逐元素相乘向量、矩阵通用
每个对应位置元素相乘*
逐元素相乘后相加也被称为点积(内积),向量,矩阵通用
向量点积vdot、dot、inner
矩阵点积vdot
矩阵乘法代数学意义的矩阵相乘
矩阵乘法dot、matmul、@
  • * :逐元素相乘
a = np.arange(4)
a
#array([0, 1, 2, 3])

a * a
#array([0, 1, 4, 9])

A = a.reshape(2, 2)
A
#array([[0, 1],
#       [2, 3]])

A * A
#array([[0, 1],
#       [4, 9]])
  • 向量点积(也被称为内积),指的是向量或矩阵对应位置元素相乘后相加。
  • 向量点积有三种实现方法,分别是 dot、vdot 和 ineer。
np.dot(a, a)
#14

a.dot(a)
#14

(a * a).sum()
#14

np.vdot(a, a)
#14

np.inner(a, a)
#14
  • 矩阵点积(内积)只有 vdot 一种方式实现。
A
#array([[0, 1],
#      [2, 3]])

np.vdot(A, A)
#14

(A * A).sum()
#14
  • 注意,高维数组的 inner 并不是内积。
  • 矩阵乘法,在 NumPy 中,我们可以使用诸多方法实现矩阵乘法,包括 dot、@、matmul 等。
a1 = np.arange(1, 7).reshape(2, 3)
a1
#array([[1, 2, 3],
#       [4, 5, 6]])

a2 = np.arange(1, 10).reshape(3, 3)
a2
#array([[1, 2, 3],
#       [4, 5, 6],
#       [7, 8, 9]])

# 矩阵乘法
np.matmul(a1, a2)
#array([[30, 36, 42],
#       [66, 81, 96]])
  • 此处也简单回顾矩阵乘法运算,上述相乘过程如下所示:

在这里插入图片描述

  • 需要注意的是,矩阵相乘要求左乘矩阵列数和右乘矩阵行数相同,而内积计算过程则严格要求两个向量/矩阵形状完全一致。

4. NumPy 中矩阵代数运算

  • 如果说矩阵的基本运算是矩阵基本性质,那么矩阵的线性代数运算,则是我们利用矩阵数据类型在求解实际问题过程中经常涉及到的线性代数方法,具体相关函数如下。
函数描述
np.trace(A)矩阵的迹
np.linalg.matrix_rank(A)矩阵的秩
np.linalg…det(A)计算矩阵A的行列式
np.linalg.inv(A)矩阵求逆
  • NumPy 中的 linalg 是 linear algebra(线性代数)的简写,也是 NumPy 中保存线性代数相关计算函数的模块。
  • 矩阵的迹(trace)运算相对简单,就是矩阵对角线元素之和,在 NumPy 中,可以使用 trace 函数进行计算。
A = np.array([[1, 2], [4, 5]])
A
#array([[1, 2],
#       [4, 5]])

np.trace(A)
#6
  • 当然,对于矩阵的迹来说,计算过程不需要是行列相同的方阵。
B = np.arange(1, 7).reshape(2, 3)
B
#array([[1, 2, 3],
#       [4, 5, 6]])
       
np.trace(B)
#6
  • 矩阵的秩(rank),是指矩阵中行或列的极大线性无关数,且矩阵中行、列极大无关数总是相同的,任何矩阵的秩都是唯一值,满秩指的是方阵(行数和列数相同的矩阵)中行数、列数和秩相同,满秩矩阵有线性唯一解等重要特性,而其他矩阵也能通过求解秩来降维,同时,秩也是奇异值分解等运算中涉及到的重要概念。
  • 线性相关,其实也就是线性表示,如果 y=wx+b,我们则称 y 可以由 x 线性表示,二者线性相关,反之则线性无关。类似,如果 y=w1x1w2x2+b,则我们称 y 可以由 x1、x2 线性表示,y与 x1、x2 线性相关。
  • matrix_rank 计算矩阵的秩。
A = np.array([[1, 3, 4], [2, 1, 3], [1, 1, 2]])
A
#array([[1, 3, 4],
#       [2, 1, 3],
#       [1, 1, 2]])

np.linalg.matrix_rank(A)
#2
  • 对于矩阵 A 来说,第三列明显可以由第一列和第二列相加得出,因此极大线性无关组只有两列。
B = np.array([[1, 3, 4], [2, 1, 3], [1, 1, 10]])
B
#array([[ 1,  3,  4],
#       [ 2,  1,  3],
#       [ 1,  1, 10]])

np.linalg.matrix_rank(B)
#3
  • 矩阵的行列式(det),通过行列式的计算,我们能够知道矩阵是否可逆,从而可以进一步求解矩阵所对应的线性方程。当然,更加专业的解释,行列式的作为一个基本数学工具,实际上就是矩阵进行线性变换的伸缩因子。
  • 对于任何一个 n 维方阵,行列式计算过程如下:

在这里插入图片描述

  • 更为简单的情况,如果对于一个 2 乘 2 的矩阵,行列式的计算就是主对角线元素之积减去另外两个元素之积。
A = np.array([[1, 2], [4, 5]])
A
#array([[1, 2],
#       [4, 5]])

np.linalg.det(A)
#-2.9999999999999996
  • A 的秩计算过程如下:

在这里插入图片描述

  • 对于行列式的计算,要求矩阵必须是方阵,也就是行列数必须一致。
B = np.arange(1, 7).reshape(2, 3)
B
#array([[1, 2, 3],
#       [4, 5, 6]])

np.linalg.det(B)

在这里插入图片描述

A = np.array([[1, 3, 4], [2, 1, 3], [1, 1, 2]])
A
#array([[1, 3, 4],
#       [2, 1, 3],
#       [1, 1, 2]])
       
np.linalg.det(A)
#0.0
  • 矩阵的逆,对于满秩的方阵来说,可以求其逆矩阵。
  • 从基本定义上来看,如果矩阵 B 和矩阵 A 相乘能够得到单位矩阵,即:B⋅A=E 则称矩阵 B 为矩阵 A 的逆矩阵,也可将矩阵 B 写作 A−1
  • 逆矩阵的性质是相互的,我们也可称 A 为 B 的逆矩阵,或者 A 和 B 互为逆矩阵。
A = np.array([[1, 1], [3, 1]])
A
#array([[1, 1],
#       [3, 1]])
  • 然后使用 inverse 函数进行逆矩阵求解。
np.linalg.inv(A)
#array([[-0.5,  0.5],
#       [ 1.5, -0.5]])
  • 简单试探逆矩阵的基本特性。
A.dot(np.linalg.inv(A))
#array([[1.00000000e+00, 1.11022302e-16],
#       [2.22044605e-16, 1.00000000e+00]])
  • 当然,对于逆矩阵,还有很多其他理解角度。
  • 例如,从方程组求解角度来看,逆矩阵的存在就代表着方程组存在唯一解,并且逆矩阵本身也是方程组求解的关键;从矩阵分解角度来看,逆矩阵是一种最为基础的矩阵分解的形式。

二、矩阵方程与向量求导方法

  • 在铺垫了基本矩阵和线性代数相关知识后,接下来,我们尝试将 Lesson 1 中的方程组表示形式转化为矩阵表示形式,并借助矩阵方法进行相关方程的求解。
  • 在 Lesson 1 中,我们已经简单讨论了最小二乘法这一优化算法的基本思路,最小二乘法一个最基础的优化算法。
  • 因此,本节开始,我们先从矩阵方程入手,先进行矩阵运算的相关方法的回顾、以及进行矩阵求导方法的讲解,讨论最小二乘法的基本原理。

1. 方程组求解与矩阵方程求解

  • 在 Lesson 1 中,我们曾经利用损失函数的偏导函数方程组进行简单线性回归模型参数的求解:
    ∂ S S E L o s s ∂ ( w ) = 2 ( 2 − w − b ) ∗ ( − 1 ) + 2 ( 4 − 3 w − b ) ∗ ( − 3 ) = 20 w + 8 b − 28 = 0 \begin{aligned} \frac{\partial{SSELoss}}{\partial{(w)}} &= 2(2-w-b)*(-1) + 2(4-3w-b)*(-3)\\ & = 20w+8b-28 \\ & = 0 \end{aligned} (w)SSELoss=2(2wb)(1)+2(43wb)(3)=20w+8b28=0 ∂ S S E L o s s ∂ ( b ) = 2 ( 2 − w − b ) ∗ ( − 1 ) + 2 ( 4 − 3 w − b ) ∗ ( − 1 ) = 8 w + 4 b − 12 = 0 \begin{aligned} \frac{\partial{SSELoss}}{\partial{(b)}} & = 2(2-w-b)*(-1) + 2(4-3w-b)*(-1)\\ & = 8w+4b-12 \\ & = 0 \end{aligned} (b)SSELoss=2(2wb)(1)+2(43wb)(1)=8w+4b12=0
  • 尽管方程组求解有很多种方法,类似 Lesson 1 中所采用的,先通过方程变量相消法反解出一个变量(w=1),再将其带入其中任意一个式子求解出另一个变量(b=1),确实能够顺利求出方程组的解。
  • 但在如果想借助编程工具求解方程组,则需要将原先的方程组求解问题转化为矩阵方程的求解问题。例如:上述求解过程方程组为:
    20 w + 8 b − 28 = 0 20w+8b-28=0 20w+8b28=0 8 w + 4 b − 12 = 0 8w+4b-12=0 8w+4b12=0
  • 我们令:
    A = [ 20 8 8 4 ] A = \left [\begin{array}{cccc} 20 &8 \\ 8 &4 \\ \end{array}\right] A=[20884] B = [ 28 12 ] B = \left [\begin{array}{cccc} 28 \\ 12 \\ \end{array}\right] B=[2812] X = [ w b ] X = \left [\begin{array}{cccc} w \\ b \\ \end{array}\right] X=[wb]
  • 其中 X 为参数向量。借助矩阵运算相关知识,上述方程组可等价表示为: A ⋅ X − B = 0 A \cdot X - B = 0 AXB=0
  • A ⋅ X = B A \cdot X = B AX=B
  • 至此我们就将方程组转化为了矩阵方程,并且,借助矩阵运算,我们可以直接在矩阵方程中对参数向量 X 进行求解。
  • 首先我们利用 NumPy 基础知识,通过创建二维张量去表示上述矩阵方程中的 A 和 B。
A = np.array([[20, 8], [8, 4]])
A
#array([[20,  8],
#       [ 8,  4]])

B = np.array([[28, 12]]).T
B
#array([[28],
#       [12]])
  • 此时 B 也是二维张量,可以使用矩阵乘法。
B.ndim
#2
  • 然后通过行列式计算结果,简单验证 A 是否满秩。
np.linalg.matrix_rank(A)
#2
  • 当然,也可以通过观察 A 的行列式计算结果是否为 0,来判断A是否满秩。
np.linalg.det(A)
#15.999999999999991
  • 对于满秩矩阵,我们可以求其逆矩阵。
np.linalg.inv(A)
#array([[ 0.25, -0.5 ],
#       [-0.5 ,  1.25]])
  • 然后在矩阵方程左右两端同时左乘其逆矩阵,即可解出 X 的取值。
    A − 1 A X = A − 1 B A^{-1}AX=A^{-1}B A1AX=A1B X = A − 1 B X=A^{-1}B X=A1B
np.matmul(np.linalg.inv(A), B)
#array([[1.],
#       [1.]])

# 也可以使用dot方法,对于二维数组,dot就是执行矩阵乘法
np.linalg.inv(A).dot(B)
#array([[1.],
#       [1.]]
  • X = [ w b ] = [ 1 1 ] X = \left [\begin{array}{cccc} w \\ b \\ \end{array}\right] =\left [\begin{array}{cccc} 1 \\ 1 \\ \end{array}\right] X=[wb]=[11]
  • 当然,此外,NumPy 中还提供了一种求解矩阵方程的函数,类似于上述 A∗XT=B 的矩阵方程,我们还可以通过下式进行求解。
np.linalg.solve(A, B)
#array([[1.],
#       [1.]])

2. 向量求导运算

2.1 向量求导基本方法

  • 首先,我们先来看相对简单的向量求导方法。假设现有一个二元函数如下。
    f ( x 1 , x 2 ) = 2 x 1 + x 2 f(x_1,x_2) = 2x_1+x_2 f(x1,x2)=2x1+x2
  • 并且,我们可以分别对该函数中的两个变量 x1、x2 依次求偏导,可得。
    ∂ f ∂ x 1 = 2 \frac{\partial f}{\partial x_1} = 2 x1f=2 ∂ f ∂ x 2 = 1 \frac{\partial f}{\partial x_2} = 1 x2f=1
  • 现在我们考虑将上述求偏导的函数组改写为矩阵形式。则根据前述内容介绍,我们可以将函数中的两个变量依次排列,组成一个向量变元,即一个由多个变量所组成的向量。
    x = [ x 1 , x 2 ] T x = [x_1, x_2]^T x=[x1,x2]T
  • 此时,如果我们按照向量变元内部的变量排列顺序,依次在每个变量位置填上该变量对应的偏导函数,则就构成了对于函数 f 进行向量变元 x 的向量求导的结果。
    ∂ f ( x ) ∂ x = [ 2 1 ] \frac{\partial f(x)}{\partial x} = \left [\begin{array}{cccc} 2 \\ 1 \\ \end{array}\right] xf(x)=[21]
  • 其中, x 为向量变元。
  • 至此,我们就完成了向量求导的基本过程。核心点在于,我们是依据向量变元中的变量排列顺序,依次填写了对应变量的偏导函数计算结果。
  • 不过,更进一步的来看,既然方程组需要改写成向量/矩阵形式,那么原始函数方程其实也同样需要改写成向量/矩阵形式。因此,原方程我们可以改写成。
    f ( x ) = A T ⋅ x f(x) = A^T \cdot x f(x)=ATx
  • 其中。
    A = [ 2 , 1 ] T A = [2, 1]^T A=[2,1]T
    x = [ x 1 , x 2 ] T x = [x_1, x_2]^T x=[x1,x2]T
  • 原方程为。
    y = 2 x 1 + x 2 y = 2x_1+x_2 y=2x1+x2
  • 结合函数求导结果,我们不难发现, ∂ f ( x ) ∂ x \frac{\partial f(x)}{\partial x} xf(x)最终计算结果就是 A A A
    ∂ f ( x ) ∂ x = ∂ ( A T ⋅ x ) ∂ x = A \frac{\partial f(x)}{\partial x} = \frac{\partial(A^T \cdot x)}{\partial x} = A xf(x)=x(ATx)=A
  • 其中 x 是向量变元, A 是列向量。
  • 很多时候我们并不区分所谓向量方程和矩阵方程,一般所有自变量为向量或矩阵的方程,我们会统一称其为矩阵方程。包含向量或者矩阵的表达式,我们也会统一称其为矩阵表达式。
  • 向量求导的定义法。
  • f ( x ) f(x) f(x) 是一个关于 x x x 的函数,其中 x x x 是向量变元,并且 x = [ x 1 , x 2 , . . . , x n ] T x = [x_1, x_2,...,x_n]^T x=[x1,x2,...,xn]T
  • ∂ f ∂ x = [ ∂ f ∂ x 1 , ∂ f ∂ x 2 , . . . , ∂ f ∂ x n ] T \frac{\partial f}{\partial x} = [\frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n}]^T xf=[x1f,x2f,...,xnf]T
  • 而该表达式也被称为向量求导的梯度向量形式。
    ∇ x f ( x ) = ∂ f ∂ x = [ ∂ f ∂ x 1 , ∂ f ∂ x 2 , . . . , ∂ f ∂ x n ] T \nabla _xf(x) = \frac{\partial f}{\partial x} = [\frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n}]^T xf(x)=xf=[x1f,x2f,...,xnf]T
  • 通过求得函数的梯度向量求解向量导数的方法,也被称为定义法求解。
  • 值得注意的是,多元函数是一定能够求得梯度向量的,但梯度向量或者说向量求导结果,能否由一些已经定义的向量解决表示,如 A A A 就是 f ( x ) f(x) f(x) 的向量求导结果,则不一定。

2.2 常见向量求导公式

  • 在前期学习中,数学理论推导涉及到的求导以向量变元求导居多,因此,除了掌握基本的向量求导方法以外,我们还需要推导几个常用的向量求导公式,在这些公式中,向量求导结果都能通过一些已经定义的向量简洁表示。
  • 同样,此处我们假设 x 为包含 n 各变量的列向量, x = [ x 1 , x 2 , . . . , x n ] T x = [x_1, x_2,...,x_n]^T x=[x1,x2,...,xn]T
  • (1) ∂ a ∂ x = 0 \frac{\partial a}{\partial x} = 0 xa=0证明:
    ∂ a ∂ x = [ ∂ a ∂ x 1 , ∂ a ∂ x 2 , . . . , ∂ a ∂ x n ] T = [ 0 , 0 , . . . , 0 ] T \frac{\partial a}{\partial x} = [\frac{\partial a}{\partial x_1}, \frac{\partial a}{\partial x_2}, ..., \frac{\partial a}{\partial x_n}]^T = [0,0,...,0]^T xa=[x1a,x2a,...,xna]T=[0,0,...,0]T
  • (2)
    ∂ ( x T ⋅ A ) ∂ x = ∂ ( A T ⋅ x ) ∂ x = A \frac{\partial(x^T \cdot A)}{\partial x} = \frac{\partial(A^T \cdot x)}{\partial x} = A x(xTA)=x(ATx)=A
  • 证明,此时 A 为拥有 n 个分量的常数向量,设 A = [ a 1 , a 2 , . . . , a n ] T A = [a_1, a_2,...,a_n]^T A=[a1,a2,...,an]T,则有
    ∂ ( x T ⋅ A ) ∂ x = ∂ ( A T ⋅ x ) ∂ x = ∂ ( a 1 ⋅ x 1 + a 2 ⋅ x 2 + . . . + a n ⋅ x n ) ∂ x = [ ∂ ( a 1 ⋅ x 1 + a 2 ⋅ x 2 + . . . + a n ⋅ x n ) ∂ x 1 ∂ ( a 1 ⋅ x 1 + a 2 ⋅ x 2 + . . . + a n ⋅ x n ) ∂ x 2 . . . ∂ ( a 1 ⋅ x 1 + a 2 ⋅ x 2 + . . . + a n ⋅ x n ) ∂ x n ] = [ a 1 a 2 . . . a n ] = A \begin{aligned} \frac{\partial(x^T \cdot A)}{\partial x} & = \frac{\partial(A^T \cdot x)}{\partial x}\\ & = \frac{\partial(a_1 \cdot x_1 + a_2 \cdot x_2 +...+ a_n \cdot x_n)}{\partial x}\\ & = \left [\begin{array}{cccc} \frac{\partial(a_1 \cdot x_1 + a_2 \cdot x_2 +...+ a_n \cdot x_n)}{\partial x_1} \\ \frac{\partial(a_1 \cdot x_1 + a_2 \cdot x_2 +...+ a_n \cdot x_n)}{\partial x_2} \\ . \\ . \\ . \\ \frac{\partial(a_1 \cdot x_1 + a_2 \cdot x_2 +...+ a_n \cdot x_n)}{\partial x_n} \\ \end{array}\right] \\ & =\left [\begin{array}{cccc} a_1 \\ a_2 \\ . \\ . \\ . \\ a_n \\ \end{array}\right] = A \end{aligned} x(xTA)=x(ATx)=x(a1x1+a2x2+...+anxn)= x1(a1x1+a2x2+...+anxn)x2(a1x1+a2x2+...+anxn)...xn(a1x1+a2x2+...+anxn) = a1a2...an =A
  • (3)
    ∂ ( x T ⋅ x ) ∂ x = 2 x \frac{\partial (x^T \cdot x)}{\partial x} = 2x x(xTx)=2x
  • 证明:
    ∂ ( x T ⋅ x ) ∂ x = ∂ ( x 1 2 + x 2 2 + . . . + x n 2 ) ∂ x = [ ∂ ( x 1 2 + x 2 2 + . . . + x n 2 ) ∂ x 1 ∂ ( x 1 2 + x 2 2 + . . . + x n 2 ) ∂ x 2 . . . ∂ ( x 1 2 + x 2 2 + . . . + x n 2 ) ∂ x n ] = [ 2 x 1 2 x 2 . . . 2 x n ] = 2 x \begin{aligned} \frac{\partial(x^T \cdot x)}{\partial x} & = \frac{\partial(x_1^2+x_2^2+...+x_n^2)}{\partial x}\\ & = \left [\begin{array}{cccc} \frac{\partial(x_1^2+x_2^2+...+x_n^2)}{\partial x_1} \\ \frac{\partial(x_1^2+x_2^2+...+x_n^2)}{\partial x_2} \\ . \\ . \\ . \\ \frac{\partial(x_1^2+x_2^2+...+x_n^2)}{\partial x_n} \\ \end{array}\right] \\ & =\left [\begin{array}{cccc} 2x_1 \\ 2x_2 \\ . \\ . \\ . \\ 2x_n \\ \end{array}\right] = 2x \end{aligned} x(xTx)=x(x12+x22+...+xn2)= x1(x12+x22+...+xn2)x2(x12+x22+...+xn2)...xn(x12+x22+...+xn2) = 2x12x2...2xn =2x
  • 此处 x T x x^Tx xTx 也被称为向量的交叉乘积(crossprod)。
  • (4)
    ∂ ( x T A x ) x = A x + A T x \frac{\partial (x^T A x)}{x} = Ax + A^Tx x(xTAx)=Ax+ATx
  • 其中 A 是一个(n*n)的矩阵, A n ∗ n = ( a i j ) a = 1 , j = 1 n , n A_{n*n}=(a_{ij})_{a=1,j=1}^{n,n} Ann=(aij)a=1,j=1n,n
  • 证明:
  • 首先,
    X T A X = [ x 1 , x 2 , . . . , x n ] ⋅ [ a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n . . . . . . . . . . . . a n 1 a n 2 . . . a n n ] ⋅ [ x 1 , x 2 , . . . , x n ] T = [ x 1 a 11 + x 2 a 21 + . . . + x n a n 1 , x 1 a 12 + x 2 a 22 + . . . + x n a n 2 , . . . , x 1 a 1 n + x 2 a 2 n + . . . + x n a n n ] ⋅ [ x 1 x 2 . . . x n ] = x 1 ( x 1 a 11 + x 2 a 21 + . . . + x n a n 1 ) + x 2 ( x 1 a 12 + x 2 a 22 + . . . + x n a n 2 ) + . . . + x n ( x 1 a 1 n + x 2 a 2 n + . . . + x n a n n ) \begin{aligned} X^TAX &= [x_1, x_2,...,x_n] \cdot \left [\begin{array}{cccc} a_{11} &a_{12} &... &a_{1n}\\ a_{21} &a_{22} &... &a_{2n}\\ ... &... &... &... \\ a_{n1} &a_{n2} &... &a_{nn}\\ \end{array}\right] \cdot [x_1, x_2,...,x_n]^T \\ &=[x_1a_{11}+x_2a_{21}+...+x_na_{n1}, x_1a_{12}+x_2a_{22}+...+x_na_{n2},...,x_1a_{1n}+x_2a_{2n}+...+x_na_{nn}] \cdot \left [\begin{array}{cccc} x_1 \\ x_2 \\ . \\ . \\ . \\ x_n \\ \end{array}\right] \\ &=x_1(x_1a_{11}+x_2a_{21}+...+x_na_{n1})+x_2(x_1a_{12}+x_2a_{22}+...+x_na_{n2})+...+x_n(x_1a_{1n}+x_2a_{2n}+...+x_na_{nn}) \end{aligned} XTAX=[x1,x2,...,xn] a11a21...an1a12a22...an2............a1na2n...ann [x1,x2,...,xn]T=[x1a11+x2a21+...+xnan1,x1a12+x2a22+...+xnan2,...,x1a1n+x2a2n+...+xnann] x1x2...xn =x1(x1a11+x2a21+...+xnan1)+x2(x1a12+x2a22+...+xnan2)+...+xn(x1a1n+x2a2n+...+xnann)
  • k ( x ) = x 1 ( x 1 a 11 + x 2 a 21 + . . . + x n a n 1 ) + x 2 ( x 1 a 12 + x 2 a 22 + . . . + x n a n 2 ) + . . . + x n ( x 1 a 1 n + x 2 a 2 n + . . . + x n a n n ) k(x) = x_1(x_1a_{11}+x_2a_{21}+...+x_na_{n1})+x_2(x_1a_{12}+x_2a_{22}+...+x_na_{n2})+...+x_n(x_1a_{1n}+x_2a_{2n}+...+x_na_{nn}) k(x)=x1(x1a11+x2a21+...+xnan1)+x2(x1a12+x2a22+...+xnan2)+...+xn(x1a1n+x2a2n+...+xnann)
  • 则有
    ∂ k ( x ) ∂ x 1 = ( x 1 a 11 + x 2 a 21 + . . . + x n a n 1 ) + ( x 1 a 11 + x 2 a 12 + . . . + x n a 1 n ) \frac{\partial k(x)}{\partial x_1} = (x_1a_{11}+x_2a_{21}+...+x_na_{n1})+ (x_1a_{11} + x_2a_{12}+...+x_na_{1n}) x1k(x)=(x1a11+x2a21+...+xnan1)+(x1a11+x2a12+...+xna1n)
  • 类似可得:
    ∂ k ( x ) ∂ x = [ ∂ k ( x ) ∂ x 1 ∂ k ( x ) ∂ x 2 . . . ∂ k ( x ) ∂ x n ] = [ ( x 1 a 11 + x 2 a 21 + . . . + x n a n 1 ) + ( x 1 a 11 + x 2 a 12 + . . . + x n a 1 n ) ( x 1 a 12 + x 2 a 22 + . . . + x n a n 2 ) + ( x 1 a 21 + x 2 a 22 + . . . + x n a 2 n ) . . . ( x 1 a 1 n + x 2 a 2 n + . . . + x n a n n ) + ( x 1 a n 1 + x 2 a n 2 + . . . + x n a n n ) ] = [ ( x 1 a 11 + x 2 a 21 + . . . + x n a n 1 ) ( x 1 a 12 + x 2 a 22 + . . . + x n a n 2 ) . . . ( x 1 a 1 n + x 2 a 2 n + . . . + x n a n n ) ] + [ ( x 1 a 11 + x 2 a 12 + . . . + x n a 1 n ) ( x 1 a 21 + x 2 a 22 + . . . + x n a 2 n ) . . . ( x 1 a n 1 + x 2 a n 2 + . . . + x n a n n ) ] = [ a 11 a 21 . . . a n 1 a 12 a 22 . . . a n 2 . . . . . . . . . . . . a 1 n a 2 n . . . a n n ] [ x 1 x 2 . . . x n ] + [ a 11 a 12 . . . a 1 n a 21 a 22 . . . a 2 n . . . . . . . . . . . . a n 1 a n 2 . . . a n n ] [ x 1 x 2 . . . x n ] = A T x + A x \begin{aligned} \frac{\partial k(x)}{\partial x} &= \left [\begin{array}{cccc} \frac{\partial k(x)}{\partial x_1} \\ \frac{\partial k(x)}{\partial x_2} \\ . \\ . \\ . \\ \frac{\partial k(x)}{\partial x_n} \\ \end{array}\right] \\ &=\left [\begin{array}{cccc} (x_1a_{11}+x_2a_{21}+...+x_na_{n1})+ (x_1a_{11} + x_2a_{12}+...+x_na_{1n}) \\ (x_1a_{12}+x_2a_{22}+...+x_na_{n2})+ (x_1a_{21} + x_2a_{22}+...+x_na_{2n}) \\ . \\ . \\ . \\ (x_1a_{1n}+x_2a_{2n}+...+x_na_{nn})+ (x_1a_{n1} + x_2a_{n2}+...+x_na_{nn}) \\ \end{array}\right] \\ &=\left [\begin{array}{cccc} (x_1a_{11}+x_2a_{21}+...+x_na_{n1}) \\ (x_1a_{12}+x_2a_{22}+...+x_na_{n2}) \\ . \\ . \\ . \\ (x_1a_{1n}+x_2a_{2n}+...+x_na_{nn}) \\ \end{array}\right] + \left [\begin{array}{cccc} (x_1a_{11}+x_2a_{12}+...+x_na_{1n}) \\ (x_1a_{21}+x_2a_{22}+...+x_na_{2n}) \\ . \\ . \\ . \\ (x_1a_{n1}+x_2a_{n2}+...+x_na_{nn}) \\ \end{array}\right] \\ &=\left [\begin{array}{cccc} a_{11} &a_{21} &... &a_{n1}\\ a_{12} &a_{22} &... &a_{n2}\\ ... &... &... &... \\ a_{1n} &a_{2n} &... &a_{nn}\\ \end{array}\right] \left [\begin{array}{cccc} x_1 \\ x_2 \\ . \\ . \\ . \\ x_n \\ \end{array}\right] +\left [\begin{array}{cccc} a_{11} &a_{12} &... &a_{1n}\\ a_{21} &a_{22} &... &a_{2n}\\ ... &... &... &... \\ a_{n1} &a_{n2} &... &a_{nn}\\ \end{array}\right] \left [\begin{array}{cccc} x_1 \\ x_2 \\ . \\ . \\ . \\ x_n \\ \end{array}\right]\\ &=A^Tx+Ax \end{aligned} xk(x)= x1k(x)x2k(x)...xnk(x) = (x1a11+x2a21+...+xnan1)+(x1a11+x2a12+...+xna1n)(x1a12+x2a22+...+xnan2)+(x1a21+x2a22+...+xna2n)...(x1a1n+x2a2n+...+xnann)+(x1an1+x2an2+...+xnann) = (x1a11+x2a21+...+xnan1)(x1a12+x2a22+...+xnan2)...(x1a1n+x2a2n+...+xnann) + (x1a11+x2a12+...+xna1n)(x1a21+x2a22+...+xna2n)...(x1an1+x2an2+...+xnann) = a11a12...a1na21a22...a2n............an1an2...ann x1x2...xn + a11a21...an1a12a22...an2............a1na2n...ann x1x2...xn =ATx+Ax
  • 至此,我们完成相关向量求导常用公式的证明。不过从上面的证明不难看出,使用定义法进行公式证明往往会非常繁琐(尽管流程相对清晰)。
  • 此外,对于矩阵来说,也有类似的求导方法。即如果变量以矩阵形式出现,则针对该矩阵的方程求导之际上也就是依照矩阵基本结构,在每个位置上对对应的变量分量求偏导函数。只不过相比向量,矩阵多了一个维度、结构更加复杂,因此求解过程也更加复杂。
  • 最后,还需要简单进行一个概念辨析,那就是关于矩阵函数和矩阵方程二者概念的区别。
  • 矩阵方程:指变量为矩阵的方程;
  • 矩阵函数:同函数矩阵,指自变量和因变量都是n阶矩阵的函数,也可以简单理解成由函数构成的矩阵,并且每个函数的变量都是矩阵。

三、最小二乘法的推导过程及使用方法

  • 有了上述内容铺垫之后,接下来,我们从数学角度讨论最小二乘法的基本理论,并见尝试简单实现最小二乘法求解损失函数的一般过程。

1. 模型及方程组的矩阵形式改写

  • 首先,我们尝试对模型进行矩阵形式改写。
  • 模型改写成矩阵表达式。
  • 假设多元线性方程有如下形式
    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 ] T w = [w_1,w_2,...w_d]^T w=[w1,w2,...wd]T x = [ x 1 , x 2 , . . . x d ] T x = [x_1,x_2,...x_d]^T x=[x1,x2,...xd]T,则上式可写为
    f ( x ) = w T x + b f(x) = w^Tx+b f(x)=wTx+b
  • 在机器学习领域,我们将线性回归自变量系数命名为 w,其实是 weight 的简写,意为自变量的权重。
  • 将带入数据后的方程组改写为矩阵方程。
  • 并且,假设现在总共有m条观测值, x ( i ) = [ x 1 ( i ) , x 2 ( i ) , . . . , x d ( i ) ] x^{(i)} = [x_1^{(i)}, x_2^{(i)},...,x_d^{(i)}] x(i)=[x1(i),x2(i),...,xd(i)],则带入模型可构成 m 个方程:
    [ w 1 x 1 ( 1 ) + w 2 x 2 ( 1 ) + . . . + w d x d ( 1 ) + b w 1 x 1 ( 2 ) + w 2 x 2 ( 2 ) + . . . + w d x d ( 2 ) + b . . . w 1 x 1 ( m ) + w 2 x 2 ( m ) + . . . + w d x d ( m ) + b ] = [ y ^ 1 y ^ 2 . . . y ^ m ] \left [\begin{array}{cccc} w_1x_1^{(1)}+w_2x_2^{(1)}+...+w_dx_d^{(1)}+b \\ w_1x_1^{(2)}+w_2x_2^{(2)}+...+w_dx_d^{(2)}+b \\ . \\ . \\ . \\ w_1x_1^{(m)}+w_2x_2^{(m)}+...+w_dx_d^{(m)}+b \\ \end{array}\right] = \left [\begin{array}{cccc} \hat y_1 \\ \hat y_2 \\ . \\ . \\ . \\ \hat y_m \\ \end{array}\right] w1x1(1)+w2x2(1)+...+wdxd(1)+bw1x1(2)+w2x2(2)+...+wdxd(2)+b...w1x1(m)+w2x2(m)+...+wdxd(m)+b = y^1y^2...y^m
  • 然后考虑如何将上述方程组进行改写,我们可令
    w ^ = [ w 1 , w 2 , . . . , w d , b ] T \hat w = [w_1,w_2,...,w_d,b]^T w^=[w1,w2,...,wd,b]T x ^ = [ x 1 , x 2 , . . . , x d , 1 ] T \hat x = [x_1,x_2,...,x_d,1]^T x^=[x1,x2,...,xd,1]T X ^ = [ x 1 ( 1 ) x 2 ( 1 ) . . . x d ( 1 ) 1 x 1 ( 2 ) x 2 ( 2 ) . . . x d ( 2 ) 1 . . . . . . . . . . . . 1 x 1 ( m ) x 2 ( m ) . . . x d ( m ) 1 ] \hat X = \left [\begin{array}{cccc} x_1^{(1)} &x_2^{(1)} &... &x_d^{(1)} &1 \\ x_1^{(2)} &x_2^{(2)} &... &x_d^{(2)} &1 \\ ... &... &... &... &1 \\ x_1^{(m)} &x_2^{(m)} &... &x_d^{(m)} &1 \\ \end{array}\right] X^= x1(1)x1(2)...x1(m)x2(1)x2(2)...x2(m)............xd(1)xd(2)...xd(m)1111 y = [ y 1 y 2 . . . y m ] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] y= y1y2...ym y ^ = [ y ^ 1 y ^ 2 . . . y ^ m ] \hat y = \left [\begin{array}{cccc} \hat y_1 \\ \hat y_2 \\ . \\ . \\ . \\ \hat y_m \\ \end{array}\right] y^= y^1y^2...y^m
  • 其中
  • w ^ \hat w w^:方程系数所组成的向量,并且我们将自变量系数和截距放到了一个向量;
  • x ^ \hat x x^:方程自变量和1共同组成的向量;
  • X ^ \hat X X^:样本数据特征构成的矩阵,并在最后一列添加一个全为1的列;
  • y y y:样本数据标签所构成的列向量;
  • y ^ \hat y y^:预测值的列向量。
  • 因此,上述方程组可表示为
    X ^ ⋅ w ^ = y ^ \hat X \cdot \hat w = \hat y X^w^=y^
  • 在改写了 x ^ \hat x x^ w ^ \hat w w^ 之后,线性模型也可以按照如下形式进行改写:
    f ( x ^ ) = w ^ T ⋅ x ^ f(\hat x) = \hat w^T \cdot \hat x f(x^)=w^Tx^

2. 构造损失函数

  • 在方程组的矩阵表示基础上,我们可以以 SSE 作为损失函数基本计算流程构建关于 w ^ \hat w w^ 的损失函数: S S E L o s s ( w ^ ) = ∣ ∣ y − X w ^ ∣ ∣ 2 2 = ( y − X w ^ ) T ( y − X w ^ ) SSELoss(\hat w) = ||y - X\hat w||_2^2 = (y - X\hat w)^T(y - X\hat w) SSELoss(w^)=∣∣yXw^22=(yXw^)T(yXw^)
  • 需要补充两点基础知识:
  • 向量的 2- 范数计算公式
    上式中, ∣ ∣ y − X w ^ T ∣ ∣ 2 ||y - X\hat w^T||_2 ∣∣yXw^T2为向量的 2- 范数的计算表达式。向量的 2- 范数计算过程为各分量求平方和再进行开平方。例如 a = [ 1 , − 1 , ] a=[1, -1,] a=[1,1,],则 ∣ ∣ a ∣ ∣ 2 = 1 2 + ( − 1 ) 2 = 2 ||a||_2= \sqrt{1^2+(-1)^2}=\sqrt{2} ∣∣a2=12+(1)2 =2
  • 向量的 1- 范数为各分量绝对值之和。值得注意的是,矩阵也有范数的概念,不过矩阵的范数计算要比向量复杂得多。
  • 2- 范数计算转化为内积运算
    向量的 2- 范数计算结果其实就是向量(将其是做矩阵)的交叉乘积计算结果后开平方。例如, a = [ 1 , − 1 ] a=[1, -1] a=[1,1],则 a a a的交叉乘积为 a ⋅ a T = [ 1 , − 1 ] ⋅ [ 1 − 1 ] = 2 a \cdot a^T = [1, -1] \cdot \left [\begin{array}{cccc} 1 \\ -1 \\ \end{array}\right]=2 aaT=[1,1][11]=2,开平方后等于其 2- 范数计算结果。

3. 最小二乘法求解损失函数的一般过程

  • 在确定损失函数的矩阵表示形式之后,接下来即可利用最小二乘法进行求解。其基本求解思路,先求导函数、再令导函数取值为零,进而解出参数取值。只不过此时求解的是矩阵方程。
  • 在此之前,需要补充两点矩阵转置的运算规则:
    ( A − B ) T = A T − B T (A-B)^T=A^T-B^T (AB)T=ATBT ( A B ) T = B T A T (AB)^T=B^TA^T (AB)T=BTAT
  • 接下来,对 S S E L o s s ( w ) SSELoss(w) SSELoss(w) 求导并令其等于 0。
    S S E L o s s ( w ^ ) ∂ w ^ = ∂ ∣ ∣ y − X w ^ ∣ ∣ 2 2 ∂ w ^ = ∂ ( y − X w ^ ) T ( y − X w ^ ) ∂ w ^ = ∂ ( y T − w ^ T X T ) ( y − X w ^ ) ∂ w ^ = ∂ ( y T y − w ^ T X T y − y T X w ^ + w ^ T X T X w ^ ) ∂ w ^ = 0 − X T y − X T y + X T X w ^ + ( X T X ) T w ^ = 0 − X T y − X T y + 2 X T X w ^ = 2 ( X T X w ^ − X T y ) = 0 \begin{aligned} \frac{SSELoss(\hat w)}{\partial{\boldsymbol{\hat w}}} &= \frac{\partial{||\boldsymbol{y} - \boldsymbol{X\hat w}||_2}^2}{\partial{\boldsymbol{\hat w}}} \\ &= \frac{\partial(\boldsymbol{y} - \boldsymbol{X\hat w})^T(\boldsymbol{y} - \boldsymbol{X\hat w})}{\partial{\boldsymbol{\hat w}}} \\ & =\frac{\partial(\boldsymbol{y}^T - \boldsymbol{\hat w^T X^T})(\boldsymbol{y} - \boldsymbol{X\hat w})}{\partial{\boldsymbol{\hat w}}}\\ &=\frac{\partial(\boldsymbol{y}^T\boldsymbol{y} - \boldsymbol{\hat w^T X^Ty}-\boldsymbol{y}^T\boldsymbol{X \hat w} +\boldsymbol{\hat w^TX^T}\boldsymbol{X\hat w})}{\partial{\boldsymbol{\hat w}}}\\ & = 0 - \boldsymbol{X^Ty} - \boldsymbol{X^Ty}+X^TX\hat w+(X^TX)^T\hat w \\ &= 0 - \boldsymbol{X^Ty} - \boldsymbol{X^Ty} + 2\boldsymbol{X^TX\hat w}\\ &= 2(\boldsymbol{X^TX\hat w} - \boldsymbol{X^Ty}) = 0 \end{aligned} w^SSELoss(w^)=w^∣∣yXw^22=w^(yXw^)T(yXw^)=w^(yTw^TXT)(yXw^)=w^(yTyw^TXTyyTXw^+w^TXTXw^)=0XTyXTy+XTXw^+(XTX)Tw^=0XTyXTy+2XTXw^=2(XTXw^XTy)=0
  • X T X w ^ = X T y X^TX\hat w = X^Ty XTXw^=XTy
  • 要使得此式有解,等价于 X T X X^TX XTX(也被称为矩阵的交叉乘积 crossprod 存在逆矩阵,若存在,则可解出 w ^ = ( X T X ) − 1 X T y \hat w = (X^TX)^{-1}X^Ty w^=(XTX)1XTy

4. 最小二乘法的简单实现

  • 接下来,我们回到最初的例子,简单尝试利用上述推导公式求解简单线性回归参数。原始数据如下。
Whole weightRings
12
34
  • 因此利用矩阵表达式,可进行如下形式的改写。
  • 特征矩阵: X ^ = [ 1 1 3 1 ] \hat X = \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right] X^=[1311]
  • 标签数组: y = [ 2 4 ] y = \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] y=[24]
  • 参数向量: w ^ = [ w b ] \hat w = \left [\begin{array}{cccc} w \\ b \\ \end{array}\right] w^=[wb]
  • 求解公式为:
    w ^ = ( X T X ) − 1 X T y = ( [ 1 1 3 1 ] T [ 1 1 3 1 ] ) − 1 [ 1 1 3 1 ] T [ 2 4 ] \begin{aligned} \hat w &= (X^TX)^{-1}X^Ty \\ &= (\left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right]^{T} \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right])^{-1} \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right]^{T} \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] \\ \end{aligned} w^=(XTX)1XTy=([1311]T[1311])1[1311]T[24]
  • 代码实现过程:
X = np.array([[1, 1], [3, 1]])
X
#array([[1, 1],
#       [3, 1]])

y = np.array([2, 4]).reshape(2, 1)
y
#array([[2],
#       [4]])

np.linalg.inv(X.T.dot(X)).dot(X.T).dot(y)
#array([[1.],
#       [1.]])
  • 即解得 w = 1 , b = 1 w=1,b=1 w=1b=1,即模型方程为 y = x + 1 y=x+1 y=x+1。至此,我们即完成了最小二乘法的推导以及简单实现。
  • 最小二乘法计算函数。
  • 当然,除了借助 NumPy 中矩阵运算的函数进行最小二乘法计算以外,NumPy中也有独立的用于计算最小二乘法的函数:np.linalg.lstsq
  • 通过该方法,我们能够在直接输入特征矩阵和标签数组的情况下进行最小二乘法的计算,并在得出最小二乘法计算结果的同时,也得到一系列相应的统计指标结果。
np.linalg.lstsq(X, y, rcond=-1)
#(array([[1.],
#        [1.]]),
# array([], dtype=float64),
# 2,
# array([3.41421356, 0.58578644]))
  • 其中,返回的元组中第一个元素是最小二乘法计算结果,第二个元素是 SSE 的计算结果,第三个元素是矩阵 X 的秩,最后一个结果是矩阵 X 的奇异值。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3 函数式组件的开发方式

声明式组件和服务式组件 无论是使用第三方组件库,还是自己封装组件,有一类组件有些与众不同,那就是函数式/服务式组件,比如 Message 消息组件、Notification 通知组件、Loading 加载组件等等。 以 ElementPlus 组件库为例&#…

.net反序列化新手入门--Json.Net

**01 **Json.net简介 Json.net即Newtonsoft.Json,是.Net中开源的Json序列化和反序列化工具,官方地址:http://www.newtonsoft.com/json。 它虽然不是官方库,但凭借其优秀的性能获得了广大开发者的喜爱。 官网给出的性能比较&…

8大预测分析工具比较

什么是预测分析工具? 预测分析工具融合了人工智能和业务报告。这些工具包括用于从整个企业收集数据的复杂管道,添加统计分析和机器学习层以对未来进行预测,并将这些见解提炼成有用的摘要,以便业务用户可以对此采取行动。 预测的…

day17集合

1.Set集合 1.1Set集合概述和特点【应用】 不可以存储重复元素没有索引,不能使用普通for循环遍历 1.2Set集合的使用【应用】 存储字符串并遍历 public class MySet1 {public static void main(String[] args) {//创建集合对象Set<String> set new TreeSet<>()…

超级详细的几道python题(附答案)含解析、建议收藏

名字&#xff1a;阿玥的小东东 学习&#xff1a;python、正在学习c 主页&#xff1a;阿玥的小东东 目录 判断字符串 a “welcome to my world” 是否包含单词 b “world”&#xff0c;包含返回 True&#xff0c;不包含返回 False。 从 0 开始计数&#xff0c;输出指定字符串…

SSH使用入门

目录 .1 基础配置 1.1 vscode使用 1.2 HOST连接 .2 文件传输 .1 基础配置 1.1 vscode使用 拓展里搜索 然后点击remote里的设置 选择配置 然后填写配置 Hostname是你要ssh的服务器的ip地址 user是你要连接的服务器的用户名 Host可以随便写一个 如果有端口号也要对应修改 …

对于KMP的next数组的新发现,好像我们并不用回溯

目录 前言 发现 总结 博客主页&#xff1a;张栩睿的博客主页 欢迎关注&#xff1a;点赞收藏留言 系列专栏&#xff1a;c语言学习 家人们写博客真的很花时间的&#xff0c;你们的点赞和关注对我真的很重要&#xff0c;希望各位路过的朋友们能多多点赞并关注我&#xff0c;我会…

datax数据导入starrocks表报列数量不匹配错误,问题解决思路

背景在做客户数据导入任务的时候&#xff0c;需要将客户oracle的数据通过datax导入到 starrocks的表中&#xff0c;但是datax的配置文件中SQL查找客户数据的列数和要导入的starrocks表的列数都是相同且对应的&#xff0c;但是导入结果就是报了列数不对等的错误&#xff0c;Erro…

把代码贴进去自动找bug,这个debug神器自动修复仅需几秒

在编写程序时&#xff0c;无论是对于初学者还是对于专业开发人员&#xff0c;都会花费大量时间来调试或修复源代码错误&#xff0c;也就是 Debug。 这个过程繁琐复杂&#xff0c;包括 Bug 复现和 Bug 定位等环节。如果有了自动化的 Debug 程序&#xff0c;就可以显著提高编程实…

网络文件服务器:FileVista 8.9.3 Crack

FileVista 用于自托管文件共享的FileVista文件管理器 在几分钟内将您的网站变成一个网络文件服务器。 在您的网站上与您的客户或员工共享文件。 将您的机密文件存储在您自己的服务器上并对其进行完全控制。使您的用户只需使用 Web 浏览器即可从任何地方安全地访问、上传和组织文…

深度学习入门基础CNN系列——感受野和多输入通道、多输出通道以及批量操作基本概念

本篇文章主要讲解卷积神经网络中的感受野和通道的基本概念&#xff0c;适合于准备入门深度学习的小白&#xff0c;也可以在学完深度学习后将其作为温习。 如果对卷积计算没有概念的可以看本博主的上篇文章深度学习入门基础CNN系列——卷积计算 一、感受野&#xff08;receptive…

基于Java+SpringBoot+Vue+uniapp微信小程序零食商城系统设计和实现

博主介绍&#xff1a;✌全网粉丝20W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

【从零开始学习深度学习】47. Pytorch图片样式迁移实战:将一张图片样式迁移至另一张图片,创作自己喜欢风格的图片【含完整源码】

目录1. 图片样式迁移的方法介绍2. 读取内容图像和样式图像3. 图像的预处理和后处理4. 图像的抽取特征5.1 内容损失5.2 样式损失5.3 总变差损失5.4 损失函数6. 创建和初始化合成图像7. 训练模型并输出合成图像总结本文将介绍如何使用卷积神经网络自动将某图像中的样式应用在另一…

分享回顾|新岁序开,2023 和Jina AI共同码梦!

在坚持开放协作精神、具备全球影响力的 Jina AI 开源社区&#xff0c;每天都有来自世界各地的开发者来到这里&#xff0c;因为技术产生联结&#xff0c;因为联结产生共创。一直以来&#xff0c;我们都为拥有这样一个全球化、多元化和高速发展的社区而感到自豪和感激&#xff01…

golang解决跨域问题

文章目录前言一、跨域问题1.是什么2.跨域的特征&#xff08;跨域报错&#xff09;二、解决跨域问题的方法1.golang解决跨域问题2.简单请求3.非简单请求过程分析&#xff08;复杂请求&#xff09;:三、状态码设置为200依旧出错前言 今天中午在部署golang与vue搭建的一个项目时&…

JavaWeb开发(三)3.3——Spring Bean详解(基于XML方式)

一、Bean的概念 由 Spring IoC 容器负责创建、管理所有的Java对象&#xff0c;这些管理的对象称为 Bean&#xff0c;Bean 根据 Spring 配置文件中的信息创建。 二、基于XML方式管理bean对象 eg&#xff1a; <?xml version"1.0" encoding"UTF-8"?&…

JupyterLab,极其强大的 10 个秘密技巧

之前一篇文章&#xff1a;整理了上千个 Python 工具库&#xff0c;涵盖24个大方向 没想到火了。喜欢的可以看一下。 今天我给大家分享一下 Jupyter Lab 的一些内容。 JupyterLab 是 Jupyter 主打的最新数据科学生产工具&#xff0c;某种意义上&#xff0c;它的出现是为了取代…

瑞芯微的接口结构学习总结

MPI 接口使用的主要数据结构&#xff1a; 瑞芯微提供的媒体处理软件平台&#xff08;Media Process Platform&#xff0c;简称 MPP&#xff09;是适用于瑞芯微芯片系列的 通用媒体处理软件平台。该平台对应用软件屏蔽了芯片相关的复杂底层处理&#xff0c;其目的是为了屏蔽不 …

2022 全球网络黑产常用攻击方法 Top 10

近几年&#xff0c;借助互联网产业发展的东风&#xff0c;网络黑产也迎来更加巅峰的状态&#xff0c;不论是从攻击效率&#xff0c;组织规模&#xff0c;亦或是收益变现能力&#xff0c;都在一天天变的成熟完善。根据艾瑞咨询 2020 年发布的《现代网络诈骗分析报告》&#xff0…

哪些数据库开了全文索引

大家好&#xff0c;才是真的好。 今天我们讨论Domino运维管理问题&#xff1a;哪些数据库开启了全文索引&#xff1f; 在前面的某些篇章中&#xff0c;我们介绍过什么是Notes应用的全文索引Full Text Index&#xff0c;以下简称FTI。它是Notes库中的单词的文本索引或列表&…