Python中的Eigendecomposition入门

163 阅读5分钟

在靠近用户的地方部署容器 Eigendecomposition是线性代数中用来将一个矩阵分解成其组成部分的一种技术。

在本教程中,我们将专注于矩阵的特征值特征向量来推导Eigendecomposition。我们还将使用方形矩阵,因为它们支持特征值特征向量的计算。

让我们用一个简单的矩阵来理解Eigendecomposition是如何得出的。

假设我们有一个2×2的正方形矩阵A。

Matrix

我们的第一步是确定其特征值和特征向量。如果你计算了特征值,你应该得到。

Eigenvalues

与这些特征值相对应的特征向量是。

Eigenvectors

当我们将特征向量归一化时,我们应该看到以下输出。

Normalized-eigenvectors

我们可以用这些成分建立以下方程式,因为它们解释了特征值和特征向量。

Au_1=lambda_1u_1Au\_1=lambda\_1u\_1

Au_2=lambda_2u_2Au\_2=lambda\_2u\_2

如果我们把这两个系统压缩成一个特征向量的矩阵和一个特征值的矩阵,就可以得到。

Matrix-equation

我们也可以使用下面的公式。

Matrices

当我们在公式(i)(i)中使用UUlambdalambda时,我们得到以下公式。

AU=U/LambdaAU=U/Lambda

为了从这个关系中得到我们的矩阵AA,我们在上面的矩阵方程的两边取UU的逆,即U1U^{-1}。我们最终得到下面的方程。

A=ULambdaU1A=U\\Lambda U^{-1}

这个部分就是我们所说的Eigendecomposition。矩阵UU包含特征向量,LambdaLambda有特征值。

为什么这个矩阵分解很重要?

如前所述,矩阵是一种转换,它将一个向量从向量空间中的一点映射到另一点。

在机器学习算法中,我们经常多次应用这种变换,直到在算法的每个阶段获得最终输出。

然而,这种应用也取决于问题的复杂性。这意味着在最后,我们将把我们的矩阵提高到某个数字的幂。

为了理解这一点,假设我们有以下的方形矩阵。

APA^{P}, 其中p=16p=16

计算这个矩阵的一个简单方法是,在每次迭代时取所有可能的对的乘积。

让我们确定计算这个矩阵所需的迭代次数,直到我们得到最终的输出为ApA^p

我们可以明确地把A写成。

A*A*A*A*A*A*A*A*A*A*A*A*A*A*A*A

当我们在第一次迭代中对A矩阵的每一对进行乘积时,我们得到。

A2\*A2\*A2\*A2\*A2\*A2\*A2\*A2A^{2}\*A^{2}\*A^{2}\*A^{2}\*A^{2}\*A^{2}\*A^{2}\*A^{2}

在下一次迭代中,我们检查上述矩阵的对积。其结果是。

A4\*A4\*A4\*A4A^{4}\*A^{4}\*A^{4}\*A^{4}

如果我们再次进行计算,我们会得到。

A8\*A8A^{8}\*A^{8}

我们确定最终的输出结果,如下图所示。

A8A^{8}

为了确定最终的输出,我们在四个不同的迭代中进行了乘法运算。

p的值很大时,我们可以使用公式log_2(p)log\_2(p)。这将使我们能够知道最终输出所需的迭代次数。

很明显,迭代次数随着p的大小而变化,这使得该方法在应用大数时效率不高。

让我们把Eigendecomposition应用于这个问题。

A=ULambdaU1A=U\\Lambda U^{-1}

当我们明确写出A时,我们应该有以下输出。

Matrix-m

要计算上面方程右边的这条长链很容易。矩阵与它的逆的乘积等于一个身份矩阵。

这意味着任何矩阵与身份矩阵相乘都等于矩阵本身。将这一知识应用于上面的方程,它可以浓缩为。

A=ULambda16U1A=U\\Lambda^{16}U^{-1}

我们唯一需要计算的矩阵是Lambda16Lambda^{16}

LambdaLambda是一个对角线矩阵。我们用它的对角线成分的功率来计算它。

为了确定输出所需的迭代次数,我们首先在第一次迭代中进行以下乘法。

Lambda16U1Lambda^{16}U^{-1}.

然后我们取U\*U\*o(第一次迭代的输出)并将其转移到第二次迭代。

因此,无论p的大小如何,在Eigendecomposition中,我们进行计算的次数保持不变。

现在让我们在python中执行Eigendecomposition。

在Python中实现Eigendecomposition

在本教程中,我们只需要Numpy Python库。让我们把它导入如下。

import numpy as np

在这个Python演示中,我们将使用以下方形矩阵。

Matrix

M=\\begin{bmatrix}1&2&1\\ 0&1&0\\ 1&0&1\\end{bmatrix}

让我们在Python中创建这个矩阵。

# create our matrix
M = np.array([ [1,2,1], [0,1,0], [1, 0, 1] ])

让我们打印矩阵以了解其组成部分。

print(M)

输出。

[[1 2 1]
 [0 1 0]
 [1 0 1]]

为了得到eigendecomposition的组成部分,我们首先需要计算特征值特征向量

#getting the eigenvalues and eigenvvector of M
Lambda, U = np.linalg.eig(M)

让我们打印出特征向量特征值

## eigenvectors
print(U)
[[ 7.07106781e-01 -7.07106781e-01  2.00093587e-17]
 [ 0.00000000e+00  0.00000000e+00  4.47213595e-01]
 [ 7.07106781e-01  7.07106781e-01 -8.94427191e-01]]
print(Lambda)

输出。

[2. 0. 1.]

我们需要LambdaLambdaU1U^-{1}来计算我们Eigendecomposition的所有组成部分。

我们将首先利用Numpy的inv() 函数来确定U1U^{-1},使用UU的逆值,如下图所示。

# getting U inverse
inv_U = np.linalg.inv(U)
inv_U

输出。

array([[ 0.70710678,  1.41421356,  0.70710678],
       [-0.70710678,  1.41421356,  0.70710678],
       [ 0.        ,  2.23606798,  0.        ]])

我们来计算对角线矩阵上的LambdaLambda。我们将使用diag() 函数和Lambda 矢量来获得这个矩阵。

Λ = np.diag(Lambda)
Λ

输出。

array([[2., 0., 0.],
       [0., 0., 0.],
       [0., 0., 1.]])

由于我们有了对角线分解的三个组成部分,让我们重新构建原始矩阵。

def round(values, decs=0): $# we don't want to include decimal points in our returned matrix
  return np.round(values*10**decs)/(10**decs)

vec = np.dot(U,np.dot(Λ, inv_U)) # taking the product of our three matrices
round(vec, decs=0)

当我们执行上面的代码时,我们应该有以下输出。

array([[ 1.,  2.,  1.],
       [ 0.,  1.,  0.],
       [ 1., -0.,  1.]])

在上面的代码中,我们已经连续从其特征成分中恢复了我们的原始矩阵。

总结

在本教程中,我们学习了如何推导出特征分解。我们还使用了一个简单的插图来确定这种形式的分解与普通的矩阵乘法相比效率如何。

最后,我们研究了如何使用 Python 进行 eigendecomposition。现在你可以利用这些知识来制作其他高质量的应用程序。