【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创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

Python开发文字版随机事件游戏的项目实例

《Python开发文字版随机事件游戏的项目实例》随机事件游戏是一种通过生成不可预测的事件来增强游戏体验的类型,在这篇博文中,我们将使用Python开发一款文字版随机事件游戏,通过这个项目,读者不仅能够... 目录项目概述2.1 游戏概念2.2 游戏特色2.3 目标玩家群体技术选择与环境准备3.1 开发环境3

Python中模块graphviz使用入门

《Python中模块graphviz使用入门》graphviz是一个用于创建和操作图形的Python库,本文主要介绍了Python中模块graphviz使用入门,具有一定的参考价值,感兴趣的可以了解一... 目录1.安装2. 基本用法2.1 输出图像格式2.2 图像style设置2.3 属性2.4 子图和聚

Python使用Matplotlib绘制3D曲面图详解

《Python使用Matplotlib绘制3D曲面图详解》:本文主要介绍Python使用Matplotlib绘制3D曲面图,在Python中,使用Matplotlib库绘制3D曲面图可以通过mpl... 目录准备工作绘制简单的 3D 曲面图绘制 3D 曲面图添加线框和透明度控制图形视角Matplotlib

一文教你Python如何快速精准抓取网页数据

《一文教你Python如何快速精准抓取网页数据》这篇文章主要为大家详细介绍了如何利用Python实现快速精准抓取网页数据,文中的示例代码简洁易懂,具有一定的借鉴价值,有需要的小伙伴可以了解下... 目录1. 准备工作2. 基础爬虫实现3. 高级功能扩展3.1 抓取文章详情3.2 保存数据到文件4. 完整示例

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

基于Python打造一个智能单词管理神器

《基于Python打造一个智能单词管理神器》这篇文章主要为大家详细介绍了如何使用Python打造一个智能单词管理神器,从查询到导出的一站式解决,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. 项目概述:为什么需要这个工具2. 环境搭建与快速入门2.1 环境要求2.2 首次运行配置3. 核心功能使用指

Java controller接口出入参时间序列化转换操作方法(两种)

《Javacontroller接口出入参时间序列化转换操作方法(两种)》:本文主要介绍Javacontroller接口出入参时间序列化转换操作方法,本文给大家列举两种简单方法,感兴趣的朋友一起看... 目录方式一、使用注解方式二、统一配置场景:在controller编写的接口,在前后端交互过程中一般都会涉及

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句