本文简要介绍 python 语言中 scipy.sparse.csgraph.laplacian
的用法。
用法:
scipy.sparse.csgraph.laplacian(csgraph, normed=False, return_diag=False, use_out_degree=False, *, copy=True, form='array', dtype=None, symmetrized=False)#
返回有向图的拉普拉斯算子。
- csgraph: 数组 或稀疏矩阵,二维
compressed-sparse 图形,形状为 (N, N)。
- normed: 布尔型,可选
如果为 True,则计算对称归一化拉普拉斯算子。默认值:假。
- return_diag: 布尔型,可选
如果为 True,则还返回与顶点度数相关的数组。默认值:假。
- use_out_degree: 布尔型,可选
如果为 True,则使用出度而不是入度。仅当图形不对称时,这种区别才重要。默认值:假。
- copy: bool, optional:
如果为 False,则尽可能更改 csgraph,避免内存使用量加倍。默认值:True,用于向后兼容。
- form: ‘array’, or ‘function’, or ‘lo’:
确定输出拉普拉斯算子的格式:
‘array’ 是一个 numpy 数组;
‘function’是评估Laplacian-vector或Laplacian-matrix产品的指针;
‘lo’ 结果采用 LinearOperator 的格式。
选择‘function’ 或‘lo’ 始终避免内存使用加倍,忽略
copy
值。默认值:‘array’,用于向后兼容。- dtype: None or one of numeric numpy dtypes, optional:
输出的数据类型。如果
dtype=None
,输出的 dtype 与输入 csgraph 的 dtype 匹配,但normed=True
和 integer-like csgraph 情况除外,其中输出 dtype 为 ‘float’ 允许精确标准化,但会显著增加内存使用。默认值:无,用于向后兼容。- symmetrized: bool, optional:
如果为 True,则输出拉普拉斯算子是对称/厄米算子。对称化是通过以下方式完成的
csgraph + csgraph.T.conj
如果可能的话,在构造拉普拉斯算子之前不除以 2 以保留整数数据类型。对称化将增加稀疏矩阵的内存占用,除非稀疏模式是对称的或形式是‘function’ 或‘lo’。默认值:False,用于向后兼容。
- lap: ndarray,或稀疏矩阵,或LinearOperator
csgraph 的 N x N 拉普拉斯算子。如果输入是密集的,则它将是 NumPy 数组(密集),否则将是稀疏矩阵,或者如果形式分别等于 ‘function’ 或 ‘lo’,则为函数格式或 LinearOperator。
- diag: ndarray,可选
拉普拉斯矩阵的 length-N 主对角线。对于归一化拉普拉斯算子,这是顶点度数的平方根数组,如果度数为零,则为 1。
参数 ::
返回 ::
注意:
图的拉普拉斯矩阵有时被称为“Kirchhoff matrix”或只是“Laplacian”,并且在谱图理论的许多部分中都很有用。特别是,拉普拉斯算子的特征分解可以深入了解图的许多属性,例如,通常用于频谱数据嵌入和聚类。
如果
copy=True
和form="array"
是默认值,则构造的拉普拉斯算子会使内存使用量加倍。除非form="array"
或矩阵以coo
格式稀疏或密集数组,否则选择copy=False
无效,但normed=True
的整数输入强制浮点输出。如果
form="array"
,稀疏输入将重新格式化为coo
,这是默认值。如果输入邻接矩阵不对称,则拉普拉斯算子也是非对称的,除非使用
symmetrized=True
。出于标准化目的,输入邻接矩阵的对角项将被忽略并替换为零,其中
normed=True
.归一化使用输入邻接矩阵的 row-sums 的反平方根,因此如果 row-sums 包含负数或具有非零虚部值的复数,则可能会失败。归一化是对称的,如果输入 csgraph 是对称的,则归一化的拉普拉斯算子也是对称的。
参考:
[1]例子:
>>> import numpy as np >>> from scipy.sparse import csgraph
我们的第一个插图是对称图
>>> G = np.arange(4) * np.arange(4)[:, np.newaxis] >>> G array([[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6], [0, 3, 6, 9]])
及其对称拉普拉斯矩阵
>>> csgraph.laplacian(G) array([[ 0, 0, 0, 0], [ 0, 5, -2, -3], [ 0, -2, 8, -6], [ 0, -3, -6, 9]])
非对称图
>>> G = np.arange(9).reshape(3, 3) >>> G array([[0, 1, 2], [3, 4, 5], [6, 7, 8]])
具有不同的行和列总和,从而产生两种拉普拉斯矩阵,使用入度(默认值)
>>> L_in_degree = csgraph.laplacian(G) >>> L_in_degree array([[ 9, -1, -2], [-3, 8, -5], [-6, -7, 7]])
或者出度
>>> L_out_degree = csgraph.laplacian(G, use_out_degree=True) >>> L_out_degree array([[ 3, -1, -2], [-3, 8, -5], [-6, -7, 13]])
构造一个对称拉普拉斯矩阵,可以将两者相加为
>>> L_in_degree + L_out_degree.T array([[ 12, -4, -8], [ -4, 16, -12], [ -8, -12, 20]])
或使用
symmetrized=True
选项>>> csgraph.laplacian(G, symmetrized=True) array([[ 12, -4, -8], [ -4, 16, -12], [ -8, -12, 20]])
这相当于将原始图对称化
>>> csgraph.laplacian(G + G.T) array([[ 12, -4, -8], [ -4, 16, -12], [ -8, -12, 20]])
归一化的目标是使拉普拉斯矩阵的非零对角线项全部为单位,同时相应地缩放非对角线项。标准化可以手动完成,例如,
>>> G = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]) >>> L, d = csgraph.laplacian(G, return_diag=True) >>> L array([[ 2, -1, -1], [-1, 2, -1], [-1, -1, 2]]) >>> d array([2, 2, 2]) >>> scaling = np.sqrt(d) >>> scaling array([1.41421356, 1.41421356, 1.41421356]) >>> (1/scaling)*L*(1/scaling) array([[ 1. , -0.5, -0.5], [-0.5, 1. , -0.5], [-0.5, -0.5, 1. ]])
或者使用
normed=True
选项>>> L, d = csgraph.laplacian(G, return_diag=True, normed=True) >>> L array([[ 1. , -0.5, -0.5], [-0.5, 1. , -0.5], [-0.5, -0.5, 1. ]])
现在返回缩放系数而不是对角线
>>> d array([1.41421356, 1.41421356, 1.41421356])
零缩放系数用 1 代替,因此缩放没有影响,例如,
>>> G = np.array([[0, 0, 0], [0, 0, 1], [0, 1, 0]]) >>> G array([[0, 0, 0], [0, 0, 1], [0, 1, 0]]) >>> L, d = csgraph.laplacian(G, return_diag=True, normed=True) >>> L array([[ 0., -0., -0.], [-0., 1., -1.], [-0., -1., 1.]]) >>> d array([1., 1., 1.])
仅实现对称归一化,当且仅当其图是对称的并且具有所有非负度时,才会产生对称拉普拉斯矩阵,如上面的示例所示。
默认情况下,输出拉普拉斯矩阵是密集数组或稀疏矩阵,从输入图矩阵推断其形状、格式和数据类型:
>>> G = np.array([[0, 1, 1], [1, 0, 1], [1, 1, 0]]).astype(np.float32) >>> G array([[0., 1., 1.], [1., 0., 1.], [1., 1., 0.]], dtype=float32) >>> csgraph.laplacian(G) array([[ 2., -1., -1.], [-1., 2., -1.], [-1., -1., 2.]], dtype=float32)
但也可以生成 matrix-free 作为 LinearOperator:
>>> L = csgraph.laplacian(G, form="lo") >>> L <3x3 _CustomLinearOperator with dtype=float32> >>> L(np.eye(3)) array([[ 2., -1., -1.], [-1., 2., -1.], [-1., -1., 2.]])
或作为lambda-function:
>>> L = csgraph.laplacian(G, form="function") >>> L <function _laplace.<locals>.<lambda> at 0x0000012AE6F5A598> >>> L(np.eye(3)) array([[ 2., -1., -1.], [-1., 2., -1.], [-1., -1., 2.]])
拉普拉斯矩阵用于频谱数据聚类和嵌入以及频谱图划分。我们的最后一个示例说明了噪声有向线性图的后者。
>>> from scipy.sparse import diags, random >>> from scipy.sparse.linalg import lobpcg
使用稀疏邻接矩阵
G
创建具有N=35
顶点的有向线性图:>>> N = 35 >>> G = diags(np.ones(N-1), 1, format="csr")
修复随机种子
rng
并向图G
添加随机稀疏噪声:>>> rng = np.random.default_rng() >>> G += 1e-2 * random(N, N, density=0.1, random_state=rng)
设置特征向量的初始近似值:
>>> X = rng.random((N, 2))
常数向量始终是要滤除的非归一化拉普拉斯算子的平凡特征向量:
>>> Y = np.ones((N, 1))
交替 (1) 图权重的符号允许在单个循环中确定谱最大和最小切割的标签。由于该图是无向的,因此在构造拉普拉斯算子时必须使用选项
symmetrized=True
。选项normed=True
不能在 (2) 中用于此处的负权重,因为对称归一化计算平方根。 (2) 中的选项form="lo"
是 matrix-free,即保证固定的内存占用和对图的只读访问。调用特征值求解器lobpcg
(3) 计算 Fiedler 向量,该向量将标签确定为 (5) 中其分量的符号。由于特征向量中的符号不是确定性的并且可以翻转,因此我们将 (4) 中第一个分量的符号固定为始终 +1。>>> for cut in ["max", "min"]: ... G = -G # 1. ... L = csgraph.laplacian(G, symmetrized=True, form="lo") # 2. ... _, eves = lobpcg(L, X, Y=Y, largest=False, tol=1e-3) # 3. ... eves *= np.sign(eves[0, 0]) # 4. ... print(cut + "-cut labels:\n", 1 * (eves[:, 0]>0)) # 5. max-cut labels: [1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1] min-cut labels: [1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0]
正如对(稍微有噪音的)线性图的预期,max-cut 剥离图的所有边,将所有奇数顶点着色为一种颜色,将所有偶数顶点着色为另一种颜色,而平衡的 min-cut 将图在中间划分为删除单个边。两个确定的分区都是最优的。
相关用法
- Python SciPy csgraph.csgraph_to_dense用法及代码示例
- Python SciPy csgraph.min_weight_full_bipartite_matching用法及代码示例
- Python SciPy csgraph.minimum_spanning_tree用法及代码示例
- Python SciPy csgraph.breadth_first_order用法及代码示例
- Python SciPy csgraph.connected_components用法及代码示例
- Python SciPy csgraph.dijkstra用法及代码示例
- Python SciPy csgraph.breadth_first_tree用法及代码示例
- Python SciPy csgraph.csgraph_from_dense用法及代码示例
- Python SciPy csgraph.floyd_warshall用法及代码示例
- Python SciPy csgraph.bellman_ford用法及代码示例
- Python SciPy csgraph.csgraph_to_masked用法及代码示例
- Python SciPy csgraph.maximum_flow用法及代码示例
- Python SciPy csgraph.csgraph_masked_from_dense用法及代码示例
- Python SciPy csgraph.shortest_path用法及代码示例
- Python SciPy csgraph.reconstruct_path用法及代码示例
- Python SciPy csgraph.johnson用法及代码示例
- Python SciPy csgraph.maximum_bipartite_matching用法及代码示例
- Python SciPy csgraph.depth_first_order用法及代码示例
- Python SciPy csgraph.csgraph_from_masked用法及代码示例
- Python SciPy csgraph.construct_dist_matrix用法及代码示例
- Python SciPy csgraph.reverse_cuthill_mckee用法及代码示例
- Python SciPy csgraph.depth_first_tree用法及代码示例
- Python SciPy csgraph.structural_rank用法及代码示例
- Python SciPy csc_array.diagonal用法及代码示例
- Python SciPy csc_matrix.nonzero用法及代码示例
注:本文由纯净天空筛选整理自scipy.org大神的英文原创作品 scipy.sparse.csgraph.laplacian。非经特殊声明,原始代码版权归原作者所有,本译文未经允许或授权,请勿转载或复制。