栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

GitModel数学建模 —— 动手学线性代数

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

GitModel数学建模 —— 动手学线性代数

线性代数(基于python) (一) 线性方程组与向量 1.1 线性方程组

二元一次方程组的未知数的阶数都是一次,式子两边都是用等式相连,因此我们给这个方程组起另一个名字:线性方程组.
什么是向量
矩阵的简介

例如,求解如下二元一次方程组,(方程组可以用向量形式表示成)

我们尝试使用python解线性方程组,Numpy中已经封装了求解线性方程组的函数,我们仅需要传入对应的系数矩阵 A mathbf{A} A以及常数向量 b b b,程序就会算出相应的结果.

import numpy as np 
A = np.array([[1, 1],
              [2, 4]])     # 将系数所有向量拼在一起
b = np.array([10,
              28])  # 常数向量
x = np.linalg.solve(A,b)   # 解线性方程组
print("线性方程组的解为:n",x)
(二) 向量空间、矩阵、行列式以及范数 2.1 向量的运算法则
  • 一个数乘一个向量;
  • 一个向量加一个向量;
    显然,当变量个数变多之后,也会满足上面这两种运算法则,因此我们接下来正式引入向量的基本运算法则:

给定 n n n维向量
x = [ x 1 x 2 ⋮ x n ] , y = [ y 1 y 2 ⋮ y n ] x= begin{bmatrix} {x_1}\ {x_2}\ {vdots}\ {x_n} end{bmatrix}, y= begin{bmatrix} {y_1}\ {y_2}\ {vdots}\ {y_n} end{bmatrix} x=⎣⎢⎢⎢⎡​x1​x2​⋮xn​​⎦⎥⎥⎥⎤​,y=⎣⎢⎢⎢⎡​y1​y2​⋮yn​​⎦⎥⎥⎥⎤​

  • 向量的加法定义为:
    x + y = [ x 1 + y 1 x 2 + y 2 ⋮ x n + y n ] , x+y = begin{bmatrix} {x_1 + y_1}\ {x_2 + y_2}\ {vdots}\ {x_n + y_n} end{bmatrix}, x+y=⎣⎢⎢⎢⎡​x1​+y1​x2​+y2​⋮xn​+yn​​⎦⎥⎥⎥⎤​,
    即两个向量对应的分量相加.

  • 向量的数乘定义为:
    对于 k ∈ R k in mathbf{R} k∈R,
    k x = [ k x 1 k x 2 ⋮ k x n ] , kx = begin{bmatrix} {kx_1 }\ {kx_2}\ {vdots}\ {kx_n} end{bmatrix}, kx=⎣⎢⎢⎢⎡​kx1​kx2​⋮kxn​​⎦⎥⎥⎥⎤​,
    即每个分量都乘上 k k k.

关于向量与向量的乘法,我们约定一个使用习惯,我们默认所有的向量都采用列向量的形式,当我们在文中书写时,为了排版优美,通常将向量由列向量转成行向量进行书写,向量的行列交换的称为向量的转置,记做 x T = ( x 1 , x 2 , ⋯   , x n ) x^T = (x_1, x_2, cdots, x_n) xT=(x1​,x2​,⋯,xn​).我们使用Numpy实现向量之间的基本计算.

import numpy as np
# 生成向量
x = np.array([1, 2, 3]) # array默认如果只有一列,就是一个向量
y = np.array([4, 5, 6])
print("x={},y={}".format(x, y))
print("x的维度为{}".format(x.shape)) # shape函数用于显示向量的维度,如果是向量默认只有一维,维度显示为(dim,)

# 向量加法
print("x+y = {}".format(x + y))

# 向量数乘
k = 3
print("kx = {}".format(k*x))

print("3x+2y ={} ".format(3*x + 2*y))
2.2 向量的线性相关与线性无关

研究向量的工具 —— 向量的线性相关与线性无关
给定一组向量 ( α 1 , α 2 , ⋯   , α k ) (alpha_1, alpha_2, cdots, alpha_k) (α1​,α2​,⋯,αk​)(注意,这个地方之所以没有转置符号,是因为这是一个向量组,每个 α alpha α都是一个列向量,需要与向量的写法做区分),对于向量 β beta β,如果能被存在一组不全为0的常数 m 1 , m 2 , ⋯   , m k m_1, m_2, cdots, m_k m1​,m2​,⋯,mk​,使得
β = m 1 α 1 + m 2 α 2 + ⋯ + m k α k beta = m_1alpha_1 + m_2alpha_2 + cdots + m_kalpha_k β=m1​α1​+m2​α2​+⋯+mk​αk​
则称向量 β beta β与向量组 ( α 1 , α 2 , ⋯   , α k ) (alpha_1, alpha_2, cdots, alpha_k) (α1​,α2​,⋯,αk​)是线性相关的,或称 β beta β可以被向量组 ( α 1 , α 2 , ⋯   , α k ) (alpha_1, alpha_2, cdots, alpha_k) (α1​,α2​,⋯,αk​)线性表出.一旦向量是线性相关的,也就说明“ β beta β是一个多余的向量,因为它可以由其他的向量去表示”.

对于方程组,如果我们把第 i i i个方程当成是一个向量 α i alpha_i αi​(这是不严谨的说法),则 α 3 = α 1 + α 2 alpha_3 = alpha_1 + alpha_2 α3​=α1​+α2​,因此第三个方程是多余的.

反之,如果 m 0 β + m 1 α 1 + m 2 α 2 + ⋯ + m k α k = 0 m_0beta + m_1alpha_1 + m_2alpha_2 + cdots + m_kalpha_k = 0 m0​β+m1​α1​+m2​α2​+⋯+mk​αk​=0当且仅当 m 0 , m 1 , m 2 , ⋯   , m k m_0, m_1, m_2, cdots, m_k m0​,m1​,m2​,⋯,mk​全都为0,则称 β , α 1 , α 2 , ⋯   , α k beta, alpha_1, alpha_2, cdots, alpha_k β,α1​,α2​,⋯,αk​是线性无关的.

判断一个方程组有唯一解我们有两条法则:

  • n n n个未知数要有 n n n个方程
  • 可以使用线性无关去判断“有效的方程”

如果当一个方程组未知数的量很大之后,需要去判断哪些方程是“有效的”是一件非常花时间的工作,有没有一个更好的方法呢?答案是有的,我们先介绍行列式的概念.矩阵就是一种数表,系数矩阵 A A A总是行数、列数相等的,因为它的方程个数等于未知数的个数,像这样行数等于列数的矩阵我们称为方阵.对于方阵而言,我们可以计算它的行列式 ∣ A ∣ |A| ∣A∣,用Numpy实现如下:

A = np.array([[1, 1, 1],
              [2, 4, 2],
              [2, 2, 2]])

np.linalg.det(A) # 计算方阵A的行列式
print("A的行列式的值为:",np.linalg.det(A))

B = np.array([[1,1,1,1],
              [1,2,0,0],
              [1,0,3,0],
              [1,0,0,4]])
B_det = np.linalg.det(B)
print("B的行列式的值为:",B_det)

# B = np.array([[1,1,1,1],
#               [1,2,0,0],
#               [1,0,0,4]])# 你可以尝试用非方阵计算行列式,压根没法算!

注:一定要是方阵才能求行列式!

有了行列式之后,以后只要我们判断了一个方程组:

  1. 未知数个数等于方程的个数
  2. 系数行列式 ∣ A ∣ ≠ 0 |A| neq 0 ∣A∣​=0
    则这个方程组是有唯一解的.

上面这个判断的法则就是著名的克莱姆法则(Cramer’s Rule),更重要的是,克莱姆法则提出了一种解的结构:
克莱姆法则
设线性方程组的表达式为: { a 11 x 1 + a 12 x 2 + ⋯ + a 1 n x n = b 1 a 21 x 1 + a 22 x 2 + ⋯ + a 2 n x n = b 2 ⋯ ⋯ a n 1 x 1 + a n 2 x 2 + ⋯ + a n n x n = b n left{begin{array}{c}a_{11} x_{1}+a_{12} x_{2}+cdots+a_{1 n} x_{n}=b_{1} \ a_{21} x_{1}+a_{22} x_{2}+cdots+a_{2 n} x_{n}=b_{2} \ cdots cdots \ a_{n 1} x_{1}+a_{n 2} x_{2}+cdots+a_{n n} x_{n}=b_{n}end{array}right. ⎩⎪⎪⎨⎪⎪⎧​a11​x1​+a12​x2​+⋯+a1n​xn​=b1​a21​x1​+a22​x2​+⋯+a2n​xn​=b2​⋯⋯an1​x1​+an2​x2​+⋯+ann​xn​=bn​​
,系数行列式为: D = ∣ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋯ ⋯ ⋯ ⋯ a n 1 a n 2 ⋯ a m n ∣ ≠ 0 D = left|begin{array}{cccc}a_{11} & a_{12} & cdots & a_{1 n} \ a_{21} & a_{22} & cdots & a_{2 n} \ cdots & cdots & cdots & cdots \ a_{n 1} & a_{n 2} & cdots & a_{m n}end{array}right| neq 0 D=∣∣∣∣∣∣∣∣​a11​a21​⋯an1​​a12​a22​⋯an2​​⋯⋯⋯⋯​a1n​a2n​⋯amn​​∣∣∣∣∣∣∣∣​​=0,则该线性方程组有且仅有唯一解:

x 1 = D 1 D , x 2 = D 2 D , ⋯   , x n = D n D x_{1}=frac{D_{1}}{D}, x_{2}=frac{D_{2}}{D}, cdots, x_{n}=frac{D_{n}}{D} x1​=DD1​​,x2​=DD2​​,⋯,xn​=DDn​​

其中, D j = ∣ a 11 ⋯ a 1 , j − 1 b 1 a 1 , j + 1 ⋯ a 1 n a 21 ⋯ a 2 , j − 1 b 2 a 2 , j + 1 ⋯ a 2 n ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ ⋯ a n 1 ⋯ a n , j − 1 b n a n , j + 1 ⋯ a n n ∣ D_{j}=left|begin{array}{ccccccc}a_{11} & cdots & a_{1, j-1} & b_{1} & a_{1, j+1} & cdots & a_{1 n} \ a_{21} & cdots & a_{2, j-1} & b_{2} & a_{2, j+1} & cdots & a_{2 n} \ cdots & cdots & cdots & cdots & cdots & cdots & cdots \ a_{n 1} & cdots & a_{n, j-1} & b_{n} & a_{n, j+1} & cdots & a_{n n}end{array}right| Dj​=∣∣∣∣∣∣∣∣​a11​a21​⋯an1​​⋯⋯⋯⋯​a1,j−1​a2,j−1​⋯an,j−1​​b1​b2​⋯bn​​a1,j+1​a2,j+1​⋯an,j+1​​⋯⋯⋯⋯​a1n​a2n​⋯ann​​∣∣∣∣∣∣∣∣​

2.3 矩阵

对于一个矩阵 A A A,假设行数为 n n n,列数为 m m m,则它的维度为 n × m n times m n×m,记作: A n × m A_{ntimes m} An×m​. 当两个矩阵要做乘法时,我们要求前一个矩阵的列数要等于后一个矩阵的行数,即:给定 A a × b , B c × d A_{atimes b},B_{c times d} Aa×b​,Bc×d​,若 A B AB AB有意义,则 b = c b=c b=c,并且结果的维度为 a × d atimes d a×d,结果矩阵的第 i j ij ij个元素为:前一个矩阵的第 i i i个行向量与后一个矩阵第 j j j个列点乘得到. 也正是如此,我们不能对矩阵乘法轻易交换顺序,也就是说 A B AB AB不一定等于 B A BA BA,这个一定要注意!

A = np.array([[1, 2],
              [1, -1]])
B = np.array([[1, 2, -3],
              [-1, 1, 2]])

print("A的规模{}".format(A.shape))
print("B的规模{}".format(B.shape))

# 计算AB
print("AB=n{}".format(np.matmul(A, B)))

# 计算BA会报错维度不对应
# np.matmul(B, A)

两个维度大小一个矩阵可以做加法,即对应位置元素相加. 一个矩阵乘一个常数等于每个位置的元素都乘这个常数

A = np.array([[1, 2],
              [1, -1]])
C = np.array([[1, 2],
                [3, 4]])
print("A+C = n", A + C) # A+C 
print("3*A = n", 3 * A) # 3*A

特殊的矩阵

  • 单位矩阵
    在矩阵的乘法中,有一种矩阵起着特殊的作用,如同数的乘法中的1,这种矩阵被称为单位矩阵. 它是个方阵,从左上角到右下角的对角线(称为主对角线)上的元素均为1,除此以外全都为0.
print("B =n", B,"n", "E = n", np.eye(3)) # 3阶单位阵

np.matmul(B, np.eye(3))
  • 初等矩阵
    如果你想让计算机懂得解方程组的三个步骤,首先我们先抽象出一个方程组的系数矩阵$A_{ntimes m} $,假设下面介绍三个操作对应的矩阵变换,称为初等矩阵.
  • 逆矩阵
    对于 n n n阶方阵 A A A,如果存在一个 n n n阶方阵 B B B,使得
    A B = B A = E n AB=BA=E_n AB=BA=En​
    则我们称 A A A是可逆的, B B B是 A A A的逆矩阵,记做 A − 1 A^{-1} A−1.

如果一个矩阵是可逆的,那么首先它一定要是个方阵,也就是行数等于列数,此外它还要满足行列式不等于0,也就是我们上面提到的非奇异矩阵.我们在此不给出严格的证明,这个可以联想除法去理解,当你要“除”过去,作为“分母”自然不能为0.
至于如何计算,我们可以通过Numpy模块求解:

import numpy as np

A = np.array([[1, 2], [3, 4]])
print(np.linalg.det(A),"行列式不为0,非奇异阵") # 检验是否奇异
print("A的逆矩阵:n", np.linalg.inv(A)) # 矩阵求逆

A_inv = np.linalg.inv(A)

print("验证AA_inv = E n", np.matmul(A, A_inv))

这里看着不像单位阵,但实际上是因为数值计算带来的后果,我们仅需要做一下数值过滤即可.事实上,为了一些应用更加简便,对于非奇异阵我们也定义了"伪逆".
它的定义是这样的:对于任意一个矩阵 A ∈ R n × m A in mathbb{R}^{ntimes m} A∈Rn×m,存在一个矩阵 A g ∈ R m × n A^g in mathbb{R}^{mtimes n} Ag∈Rm×n,使得 A A g A = A AA^gA=A AAgA=A,则称 A g A^g Ag为 A A A的伪逆(广义逆).
具体实现如下:

B = np.array([[0, 1],
              [0, -1]])
print(np.linalg.det(B),"行列式为0,奇异阵") # 检验是否奇异
# print("B的逆矩阵:n", np.linalg.inv(B)) # 直接求逆会报错

print(np.linalg.pinv(B))
print(np.matmul(np.matmul(B, np.linalg.pinv(B)),B)) # 验证广义逆的定义
(三) 对角化、矩阵的特征值与特征向量、正交化

重要的核心概念:向量在空间中的位置是绝对的,而其坐标值却是相对的,坐标的取值依托于其所选取的坐标向量(基底)

  • 相似矩阵
    一个向量在空间位置里,选取不同的坐标系,其坐标值是不同的. 对于空间中同一个线性变换,在不同的坐标系下,用于描述这个变换的矩阵也是不同的, 而这些不同矩阵所描述的线性变换是相似的,因此我们称他们为相似矩阵.
  • 对角矩阵
    使得线性变换的矩阵是最佳的
    当我们同时需要经历很多次线性变换的时候,对角矩阵能极大的减少我们的计算量

特征值与特征向量

-正交矩阵(*)
令一个向量进行旋转变换或者镜像变换的矩阵

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/976849.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号