构建稀疏矩阵
- 构建步骤
-
- 构建邻接矩阵
- 生成归一化邻接矩阵(考虑自身影响)
- 生成归一化邻接矩阵(不考虑自身影响)
- 稀疏矩阵(Sparse Matrix)转换为 PyTorch 稀疏张量(Sparse Tensor)
- 代码实现
-
- 构建数据
- 构建邻接矩阵
- 生成归一化邻接矩阵(考虑自身影响)
- 生成归一化邻接矩阵(不考虑自身影响)
- 稀疏矩阵(Sparse Matrix)转换为 PyTorch 稀疏张量(Sparse Tensor)
以用户-物品为例,构建二部图 : 假设现有5个用户,10个物品
构建步骤
构建邻接矩阵
1、创建大小为【(用户数量+物品数量) * (用户数量+物品数量) 】的空稀疏矩阵A(邻接矩阵)
2、创建【用户数量 * 物品数量】的空稀疏矩阵B
3、在稀疏矩阵B中,将用户访问过的物品的位置设为1.
3、将稀疏矩阵A、B转换为 LIL 格式,LIL 是 SciPy 中的一种稀疏矩阵存储格式,它以两个列表表示稀疏矩阵的非零元素:一个存储每一行的非零元素及其对应的列索引,另一个存储每一行的长度。
4、将B赋值给A,稀疏矩阵A,如图所示:
5、将得到的 LIL 格式的稀疏矩阵再转回为 DOK 格式的稀疏矩阵
生成归一化邻接矩阵(考虑自身影响)
1、将邻接矩阵和同样大小的单位矩阵相加得到新的邻接矩阵
2、计算邻接矩阵每行的和,得到一个包含每行和的 NumPy 数组。
3、计算每行和的倒数
4、将无穷大的元素(原本是分母为0的情况)设置为0。这是为了避免除以0的情况。
5、创建一个对角矩阵,对角线上的元素为 d_inv 数组中的元素。这个对角矩阵实际上是d_inv的逆矩阵。
6、计算归一化邻接矩阵,即 D^-1 * A。
7、将结果矩阵转换为 COO 格式(Coordinate format,坐标格式)
生成归一化邻接矩阵(不考虑自身影响)
1、计算邻接矩阵每行的和,得到一个包含每行和的 NumPy 数组。
2、计算每行和的倒数
3、将无穷大的元素(原本是分母为0的情况)设置为0。这是为了避免除以0的情况。
4、创建一个对角矩阵,对角线上的元素为 d_inv 数组中的元素。这个对角矩阵实际上是d_inv的逆矩阵。
5、计算归一化邻接矩阵,即 D^-1 * A。
6、将结果矩阵转换为 COO 格式(Coordinate format,坐标格式)
稀疏矩阵(Sparse Matrix)转换为 PyTorch 稀疏张量(Sparse Tensor)
1、创建一个包含两个数组coo.row 和 coo.col 的张量
2、 创建一个稀疏张量。
代码实现
背景描述:
商品又:商品1: 电子产品 - 智能手机;商品2: 家居用品 - 双人床;商品3: 服装配饰 - 运动鞋;商品4: 图书 - 小说;商品5: 食品 - 咖啡豆;商品6: 家电 - 液晶电视;商品7: 美妆 - 口红;商品8: 运动户外 - 自行车;商品9: 宠物用品 - 猫粮;商品10: 儿童玩具 - 拼图玩具
Alice 购买了 智能手机 (商品1)
Bob 购买了 双人床 (商品2)
Charlie 购买了 运动鞋 (商品3)
David 购买了 小说 (商品4)
Emily 购买了 咖啡豆 (商品5)
构建数据
import pandas as pd # 用户名数据 user_data = { 'User_ID': [1, 2, 3, 4, 5], 'Username': ['Alice', 'Bob', 'Charlie', 'David', 'Emily'] } # 商品数据 product_data = { 'Product_ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'Category': ['电子产品', '家居用品', '服装配饰', '图书', '食品', '家电', '美妆', '运动户外', '宠物用品', '儿童玩具'], 'Product_Name': ['智能手机', '双人床', '运动鞋', '小说', '咖啡豆', '液晶电视', '口红', '自行车', '猫粮', '拼图玩具'] } # 购买关系数据 purchase_data = { 'User_ID': [1, 2, 3, 4, 5], 'Product_ID': [1, 2, 3, 4, 5] } # 创建DataFrame users_df = pd.DataFrame(user_data) products_df = pd.DataFrame(product_data) purchases_df = pd.DataFrame(purchase_data) # 将User_ID和Product_ID用作索引,以便连接DataFrame users_df.set_index('User_ID', inplace=True) products_df.set_index('Product_ID', inplace=True) # 连接DataFrame,形成购买关系DataFrame purchase_df = pd.merge(purchases_df, users_df, how='left', left_on='User_ID', right_index=True) purchase_df = pd.merge(purchase_df, products_df, how='left', left_on='Product_ID', right_index=True) # 显示结果 print(purchase_df)
构建邻接矩阵
import scipy.sparse as sp import numpy as np n_users = len(set(purchase_df["User_ID"])) n_items = len(set(purchase_df["Product_ID"])) adj_A = sp.dok_matrix((n_users + n_items, n_users + n_items), dtype=np.float32) adj_B = sp.dok_matrix((n_users, n_items), dtype=np.float32) for user in set(purchase_df["User_ID"]): for item in set(purchase_df[purchase_df["User_ID"] == user]["Product_ID"]): adj_B[user - 1, item - 1] = 1. # 减1是因为物品和用户标号从1开始 adj_B = adj_B.tolil() adj_A = adj_A.tolil() # # 查看adj_B的值 # for i in range(adj_B.shape[0]): # row_values = adj_B.data[i] # row_indices = adj_B.rows[i] # for col_index, value in zip(row_indices, row_values): # print(f"Value at ({i}, {col_index}): {value}") # # 查看adj_B.T的值 # for i in range(adj_B.T.shape[0]): # row_values = adj_B.T.data[i] # row_indices = adj_B.T.rows[i] # for col_index, value in zip(row_indices, row_values): # print(f"Value at ({i}, {col_index}): {value}") adj_A[:n_users, n_users:] = adj_B adj_A[n_users:, :n_users] = adj_B.T adj_A= adj_A.todok() # # 查看adj_A的值 # for (row, col), value in adj_A.items(): # print(f"Value at ({row}, {col}): {value}")
生成归一化邻接矩阵(考虑自身影响)
adj_mat= adj_A+ sp.eye(adj_A.shape[0]) # #--- 查看adj_mat的数据 # # coo_mat = adj_mat.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # ---------------------------------------------- row_sum = np.array(adj_mat.sum(1)) # 每行和 d_inv = np.power(row_sum, -1).flatten() # 和倒数 d_inv[np.isinf(d_inv)] = 0. d_mat_inv = sp.diags(d_inv) # 对角矩阵 # #--- 查看d_mat_inv的数据 # # coo_mat = d_mat_inv.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # # ---------------------------------------------------- norm_adj = d_mat_inv.dot(adj_mat) # #--- 查看norm_adj的数据 # # coo_mat = norm_adj.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # -------------------------------------------------------- norm_adj = norm_adj.tocoo()
生成归一化邻接矩阵(不考虑自身影响)
adj_mat= adj_A # #--- 查看adj_mat的数据 # # coo_mat = adj_mat.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # ---------------------------------------------- row_sum = np.array(adj_mat.sum(1)) # 每行和 d_inv = np.power(row_sum, -1).flatten() # 和倒数 d_inv[np.isinf(d_inv)] = 0. d_mat_inv = sp.diags(d_inv) # 对角矩阵 # #--- 查看d_mat_inv的数据 # # coo_mat = d_mat_inv.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # # ---------------------------------------------------- norm_adj = d_mat_inv.dot(adj_mat) # #--- 查看norm_adj的数据 # # coo_mat = norm_adj.tocoo() # # for i, j, value in zip(coo_mat.row, coo_mat.col, coo_mat.data): # # print(f"Value at ({i}, {j}): {value}") # -------------------------------------------------------- norm_adj = norm_adj.tocoo()
稀疏矩阵(Sparse Matrix)转换为 PyTorch 稀疏张量(Sparse Tensor)
i = torch.LongTensor([norm_adj.row, norm_adj.col]) v = torch.from_numpy(norm_adj.data).float() sparse_norm_adj = torch.sparse.FloatTensor(i, v, norm_adj.shape) # tensor(indices=tensor([[0, 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 5, 6, 6, # 6, 7, 7, 8, 8, 9, 9, 9, 9], # [9, 5, 0, 6, 1, 7, 6, 5, 2, 9, 8, 3, 9, 4, 5, 2, 0, 6, 2, # 1, 7, 2, 8, 3, 9, 4, 3, 0]]), # values=tensor([0.3333, 0.3333, 0.3333, 0.5000, 0.5000, 0.2500, 0.2500, # 0.2500, 0.2500, 0.3333, 0.3333, 0.3333, 0.5000, 0.5000, # 0.3333, 0.3333, 0.3333, 0.3333, 0.3333, 0.3333, 0.5000, # 0.5000, 0.5000, 0.5000, 0.2500, 0.2500, 0.2500, 0.2500]), # size=(10, 10), nnz=28, layout=torch.sparse_coo)
Tips:
如有问题,麻烦指正,谢谢各位!
如有疑问,请留言,谢谢!
持续更新…