05_自动求导

1. 向量链式法则

在这里插入图片描述

① 例子1是一个线性回归的例子,如下图所示。

在这里插入图片描述
在这里插入图片描述

2. 自动求导

在这里插入图片描述

3. 计算图

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

4. 两种模型

在这里插入图片描述
在这里插入图片描述

① b是之前计算的结果,是一个已知的值。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

5. 复杂度

在这里插入图片描述

6. 自动求导

① 假设想对函数y=2x⊤xy=2\mathbf{x}^{\top}\mathbf{x}y=2xx关于列向量x求导。

import torch
x = torch.arange(4.0)
x
tensor([0., 1., 2., 3.])

② 在外面计算y关于x的梯度之前,需要一个地方来存储梯度。

import torch
x = torch.arange(4.0)
x.requires_grad_(True) # 等价于 x = torch.arange(4.0,requires_grad=True)
print(x.grad) # 默认为None
None
import torch
x = torch.arange(4.0,requires_grad=True)
print(x.grad) # x.grad是存梯度的地方,默认为None,即还没有求导求出梯度出来
None

③ 现在计算y。

import torch
a = torch.arange(4.0)
print(a)
print(torch.dot(a,a))

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
print(y) # grad_fn是隐式的构造了梯度函数
tensor([0., 1., 2., 3.])
tensor(14.)
tensor(28., grad_fn=<MulBackward0>)

④ 通过调用反向传播函数来自动计算y关于x每个分量的梯度。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward() # 反向传播后会有梯度计算出来
print(x.grad) # 访问导数,即访问梯度
print(x.grad == 4 * x) # 4 * x 是 2 * x * x 的导数
tensor([ 0.,  4.,  8., 12.])
tensor([True, True, True, True])

⑤ 计算x的另一个函数。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
# 默认情况下,PyTorch会累积梯度,需要清除之前的值
x.grad.zero_() # y.backward() 后才能产生梯度,才能梯度清零,没有反向传播,无法梯度清零
y = x.sum() # 这里的y是一个标量,sum函数其实就是x_1+x_2+...x_n,求偏导自然是全1啊
y.backward()
print(x.grad)
tensor([1., 1., 1., 1.])

⑥ 在深度学习中,目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
# 默认情况下,PyTorch会累积梯度,需要清除之前的值
# 对非标量调用 'backward' 需要传入一个 'gradient' 参数,该参数指定微分函数
x.grad.zero_()
y = x * x  # 这里的y不是一个标量,这是一个向量
print(y)
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward() # y.sum()后就讲向量转为标量了,对标量求导
x.grad
tensor([0., 1., 4., 9.], grad_fn=<MulBackward0>)

tensor([0., 2., 4., 6.])

⑦ 将某些计算移动到记录的计算图之外。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
x.grad.zero_()
y = x * x
print(y)
u = y.detach() # y.detach把y当作一个常数,而不是关于x的一个函数
print(y.detach())
print(u)
z = u * x
z.sum().backward()
x.grad == u
tensor([0., 1., 4., 9.], grad_fn=<MulBackward0>)
tensor([0., 1., 4., 9.])
tensor([0., 1., 4., 9.])

tensor([True, True, True, True])
import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
x.grad.zero_()
y = x * x  # 这里的y是关于x的函数
x.grad.zero_()
y.sum().backward()
x.grad == 2 * x
tensor([True, True, True, True])

⑧ 即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),仍然可以计算得到的变量的梯度。

def f(a):
    b = a * 2
    while b.norm() < 1000: # norm是L2范数
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c

a = torch.randn(size=(),requires_grad=True)
print(a)
d = f(a)
d.backward()
print(a.grad)
print(d/a)
a.grad == d/a # d是a的线性函数,所以导数就是斜率d/a
tensor(-0.7712, requires_grad=True)
tensor(204800.)
tensor(204800., grad_fn=<DivBackward0>)

tensor(True)

在这里插入图片描述

在这里插入图片描述

rom operator import index import torch import numpy as np import pickle,argparse,os,math,rdkit import rdkit.Chem as Chem from torch.utils.data import Dataset,DataLoader from PLANET_model import PLANET import pandas as pd from sklearn.metrics import roc_auc_score,precision_recall_curve,auc from chemutils import ProteinPocket,mol_batch_to_graph,tensorize_protein_pocket class VirtualScreening_Dataset(Dataset): def __init__(self,smi_file,batch_size=32): self.batch_size = batch_size with open(smi_file,'r') as f: smi_content = [line.strip().split()[0] for line in f] self.smi_content = [smi_content[i:i+batch_size] for i in range(0,len(smi_content),batch_size)] def __len__(self): return len(self.smi_content) def __getitem__(self,idx): return self.tensorize(idx) def tensorize(self,idx): mol_smi_batch = self.smi_content[idx] mol_batch = [Chem.AddHs(Chem.MolFromSmiles(smi)) for smi in mol_smi_batch if Chem.MolFromSmiles(smi) is not None] mol_feature_batch = mol_batch_to_graph(mol_batch,auto_detect=False) mol_smiles = [smi for smi in mol_smi_batch if Chem.MolFromSmiles(smi) is not None] return (mol_feature_batch,mol_smiles) def predict(model:PLANET,protein_pdb,ligand_sdf,dataloader): #model.eval() pocket = ProteinPocket(protein_pdb=protein_pdb,ligand_sdf=ligand_sdf) fresidues = model.cal_res_features_helper(pocket.res_features,pocket.alpha_coordinates) predicted_affinities,smiles = [],[] for (mol_feature_batch,mol_smiles) in dataloader: fresidues_batch,res_scope = model.cal_res_features(fresidues,len(mol_smiles)) predicted_affinity = model.screening(fresidues_batch,res_scope,mol_feature_batch) predicted_affinities.append(np.array(predicted_affinity.squeeze().detach().cpu().reshape([-1]))) smiles.extend(mol_smiles) predicted_affinities = np.concatenate(predicted_affinities,axis=0) return predicted_affinities,smiles def workflow(model,folder_path,out_folder): #receptor_name = folder_path.split('/')[-1] actives_smi = os.path.join(folder_path,'actives_prep.smi') decoys_smi = os.path.join(folder_path,'decoys_prep.smi') crystal_ligand = os.path.join(folder_path,'crystal_ligand.sdf') pdb_path = os.path.join(folder_path,'prepared_receptor.pdb') active_dataset = VirtualScreening_Dataset(actives_smi) active_loader = DataLoader(active_dataset,batch_size=1,shuffle=False,num_workers=4,drop_last=False,collate_fn=lambda x:x[0]) decoy_dataset = VirtualScreening_Dataset(decoys_smi) decoy_loader = DataLoader(decoy_dataset,batch_size=1,shuffle=False,num_workers=4,drop_last=False,collate_fn=lambda x:x[0]) predicted_active_affinities,active_smiles = predict(model,pdb_path,crystal_ligand,active_loader) predicted_decoy_affinities,decoy_smiles = predict(model,pdb_path,crystal_ligand,decoy_loader) active_path = os.path.join(out_folder,'active.csv') decoy_path = os.path.join(out_folder,'decoy.csv') write_csv(predicted_active_affinities,active_smiles,active_path) write_csv(predicted_decoy_affinities,decoy_smiles,decoy_path) return predicted_active_affinities,predicted_decoy_affinities def write_csv(affinities,smiles,out_path): csv_frame = pd.DataFrame([ { 'Affinity':affinity,'SMILES':smi, } for affinity,smi in zip(affinities,smiles) ]) csv_frame.to_csv(out_path) def EF_sort(active_pK,decoy_pK): all_pk = np.concatenate([active_pK,decoy_pK]) cat_array = np.concatenate([np.ones_like(active_pK),np.zeros_like(decoy_pK)]) auc_score = roc_auc_score(cat_array,all_pk) sorted_index = np.argsort(all_pk*(-1)) sorted_array = np.array([cat_array[index] for index in sorted_index]) return sorted_array,auc_score def EF_calculate(sorted_array,factor): all_count = len(sorted_array) sample_count = math.ceil(all_count*factor) hits_total = sorted_array.sum() hits_count = sorted_array[:sample_count].sum() EF = (hits_count/sample_count) / (hits_total/all_count) return EF def _percision_recall_area(active_pK,decoy_pK): y_pred = np.concatenate([active_pK,decoy_pK]) y_true = np.concatenate([np.ones_like(active_pK),np.zeros_like(decoy_pK)]) precision, recall, thresholds = precision_recall_curve(y_true,y_pred) area = auc(recall, precision) return area if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument('-f','--PLANET_file',required=True) parser.add_argument('-d','--DUDE',required=True) parser.add_argument('-o','--out_dir',required=True) parser.add_argument('-s','--feature_dims', type=int, default=300) parser.add_argument('-n','--nheads', type=int, default=8) parser.add_argument('-k','--key_dims', type=int, default=300) parser.add_argument('-va','--value_dims', type=int, default=300) parser.add_argument('-pu','--pro_update_inters', type=int, default=3) parser.add_argument('-lu','--lig_update_iters',type=int,default=10) parser.add_argument('-pl','--pro_lig_update_iters',type=int,default=1) args = parser.parse_args() feature_dims,nheads,key_dims,value_dims,pro_update_inters,lig_update_iters,pro_lig_update_iters = args.feature_dims,args.nheads,args.key_dims,args.value_dims,\ args.pro_update_inters,args.lig_update_iters,args.pro_lig_update_iters PLANET = PLANET(feature_dims,nheads,key_dims,value_dims,pro_update_inters,lig_update_iters,pro_lig_update_iters,'cuda').cuda() PLANET.load_state_dict(torch.load(args.PLANET_file)) out_dir = args.out_dir os.makedirs(args.out_dir,exist_ok=True) target_names,active_means,active_medians,decoy_means,decoy_medians,EF_05,EF_1,EF_2,EF_5,auc_scores,auc_prs = [],[],[],[],[],[],[],[],[],[],[] PLANET.eval() with torch.no_grad(): for folder in os.listdir(args.DUDE): work_folder = os.path.join(args.DUDE,folder) out_folder = os.path.join(out_dir,folder) os.makedirs(out_folder,exist_ok=True) predicted_active_affinities,predicted_decoy_affinities = workflow(model=PLANET,folder_path=work_folder,out_folder=out_folder) sorted_array,auc_score = EF_sort(predicted_active_affinities,predicted_decoy_affinities) auc_pr = _percision_recall_area(predicted_active_affinities,predicted_decoy_affinities) target_names.append(str(folder).upper()) active_means.append(predicted_active_affinities.mean()) active_medians.append(np.median(predicted_active_affinities)) decoy_means.append(predicted_decoy_affinities.mean()) decoy_medians.append(np.median(predicted_decoy_affinities)) EF_05.append(EF_calculate(sorted_array,0.005)) EF_1.append(EF_calculate(sorted_array,0.01)) EF_2.append(EF_calculate(sorted_array,0.02)) EF_5.append(EF_calculate(sorted_array,0.05)) auc_scores.append(auc_score) auc_prs.append(auc_pr) torch.cuda.empty_cache() #active_result_path = os.path.join(work_folder,'{}_active.dat'.format(folder)) #decoy_result_path = os.path.join(work_folder,'{}_decoy.dat'.format(folder)) #with open(active_result_path,'w') as active_dat: #for item in active_affinities.tolist(): # active_dat.write(str(item)+'\n') #with open(decoy_result_path,'w') as decoy_dat: # for item in decoy_affinities.tolist(): # decoy_dat.write(str(item)+'\n') csv_frame = pd.DataFrame([ { 'Target Name':target_name,'Active Mean':active_mean,'Active Median':active_median, 'Decoy Mean':decoy_mean,'Decoy Median':decoy_median,'Delta Mean':active_mean-decoy_mean,'Delta Median':active_mean-decoy_median, 'EF_0.5%':x,'EF_1%':y,'EF_2%':z,'EF_5%':w,'ROC_AUC Score':auc_score,'ROC_PR Score':auc_pr } for target_name,active_mean,active_median,decoy_mean,decoy_median,x,y,z,w,auc_score in zip(target_names,active_means,active_medians,decoy_means,decoy_medians,EF_05,EF_1,EF_2,EF_5,auc_scores,auc_prs) ]) csv_frame.to_csv(os.path.join(out_dir,'summary.csv'))这个是什么代码,作用和意义
最新发布
10-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

热衷技术的尼古拉斯

您的鼓励是我创作的最大动力。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值