【Python-图结构准备】“pickled object“、 调整邻接矩阵使其对称、图加自环 图邻接矩阵归一化、稀疏邻接矩阵格式转换

本文主要是介绍【Python-图结构准备】“pickled object“、 调整邻接矩阵使其对称、图加自环 图邻接矩阵归一化、稀疏邻接矩阵格式转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

  • 引言:python代码学习,本博客对python的"pickled object" (腌制对象,也叫序列化对象), 调整邻接矩阵使其对称图加自环 & 图邻接矩阵归一化稀疏邻接矩阵格式转换从代码实现的角度进行介绍。我们先引入一段代码,通过这段代码来解释相应的知识点。
with open('data/' + args.dataset + '_mean_' + args.diffusion_model + str(10*args.seed_rate) + '.SG', 'rb') as f:graph = pickle.load(f)adj, inverse_pairs = graph['adj'], graph['inverse_pairs']adj = adj + adj.T.multiply(adj.T > adj) - adj.multiply(adj.T > adj)
adj = normalize_adj(adj + sp.eye(adj.shape[0]))
adj = torch.Tensor(adj.toarray()).to_sparse()
  • 上述代码是什么意思呢?我们逐行来分析。

知识点一:pickled object

  • “pickled object”(腌制对象)是指一个已经被序列化(serialized)的对象。序列化是将对象的状态信息转换为可以存储或传输的形式的过程。在Python中,这个过程通常是通过pickle模块来完成的。

  • 当使用pickle模块的dump函数将一个对象序列化到一个文件或字节流中时,这个对象就被"pickled"(腌制)了。序列化后的数据可以被存储在文件中,通过网络传输,或者以其他方式保存,被"pickled"的数据可以被pickle模块的load函数重新加载,恢复成原始的对象。

  • 例如,如果你有一个复杂的Python对象,比如一个包含多个嵌套字典和列表的数据结构,你可以使用pickle将其序列化到一个文件中:

import pickle
# 创建一个复杂的数据结构
data = {'name': 'Alice','age': 30,'friends': ['Bob', 'Charlie'],'scores': {'math': 90, 'english': 85}
}
# 将数据结构序列化到一个文件中
with open('data.pkl', 'wb') as f:pickle.dump(data, f)
  • 之后,你可以使用pickle.load函数从文件中加载这个pickled对象,并恢复成原始的数据结构:
# 从文件中加载pickled对象
with open('data.pkl', 'rb') as f:loaded_data = pickle.load(f)
# 现在loaded_data包含了原始的数据结构
print(loaded_data)
  • 需要注意的是,pickle模块是Python特有的,它生成的序列化数据是依赖于Python的实现细节的,因此不能跨语言使用。此外,由于pickle可以重建任何Python对象,包括执行代码,因此它可能存在安全风险,不应该用于加载不受信任或未经身份验证的数据。

知识点二 调整邻接矩阵使其对称

  • 本文开头提到的代码中,adj, inverse_pairs = graph['adj'], graph['inverse_pairs'] 这行代码从名为graph的字典中提取了两个键值对,adj和inverse_pairs。adj通常代表图的邻接矩阵,而inverse_pairs则是一些额外的图信息。
  • adj = adj + adj.T.multiply(adj.T > adj) - adj.multiply(adj.T > adj)
    • adj.T 是矩阵 adj 的转置矩阵。
    • (adj.T > adj) 是一个布尔矩阵,其中每个元素是 adj.T 中的元素与 adj 中对应位置的元素比较的结果。如果 adj.T 中的元素大于 adj 中的对应元素,则该位置为 True,否则为 False。
    • adj.T.multiply(adj.T > adj) 是矩阵乘法,它将 adj.T 中的每个元素与其对应位置的布尔值相乘。如果布尔值为 True,则结果是 adj.T 中的元素;如果布尔值为 False,则结果是 0。
    • adj.multiply(adj.T > adj) 是同样的操作,但是这次是使用 adj 矩阵。
    • adj + adj.T.multiply(adj.T > adj) - adj.multiply(adj.T > adj) 将原始矩阵 adj 与步骤3的结果相加,然后减去步骤4的结果。
    • 最终,这行代码的结果是一个新的矩阵,其中每个元素是原始矩阵 adj 中的元素,如果 adj.T 中的对应元素大于 adj 中的元素,则该元素被替换为 adj.T 中的对应元素;否则,该元素保持不变。换句话说,这行代码将 adj 中的每个元素替换为 adj.T 中对应位置的元素,前提是 adj.T 中的元素大于 adj 中的元素。
    • 如果用数学表达式来描述这个操作,对于矩阵 adj 中的每个元素 a_ij,新的值 a’_ij 将是:a'_ij = a_ij + (a_ji - a_ij) * (a_ji > a_ij),其中 a_ji 是 adj 的转置矩阵中对应位置的元素。如果 a_ji > a_ij,则 a’_ij = a_ji;否则,a’_ij = a_ij。

知识点三 图加自环 & 图邻接矩阵归一化

  • adj = normalize_adj(adj + sp.eye(adj.shape[0])) 这行代码调用了一个名为normalize_adj的函数,该函数用于归一化邻接矩阵。在归一化之前,它先将单位矩阵(sp.eye(adj.shape[0]))加到adj上。单位矩阵的对角线元素都是1,非对角线元素都是0,这个操作是为了确保每个节点至少与自己相连(自环)。
  • 其中 normalize_adj函数为:
def normalize_adj(mx):"""Row-normalize sparse matrix"""rowsum = np.array(mx.sum(1))r_inv_sqrt = np.power(rowsum, -0.5).flatten()r_inv_sqrt[np.isinf(r_inv_sqrt)] = 0.r_mat_inv_sqrt = sp.diags(r_inv_sqrt)return mx.dot(r_mat_inv_sqrt).transpose().dot(r_mat_inv_sqrt)
  • rowsum = np.array(mx.sum(1)) :这行代码计算了输入矩阵 mx 的每行之和,并将结果存储在 rowsum 数组中。

  • r_inv_sqrt = np.power(rowsum, -0.5).flatten():这行代码计算了 rowsum 数组中每个元素的负二分之一次方,即求每个行和的平方根的倒数。这样做的目的是为了准备对矩阵进行归一化。flatten() 函数将结果展平为一维数组。

  • r_inv_sqrt[np.isinf(r_inv_sqrt)] = 0. :这行代码检查 r_inv_sqrt 数组中是否有无穷大的值(这可能是因为行和为0导致的),并将这些无穷大的值替换为0。

  • r_mat_inv_sqrt = sp.diags(r_inv_sqrt):这行代码使用 r_inv_sqrt 数组创建了一个对角稀疏矩阵 r_mat_inv_sqrt,其中对角线上的元素是 r_inv_sqrt 中的值。

  • return mx.dot(r_mat_inv_sqrt).transpose().dot(r_mat_inv_sqrt) :这行代码返回了归一化后的矩阵。首先,mx.dot(r_mat_inv_sqrt) 将原始矩阵 mx 与 r_mat_inv_sqrt 相乘,这实际上是对 mx 的每一列进行缩放,使得每行的和为1。然后,transpose() 函数将结果转置,接着再次与 r_mat_inv_sqrt 相乘。这个转置和再次相乘的操作确保了归一化后的矩阵是对称的,这在图数据处理中是常见的,因为邻接矩阵通常是对称的。

知识点四 稀疏矩阵格式转换

  • adj = torch.Tensor(adj.toarray()).to_sparse() 这行代码将归一化后的邻接矩阵从稀疏矩阵格式转换为密集矩阵格式(toarray()),然后将其转换为PyTorch张量(torch.Tensor)。最后,它将这个张量转换为稀疏张量(to_sparse())。稀疏张量是一种优化表示,用于存储大多数元素为0的矩阵,这样可以节省内存和计算资源。
    在这行代码中,toarray() 和 to_sparse() 是两个不同的操作,它们分别将稀疏矩阵转换为密集数组,然后再将密集数组转换回稀疏张量。下面是这两个操作的详细解释:

  • toarray() :这个方法用于将稀疏矩阵(通常是 SciPy 的稀疏矩阵格式,如 scipy.sparse.csr_matrix 或 scipy.sparse.csc_matrix)转换为密集数组(即 NumPy 数组)。稀疏矩阵是一种特殊的矩阵表示形式,它只存储非零元素的位置和值,而不是存储整个矩阵的所有元素,这样可以节省内存和计算资源,特别是当矩阵非常稀疏时。toarray() 方法将稀疏矩阵转换为常规的二维数组,其中包含了所有元素,包括零元素。

  • to_sparse() :这个方法用于将密集张量(在 PyTorch 中是 torch.Tensor)转换为稀疏张量。在 PyTorch 中,稀疏张量是一种特殊的数据结构,它只存储非零元素的位置和值。这种表示形式对于处理大规模稀疏数据非常有用,因为它可以减少内存使用并提高计算效率。to_sparse() 方法创建一个稀疏张量,其中包含了密集张量中的非零元素。

  • 这行代码的意义在于:首先,它将原始的稀疏矩阵转换为密集数组,这可能是因为某些操作(如矩阵乘法)在密集数组上更容易执行,或者是因为需要将数据转换为 PyTorch 可以处理的格式。然后,它将密集数组转换回稀疏张量。这可能是因为在 PyTorch 中进行后续的稀疏矩阵操作,或者是因为稀疏张量在内存使用和计算效率方面有优势。

这篇关于【Python-图结构准备】“pickled object“、 调整邻接矩阵使其对称、图加自环 图邻接矩阵归一化、稀疏邻接矩阵格式转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/989462

相关文章

Python如何计算两个不同类型列表的相似度

《Python如何计算两个不同类型列表的相似度》在编程中,经常需要比较两个列表的相似度,尤其是当这两个列表包含不同类型的元素时,下面小编就来讲讲如何使用Python计算两个不同类型列表的相似度吧... 目录摘要引言数字类型相似度欧几里得距离曼哈顿距离字符串类型相似度Levenshtein距离Jaccard相

Python安装时常见报错以及解决方案

《Python安装时常见报错以及解决方案》:本文主要介绍在安装Python、配置环境变量、使用pip以及运行Python脚本时常见的错误及其解决方案,文中介绍的非常详细,需要的朋友可以参考下... 目录一、安装 python 时常见报错及解决方案(一)安装包下载失败(二)权限不足二、配置环境变量时常见报错及

Python中顺序结构和循环结构示例代码

《Python中顺序结构和循环结构示例代码》:本文主要介绍Python中的条件语句和循环语句,条件语句用于根据条件执行不同的代码块,循环语句用于重复执行一段代码,文章还详细说明了range函数的使... 目录一、条件语句(1)条件语句的定义(2)条件语句的语法(a)单分支 if(b)双分支 if-else(

Python itertools中accumulate函数用法及使用运用详细讲解

《Pythonitertools中accumulate函数用法及使用运用详细讲解》:本文主要介绍Python的itertools库中的accumulate函数,该函数可以计算累积和或通过指定函数... 目录1.1前言:1.2定义:1.3衍生用法:1.3Leetcode的实际运用:总结 1.1前言:本文将详

Java深度学习库DJL实现Python的NumPy方式

《Java深度学习库DJL实现Python的NumPy方式》本文介绍了DJL库的背景和基本功能,包括NDArray的创建、数学运算、数据获取和设置等,同时,还展示了如何使用NDArray进行数据预处理... 目录1 NDArray 的背景介绍1.1 架构2 JavaDJL使用2.1 安装DJL2.2 基本操

在不同系统间迁移Python程序的方法与教程

《在不同系统间迁移Python程序的方法与教程》本文介绍了几种将Windows上编写的Python程序迁移到Linux服务器上的方法,包括使用虚拟环境和依赖冻结、容器化技术(如Docker)、使用An... 目录使用虚拟环境和依赖冻结1. 创建虚拟环境2. 冻结依赖使用容器化技术(如 docker)1. 创

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

Python创建Excel的4种方式小结

《Python创建Excel的4种方式小结》这篇文章主要为大家详细介绍了Python中创建Excel的4种常见方式,文中的示例代码简洁易懂,具有一定的参考价值,感兴趣的小伙伴可以学习一下... 目录库的安装代码1——pandas代码2——openpyxl代码3——xlsxwriterwww.cppcns.c

Python中Markdown库的使用示例详解

《Python中Markdown库的使用示例详解》Markdown库是一个用于处理Markdown文本的Python工具,这篇文章主要为大家详细介绍了Markdown库的具体使用,感兴趣的... 目录一、背景二、什么是 Markdown 库三、如何安装这个库四、库函数使用方法1. markdown.mark

一分钟带你上手Python调用DeepSeek的API

《一分钟带你上手Python调用DeepSeek的API》最近DeepSeek非常火,作为一枚对前言技术非常关注的程序员来说,自然都想对接DeepSeek的API来体验一把,下面小编就来为大家介绍一下... 目录前言免费体验API-Key申请首次调用API基本概念最小单元推理模型智能体自定义界面总结前言最