欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

第 2 课矩阵运算、矩阵推导和最小二乘法基础-1

最编程 2024-03-10 19:57:10
...

文章目录


一、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]])


此处也简单回顾矩阵乘法运算,上述相乘过程如下所示:

网络异常,图片无法展示
|


上一篇: 学习笔记:线性代数 - 正交基和标准正交基

下一篇: 线性代数 - MIT 18.06 (ix)