Mutagenicity数据集是用于图分类的数据集。判断该化合物是否具有致突变性。具体信息见代码吧。
导库
from torch_geometric.datasets import TUDataset
下载数据打印信息
dataset=TUDataset(root="C:/Users/19216/Desktop/Project/Project1/Integrated_Gradients",name='Mutagenicity').shuffle()
print(dataset.num_edge_features,dataset.num_node_features,dataset.num_classes,len(dataset))
PS:下载有问题就直接手动下载
观察一些图的性质
data=dataset[0];print(data.is_directed());data=dataset[1];print(data.is_directed())
我们把图给画出来
导库
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)
长啥样吧,不然这段代码虽然很好理解但是过于黑箱:
[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
model=Net(dim=32)
optimizer=torch.optim.Adam(model.parameters(),lr=0.001)
print(model)
训练准备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
文章目的:解释深层网络输入输出关联
文章概述:文章证明了两个新定理
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)=(xi−xi′)∫α=01∂xi∂F(x′+α×(x−x′))dα。这里
Attribution_{e_i}=\int_{\alpha=0}^1\frac{\partial F(x_{\alpha})}{\partial \omega_{e_i}}d\alpha
Attributionei=∫α=01∂ωei∂F(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内的输出如下
PS:越深说明对于目标影响越大。比如这里含氮容易导致突变。
来自Manolis Kellis教授的课《人工智能与机器学习》,中间结合李沐老师的两个精读视频(GNN和AlphaFold2)作为补充。本节课主要介绍了几何深度学习、图神经网络
主要内容有图神经网络、GNN、GCN、对称性、等变性、信息传递、蛋白质空间结构预测(AlphaFold2)、药物设计(虚拟药物筛选和新药设计)。
随着新的神经网络架构不时出现,很难跟踪这些架构。知道所有缩写(DCIGN,BiLSTM,DCGAN,任何人?)起初可能有点压倒性。
所以我决定编写一个包含许多这些体系结构的备忘单。这些大多数是神经网络,有些是完全不同的野兽。虽然所有这些体系结构都是新颖而独特的,但是当我绘制节点结构时......它们的基础关系开始变得更有意义。
归因是可解释性工具包中的一种工具,它提供输入(x)相对于输出(y)的排名重要性值。 如果您想建立可信度,调试模型或为科学发现创建假设,则可能需要在模型上使用归因技术。 并非所有的归因方法都是平等的,从业人员应了解这些技术的优缺点。 我们可以评估这些技术,因为图形是自然的测试平台:我们可以创建综合图形任务,在其中可以生成标签和基本事实归因。
演示如何在图形上创建归因的代码段:
import graph_attribution as gatt
task_type = 'benzene'
block_type = 'gcn'
exp , task , methods = gatt . experiments . get_experiment_setup ( task_type , block_type )
hp = gatt . hparams . get_hparams
手绘碳氢化合物识别
此仓库包含生成论文所有数据所需的代码和数据
“使用神经网络识别手绘的碳氢化合物结构:化学上下文中的深度学习和合成数据生成的实际案例研究” Weir,H.,Thompson,K.,Woodward,A.,Choi,B.,Braun,A 。,Martinez,TJ
包括Im2Smiles神经网络和用于构建训练数据集的代码。
Guillaume Genthial从修改了Im2Smiles代码。
创建一个Python 2.7 conda环境$ conda create -n im2smiles python=2.7
激活环境$ source activate im2smiles 或者$ conda activate im2smiles
克隆ChemPixCH回购$ git clone https://github.com/mtzgroup/ChemPixCH.
一个用于使用路径归因方法解释深度神经网络中的特征重要性和特征交互作用的存储库。
该存储库包含使用“和“解释和解释机器学习模型的工具。 此外,它包含用于解释使用Integrated Hessians和Expected Hessians在深层网络中进行交互的代码-我们在最新论文中介绍的方法:“解释说明:深层网络的公理特征交互”( )。 如果您使用我们的工作来解释您的网络,请引用本文。
@misc{janizek2020explaining,
title={Explaining Explanations: Axiomatic Feature Interactions for Deep Networks},
author={Joseph D. Janizek and Pascal Sturmfels and Su-In Lee},
year={2020},
def squad_pos_forward_func(input_ids, attention_mask, position=0):
pred = model(input_ids, attention_mask) # 获取预测结果
pred = pred[position] # 当 position 为 0 时,取的是起始位置所在的分布,为 1 时,取的是结束位置所在的分布
return pred.max(1).values # 取分布的最大值,即预测结果
本文研究的问题是,将深度网络的预测结果归因到输入的特征中。
本文确定了两条归因的基本公理:Sensitivity和Implementation Invariance,并基于这两个公理设计了一种新的归因方法,称为积分梯度法(Integrated Gradients)。
该论文之前的许多归因方法并不完全满足这两条公理。
积分梯度法(Integrated Gradients)使用起来很简单,不需要修改原