基于Pytorch的卷积神经网络CNN实例应用及详解
一、卷积神经网络CNN定义
卷积神经网络(CNN,有时被称为 ConvNet)是很吸引人的。在短时间内,它们变成了一种颠覆性的技术,打破了从文本、视频到语音等多个领域所有最先进的算法,远远超出了其最初在图像处理的应用范围。CNN 由许多神经网络层组成。卷积和池化这两种不同类型的层通常是交替的。网络中每个滤波器的深度从左到右增加。最后通常由一个或多个全连接的层组成。
二、卷积神经网络CNN的原理
- 博主学习卷积神经网络CNN主要参考下面的两篇文章:
- 第一篇参考文章:点击打开《卷积神经网络推导和实现》文章
- 第二篇参考文章:点击打开《卷积神经网络(CNN)基础及经典模型介绍》文章
- 阅读上面两篇文章主要需要掌握CNN的数学原理公式,卷积、填充、池化、全连接等的概念。
三、卷积神经网络CNN实现的前期准备
- 下载编辑器和配置程序运行环境:点击打开《基于Windows中学习Deep Learning之搭建Anaconda+Pytorch(Cuda+Cudnn)+Pycharm工具和配置环境完整最简版》文章
- 项目实现用到的知识点如下:
- 点击打开《Pytorch实践中的list、numpy、torch.tensor之间数据格式的相互转换方法》文章
- 点击打开《Pytorch之nn.Conv1d学习个人见解》文章
- 点击打开《Pytorch中使用torch.nn模块进行神经网络模型初步构造》文章
- 点击打开《Pytorch中设计随机数种子的必要性》文章
- 点击打开《Pytorch中Trying to backward through the graph和one of the variables needed for gradient错误解决方案》文章
四、卷积神经网络CNN实现案例分析
-
案例目的:是构造卷积神经网络模型训练后进行药物靶体交互的二分类(0和1)预测。
-
数据集及格式说明:首先案例用到的所有数据集是来自KIBA 数据集,数据以txt文本数据存储。
-
亲和矩阵数据集Y说明:亲和矩阵的维度是[229,2110],分别表示229种蛋白质和2110种药物分子,矩阵对应的数值表示对应蛋白质和药物分子交互的亲和性,若为“nan”表示无亲和性也就是后续分类为0,其余为1。
-
药物及其smiles序列数据集ligands_iso说明:药物名称序号和对应的结构smiles序列,以字典形式保存,长度是2111(表示有2111种药物)。
-
蛋白质及其sequences序列数据集proteins说明:蛋白质名称序号和对应的结构sequences序列,以字典形式保存,长度为229(表示有229种蛋白质)。
-
训练集train_fold_setting说明:数据维度是[5,19709],也就是分为五组,每组包含19709个数字,其中数字N表示为亲和矩阵数据集Y所有行列组合数目是483190(229*2110)种组合中按顺序排的第N组。
-
测试集test_fold_setting说明:数据维度是[19709],也就是只有一组,该组包含19709个数字,其中数字N表示为亲和矩阵数据集Y所有行列组合数目是483190(229*2110)种组合中按顺序排的第N组。
-
DTI案例CNN模型搭建大致如下(具体实现细节可见后面的代码):
-
Label encoding 说明:将药物分子和蛋白质的序列的各种字符用数字字符替换,便于后面的词嵌入操作。
-
Embedding layer 说明:将药物分子和蛋白质的数字序列进行词嵌入操作,也就是增加一维度表示,比如原来的维度是一维只有长度(药物分子初始设置为100,蛋白质初始设置为1000),增加宽度(宽度初始设置都为128)这一维度。注意:卷积后长度宽度初始设置会变化。
-
concatenation(串联)说明:将原本分开的每组药物分子特征和蛋白质序列特征拼接起来,也就是根据宽度相同将两者的长拼接起来,所以拼接的宽度不变,长度两者相加。
五、卷积神经网络CNN实现完整代码和结果
import torch as t
import pickle
import numpy as np
import json
import math
from torch import nn
import torch.nn.functional as F
from sklearn.metrics import accuracy_score
# 构建训练集和测试集数据转换函数,对蛋白质和药物分子数据进行数据转换
def datatransform(data):
drug = [] # 训练集和测试集对应的各下标的药物(配体)
protein = [] # 训练集和测试集对应的各下标的蛋白质(靶体)
for i in range(len(data)):
drug.append(math.floor(data[i] / 229))
protein.append((data[i] % 229))
# 读取亲和矩阵Y数据
# 亲和矩阵Y的维度是[229,2110],229表示蛋白质的种类数量,2110表示药物分子的种类数量,矩阵元素的值表示蛋白质与药物分子结合的亲和性,nan值表示不亲和也就是互相无作用
Y = pickle.load(open("E:/data/kiba/Y", "rb"), encoding='latin1')
effective = [] # 训练集和测试集对应的各下标的药物和蛋白质结合的有效性(亲和性)
for i in range(len(data)):
d = drug[i]
p = protein[i]
if np.isnan(Y[d][p]): # 判断受体靶体有无亲和性
effective.append(0) # 受体靶体无亲和性
else:
effective.append(1) # 受体靶体有亲和性
# list转为tensor
effectives = t.LongTensor(effective) # 为损失函数计算做准备
# 读取药物和其smiles序列
drugs = json.load(open("E:\data\kiba\ligands_iso.txt"))
drug_smiles = [] # 提取药物的smiles序列
train_drug_smiles = [] # 进一步提取训练集和测试集药物的smiles序列
for d in drugs.values():
drug_smiles.append(d) # 只提取药物对应的smiles
for td in range(len(drug)): # 每批次的药物数量
train_drug_smiles.append(drug_smiles[drug[td]]) # 每批次要获取的药物数量对应的smiles序列
# 读取蛋白质和其sequences序列
proteins = json.load(