图神经网络:(化学领域)再次认识图神经网络

news2024/12/23 22:16:32

文章说明:
1)参考资料:PYG官方文档。超链。
2)博主水平不高,如有错误还望批评指正。
3)我在百度网盘上传了这篇文章的jupyter notebook和有关文献。超链。提取码8848。

文章目录

    • Mutagenicity数据集
    • 搭建模型
    • 训练模型
    • 文献阅读
    • 重新回来

Mutagenicity数据集

Mutagenicity数据集是用于图分类的数据集。判断该化合物是否具有致突变性。具体信息见代码吧。
导库

from torch_geometric.datasets import TUDataset

下载数据,导入数据,打印信息

dataset=TUDataset(root="/DATA/TUDataset",name='Mutagenicity').shuffle()
print(dataset.num_edge_features,dataset.num_node_features,dataset.num_classes,len(dataset))
#输出如下:
#3 14 2 4337

PS:下载有问题就直接手动下载
观察具体的图

data=dataset[0];print(data.is_directed());data=dataset[1];print(data.is_directed())
#输出如下:
#False
#False

我们把这两幅图画出来
导库

from torch_geometric.utils import to_networkx

定义格式转换函数

def to_molecule(data):
    ATOM_MAP=['C','O','Cl','H','N','F','Br','S','P','I','Na','K','Li','Ca']
    g=to_networkx(data,node_attrs=['x'])
    for u,data in g.nodes(data=True):
        data['name']=ATOM_MAP[data['x'].index(1.0)]
        del data['x']
    return g

PS:我来描述一下g.nodes(data=True)长啥样吧,不然这段代码虽然很好理解但是过于黑箱: [ ( 元素 1 , { “ n a m e ” : 列表 1 } ) , ( 元素 2 , { “ n a m e ” : 列表 2 } ) , … … ( 元素 n , { “ n a m e ” : 列表 n } ) ] [(元素1,\{“name”:列表1\}),(元素2,\{“name”:列表2\}),\dots\dots(元素n,\{“name”:列表n\})] [(元素1,{name:列表1}),(元素2,{name:列表2}),……(元素n,{name:列表n})]。元素 n n n对应 u u u,这里没用;描述一下列表 n n n [ i = 1    i f    n [ i ] = = A T O M _ M A P [ i ]    e l s e    0    f o r    i    i n    r a n g e ( 14 ) ] [i=1 \;if \;n[i]==ATOM\_MAP[i] \;else\;0\; for\;i\;in\;range(14)] [i=1ifn[i]==ATOM_MAP[i]else0foriinrange(14)]
导库

import matplotlib.pyplot as plt
import networkx as nx

绘图函数

def draw_molecule(g,edge_mask=None,draw_edge_labels=False):
    g=g.copy().to_undirected()
    node_labels={}
    for u,data in g.nodes(data=True):
        node_labels[u]=data['name']
    pos=nx.planar_layout(g)
    pos=nx.spring_layout(g,pos=pos)
    if edge_mask is None:
        edge_color='black'
        widths=None
    else:
        edge_color=[edge_mask[(u,v)] for u,v in g.edges()]
        widths=[x*10 for x in edge_color]
    nx.draw(g,pos=pos,labels=node_labels,width=widths,edge_color=edge_color,edge_cmap=plt.cm.Blues,node_color='azure')
    if draw_edge_labels and edge_mask is not None:
        edge_labels={k:('%.2f' % v) for k,v in edge_mask.items()}    
        nx.draw_networkx_edge_labels(g,pos,edge_labels=edge_labels,font_color='red')
    plt.show()

第一幅图

g1=to_molecule(dataset[0])
draw_molecule(g1)

jupyter notebook内的输出如下
在这里插入图片描述

第二幅图

g2=to_molecule(dataset[1])
draw_molecule(g2)

jupyter notebook内的输出如下
在这里插入图片描述

搭建模型

回到正题,目标是图的二分类。
导库

from torch_geometric.nn import GraphConv,global_add_pool
import torch.nn.functional as F
from torch.nn import Linear
import torch

搭建模型

class Net(torch.nn.Module):

    def __init__(self,dim):
        super(Net,self).__init__()
        self.conv1=GraphConv(dataset.num_features,dim)
        self.conv2=GraphConv(dim,dim)
        self.conv3=GraphConv(dim,dim)
        self.conv4=GraphConv(dim,dim)
        self.conv5=GraphConv(dim,dim)
        self.lin1=Linear(dim,dim)
        self.lin2=Linear(dim,dataset.num_classes)

    def forward(self,x,edge_index,batch,edge_weight=None):
        x=self.conv1(x,edge_index,edge_weight).relu()
        x=self.conv2(x,edge_index,edge_weight).relu()
        x=self.conv3(x,edge_index,edge_weight).relu()
        x=self.conv4(x,edge_index,edge_weight).relu()
        x=self.conv5(x,edge_index,edge_weight).relu()
        x=global_add_pool(x,batch)
        x=self.lin1(x).relu()
        x=F.dropout(x,p=0.5,training=self.training)
        x=self.lin2(x)
        return F.log_softmax(x,dim=-1)

训练模型

训练准备1:定义设备模型与优化器

device=torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model=Net(dim=32).to(device)
optimizer=torch.optim.Adam(model.parameters(),lr=0.001)
print(model)
#输出如下:
#Net(
#  (conv1): GraphConv(14, 32)
#  (conv2): GraphConv(32, 32)
#  (conv3): GraphConv(32, 32)
#  (conv4): GraphConv(32, 32)
#  (conv5): GraphConv(32, 32)
#  (lin1): Linear(in_features=32, out_features=32, bias=True)
#  (lin2): Linear(in_features=32, out_features=2, bias=True)
#)

训练准备2:导库训测拆分以及批量划分

from torch_geometric.loader import DataLoader
test_dataset=dataset[:len(dataset)//10]
train_dataset=dataset[len(dataset)//10:]
test_loader=DataLoader(test_dataset,batch_size=128)
train_loader=DataLoader(train_dataset,batch_size=128)

训练准备3:定义训练以及测试

def train(epoch):
    model.train()
    if epoch==51:
        for param_group in optimizer.param_groups:
            param_group['lr']=0.5*param_group['lr']
    loss_all=0
    for data in train_loader:
        data=data.to(device)
        optimizer.zero_grad()
        output=model(data.x,data.edge_index,data.batch)
        loss=F.nll_loss(output,data.y)
        loss.backward()
        loss_all+=loss.item()*data.num_graphs
        optimizer.step()
    return loss_all/len(train_dataset)

def test(loader):
    model.eval()
    correct=0
    for data in loader:
        data=data.to(device)
        output=model(data.x,data.edge_index,data.batch)
        pred=output.max(dim=1)[1]
        correct+=pred.eq(data.y).sum().item()
    return correct/len(loader.dataset)

开始训练

for epoch in range(1,101):
    loss=train(epoch)
    train_acc=test(train_loader)
    test_acc=test(test_loader)
    print(f'Epoch: {epoch:03d}, Loss: {loss:.4f}, 'f'Train Acc: {train_acc:.4f}, Test Acc: {test_acc:.4f}')

jupyter notebook内的输出如下
在这里插入图片描述

文献阅读

参考文献:Axiomatic Attribution for Deep Networks
文章目的:解释深度神经网络输出与输入的关联(这里下面统称解决这个问题的方法为归因方法)
文章概述:文章证明了两个新定理 S e n s i t i v i t y Sensitivity Sensitivity以及 I m p l e m e n t a t i o n    I n v a r i a n c e Implementation\;Invariance ImplementationInvariance并且说明所有归因方法应该满足两个定理。之前大多方法均不满足所以作者提出一种新的归因方法满足两个定理—— I n t e g r a t e d    G r a d i e n t s Integrated\;Gradients IntegratedGradients
S e n s i t i v i t y Sensitivity Sensitivity:要求对于输入变化输出变化应该一致。举个反例模型存在梯度消失。
I m p l e m e n t a t i o n    I n v a r i a n c e Implementation\;Invariance ImplementationInvariance:要求对于相同输入无论使用哪种网络输出不变。否则不是等效网络。
I n t e g r a t e d G r a d i e n t s IntegratedGradients IntegratedGradients I n t e g r a t e d G r a n d s i ( x ) = ( x i − x i ′ ) ∫ α = 0 1 ∂ F ( x ′ + α × ( x − x ′ ) ) ∂ x i d α IntegratedGrands_i(x)=(x_i-x_i')\int_{\alpha=0}^{1}\frac{\partial F(x'+\alpha\times(x-x'))}{\partial x_i}d\alpha IntegratedGrandsi(x)=(xixi)α=01xiF(x+α×(xx))dα。这里 x ′ x' x是基准输入。
在这里插入图片描述
在这里插入图片描述
PS1:这个图展示了积分梯度的优越性。
PS2:文章结论可以用于多种神经网络模型并且效果出类拔萃。文章还有许多其他工作这里并不展开因为时间篇幅原因还请读者自行阅读。这篇文章是很好的。

重新回来

阅读文献之后我们重新回来。现在有了两种方法求解输出相对边权重的梯度1. A t t r i b u t i o n e i = ∣ ∂ F ( x ) ∂ ω e i ∣ Attribution_{e_i}=|\frac{\partial F(x)}{\partial \omega_{e_i}}| Attributionei=ωeiF(x) 2. A t t r i b u t i o n e i = ∫ α = 0 1 ∂ F ( x α ) ∂ ω e i d α Attribution_{e_i}=\int_{\alpha=0}^1\frac{\partial F(x_{\alpha})}{\partial \omega_{e_i}}d\alpha Attributionei=α=01ωeiF(xα)dα。这里我们初始边缘权重为1基线为0简化公式否则就是十分复杂。
导库

from captum.attr import Saliency,IntegratedGradients
import numpy as np

定义函数

def model_forward(edge_mask,data):
    batch=torch.zeros(data.x.shape[0],dtype=int)
    out=model(data.x,data.edge_index,batch,edge_mask)
    return out

def explain(method,data,target=0):
    input_mask=torch.ones(data.edge_index.shape[1]).requires_grad_(True)
    if method=='ig':
        ig=IntegratedGradients(model_forward)
        mask=ig.attribute(input_mask,target=target,additional_forward_args=(data,),internal_batch_size=data.edge_index.shape[1])
    elif method=='saliency':
        saliency=Saliency(model_forward)
        mask=saliency.attribute(input_mask,target=target,additional_forward_args=(data,))
    else:
        raise Exception('Unknown explanation method')
    edge_mask=np.abs(mask.cpu().detach().numpy())
    if edge_mask.max()>0:
        edge_mask=edge_mask/edge_mask.max()
    return edge_mask

导库

from collections import defaultdict
import random

定义函数

def aggregate_edge_directions(edge_mask,data):
    edge_mask_dict=defaultdict(float)
    for val,u,v in list(zip(edge_mask,*data.edge_index)):
        u,v=u.item(),v.item()
        if u>v:
            u,v=v,u
        edge_mask_dict[(u,v)]+=val
    return edge_mask_dict

开始绘制

data=random.choice([t for t in test_dataset if not t.y.item()])
mol=to_molecule(data)
for title,method in [('Integrated Gradients','ig'),('Saliency','saliency')]:
    edge_mask=explain(method,data,target=0)
    edge_mask_dict=aggregate_edge_directions(edge_mask,data)
    plt.figure(figsize=(10,5))
    plt.title(title)
    draw_molecule(mol,edge_mask_dict)

jupyter notebook内的输出如下
在这里插入图片描述
PS1:如果报错发现多个运行设备让它们全在CPU上跑就好。
PS2:越深说明对于目标影响越大。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/555776.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

day36_JQuery

今日内容 零、 复习昨日 一、正则表达式 二、JQuery 零、 复习昨日 零、正则表达式 Regular expression RegExp 0.1 正则表达式 正则表达式是描述字符模式的对象。正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具。语法: va…

京东云技术团队 —— 浅谈测试用例设计

一、测试用例为什么存在 1.1 定义 测试用例(Test Case)是指对特定的软件产品进行测试任务的描述,体现测试方案、方法、技术和策略。测试用例内容包括测试目标、测试环境、输入数据、测试步骤、预期结果、测试脚本等,最终形成文档类的输出。简而言之&am…

04. 数据结构之栈

前言 栈(stack)是一种线性数据的逻辑存储结构。栈中的元素只能先入后出(First In Last Out,简称FILO)。最早进入的元素存放的位置叫作栈底(bottom),最后进入的元素存放的位置叫作栈…

网络故障老搞不定,就看这篇笔记

大家好,我是老杨。 做咱们这行,每天遇到的故障千奇百怪什么都有。很多网工每天只是在工作而已,遇到一个问题,就解决一个问题,每天的日子都是一样的,枯燥无趣。 但是,就很少有人去汇总问题&…

分布式事务的21种武器 - 1

在分布式系统中,事务的处理分布在不同组件、服务中,因此分布式事务的ACID保障面临着一些特殊难点。本系列文章介绍了21种分布式事务设计模式,并分析其实现原理和优缺点,在面对具体分布式事务问题时,可以选择合适的模式…

Scala学习(五)---面向对象

文章目录 1.Scala面向对象的构造器1.1 主构造器和从构造器(辅助构造器)1.2 主构造器参数 2.继承2.1 抽象属性和方法2.2 匿名子类 1.Scala面向对象的构造器 1.1 主构造器和从构造器(辅助构造器) //主构造器 class ConstructorTest(name:String) {//主构造器调用val name1:Stri…

【MyBatis框架】

文章目录 Mybatis1.简介1.1MyBatis历史1.2MyBatis特性1.3MyBatis下载1.4和其它持久化层技术对比 2.搭建MyBatis2.1创建maven工程2.2创建MyBatis的核心配置文件2.3创建mapper接口2.4创建实体类2.5创建MyBatis的映射文件2.6通过junit测试功能2.7加入log4j日志功能2.8MyBatis的增删…

pytorch的学习与总结(第二次组会)

pytorch的学习与总结 一、pytorch的基础学习1.1 dataset与dataloader1.2 可视化工具(tensorboard)、数据转换工具(transforms)1.3 卷积、池化、线性层、激活函数1.4 损失函数、反向传播、优化器1.5 模型的保存、加载、修改 二、 pytorch分类项目实现2.1 网络模型2.2 具体代码 一…

新星计划2023【《计算之魂》读书会】学习方向报名入口!

前排提醒:这里是新星计划2023【《计算之魂》读书会】学习方向的报名入口,一经报名,不可更换。 ↓↓↓报名方式:(下滑到本页面底部) 一、关于本学习方向导师 博客昵称:异步社区博客主页&#x…

AI大模型时代,云从科技携“从容大模型”入场如何“从容”?

5月18日,在“AI赋能数字中国产业论坛暨2023云从科技人机协同发布会”上,云从科技自研“从容大模型”正式亮相。 根据发布会信息,“从容大模型”具备问答、阅读理解、文学创作以及解题方面的能力。受发布会消息影响,5月18日午间休盘…

【libdatachannel】cmake+vs2022 构建

libdatachannel libdatachannel 是基于c++17实现的构建 OpenSSL 找不到 Selecting Windows SDK version 10.0.22000.0 to target Windows 10.0.22621. The CXX compiler identification is MSVC 19.35.32217.1 Detecting CXX compiler ABI info Detecting CXX compiler ABI inf…

利用GPIO线进行板间通信-23-5-22

本项目基于VU9P(xcvu9pflga2105)板卡以及ZYNQ(xc7z015clg485) 简单结构流程介绍: 1.上位机通过千兆网将指令下发到ZYNQ,ZYNQ进行解帧,将数据解析出来后存储到RAM中,RAM将数据不断输送给GPIO模块,GPIO模块根据对应地址输出数据是…

新来的00后实习生太牛了,已经被取代了.....

前几天有个朋友向我哭诉,说她在公司工作(软件测试)了7年了,却被一个00后实习生代替了,该何去何从? 这是一个值得深思的问题,作为职场人员,我们确实该思考,我们的工作会被…

1718_Linux命令模式下查看日历

全部学习汇总: GreyZhang/bash_basic: my learning note about bash shell. (github.com) 前面发布了一份学习笔记,涉嫌过渡宣传,虽然我也没搞懂为什么。有一系列修改建议,我觉得直接放弃了。还是发一份新的吧! Linux命…

【数据结构】哈希底层结构

目录 一、哈希概念 二、哈希实现 1、闭散列 1.1、线性探测 1.2、二次探测 2、开散列 2.1、开散列的概念 2.2、开散列的结构 2.3、开散列的查找 2.4、开散列的插入 2.5、开散列的删除 3、性能分析 一、哈希概念 顺序结构以及平衡树中,元素关键码与其存储位…

如何用Postman做接口自动化测试?

本文适合已经掌握 Postman 基本用法的读者,即对接口相关概念有一定了解、已经会使用 Postman 进行模拟请求等基本操作。 工作环境与版本: Window 7(64位)Postman (Chrome App v5.5.3) P.S. 不同版本页面 U…

JAVA—实验4 继承、接口与多态

一、实验目的 掌握类的继承机制掌握接口的定义方法熟悉成员方法或构造方法多态性 二、实验内容 1.卖车-接口与多态编程 【问题描述】 (1) 汽车接口(Car):有两个方法, getName()、getPrice()(接口源文件可以自己写,也…

2024总统大选,成为“关乎比特币未来的公投”?背后是怎样的政治抱负?

在今年的迈阿密比特币大会上,Robert F.Kennedy Jr和Vivek Ramaswamy相继发布声明表示,他们将在2024年初选前接受比特币(BTC)的捐款。 RFK Jr作为美国前总统约翰肯尼迪的侄子,是第一个公开接受Crypto的总统候选人&#…

chatgpt赋能Python-pythons_9_98_987

用Python计算s998987的方法及重要性分析 介绍 Python是一种开源的高级编程语言,它被广泛应用于数据处理、web开发和人工智能等领域。它的简洁、易读易写的语法使得很多程序员喜爱使用它来完成各种工作。本文将介绍如何用Python计算一个简单的数学表达式&#xff1…

微服务基础环境搭建--和创建公用模块

目录 微服务基础环境搭建 创建父工程,用于聚合其它微服务模块 创建父项目, 作为聚合其它微服务模块 项目设置​编辑 ​编辑 删除src, 保留一个纯净环境​编辑 1. 配置父工程pom.xml, 作为聚合其它模块 2、修改e-commerce-center\pom.xml,删除不需要的配置节…