拉普拉斯矩阵的python实现

代码是从github下载的增加了点注释,关于注释中的栗子,是自己随意创建的一个matrix,方便理解。

    def get_norm_adj_mat(self):
        # build adj matrix
        A = sp.dok_matrix((self.n_users + self.n_items, self.n_users + self.n_items), dtype=np.float32)
        # doc_matrix的策略是采用字典来记录矩阵中不为0的元素

        inter_M = self.interaction_matrix  # 获取用户-项目相互稀疏矩阵 ( , )=1 or =None
        inter_M_t = self.interaction_matrix.transpose()   # 转置
        data_dict = dict(zip(zip(inter_M.row, inter_M.col + self.n_users), [1] * inter_M.nnz))
        # zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,
        # 原本(inter_M.row, inter_M.col)对应了行和列,然后列加上了user(5)   0,0 ->1 现在 0,5-> 1
        # data_dict中存放的{(0, 5): 1, (3, 8): 1, (1, 6): 1, (0, 7): 1}
        data_dict.update(dict(zip(zip(inter_M_t.row + self.n_users, inter_M_t.col), [1] * inter_M_t.nnz)))
        # 此时data_dict中存放了{(0, 5): 1, (3, 8): 1, (1, 6): 1, (0, 7): 1, (5, 0): 1, (8, 3): 1, (6, 1): 1, (7, 0): 1}
        A._update(data_dict)
        # 更新之前创建的稀疏矩阵,将转置和非转置信息加入到稀疏矩阵中  A就相当于邻接矩阵
        # norm adj matrix
        sumArr = (A > 0).sum(axis=1)   # 返回的是每一行的为True的个数  m*1   sumArr度矩阵
        # add epsilon to avoid divide by zero Warning  添加 epsilon 以避免除以零警告
        diag = np.array(sumArr.flatten())[0] + 1e-7   # 返回是一个array,也就是sumArr平铺+1e-7 []
        diag = np.power(diag, -0.5)  # 求diag的-1/2次方
        D = sp.diags(diag)  # 把它真正转换为矩阵形式
        L = D * A * D  # 计算出来了拉普拉斯矩阵
        # covert norm_adj matrix to tensor
        L = sp.coo_matrix(L)
        row = L.row
        col = L.col
        i = torch.LongTensor([row, col])
        data = torch.FloatTensor(L.data)
        SparseL = torch.sparse.FloatTensor(i, data, torch.Size(L.shape))
        """ SparseL最后返回的是这个
        tensor(indices=tensor([[0, 0, 1, 3, 5, 6, 7, 8],
                       [5, 7, 6, 8, 0, 1, 0, 3]]),
        values=tensor([0.7071, 0.7071, 1.0000, 1.0000, 0.7071, 1.0000, 0.7071,
                      1.0000]),
        size=(12, 12), nnz=8, layout=torch.sparse_coo)
        """
        return SparseL

jupyter notebook中的示例如下

import numpy as np
row = np.array([0, 3, 1, 0])
col = np.array([0, 3, 1, 2])
data = np.array([4,5,7,8])
import scipy.sparse as sp
from scipy.sparse import coo_matrix, csr_matrix
d1 = coo_matrix((data, (row, col)))
d1.toarray()

在这里插入图片描述

data_dict = dict(zip(zip(d1.row, d1.col + 5), [1] * d1.nnz))
data_dict

在这里插入图片描述

d2 = d1.transpose()
data_dict.update(dict(zip(zip(d2.row + 5, d2.col), [1] * d2.nnz)))
data_dict

在这里插入图片描述

 A = sp.dok_matrix((12, 12), dtype=np.float32) 
 # 这里是随机创建的12*12的矩阵,实际应该是(user+item)*(user+item)
 A._update(data_dict)
 A.toarray() # 查看一下

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

Python中,归一化拉普拉斯矩阵通常用于图论中的邻接矩阵表示,它是一种稀疏矩阵,用于计算图的局部特征。归一化的拉普拉斯矩阵可以帮助我们处理各种图形分析任务,如社区检测、谱聚类等。 归一化拉普拉斯矩阵有几种形式,其中最常见的是随机游走拉普拉斯矩阵(Random Walk Laplacian)和共轭拉普拉斯矩阵(Conjugate Gradient Laplacian)。这两种归一化方法的区别在于对度矩阵(Degree Matrix)的处理: 1. 随机游走拉普拉斯矩阵(Normalized Random Walk Laplacian, NRM): \( L = D^{-\frac{1}{2}}AD^{-\frac{1}{2}} \) 其中 \( A \) 是原始的邻接矩阵,\( D \) 是度矩阵(对角线元素为A的所有列和),\( D^{-\frac{1}{2}} \) 表示D的平方根的逆。 2. 共轭拉普拉斯矩阵(Symmetric Normalized Laplacian, SNC)或改进的共轭拉普拉斯矩阵(Graph Shift Operator, GSO): \( L = I - D^{-\frac{1}{2}}AD^{-\frac{1}{2}} \) 这里 \( I \) 是单位矩阵,这种归一化更有利于信号传播。 在Python中,可以使用Scipy库中的sparse模块来创建和操作稀疏矩阵。例如,如果你有一个二维数组表示邻接矩阵,可以这样做: ```python import numpy as np from scipy.sparse import lil_matrix # 假设adj_matrix是一个二维numpy数组,代表邻接矩阵 adj_matrix = ... # 根据实际数据填充 # 将邻接矩阵转换为scipy的lil_matrix格式 sparse_adj = lil_matrix(adj_matrix) # 计算度矩阵 degree_matrix = sparse_adj.sum(axis=0).reshape(-1, 1) # 归一化拉普拉斯矩阵 rw_laplacian = degree_matrix.power(-0.5) @ sparse_adj @ degree_matrix.power(-0.5) snc_laplacian = sparse.eye(rw_laplacian.shape[0]) - rw_laplacian ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值