代码是从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() # 查看一下