添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接


学习心得

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

文章目录

一、背景介绍

1.1 图论基础

定义一(图的邻接矩阵)

  • 给定一个图 Python求解拉普拉斯矩阵及其特征值_特征向量_03 ,其对应的 邻接矩阵 被记为 Python求解拉普拉斯矩阵及其特征值_python_04 Python求解拉普拉斯矩阵及其特征值_邻接矩阵_05 表示存在从结点 Python求解拉普拉斯矩阵及其特征值_特征向量_06 Python求解拉普拉斯矩阵及其特征值_特征值_07 的边,反之表示不存在从结点 Python求解拉普拉斯矩阵及其特征值_特征向量_06 Python求解拉普拉斯矩阵及其特征值_特征值_07 的边。
  • 无向图 中,从结点 Python求解拉普拉斯矩阵及其特征值_特征向量_06 Python求解拉普拉斯矩阵及其特征值_特征值_07 的边存在,意味着从结点 Python求解拉普拉斯矩阵及其特征值_特征值_07 Python求解拉普拉斯矩阵及其特征值_特征向量_06 的边也存在。因而 无向图的邻接矩阵是对称的
  • 无权图 中, 各条边的权重被认为是等价的 ,即认为 各条边的权重为 Python求解拉普拉斯矩阵及其特征值_线性代数_14
  • 对于 有权图 ,其对应的邻接矩阵通常被记为 Python求解拉普拉斯矩阵及其特征值_特征向量_15 ,其中 Python求解拉普拉斯矩阵及其特征值_线性代数_16 表示从结点 Python求解拉普拉斯矩阵及其特征值_特征向量_06 Python求解拉普拉斯矩阵及其特征值_特征值_07 的边的权重。若边不存在时,边的权重为 Python求解拉普拉斯矩阵及其特征值_特征向量_19
    一个无向无权图的例子:
  • Python求解拉普拉斯矩阵及其特征值_线性代数_20

  • 其邻接矩阵为:
    Python求解拉普拉斯矩阵及其特征值_特征值_21

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

  • 给定一个图 Python求解拉普拉斯矩阵及其特征值_python_22 ,其邻接矩阵为 Python求解拉普拉斯矩阵及其特征值_特征值_23 ,其拉普拉斯矩阵定义为 Python求解拉普拉斯矩阵及其特征值_python_24 ,其中度矩阵 Python求解拉普拉斯矩阵及其特征值_线性代数_25

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

  • 给定一个图 Python求解拉普拉斯矩阵及其特征值_python_22 ,其邻接矩阵为 Python求解拉普拉斯矩阵及其特征值_特征值_23 ,其规范化的拉普拉斯矩阵定义为

Python求解拉普拉斯矩阵及其特征值_特征向量_28

1.2 拉普拉斯矩阵的变体

节点数为 Python求解拉普拉斯矩阵及其特征值_python_29 的简单图 Python求解拉普拉斯矩阵及其特征值_特征值_30 Python求解拉普拉斯矩阵及其特征值_python_31 Python求解拉普拉斯矩阵及其特征值_特征值_30 的邻接矩阵,则如上面介绍的那样, Python求解拉普拉斯矩阵及其特征值_特征值_30 的拉普拉斯矩阵即 Python求解拉普拉斯矩阵及其特征值_邻接矩阵
(1)对称归一化后的拉普拉斯矩阵: Python求解拉普拉斯矩阵及其特征值_特征向量_35
(2)随机游走归一化的拉普拉斯矩阵: Python求解拉普拉斯矩阵及其特征值_特征向量_36

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

  • 拉普拉斯矩阵是半正定对称矩阵
  • 对称矩阵有n个线性无关的特征向量,n是Graph中节点的个数 Python求解拉普拉斯矩阵及其特征值_线性代数_37
  • 半正定矩阵的特征值非负
  • 对称矩阵的特征向量构成的矩阵为正交阵 Python求解拉普拉斯矩阵及其特征值_特征向量_38

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 -

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

# 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]]

三阶矩阵试试,回归考研线代的题目:

Python求解拉普拉斯矩阵及其特征值_特征向量_39


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

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变换

根据卷积原理,卷积公式可以写成
Python求解拉普拉斯矩阵及其特征值_特征值_41
正、逆Fourier变换
Python求解拉普拉斯矩阵及其特征值_特征值_42

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

一阶导数定义
Python求解拉普拉斯矩阵及其特征值_线性代数_44
拉普拉斯相当于二阶导数
Python求解拉普拉斯矩阵及其特征值_python_45
在graph上,定义一阶导数为
Python求解拉普拉斯矩阵及其特征值_python_46
对应的拉普拉斯算子定义为
Python求解拉普拉斯矩阵及其特征值_特征值_47
假设 Python求解拉普拉斯矩阵及其特征值_特征值_48 Python求解拉普拉斯矩阵及其特征值_线性代数_49 的度矩阵(degree matrix)
Python求解拉普拉斯矩阵及其特征值_python_50
Python求解拉普拉斯矩阵及其特征值_python_31 Python求解拉普拉斯矩阵及其特征值_线性代数_49 的邻接矩阵(adjacency matrix)
Python求解拉普拉斯矩阵及其特征值_python_53
那么图上的Laplacian算子可以写成
Python求解拉普拉斯矩阵及其特征值_python_54
标准化后得到
Python求解拉普拉斯矩阵及其特征值_python_55
定义Laplacian算子的目的是为了找到Fourier变换的基

传统Fourier变换的基就是Laplacian算子的一组特征向量
Python求解拉普拉斯矩阵及其特征值_邻接矩阵_56
类似的,在graph上,有
Python求解拉普拉斯矩阵及其特征值_特征向量_57
图拉普拉斯算子作用在由图节点信息构成的向量 Python求解拉普拉斯矩阵及其特征值_特征向量_58 上得到的结果等于图拉普拉斯矩阵和向量 Python求解拉普拉斯矩阵及其特征值_特征向量_58 的点积

那么graph上的Fourier基就是 Python求解拉普拉斯矩阵及其特征值_邻接矩阵_60 矩阵的 Python求解拉普拉斯矩阵及其特征值_python_29 个特征向量 Python求解拉普拉斯矩阵及其特征值_python_62 Python求解拉普拉斯矩阵及其特征值_邻接矩阵_60 可以分解成 Python求解拉普拉斯矩阵及其特征值_线性代数_64 ,其中, Python求解拉普拉斯矩阵及其特征值_线性代数_65 是特征值组成的对角矩阵。

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

Python求解拉普拉斯矩阵及其特征值_线性代数_66

Python求解拉普拉斯矩阵及其特征值_python_67 看成是第 Python求解拉普拉斯矩阵及其特征值_线性代数_68 个点上的signal,用向量 Python求解拉普拉斯矩阵及其特征值_特征向量_69 来表示。矩阵形式的graph的Fourier变换为
Python求解拉普拉斯矩阵及其特征值_线性代数_70
类似的graph上的Fourier逆变换为
Python求解拉普拉斯矩阵及其特征值_线性代数_71

Reference

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


freemarker java 多线程 java多线程代码

目录实现多线程的两种基础方式方式一:继承Thread类方式二:实现Runnable接口线程常用方法线程优先级设置线程的插队和礼让线程的中断守护线程 线程同步多线程时间比较实现多线程的两种基础方式方式一:继承Thread类java中一个类只能继承一个父类,如果当前类已经继承了其他类了,则不能使用这种方法。class Way1 extends Thread { private boole

java中StringJoiner java中stringjoiner用法

StringJoiner是java.util包下的一个工具类,jdk1.8出来的作用是在构造字符串时,可以自动添加前缀、后缀及分隔符,而不需要自己去实现这些添加字符的逻辑先看一个简单的demoStringJoiner sj1 = new StringJoiner(","); StringJoiner sj2 = new StringJoiner(",", "[", "]"); System.ou