• QR分解迭代求特征值——原生python实现(不使用numpy)


    QR分解:

    有很多方法可以进行QR迭代,本文使用的是Schmidt正交化方法

    具体证明请参考链接 https://wenku.baidu.com/view/c2e34678168884868762d6f9.html

    迭代格式

    实际在进行QR分解之前一般将矩阵化为上hessnberg矩阵(奈何这个过程比较难以理解,本人智商不够,就不做这一步了哈哈哈)

    迭代终止条件

    看了很多文章都是设置一个迭代次数,感觉有些不是很合理,本来想采用A(k+1)-A(k)的对角线元素的二范数来作为误差的,但是我有没有一些严格的证明,所以本文也采用比较大众化的思路,设置迭代次数。

    Python实现

      1 M = [[2, 4, 2], [-1, 0, -4], [2, 2, 1]]
      2 
      3 import copy
      4 import math
      5 
      6 
      7 class QR(object):
      8 
      9     def __init__(self, data):
     10         self.M = data
     11         self.degree = len(data)
     12 
     13     def get_row(self, index):
     14         res = []
     15         for i in range(self.degree):
     16             res.append(self.M[i][index])
     17         return res
     18 
     19     def get_col(self, index):
     20         res = []
     21         for i in range(self.degree):
     22             res.append(self.M[i][index])
     23         return res
     24 
     25     @staticmethod
     26     def dot(m1, m2):
     27         res = 0
     28         for i in range(len(m1)):
     29             res += m1[i] * m2[i]
     30         return res
     31 
     32     @staticmethod
     33     def list_multi(k, lt):
     34         res = []
     35         for i in range(len(lt)):
     36             res.append(k * lt[i])
     37         return res
     38 
     39     @staticmethod
     40     def one_item(x, yArr):
     41         res = [0 for i in range(len(x))]
     42         temp_y_arr = []
     43 
     44         n = len(yArr)
     45         if n == 0:
     46             res = x
     47         else:
     48             for item in yArr:
     49                 k = QR.dot(x, item) / QR.dot(item, item)
     50                 temp_y_arr.append(QR.list_multi(-k, item))
     51             temp_y_arr.append(x)
     52 
     53             for item in temp_y_arr:
     54                 for i in range(len(item)):
     55                     res[i] += item[i]
     56         return res
     57 
     58     @staticmethod
     59     def normal(matrix):
     60         yArr = []
     61         yArr.append(matrix[0])
     62 
     63         for i in range(1, len(matrix)):
     64             yArr.append(QR.one_item(matrix[i], yArr))
     65         return yArr
     66 
     67     @staticmethod
     68     def normalized(lt):
     69         res = []
     70         sm = 0
     71         for item in lt:
     72             sm += math.pow(item, 2)
     73         sm = math.sqrt(sm)
     74         for item in lt:
     75             res.append(item / sm)
     76         return res
     77 
     78     @staticmethod
     79     def matrix_T(matrix):
     80         mat = copy.deepcopy(matrix)
     81         m = len(mat[0])
     82         n = len(mat)
     83         for i in range(m):
     84             for j in range(n):
     85                 if i < j:
     86                     temp = mat[i][j]
     87                     mat[i][j] = mat[j][i]
     88                     mat[j][i] = temp
     89         return mat
     90 
     91     @staticmethod
     92     def matrix_multi(mat1, mat2):
     93         res = []
     94         rows = len(mat1[0])
     95         cols = len(mat1)
     96         for i in range(rows):
     97             temp = [0 for i in range(cols)]
     98             res.append(temp)
     99 
    100         for i in range(rows):
    101             for j in range(cols):
    102                 sm = 0
    103                 for k in range(cols):
    104                     sm += (mat1[k][i] * mat2[j][k])
    105                 res[j][i] = sm
    106         return res
    107 
    108     def execute(self):
    109         xArr = []
    110         for i in range(self.degree):
    111             xArr.append(self.get_col(i))
    112         yArr = QR.normal(xArr)
    113         self.Q = []
    114         for item in yArr:
    115             self.Q.append(QR.normalized(item))
    116 
    117         self.R = QR.matrix_multi(QR.matrix_T(self.Q), xArr)
    118         return (self.Q, self.R)
    119 
    120 
    121 # A = [
    122 #     [1, 0, -1, 2, 1],
    123 #     [3, 2, -3, 5, -3],
    124 #     [2, 2, 1, 4, -2],
    125 #     [0, 4, 3, 3, 1],
    126 #     [1, 0, 8, -11, 4]
    127 # ]
    128 # A = [
    129 #     [1, 2, 2],
    130 #     [2, 1, 2],
    131 #     [2, 2, 1]
    132 # ]
    133 A = [
    134     [3, 2, 4],
    135     [2, 0, 2],
    136     [4, 2, 3]
    137 ]
    138 
    139 temp = copy.deepcopy(A)
    140 val = []  # 特征值
    141 times = 20  # 迭代次数
    142 for i in range(times):
    143     qr = QR(temp)
    144     (q, r) = qr.execute()
    145     temp = QR.matrix_multi(r, q)
    146     temp = QR.matrix_T(temp)
    147 
    148 for i in range(len(temp)):
    149     for j in range(len(temp[0])):
    150         if i == j:
    151             val.append(temp[i][j])
    152 # 特征值
    153 print(val)

    结果展示

    总结

    使用QR分解迭代求特征值,收敛的比较快,也可以求出所有的特征值,但是如果要求特征向量的话,还是需要求解线性方程组(感觉很麻烦) 

  • 相关阅读:
    etcd
    mesos+marathon+zookeeper+docker
    安装好dashboard 登录出现错误
    最小化centos7离线安装docker环境
    centons7安装ftp
    TensorFlow运行模型demo时常见问题
    centos7全新系统安装TensorFlow
    vmware创建虚拟机并安装centos7系统
    python使用moviepy模块对视频进行操作
    iis7/8隐藏banner信息
  • 原文地址:https://www.cnblogs.com/oldBook/p/9927217.html
Copyright © 2020-2023  润新知