zoukankan      html  css  js  c++  java
  • 人工智能必备数学知识学习笔记15:特征值与特征向量

    •  什么是特征值和特征向量

     

     

     

     

     

     

     

     

     



    •  特征值和特征向量的相关概 

     

     

     

     



    • 特征值与特征向量的性质

     

     

     

     

     



    直观理解特征值与特征向量

     

     

     

     

     



    • “不简单”的特征值

     

     

     

     

    代码实现:

     

     

     1.文件 main_eigen.py 编写代码:

     1 #在numpy中求解特征值与特征向量
     2 import numpy as np
     3 from numpy.linalg import eig
     4 
     5 if __name__ == "__main__":
     6 
     7     A1 = np.array([[4, -2],
     8                    [1, 1]]);
     9     eigenvalues1, eigenvectors1 = eig(A1)#求取矩阵的特征值与特征向量  eigenvalues:特征值 eigenvectors:特征向量
    10     print(eigenvalues1) #特征值
    11     print(eigenvectors1)#特征向量
    12     print()
    13 
    14     # 关于y=x翻转
    15     A2 = np.array([[0, 1],
    16                    [1, 0]]);
    17     eigenvalues2, eigenvectors2 = eig(A2)#求取矩阵的特征值与特征向量  eigenvalues:特征值 eigenvectors:特征向量
    18     print(eigenvalues2) #特征值
    19     print(eigenvectors2)#特征向量
    20     print()
    21 
    22     # 旋转90
    23     A3 = np.array([[0, -1],
    24                    [1, 0]]);
    25     eigenvalues3, eigenvectors3 = eig(A3)#求取矩阵的特征值与特征向量  eigenvalues:特征值 eigenvectors:特征向量
    26     print(eigenvalues3) #特征值
    27     print(eigenvectors3)#特征向量
    28     print()
    29 
    30     # 单位矩阵
    31     A4 = np.array([[1, 0],
    32                    [0, 1]]);
    33     eigenvalues4, eigenvectors4 = eig(A4)#求取矩阵的特征值与特征向量  eigenvalues:特征值 eigenvectors:特征向量
    34     print(eigenvalues4) #特征值
    35     print(eigenvectors4)#特征向量
    36     print()
    37 
    38     # 几何重数为1
    39     A5 = np.array([[3, 1],
    40                    [0, 3]]);
    41     eigenvalues5, eigenvectors5 = eig(A5)#求取矩阵的特征值与特征向量  eigenvalues:特征值 eigenvectors:特征向量
    42     print(eigenvalues5) #特征值
    43     print(eigenvectors5)#特征向量
    44     print()
    45 
    46     

    2.文件 main_eigen.py 运行结果:

     1 /Users/liuxiaoming/PycharmProjects/LinearAlgebra/venv/bin/python /Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py --mode=client --port=62920
     2 import sys; print('Python %s on %s' % (sys.version, sys.platform))
     3 sys.path.extend(['/Users/liuxiaoming/PycharmProjects/LinearAlgebra'])
     4 PyDev console: starting.
     5 Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
     6 [Clang 6.0 (clang-600.0.57)] on darwin
     7 runfile('/Users/liuxiaoming/PycharmProjects/LinearAlgebra/main_eigen.py', wdir='/Users/liuxiaoming/PycharmProjects/LinearAlgebra')
     8 [3. 2.]
     9 [[0.89442719 0.70710678]
    10  [0.4472136  0.70710678]]
    11 [ 1. -1.]
    12 [[ 0.70710678 -0.70710678]
    13  [ 0.70710678  0.70710678]]
    14 [0.+1.j 0.-1.j]
    15 [[0.70710678+0.j         0.70710678-0.j        ]
    16  [0.        -0.70710678j 0.        +0.70710678j]]
    17 [1. 1.]
    18 [[1. 0.]
    19  [0. 1.]]
    20 [3. 3.]
    21 [[ 1.00000000e+00 -1.00000000e+00]
    22  [ 0.00000000e+00  6.66133815e-16]]


    • 矩阵相似和背后的重要含义

     

     

     

     

     



    • 矩阵对角 

     

     

     

     代码实现:

     

     1.调用文件 Matrix.py :

      1 #矩阵类
      2 from playLA.Vector import Vector
      3 
      4 
      5 class Matrix:
      6     # 参数2:二维数组
      7     def __init__(self, list2d):
      8         if isinstance(list2d[0], list):  #若二维数组为 list 集合
      9             self._values = [row[:] for row in list2d] # 将数组变为矩阵
     10         elif isinstance(list2d[0], Vector): #若二维数组 为向量时
     11             self._values = [row.underlying_list() for row in list2d] #将数组中的每一行作为一个数组放到一个大的数组中
     12 
     13     #矩阵类方法:返回一个r行c列的零矩阵:参数1:为零的类对象
     14     @classmethod
     15     def zero(cls,r,c):
     16         return cls([[0] * c for _ in range(r)]) #创建一个r行c列为零的一个列表
     17 
     18     #单位矩阵类方法:返回一个n行n列的单位矩阵
     19     @classmethod
     20     def identity(cls, n):
     21         m = [[0] * n for _ in range(n)] #此处 m 代表有 n 行,每一行有 n 个 0
     22         for i in range(n):
     23             m[i][i] = 1  #此处代表将矩阵 m 的 第i行的第i个元素赋值为1
     24         return cls(m)
     25 
     26     #返回矩阵的转置矩阵
     27     def T(self):
     28         #将每一行的相同位置(每一列)元素提取出来变为行组成新的矩阵
     29         return Matrix([[e for e in self.col_vector(i)]
     30                        for i in range(self.col_num())])
     31 
     32     #返回两个矩阵的加法结果
     33     def __add__(self, another):
     34         # 校验两个矩阵的形状为一致(行数、列数一致)
     35         assert self.shape() == another.shape(), 
     36             "Error in adding. Shape of matrix must be same."
     37         # 根据矩阵的加法公式:两个矩阵对应的每一行的每一个元素相加,获得新的矩阵(遍历两个矩阵对应的每一个行每个元素进行相加<第二步>,外部再遍历该矩阵的行数(循环的次数)<第一步>)
     38         return Matrix([[a+b for a,b in zip(self.row_vector(i),another.row_vector(i))]
     39                        for i in range(self.row_num())])
     40 
     41     # 返回两个矩阵的减法结果
     42     def __sub__(self, another):
     43         assert self.shape() == another.shape(), 
     44             "Error in subtracting. Shape of matrix must be same."
     45         return Matrix([[a - b for a, b in zip(self.row_vector(i), another.row_vector(i))]
     46                        for i in range(self.row_num())])
     47 
     48     #返回两个矩阵的乘法结果(矩阵乘以矩阵)
     49     def dot(self,another):
     50         if isinstance(another,Vector):#判断是否为向量:矩阵与向量的乘法
     51             assert self.col_num() == len(another),
     52                 "Error in Matrix_Vector Multiplication." #矩阵与向量的乘法错误
     53             return Vector([self.row_vector(i).dot(another) for i in range(self.row_num())])
     54         if isinstance(another,Matrix):#判断是否为矩阵:矩阵与矩阵的乘法
     55             assert self.col_num() == another.row_num(),
     56                 "Error in Matrix-Matrix Multiplication." #矩阵与矩阵的乘法错误
     57             # 将矩阵的每一行与另一矩阵的每一列进行向量间的点乘
     58             return Matrix([[self.row_vector(i).dot(another.col_vector(j)) for j in range(another.col_num())]
     59                             for i in range(self.row_num())])
     60 
     61     #返回矩阵的数量乘结果(矩阵乘以数字):self * k
     62     def __mul__(self, k):
     63         #通过遍历每一行的每个元素e后分别乘以k<第一步>,外部再遍历该矩阵的行数(循环的次数)<第二步>
     64         return Matrix([[e * k for e in self.row_vector(i)]
     65                        for i in range(self.row_num())])
     66 
     67     # 返回矩阵的数量乘结果(数字乘以矩阵):k * self
     68     def __rmul__(self, k):
     69         return self * k
     70 
     71     #返回数量除法的结果矩阵:self / k
     72     def __truediv__(self, k):
     73         return (1 / k) * self
     74 
     75     #返回矩阵取正的结果
     76     def __pos__(self):
     77         return 1 * self
     78 
     79     #返回矩阵取负的结果
     80     def __neg__(self):
     81         return -1 * self
     82 
     83     #返回矩阵的第index个行向量
     84     def row_vector(self,index):
     85         return Vector(self._values[index])
     86 
     87     # 返回矩阵的第index个列向量
     88     def col_vector(self, index):
     89         return Vector([row[index] for row in self._values])
     90 
     91     #返回矩阵pos位置的元素(根据元素的位置取元素值) :参数2:元组
     92     def __getitem__(self, pos):
     93         r,c = pos
     94         return self._values[r][c]
     95 
     96     #返回矩阵的元素个数
     97     def size(self):
     98         r,c = self.shape()
     99         return r*c
    100 
    101     #返回矩阵行数
    102     def row_num(self):
    103         return self.shape()[0]
    104 
    105     __len__ = row_num
    106 
    107     #返回矩阵列数
    108     def col_num(self):
    109         return self.shape()[1]
    110 
    111     #返回矩阵形状:(行数,列数)
    112     def shape(self):
    113         return len(self._values),len(self._values[0])
    114 
    115     #矩阵展示
    116     def __repr__(self):
    117         return "Matrix({})".format(self._values)
    118 
    119     __str__ = __repr__

    2.调用文件 LinearSystem.py :

      1 from playLA.Matrix import Matrix
      2 from playLA.Vector import Vector
      3 from playLA._global import is_zero
      4 
      5 
      6 #线性系统
      7 class LinearSystem:
      8 
      9     #初始化函数:参数A:增广矩阵的等号左边的系数 参数b:增广矩阵的等号右边的值(方程右边的结果)
     10     def __init__(self, A, b):
     11         #判断 b为None 或者 矩阵A的行数等于b的列数
     12         assert b is None or A.row_num() == len(b),
     13             "row number of A must be equal to the length of b"
     14         self._m = A.row_num()#行数
     15         self._n = A.col_num()#列数
     16 
     17         #判断若b为空时,则该矩阵为A矩阵 TODO:2020-08-22
     18         if b is None:
     19             self.Ab = [A.row_vector(i) for i in range(self._m)]
     20 
     21         if isinstance(b, Vector):#如果等号右侧方程结果为列向量时
     22             #增广矩阵
     23             self.Ab = [Vector(A.row_vector(i).underlying_list() + [b[i]])
     24                        for i in range(self._m)]
     25 
     26         if isinstance(b, Matrix):#如果等号右侧方程结果为单位矩阵时
     27             #增广矩阵
     28             self.Ab = [Vector(A.row_vector(i).underlying_list() + b.row_vector(i).underlying_list())
     29                        for i in range(self._m)]
     30         #主元
     31         self.pivots = []
     32 
     33     #寻找最大主源系数
     34     def _max_row(self, index_i, index_j, n):
     35         best, ret = self.Ab[index_i][index_j], index_i #存储第index行index列的元素值与当前index的值
     36         for i in range(index_i + 1, n): #从index+1开始一直遍历到n
     37             if self.Ab[i][index_j] > best:
     38                 best, ret = self.Ab[i][index_j], i
     39         return ret
     40 
     41     #高斯—约旦消元法-前向过程
     42     def _forward(self):
     43 
     44        i,k = 0,0
     45        while i < self._m and k < self._n:
     46             #看Ab[i][k]位置是否为主元
     47             max_row = self._max_row(i, k, self._m)#寻找最大主源系数的行数
     48             self.Ab[i], self.Ab[max_row] = self.Ab[max_row],self.Ab[i] #行交换操作
     49 
     50             if is_zero(self.Ab[i][k]):#判断此时该值是否为0
     51                 k += 1
     52             else:
     53                 #将主元归为一
     54                 self.Ab[i] = self.Ab[i] / self.Ab[i][k]
     55                 #将当前主源下的所有行对应主源列的元素全部归为0 :也就是第一次循环会将该主源下的所有对应列变为0,第二次循环会将第二次主源列下的所有对应列变为0
     56                 for j in range(i + 1, self._m):
     57                     self.Ab[j] =self.Ab[j] -self.Ab[j][k] * self.Ab[i]#该主源行下的所有行减去主源行
     58                 self.pivots.append(k)
     59                 i += 1
     60 
     61     #高斯-约旦消元法-后向过程
     62     def _backward(self):
     63         n = len(self.pivots)
     64         #n = self._m #行数
     65         for i in range(n-1, -1, -1): #反向遍历且 从参数1的位置遍历到参数2的位置,也就是从倒数第一个位置遍历到第一个位置,参数3为步长(遍历的方向及单位)
     66             k = self.pivots[i]
     67             #Ab[i][k]为主源
     68             for j in range(i-1, -1, -1):
     69                 self.Ab[j] = self.Ab[j] - self.Ab[j][k] * self.Ab[i]#该主源行上的所有行减去主源行
     70 
     71     #高斯-约旦消元法:如果有解,返回True;如果没有解,返回False
     72     def gauss_jordan_elimination(self):
     73         # 高斯—约旦消元法-前向过程
     74         self._forward()
     75         # 高斯-约旦消元法-后向过程
     76         self._backward()
     77         for i in range(len(self.pivots), self._m):#此处为最后一行的非零行下一行的全零行的结果值不为零的判断   0.0 0.0 | 5.0
     78             if not is_zero(self.Ab[i][-1]):
     79                 return False
     80         return True
     81 
     82     # 打印结果(求每个未知数的值)
     83     def fancy_print(self):
     84         for i in range(self._m):
     85             print(" ".join(str(self.Ab[i][j]) for j in range(self._n)),end=" ")
     86             print("|",self.Ab[i][-1])
     87 
     88 
     89 #求增广矩阵的逆
     90 def inv(A):
     91 
     92     if A.row_num() != A.col_num():#判断矩阵行是否等于列,若不等于无解
     93         return None
     94 
     95     n = A.row_num() # TODO:A.row_num 无括号代表方法,类型为method   A.row_num() 有括号代表具体的返回值
     96     print(n,type(n))
     97     ls = LinearSystem(A, Matrix.identity(n))#实例化一个线性系统(创建一个增广矩阵)
     98     if not ls.gauss_jordan_elimination(): #判断是否有逆矩阵(是否有解)
     99         return None
    100 
    101     invA = [[row[i] for i in range(n, n*n)] for row in ls.Ab] #将右侧的单位矩阵拼接到矩阵中
    102 
    103     return Matrix(invA)
    104 
    105 
    106 #求矩阵的秩(主元数量)
    107 def rank(A):
    108 
    109     ls = LinearSystem(A,None) #声明一个矩阵A
    110     ls.gauss_jordan_elimination() #将矩阵进行高斯消元
    111 
    112     zero = Vector.zero(A.col_num())      #创建零向量(维度为该矩阵的列数即可,每一行的元素个数)
    113     return sum([row != zero for row in ls.Ab])  #判断有多少非零行  (不等指的是向量间是否不等)

    3.文件 main_diag.py 编写代码:

     1 import numpy as np
     2 from numpy.linalg import eig, inv # eig:特征值、特征向量  inv:矩阵的逆
     3 from playLA.LinearSystem import rank # 矩阵的秩(主元数量)
     4 from playLA.Matrix import Matrix
     5 
     6 #矩阵的对角化
     7 def diagonalize(A):
     8 
     9     assert A.ndim == 2 #判断A的维度为2
    10     assert A.shape[0] == A.shape[1] #判断矩阵A的长等于宽(是否为方阵)
    11 
    12     eigenvalues, eigenvectors = eig(A)#求取矩阵的特征值与特征向量
    13 
    14     P = eigenvectors            #特征向量
    15     if rank(Matrix(P.tolist())) != A.shape[0]:# 判断矩阵是否满秩(满秩矩阵可逆,不满秩则矩阵不可逆)
    16         print("Matrix can not be diagonalized")#矩阵不能对角化
    17         return None, None, None
    18 
    19     D = np.diag(eigenvalues)    #将特征值放入矩阵的对角线上
    20     Pinv = inv(P)               #特征向量的逆
    21 
    22 
    23     return P, D, Pinv
    24 
    25 
    26 if __name__ == "__main__":
    27 
    28     A1 = np.array([[4, -2],
    29                    [1, 1]])
    30     P1, D1, Pinv1 = diagonalize(A1)
    31     print(P1)
    32     print(D1)
    33     print(Pinv1)
    34     print(P1.dot(D1).dot(Pinv1))
    35 
    36     A2 = np.array([[3, 1],
    37                    [0, 3]])
    38     P2, D2, Pinv2 = diagonalize(A2)
    39     print(P2)
    40     print(D2)
    41     print(Pinv2)

    4.文件 main_diag.py 运行结果:

     1 /Users/liuxiaoming/PycharmProjects/LinearAlgebra/venv/bin/python /Applications/PyCharm.app/Contents/plugins/python/helpers/pydev/pydevconsole.py --mode=client --port=63553
     2 import sys; print('Python %s on %s' % (sys.version, sys.platform))
     3 sys.path.extend(['/Users/liuxiaoming/PycharmProjects/LinearAlgebra'])
     4 PyDev console: starting.
     5 Python 3.8.2 (v3.8.2:7b3ab5921f, Feb 24 2020, 17:52:18) 
     6 [Clang 6.0 (clang-600.0.57)] on darwin
     7 runfile('/Users/liuxiaoming/PycharmProjects/LinearAlgebra/main_diag.py', wdir='/Users/liuxiaoming/PycharmProjects/LinearAlgebra')
     8 [[0.89442719 0.70710678]
     9  [0.4472136  0.70710678]]
    10 [[3. 0.]
    11  [0. 2.]]
    12 [[ 2.23606798 -2.23606798]
    13  [-1.41421356  2.82842712]]
    14 [[ 4. -2.]
    15  [ 1.  1.]]
    16 Matrix can not be diagonalized
    17 None
    18 None
    19 None


    • 矩阵对角化的应用:求解矩阵的幂和动态系统

     

     

     

     

     

  • 相关阅读:
    delphi 的插件机制与自动更新
    delphi 的 ORM 框架
    canner CMS 系统 (公司在台湾) https://www.canner.io/
    区块链 ---- 数字货币交易
    BIM平台 http://gzcd.bim001.cn
    TreeGrid 控件集 :delphi 学习群 ---- 166637277 (Delphi学习交流与分享)
    UniGUI 如何进行 UniDBGrid 的单元 Cell 的计算 ?
    国产 WEB UI 框架 (收费)-- Quick UI,Mini UI
    iOS尽量不要在viewWillDisappear:方法中移除通知
    Tips:取消UICollectionView的隐式动画
  • 原文地址:https://www.cnblogs.com/liuxiaoming123/p/13611434.html
Copyright © 2011-2022 走看看