我是靠谱客的博主 无心衬衫,最近开发中收集的这篇文章主要介绍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 图论基础
      • 1.2 拉普拉斯矩阵的变体
      • 1.3 拉普拉斯矩阵的优良性质:
      • 1.4 GCN为啥要用拉普拉斯矩阵
    • 二、Python代码实现
    • 三、关于图Fourier变换
    • Reference

一、背景介绍

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 Ntimes{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 Ntimes{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)原理解析

最后

以上就是无心衬衫为你收集整理的Python求解拉普拉斯矩阵及其特征值的全部内容,希望文章能够帮你解决Python求解拉普拉斯矩阵及其特征值所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(45)

评论列表共有 0 条评论

立即
投稿
返回
顶部