第一句子网 - 唯美句子、句子迷、好句子大全
第一句子网 > 基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

时间:2020-07-20 08:51:42

相关推荐

基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

基于pytorch使用实现CNN 如何使用pytorch构建CNN卷积神经网络

所用工具文件结构:数据:代码:结果:改进思路拓展

本文是一个基于pytorch使用CNN在生物信息学上进行位点预测的例子

基于pytorch实现CNN,基于CNN进行位点预测,将CNN代码进行封装,可以非常简单的使用代码,基于最简单的特征提取方法。

所用工具

使用了python和pytorch进行实现

python3.6

toch1.10

文件结构:

如下图所示:

数据:

百度网盘地址(数据很小):

链接:/s/1uvYs7EBJiK3U89v7vMX9yw

提取码:nii4

代码:

以下代码直接复制可以运行

import torch # 需要的各种包import torch.nn as nnfrom sklearn.metrics import roc_auc_scorefrom sklearn.model_selection import StratifiedKFoldfrom torch.autograd import Variableimport torch.utils.data as Dataimport torch.utils.data as dataimport torchvision # 数据库模块import pandas as pdimport numpy as nptorch.manual_seed(1) # reproducible 将随机数生成器的种子设置为固定值,这样,当调用时torch.rand(x),结果将可重现from sklearn.preprocessing import LabelEncoder,OneHotEncoderclass CNN(nn.Module):def __init__(self, seq_len):super(CNN, self).__init__() # 固定写法self.conv1 = nn.Sequential( # 假设输入为(1,21)nn.Conv1d(in_channels=1, # input height 必须手动提供 输入张量的channels数out_channels=16, # n_filter 必须手动提供 输出张量的channels数kernel_size=3, # filter size 必须手动提供 卷积核的大小stride=1, # filter step 卷积核在图像窗口上每次平移的间隔,即所谓的步长padding=1 # 填补为2), # output shape (16,21)nn.ReLU(), # 分段线性函数,把所有的负值都变为0,而正值不变,即单侧抑制nn.MaxPool1d(kernel_size=3, stride=1, padding=1), # 2采样,28/2=14,output shape (16,14,14) maxpooling有局部不变性而且可以提取显著特征的同时降低模型的参数,从而降低模型的过拟合nn.Dropout(p=0.2))self.conv2 = nn.Sequential(nn.Conv1d(16, 32, 3, 1, 1),nn.ReLU(), # 分段线性函数,把所有的负值都变为0,而正值不变,即单侧抑制nn.MaxPool1d(kernel_size=3, stride=1, padding=1),# 2采样,28/2=14,output shape (16,14,14) maxpooling有局部不变性而且可以提取显著特征的同时降低模型的参数,从而降低模型的过拟合nn.Dropout(p=0.2)) # 输出为 max_len/self.out = nn.Linear(seq_len*32, 2) # 全连接层,输出为2个one_hot编码def forward(self, x):x = self.conv1(x) # 卷一次x = self.conv2(x) # 卷两次x = x.view(x.size(0), -1) # 展平, 将前面多维度的tensor展平成一维 x.size(0)指batchsize的值output = self.out(x) # fc out全连接层 分类器return outputclass Use_torch_CNN():def __init__(self, epoch, batch_size, lr):self.epoch = epochself.batch_size =batch_sizeself.lr = lrdef to_torch(self, X_train, y_train): # 转化为torch数据BATCH_SIZE = self.batch_sizeX_train = torch.FloatTensor(X_train)y_train = torch.FloatTensor(y_train)train_loader = Data.DataLoader(Data.TensorDataset(X_train, y_train), BATCH_SIZE,shuffle=False) # 自动划分Batch_sizereturn train_loaderdef train(self, X_train, y_train):seq_len = X_train.shape[-1]train_loader = self.to_torch(X_train, y_train)####### 以下为数据训练 ##########n = CNN(seq_len=seq_len) # 创建网络print(n) # 查看网络结构optimizer = torch.optim.Adam(n.parameters(), lr=self.lr) # optimizer 优化器loss_func = nn.CrossEntropyLoss() # 损失函数 交叉熵for epoch in range(self.epoch):for step, (x, y) in enumerate(train_loader):batch_x = Variable(x)batch_x = torch.unsqueeze(batch_x, dim=1)batch_y = Variable(y)optimizer.zero_grad() # 梯度归零 必须项output = n(batch_x) # 输入训练数据loss = loss_func(output, batch_y) # 计算误差 #实际输出,期望输出loss.backward() # 误差反向传递 只需要调用.backward()即可optimizer.step()print(f"epoch:{epoch} loss:{loss}")def predict_proba(self, X_valid):val_data_x = torch.FloatTensor(X_valid)val_data_x = torch.unsqueeze(val_data_x, dim=1)test_output = n(val_data_x)y_scores = test_output.detach().numpy()return y_scoresdef predict(self, X_valid):y_scores = self.predict_proba(X_valid)return np.argmax(y_scores, axis=1)def ex_feature(data_pos, data_neg): ## 提取特征def split_word(data_init, k=1): ## 分词处理 一般为1分词data = data_init.tolist()split_dict = {'[PAD]': 0, '[CLS]': 1, '[SEP]': 2, '[MASK]': 3, 'B': 4,'Q': 5, 'I': 6, 'D': 7, 'M': 8, 'V': 9, 'G': 10, 'K': 11,'Y': 12, 'P': 13, 'H': 14, 'Z': 15, 'W': 16, 'U': 17, 'A': 18,'N': 19, 'F': 20, 'R': 21, 'S': 22, 'C': 23, 'E': 24, 'L': 25,'T': 26, 'X': 27, 'O': 28}def str_sum(s, i):d = ''for j in range(k):d += s[i + j]return dfor i, seq in enumerate(data):data[i] = seq[0]token_list = list()max_len = 0 ## 最大长度for seq in data:seq_id = [split_dict[str_sum(seq, i)] for i in range(len(seq) - k + 1) if i % k == 0] # 字符转为数字token_list.append(seq_id)if len(seq_id) > max_len:max_len = len(seq_id) ## 获取最大长度return token_list, max_lendef add_CLS_SEP(token_list, max_len): # 增加标志 以及 补零split_dict = {'[PAD]': 0, '[CLS]': 1, '[SEP]': 2, '[MASK]': 3, 'B': 4,'Q': 5, 'I': 6, 'D': 7, 'M': 8, 'V': 9, 'G': 10, 'K': 11,'Y': 12, 'P': 13, 'H': 14, 'Z': 15, 'W': 16, 'U': 17, 'A': 18,'N': 19, 'F': 20, 'R': 21, 'S': 22, 'C': 23, 'E': 24, 'L': 25,'T': 26, 'X': 27, 'O': 28}data = []for i in range(len(token_list)): # 由于长度不一致,不建议用numpy操作token_list[i] = [split_dict['[CLS]']] + token_list[i] + [split_dict['[SEP]']]n_pad = max_len - len(token_list[i])token_list[i].extend([0] * n_pad) # 补零对齐data.append(token_list[i])return datadata_pos, max_len_pos = split_word(data_pos)data_neg, max_len_neg = split_word(data_neg)max_len = np.max([max_len_pos, max_len_neg])data_pos = add_CLS_SEP(data_pos, max_len)data_neg = add_CLS_SEP(data_neg, max_len)return data_pos, data_negdef generate_train_test(Px, Nx): # 分出X YPx = np.array(Px)Nx = np.array(Nx)Py = np.ones((Px.shape[0], 1))Ny = np.zeros((Nx.shape[0], 1))P_train = np.concatenate((Px, Py), axis=1) # 按列合并N_train = np.concatenate((Nx, Ny), axis=1) # 按列合并data_train = np.concatenate((P_train, N_train), axis=0) # 按行合并np.random.seed(42)np.random.shuffle(data_train) # 混淆数据X = data_train[:,:-1] # 除-1列外的所有列Y = (data_train[:,-1]).reshape(-1,1)return X, Ydef get_kfold_data(X, Y, k=5):X = np.array(X)Y = np.array(Y)kfold = StratifiedKFold(n_splits=k, shuffle=True, random_state=520)data_kfold_list = []for train_idx, val_idx in kfold.split(X,y):data_kfold_list.append({'train':{'X':X[train_idx],'Y':Y[train_idx]},'val':{'X':X[val_idx],'Y':Y[val_idx]}})return data_kfold_list### 迭代器形式 省内存 #### for train_idx, val_idx in kfold.split(X,y):#data_kfold_list = {'train':{'X':X[train_idx],'Y':y[train_idx]},# 'val':{'X':X[val_idx],'Y':y[val_idx]}}#yield data_kfold_list# returndef get_one_data(X, Y, k=5):X = np.array(X)Y = np.array(Y)One_Hot = OneHotEncoder().fit(Y)Y_one_hot = One_Hot.transform(Y).toarray()kfold = StratifiedKFold(n_splits=k, shuffle=True, random_state=520)for train_idx, val_idx in kfold.split(X,Y):return X[train_idx], Y_one_hot[train_idx], X[val_idx], Y_one_hot[val_idx]if __name__ == '__main__':EPOCH = 10 # 训练迭代次数BATCH_SIZE = 32 # 分块送入训练器LR = 0.001 # 学习率 learning rate######## 以下为数据加载 #######data_pos = np.array(pd.read_csv('./data/gly_pos.fa', header=None))data_neg = np.array(pd.read_csv('./data/gly_neg.fa', header=None))data_pos, data_neg = ex_feature(data_pos, data_neg) # 提取特征train_x, train_y = generate_train_test(data_pos, data_neg)X_train, y_train, X_valid, y_valid = get_one_data(train_x, train_y)cnn = Use_torch_CNN(epoch=EPOCH, batch_size=BATCH_SIZE, lr=LR) # 构建模型cnn.train(X_train, y_train) # 训练模型y_scores = cnn.predict_proba(X_valid) # 预测auc = roc_auc_score(y_valid[:,1], y_scores[:,1]) # y_true, y_scoreprint(f'auc:{auc}')

结果:

如下图所示,结果并不好,原因很简单,因为这个模型“提取特征”部分没做好:

改进思路

1、增加特征提取方式

2、利用自编码器提取特征

拓展

卷积神经网络概念

上世纪60年代,Hubel等人通过对猫视觉皮层细胞的研究,提出了感受野这个概念,到80年代,Fukushima在感受野概念的基础之上提出了神经认知机的概念,可以看作是卷积神经网络的第一个实现网络,神经认知机将一个视觉模式分解成许多子模式(特征),然后进入分层递阶式相连的特征平面进行处理,它试图将视觉系统模型化,使其能够在即使物体有位移或轻微变形的时候,也能完成识别。

卷积神经网络(Convolutional Neural Networks, CNN)是多层感知机(MLP)的变种。由生物学家休博尔和维瑟尔在早期关于猫视觉皮层的研究发展而来。视觉皮层的细胞存在一个复杂的构造。这些细胞对视觉输入空间的子区域非常敏感,我们称之为感受野,以这种方式平铺覆盖到整个视野区域。这些细胞可以分为两种基本类型,简单细胞和复杂细胞。简单细胞最大程度响应来自感受野范围内的边缘刺激模式。复杂细胞有更大的接受域,它对来自确切位置的刺激具有局部不变性。

通常神经认知机包含两类神经元,即承担特征提取的采样元和抗变形的卷积元,采样元中涉及两个重要参数,即感受野与阈值参数,前者确定输入连接的数目,后者则控制对特征子模式的反应程度。卷积神经网络可以看作是神经认知机的推广形式,神经认知机是卷积神经网络的一种特例。

CNN由纽约大学的Yann LeCun于1998年提出。CNN本质上是一个多层感知机,其成功的原因关键在于它所采用的局部连接和共享权值的方式,一方面减少了的权值的数量使得网络易于优化,另一方面降低了过拟合的风险。CNN是神经网络中的一种,它的权值共享网络结构使之更类似于生物神经网络,降低了网络模型的复杂度,减少了权值的数量。该优点在网络的输入是多维图像时表现的更为明显,使图像可以直接作为网络的输入,避免了传统识别算法中复杂的特征提取和数据重建过程。在二维图像处理上有众多优势,如网络能自行抽取图像特征包括颜色、纹理、形状及图像的拓扑结构;在处理二维图像问题上,特别是识别位移、缩放及其它形式扭曲不变性的应用上具有良好的鲁棒性和运算效率等。

CNN本身可以采用不同的神经元和学习规则的组合形式。

CNN具有一些传统技术所没有的优点:良好的容错能力、并行处理能力和自学习能力,可处理环境信息复杂,背景知识不清楚,推理规则不明确情况下的问题,允许样品有较大的缺损、畸变,运行速度快,自适应性能好,具有较高的分辨率。它是通过结构重组和减少权值将特征抽取功能融合进多层感知器,省略识别前复杂的图像特征抽取过程。

CNN的泛化能力要显著优于其它方法,卷积神经网络已被应用于模式分类,物体检测和物体识别等方面。利用卷积神经网络建立模式分类器,将卷积神经网络作为通用的模式分类器,直接用于灰度图像。

CNN是一个前溃式神经网络,能从一个二维图像中提取其拓扑结构,采用反向传播算法来优化网络结构,求解网络中的未知参数。

CNN是一类特别设计用来处理二维数据的多层神经网络。CNN被认为是第一个真正成功的采用多层层次结构网络的具有鲁棒性的深度学习方法。CNN通过挖掘数据中的空间上的相关性,来减少网络中的可训练参数的数量,达到改进前向传播网络的反向传播算法效率,因为CNN需要非常少的数据预处理工作,所以也被认为是一种深度学习的方法。在CNN中,图像中的小块区域(也叫做“局部感知区域”)被当做层次结构中的底层的输入数据,信息通过前向传播经过网络中的各个层,在每一层中都由过滤器构成,以便能够获得观测数据的一些显著特征。因为局部感知区域能够获得一些基础的特征,比如图像中的边界和角落等,这种方法能够提供一定程度对位移、拉伸和旋转的相对不变性。

CNN中层次之间的紧密联系和空间信息使得其特别适用于图像的处理和理解,并且能够自动的从图像抽取出丰富的相关特性。

CNN通过结合局部感知区域、共享权重、空间或者时间上的降采样来充分利用数据本身包含的局部性等特征,优化网络结构,并且保证一定程度上的位移和变形的不变性。

CNN受视觉神经机制的启发而设计,是为识别二维或三维信号而设计的一个多层感知器,这种网络结构对平移、缩放、倾斜等变形具有高度不变性。

CNN可以用来识别位移、缩放及其它形式扭曲不变性的二维或三维图像。CNN的特征提取层参数是通过训练数据学习得到的,所以其避免了人工特征提取,而是从训练数据中进行学习;其次同一特征图的神经元共享权值,减少了网络参数,这也是卷积网络相对于全连接网络的一大优势。共享局部权值这一特殊结构更接近于真实的生物神经网络使CNN在图像处理、语音识别领域有着独特的优越性,另一方面权值共享同时降低了网络的复杂性,且多维输入信号(语音、图像)可以直接输入网络的特点避免了特征提取和分类过程中数据重排的过程。

CNN是一种特殊的深层的神经网络模型,它的特殊性体现在两个方面,一方面它的神经元的连接是非全连接的,另一方面同一层中某些神经元之间的连接的权重是共享的(即相同的)。它的非全连接和权值共享的网络结构使之更类似于生物神经网络,降低了网络模型的复杂度(对于很难学习的深层结构来说,这是非常重要的),减少了权值的数量。

CNN是一种深度的监督学习下的机器学习模型,具有极强的适应性,善于挖掘数据局部特征,提取全局训练特征和分类,它的权值共享结构网络使之更类似于生物神经网络,在模式识别各个领域都取得了很好的成果。

稀疏连接:在BP神经网络中,每一层的神经元节点是一个线性一维排列结构,层与层各神经元节点之间是全连接的。卷积神经网络中,层与层之间的神经元节点不再是全连接形式,利用层间局部空间相关性将相邻每一层的神经元节点只与和它相近的上层神经元节点连接,即局部连接。这样大大降低了神经网络架构的参数规模。

权重共享:在卷积神经网络中,卷积层的每一个卷积滤波器重复的作用于整个感受野中,对输入图像进行卷积,卷积结果构成了输入图像的特征图,提取出图像的局部特征。每一个卷积滤波器共享相同的参数,包括相同的权重矩阵和偏置项。共享权重的好处是在对图像进行特征提取时不用考虑局部特征的位置。而且权重共享提供了一种有效的方式,使要学习的卷积神经网络模型参数数量大大降低。

最大池采样:它是一种非线性降采样方法。在通过卷积获取图像特征之后是利用这些特征进行分类。可以用所有提取到的特征数据进行分类器的训练,但这通常会产生极大的计算量。所以在获取图像的卷积特征后,要通过最大池采样方法对卷积特征进行降维。将卷积特征划分为数个n*n的不相交区域,用这些区域的最大(或平均)特征来表示降维后的卷积特征。这些降维后的特征更容易进行分类。

最大池采样在计算机视觉中的价值体现在两个方面:(1)、它减小了来自上层隐藏层的计算复杂度;(2)、这些池化单元具有平移不变性,即使图像有小的位移,提取到的特征依然会保持不变。由于增强了对位移的鲁棒性,最大池采样方法是一个高效的降低数据维度的采样方法。

Softmax回归:它是在逻辑回归的基础上扩张而来,它的目的是为了解决多分类问题。在这类问题中,训练样本的种类一般在两个以上。Softmax回归是有监督学习算法,它也可以与深度学习或无监督学习方法结合使用。

CNN是一种带有卷积结构的深度神经网络,通常至少有两个非线性可训练的卷积层,两个非线性的固定卷积层(又叫Pooling Laye)和一个全连接层,一共至少5个隐含层。

卷积神经网络中,输入就是一幅幅的图像,权值W就是卷积模板,一般是卷积层和下采样层交替,最后是全连接的神经网络。

局部区域感知能够发现数据的一些局部特征,比如图片上的一个角,一段弧,这些基本特征是构成动物视觉的基础。

CNN中每一层的由多个map组成,每个map由多个神经单元组成,同一个map的所有神经单元共用一个卷积核(即权重),卷积核往往代表一个特征,比如某个卷积核代表一段弧,那么把这个卷积核在整个图片上滚一下,卷积值较大的区域就很有可能是一段弧。注意卷积核其实就是权重,我们并不需要单独去计算一个卷积,而是一个固定大小的权重矩阵去图像上匹配时,这个操作与卷积类似,因此我们称为卷积神经网络,实际上,BP也可以看作一种特殊的卷积神经网络,只是这个卷积核就是某层的所有权重,即感知区域是整个图像。权重共享策略减少了需要训练的参数,使得训练出来的模型的泛华能力更强。

CNN一般采用卷积层与采样层交替设置,即一层卷积层接一层采样层,采样层后接一层卷积…这样卷积层提取出特征,再进行组合形成更抽象的特征,最后形成对图片对象的描述特征,CNN后面还可以跟全连接层,全连接层跟BP一样。

CNN的最大特点就是稀疏连接(局部感受)和权值共享。稀疏连接和权值共享可以减少所要训练的参数,减少计算复杂度。

卷积神经网络是一个多层的神经网络,每层由多个二维平面组成,而每个平面由多个独立神经元组成。

卷积网络在本质上是一种输入到输出的映射,它能够学习大量的输入与输出之间的映射关系,而不需要任何输入和输出之间的精确的数学表达式,只要用已知的模式对卷积网络加以训练,网络就具有输入输出对之间的映射能力。卷积网络执行的是有导师训练,所以其样本集是由形如:(输入向量,理想输出向量)的向量对构成的。所有这些向量对,都应该是来源于网络即将模拟的系统的实际“运行”结果。它们可以是从实际运行系统中采集来的。在开始训练前,所有的权都应该用一些不同的小随机数进行初始化。“小随机数”用来保证网络不会因权值过大而进入饱和状态,从而导致训练失败;“不同”用来保证网络可以正常地学习。实际上,如果用相同的数去初始化权矩阵,则网络无能力学习。训练算法与传统的BP算法差不多。 【来源:/p/514258221】

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。