Python求解拉普拉斯矩阵及其特征值

学习心得

(1)laplacian matrix就是无向图中定义 L = D − A L=D-A L=DA,其中D为度矩阵,A为邻接矩阵。本文用的python计算拉普拉斯矩阵及其特征值、特征向量。
(2)numpy中文文档:https://www.numpy.org.cn/user/,可以配spyder看对应变量的矩阵元素。
(3)求图拉普拉斯矩阵的特征值:时间复杂度是 O ( n 3 ) O(n^3) O(n3)(n为节点数),所以当图很大时用该方法效率很低。

一、背景介绍

1.1 图论基础

定义一(图的邻接矩阵)

  • 给定一个图 G = { V , E } \mathcal{G}=\{\mathcal{V}, \mathcal{E}\} G={V,E},其对应的邻接矩阵被记为 A ∈ { 0 , 1 } N × N \mathbf{A} \in\{0,1\}^{N \times N} A{0,1}N×N A i , j = 1 \mathbf{A}_{i, j}=1 Ai,j=1表示存在从结点 v i v_i vi v j v_j vj的边,反之表示不存在从结点 v i v_i vi v j v_j vj的边。

  • 无向图中,从结点 v i v_i vi v j v_j vj的边存在,意味着从结点 v j v_j vj v i v_i vi的边也存在。因而无向图的邻接矩阵是对称的

  • 无权图中,各条边的权重被认为是等价的,即认为各条边的权重为 1 1 1

  • 对于有权图,其对应的邻接矩阵通常被记为 W ∈ { 0 , 1 } N × N \mathbf{W} \in\{0,1\}^{N \times N} W{0,1}N×N,其中 W i , j = w i j \mathbf{W}_{i, j}=w_{ij} Wi,j=wij表示从结点 v i v_i vi v j v_j vj的边的权重。若边不存在时,边的权重为 0 0 0

    一个无向无权图的例子:
    在这里插入图片描述
    其邻接矩阵为:
    A = ( 0 1 0 1 1 1 0 1 0 0 0 1 0 0 1 1 0 0 0 1 1 0 1 1 0 ) \mathbf{A}=\left(\begin{array}{lllll} 0 & 1 & 0 & 1 & 1 \\ 1 & 0 & 1 & 0 & 0 \\ 0 & 1 & 0 & 0 & 1 \\ 1 & 0 & 0 & 0 & 1 \\ 1 & 0 & 1 & 1 & 0 \end{array}\right) A= 0101110100010011000110110

定义二(拉普拉斯矩阵,Laplacian Matrix)

  • 给定一个图 G = { V , E } \mathcal{G}=\{\mathcal{V}, \mathcal{E}\} G={V,E},其邻接矩阵为 A A A,其拉普拉斯矩阵定义为 L = D − A \mathbf{L=D-A} L=DA,其中度矩阵 D = d i a g ( d ( v 1 ) , ⋯   , d ( v N ) ) \mathbf{D=diag(d(v_1), \cdots, d(v_N))} D=diag(d(v1),,d(vN))

定义三(对称归一化的拉普拉斯矩阵,Symmetric normalized Laplacian)

  • 给定一个图 G = { V , E } \mathcal{G}=\{\mathcal{V}, \mathcal{E}\} G={V,E},其邻接矩阵为 A A A,其规范化的拉普拉斯矩阵定义为

L = D − 1 2 ( D − A ) D − 1 2 = I − D − 1 2 A D − 1 2 \mathbf{L=D^{-\frac{1}{2}}(D-A)D^{-\frac{1}{2}}=I-D^{-\frac{1}{2}}AD^{-\frac{1}{2}}} L=D21(DA)D21=ID21AD21

1.2 拉普拉斯矩阵的变体

节点数为 n n n的简单图 G G G A A A G G G的邻接矩阵,则如上面介绍的那样, G G G的拉普拉斯矩阵即 L = D − A L=D-A L=DA
(1)对称归一化后的拉普拉斯矩阵: L s y s = D − 1 / 2 L D − 1 / 2 = I − D − 1 / 2 A D − 1 / 2 L^{s y s}=D^{-1 / 2} L D^{-1 / 2}=I-D^{-1 / 2} A D^{-1 / 2} Lsys=D1/2LD1/2=ID1/2AD1/2
(2)随机游走归一化的拉普拉斯矩阵: L r w = D − 1 L = I − D − 1 A L i , j r w : = { 1 i = j − 1 diag ⁡ ( v i )  if  i ≠ j  and  v i  adjacent to  v j 0  othewise  \begin{aligned} &L^{r w}=D^{-1} L=I-D^{-1} A \\ &L_{i, j}^{r w}:= \begin{cases}1 & \mathrm{i}=\mathrm{j} \\ \frac{-1}{\sqrt{\operatorname{diag}\left(v_{i}\right)}} & \text { if } i \neq j \text { and } v_{i} \text { adjacent to } v_{j} \\ 0 & \text { othewise }\end{cases} \end{aligned} Lrw=D1L=ID1ALi,jrw:= 1diag(vi) 10i=j if i=j and vi adjacent to vj othewise 

1.3 拉普拉斯矩阵的优良性质:

  • 拉普拉斯矩阵是半正定对称矩阵
  • 对称矩阵有n个线性无关的特征向量,n是Graph中节点的个数 ⇒ \Rightarrow 拉普拉斯矩阵可以特征分解
  • 半正定矩阵的特征值非负
  • 对称矩阵的特征向量构成的矩阵为正交阵 ⇒ U T U = E \Rightarrow U^{T} U=E UTU=E

1.4 GCN为啥要用拉普拉斯矩阵

  • 拉普拉斯矩阵可以谱分解(特征分解)GCN是从谱域的角度提取拓扑图的空间特征的。
  • 拉普拉斯矩阵只在中心元素和一阶相邻元素处有非零元素,其他位置皆为0.
  • 传统傅里叶变换公式中的基函数是拉普拉斯算子,借助拉普拉斯矩阵,通过类比可以推导出Graph上的傅里叶变换公式。

二、Python代码实现

这是networkX库对稀疏矩阵A的处理方式,有少量改进(将所有内容保持稀疏):

n,m = A.shape
diags = A.sum(axis=1)
D = sps.spdiags(diags.flatten(), [0], m, n, format='csr')
D - A

numpyscipy两个库中模块中都提供了线性代数的库linalg,但scipylinalg的更全面一些。

# laplacian矩阵
import numpy as np
def unnormalized_laplacian(adj_matrix):
    # 先求度矩阵
    R = np.sum(adj_matrix, axis=1)
    degreeMatrix = np.diag(R)
    return degreeMatrix - adj_matrix
    
# 对称归一化的laplacian矩阵
def normalized_laplacian(adj_matrix):
    R = np.sum(adj_matrix, axis=1)
    R_sqrt = 1/np.sqrt(R)
    D_sqrt = np.diag(R_sqrt)
    I = np.eye(adj_matrix.shape[0])
    return I - np.matmul(np.matmul(D_sqrt, adj_matrix), D_sqrt)

matlab的代码实现为:

L = diag(sum(A,2)) - A   % or L=diag(sum(A))-A because A is symmetric

那么如何求矩阵的特征值呢——利用numpy的linalg.eig

# !/usr/bin/python
## -*-coding:utf-8 -*-

import numpy as np
A = np.array([[3,-1],[-1,3]])
print('打印A:\n{}'.format(A))
a, b = np.linalg.eig(A)
print('打印特征值a:\n{}'.format(a))
print('打印特征向量b:\n{}'.format(b))

得到特征值和特征向量:

打印A:  
[[ 3 -1] 
 [-1  3]]
打印特征值a:
[4. 2.]
打印特征向量b:
[[ 0.70710678  0.70710678] 
 [-0.70710678  0.70710678]]

三阶矩阵试试,回归考研线代的题目:
在这里插入图片描述
在这里插入图片描述

import numpy as np
A = np.array([[2,-3,1],[1,-2,1],[1,-3,2]])
print('打印A:\n{}'.format(A))
a, b = np.linalg.eig(A)
print('打印特征值a:\n{}'.format(a))
print('打印特征向量b:\n{}'.format(b))

结果如下,看结果的特征向量矩阵,每一列代表一个一个特征向量,都是

打印A:
[[ 2 -3  1]
 [ 1 -2  1]
 [ 1 -3  2]]
打印特征值a:
[2.09037533e-15+0.00000000e+00j 1.00000000e+00+5.87474805e-16j
 1.00000000e+00-5.87474805e-16j]
打印特征向量b:
[[0.57735027+0.j         0.84946664+0.j         0.84946664-0.j        ]
 [0.57735027+0.j         0.34188085-0.11423045j 0.34188085+0.11423045j]
 [0.57735027+0.j         0.17617591-0.34269135j 0.17617591+0.34269135j]]

三、关于图Fourier变换

根据卷积原理,卷积公式可以写成
f ∗ g = F − 1 { F { f } ⋅ F { g } } f * g=\mathcal{F}^{-1}\{\mathcal{F}\{f\} \cdot \mathcal{F}\{g\}\} fg=F1{F{f}F{g}}
正、逆Fourier变换
F ( v ) = ∫ R f ( x ) e − 2 π i x ⋅ v d x \mathcal{F}(v)=\int_{\mathrm{R}} f(x) e^{-2 \pi i x \cdot v} d x F(v)=Rf(x)e2πixvdx

f ( x ) = ∫ R F ( v ) e 2 π i x ⋅ v d v f(x)=\int_{\mathbb{R}} \mathcal{F}(v) e^{2 \pi i x \cdot v} d v f(x)=RF(v)e2πixvdv

一阶导数定义
f ′ ( x ) = lim ⁡ h → 0 f ( x + h ) − f ( x ) h f^{\prime}(x)=\lim _{h \rightarrow 0} \frac{f(x+h)-f(x)}{h} f(x)=h0limhf(x+h)f(x)
拉普拉斯相当于二阶导数
Δ f ( x ) = lim ⁡ h → 0 f ( x + h ) − 2 f ( x ) + f ( x − h ) h 2 \Delta f(x)=\lim _{h \rightarrow 0} \frac{f(x+h)-2 f(x)+f(x-h)}{h^{2}} Δf(x)=h0limh2f(x+h)2f(x)+f(xh)
在graph上,定义一阶导数为
f ∗ g ′ ( x ) = f ( x ) − f ( y ) f_{* g}^{\prime}(x)=f(x)-f(y) fg(x)=f(x)f(y)
对应的拉普拉斯算子定义为
Δ ∗ g f ′ ( x ) = Σ y ∼ x ( f ( x ) − f ( y ) ) \Delta_{*g} f^{\prime}(x)=\Sigma_{y \sim x} (f(x)-f(y)) Δgf(x)=Σyx(f(x)f(y))
假设 D D D N × N N\times{N} N×N的度矩阵(degree matrix)
D ( i , j ) = { d i  if  i = j 0  otherwise  D(i, j)=\left\{\begin{array}{ll}{d_{i}} & {\text { if } i=j} \\ {0} & {\text { otherwise }}\end{array}\right. D(i,j)={di0 if i=j otherwise 
A A A N × N N\times{N} N×N的邻接矩阵(adjacency matrix)
A ( i , j ) = { 1  if  x i ∼ x j 0  otherwise  A(i, j)=\left\{\begin{array}{ll}{1} & {\text { if } x_{i} \sim x_{j}} \\ {0} & {\text { otherwise }}\end{array}\right. A(i,j)={10 if xixj otherwise 
那么图上的Laplacian算子可以写成
L = D − A L=D-A L=DA
标准化后得到
L = I N − D − 1 2 A D − 1 2 L=I_{N}-D^{-\frac{1}{2}} A D^{-\frac{1}{2}} L=IND21AD21
定义Laplacian算子的目的是为了找到Fourier变换的基

传统Fourier变换的基就是Laplacian算子的一组特征向量
Δ e 2 π i x ⋅ v = λ e 2 π i x ⋅ v \Delta e^{2 \pi i x \cdot v}=\lambda e^{2 \pi i x \cdot v} Δe2πixv=λe2πixv
类似的,在graph上,有
Δ f = ( D − A ) f = L f \Delta{f}=(D-A)f=Lf Δf=(DA)f=Lf
图拉普拉斯算子作用在由图节点信息构成的向量 f f f上得到的结果等于图拉普拉斯矩阵和向量 f f f的点积

那么graph上的Fourier基就是 L L L矩阵的 n n n个特征向量 U = [ u 1 … u n ] U=\left[u_{1} \dots u_{n}\right] U=[u1un] L L L可以分解成 L = U Λ U T L=U \Lambda U^{T} L=UΛUT,其中, Λ \Lambda Λ是特征值组成的对角矩阵。

传统的Fourier变换与graph的Fourier变换区别

在这里插入图片描述

f ( i ) f(i) f(i)看成是第 i i i个点上的signal,用向量 x = ( f ( 1 ) … f ( n ) ) ∈ R n x=(f(1) \ldots f(n)) \in \mathbb{R}^{n} x=(f(1)f(n))Rn来表示。矩阵形式的graph的Fourier变换为
G F { x } = U T x \mathcal{G F}\{x\}=U^{T} x GF{x}=UTx
类似的graph上的Fourier逆变换为
I G F { x } = U x \mathcal{I} \mathcal{G} \mathcal{F}\{x\}=U x IGF{x}=Ux

Reference

(1)Python计算特征值与特征向量案例
(2)numpy的linalg官方文档:https://docs.scipy.org/doc/numpy-1.13.0/reference/routines.linalg.html
(3)用python求解特征向量和拉普拉斯矩阵
(4)图卷积网络(GCN)原理解析

评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

山顶夕景

小哥哥给我买个零食可好

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值