CNN、RNN学习笔记(自用)

本文介绍了卷积神经网络(CNN)、循环神经网络(RNN)和深度神经网络(DNN)在图像处理、序列分析等领域的应用,涉及局部感受野、共享权值、池化操作、RNN的时序处理和CNN的前向传播流程。作者还提供了使用PyTorch实现CNN和RNN的代码示例。
摘要由CSDN通过智能技术生成

应用场景

  • CNN:卷积神经网络,专门用于图像处理的神经网络,能够自动学习图像中的特征数据,在图像识别、对象检测和自动驾驶中表现出色;
  • RNN:循环神经网络,具有时间序列处理能力,捕捉序列中的长期依赖关系,在NLP、语音识别、机器翻译中表现出色;
  • DNN:深度神经网络,可以处理各种数据,包括图像、文本、时间序列,能够学习复杂的表示,在图像识别、自然语言处理、推荐系统等场景中都可使用。

相关概念

CNN

  • 局部感受野:卷积神经网络将每一个隐藏节点仅连接到图像的某个局部区域,减少参数训练的数量。如一张1024*720的图像,使用9*9的感受野,则只需要81个权值参数,更关注局部信息。
  • 共享权值:在卷积神经网络的卷积层中,神经元对应的权值相同,即每个神经元连接数据窗的权重是固定的,每个神经元只关注一个特征。共享的权值和偏置也称为卷积核或滤波器。比如边缘检测专用的Sobel滤波器,即卷积层的每个滤波器都会有自己所关注一个图像特征,比如垂直边缘,水平边缘,颜色,纹理等等,这些所有神经元加起来就好比就是整张图像的特征提取器集合。
  • 池化:通过下采样的过程,对执行卷积操作后的图像进行类似于压缩的操作。两种类型,一种是最大值池化 Max Pooling(更常用),一种是平均值池化 Mean/Average Pooling。

        最大值池化,是取当前池化视野中所有元素的最大值,输出到下一层特征图中。

        平均值池化,是取当前池化视野中所有元素的平均值,输出到下一层特征图中。

池化作用:

  1. 在减少参数量的同时,还保留了原图像的原始特征
  2. 有效防止过拟合
  3. 为卷积神经网络带来平移不变性
  4. 维持同尺寸图片,便于后端处理:假设输入的图片不是一样大小的,就需要用池化来转换成同尺寸图片

平移不变性说明:

虽然池化之前两幅图片的眼睛特征不在一个位置,但是经过池化之后,眼睛特征的位置都是相同的

  • feature map:在cnn的每个卷积层,数据都是以三维形式存在的。可以把它看成许多个二维图片叠在一起(像豆腐皮竖直的贴成豆腐块一样),其中每一个称为一个feature map。在输入层,如果是灰度图片,那就只有一个feature map;如果是彩色图片(RGB),一般就是3个feature map(红绿蓝)

        层与层之间会有若干个卷积核(kernel)(也称为过滤器),卷积核深度与初始图片的通道数一致。

        上一层所有feature map 对应的 某个卷积核的所有层做卷积,结果相加(或者再加上偏置),都会产生下一层的一个feature map,有N个卷积核,下层就会产生N个feather map。即:输入图片不论通道数是1(灰色)还是3(彩色)or其他值,经过卷积核处理后,都会统一拍平成深度为1的feature map。有几个卷积核就生成几个feature map,与输入图片的通道数无关。

        多个feature map作用:我们希望构造一组基,这组基能够形成对于一个事物完备的描述,例如描述一个人时我们通过描述身高/体重/相貌等,在卷积网中也是如此。在同一层,我们希望得到对于一张图片多种角度的描述,具体来讲就是用多种不同的卷积核对图像进行卷,得到不同核(这里的核可以理解为描述)上的响应,作为图像的特征。他们的联系在于形成图像在同一层次不同基上的描述。

RNN

(a) 全连接式

(b)自己对自己

      RNN关注隐层每个神经元在时间维度上的不断成长与进步,变换一下3D的视角,网络结构不变,没有添加新的神经元,但是沿着时间轴recurrent,也就是重复,建立时序上的关联,这里的层级扩展并非神经元数量的真实增加,而是表示隐层在不同时刻的状态。RNN本质上是用一种看似是级联,但实际上却是沿着时序,反复迭代的网络结构,实现了对序列数据的学习。

      假如用W{s}来表示层级间的权重矩阵,RNN通常会假定不同的层,其实也就是不同的时刻共享一个W{s},这样可以有效地减少训练参数。  

算法原理

CNN

        在CNN中,卷积层用于学习图像的局部特征,然后这些特征被传递到全连接层,以进行分类或其他任务。具体来说,CNN的算法步骤如下:

  1. 初始化权重矩阵。                                                                【数据输入层/input layer】
  2. 对于每个卷积核,对输入图像进行卷积操作。                     【卷积计算层/CONV layer】
  3. 对卷积结果进行激活函数处理。                                           【ReLU激励层/ReLU layer】
  4. 对卷积结果进行池化操作。                                                  【池化层/Pooling layer】
  5. 将池化结果传递到全连接层。                                               【全连接层/FC layer】
  6. 在全连接层,对输入数据进行处理,然后将其传递到输出层。【输出层/output layer】
  7. 在输出层,计算分类结果。

整体过程

提取人眼睛特征过程

RNN

     RNN的算法原理是基于循环连接的。在RNN中,每个隐藏单元都有一个状态,这个状态在每个时间步被更新。这使得RNN能够捕捉到序列中的长期依赖关系。具体来说,RNN的算法步骤如下:

  1. 初始化隐藏状态为零向量。
  2. 对于每个时间步,对输入数据进行处理,然后将其传递到隐藏层。
  3. 在隐藏层,每个隐藏单元根据其前一个状态和输入数据计算新的状态。
  4. 对于每个输出单元,计算输出值。
  5. 更新隐藏状态。
  6. 重复步骤2-5,直到所有输入数据被处理。

算法实现

CNN

import torch # 需要的各种包
import torch.nn as nn
from torch.autograd import Variable
import torch.utils.data as data
import matplotlib.pyplot as plt
import torchvision # 数据库模块
 
 
# 数据预处理
# 将training data转化成torch能够使用的DataLoader,这样可以方便使用batch进行训练
torch.manual_seed(1) # reproducible 将随机数生成器的种子设置为固定值,这样,当调用时torch.rand(x),结果将可重现
 
# Hyper Parameters
EPOCH = 1 # 训练迭代次数
BATCH_SIZE = 50 # 分块送入训练器
LR = 0.001 # 学习率 learning rate
 
train_data = torchvision.datasets.MNIST(
    root='./mnist/', # 保存位置 若没有就新建
    train=True, # training set
    transform=torchvision.transforms.ToTensor(), # 
    # converts a PIL.Image or numpy.ndarray to torch.FloatTensor(C*H*W) in range(0.0,1.0)
    download=True
)
 
test_data = torchvision.datasets.MNIST(root='./MNIST/')
 
# 如果是普通的Tensor数据,想使用 torch_dataset = data.TensorDataset(data_tensor=x, target_tensor=y)
# 将Tensor转换成torch能识别的dataset
# 批训练, 50 samples, 1 channel, 28*28, (50, 1, 28 ,28)
train_loader = data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
 
test_x = Variable(torch.unsqueeze(test_data.test_data, dim=1), volatile=True).type(torch.FloatTensor)[:2000]/255.
# torch.unsqueeze 返回一个新的张量,对输入的既定位置插入维度 1
 
test_y = test_data.test_lables[:2000]
# 数据预处理
 
 
# 定义网络结构
# 1)class CNN需要·继承·Module 
# 2)需要·调用·父类的构造方法:super(CNN, self).__init__()
# 3)在Pytorch中激活函数Relu也算是一层layer
# 4)需要·实现·forward()方法,用于网络的前向传播,而反向传播只需要·调用·Variable.backward()即可。
# 输入的四维张量[N, C, H, W]
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        # nn.Sequential一个有序的容器,神经网络模块将按照在传入构造器的顺序依次被添加到计算图中执行,
        # 同时以神经网络模块为元素的有序字典也可以作为传入参数
        # nn.Conv2d 二维卷积 先实例化再使用 在Pytorch的nn模块中,它是不需要你手动定义网络层的权重和偏置的
        self.conv1 = nn.Sequential( #input shape (1,28,28)
            nn.Conv2d(in_channels=1, #input height 必须手动提供 输入张量的channels数
                      out_channels=16, #n_filter 必须手动提供 输出张量的channels数
                      kernel_size=5, #filter size 必须手动提供 卷积核的大小 
                      # 如果左右两个数不同,比如3x5的卷积核,那么写作kernel_size = (3, 5),注意需要写一个tuple,而不能写一个列表(list)
                      stride=1, #filter step 卷积核在图像窗口上每次平移的间隔,即所谓的步长
                      padding=2 #con2d出来的图片大小不变 Pytorch与Tensorflow在卷积层实现上最大的差别就在于padding上
            ), # output shape (16,28,28) 输出图像尺寸计算公式是唯一的 # O = (I - K + 2P)/ S +1
            nn.ReLU(), # 分段线性函数,把所有的负值都变为0,而正值不变,即单侧抑制
            nn.MaxPool2d(kernel_size=2) #2x2采样,28/2=14,output shape (16,14,14) maxpooling有局部不变性而且可以提取显著特征的同时降低模型的参数,从而降低模型的过拟合
        ) 
        self.conv2 = nn.Sequential(nn.Conv2d(16, 32, 5, 1, 2), #output shape (32,7,7)
                                  nn.ReLU(),
                                  nn.MaxPool2d(2))
        # 因上述几层网络处理后的output为[32,7,7]的tensor,展开即为7*7*32的一维向量,接上一层全连接层,最终output_size应为10,即识别出来的数字总类别数
        # 在二维图像处理的任务中,全连接层的输入与输出一般都设置为二维张量,形状通常为[batch_size, size]
        self.out = nn.Linear(32*7*7, 10) # 全连接层 7*7*32, num_classes
        
    def forward(self, x):
        x = self.conv1(x) # 卷一次
        x = self.conv2(x) # 卷两次
        x = x.view(x.size(0), -1) #flat (batch_size, 32*7*7) 
        # 将前面多维度的tensor展平成一维 x.size(0)指batchsize的值
        # view()函数的功能根reshape类似,用来转换size大小
        output = self.out(x) # fc out全连接层 分类器
        return output
# 定义网络结构
 
 
# 查看网络结构
cnn = CNN()
print(cnn) # 使用print(cnn)可以看到网络的结构详细信息,可以看到ReLU()也是一层layer
# 查看网络结构
 
 
# 训练 需要特别指出的是记得每次反向传播前都要清空上一次的梯度,optimizer.zero_grad()
# optimizer 可以指定程序优化特定的选项,例如学习速率,权重衰减等
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) # torch.optim是一个实现了多种优化算法的包
 
# loss_fun CrossEntropyLoss 交叉熵损失
# 信息量:它是用来衡量一个事件的不确定性的;一个事件发生的概率越大,不确定性越小,则它所携带的信息量就越小。
# 熵:它是用来衡量一个系统的混乱程度的,代表一个系统中信息量的总和;信息量总和越大,表明这个系统不确定性就越大。
# 交叉熵:它主要刻画的是实际输出(概率)与期望输出(概率)的距离,也就是交叉熵的值越小,两个概率分布就越接近
loss_func = nn.CrossEntropyLoss() # 该损失函数结合了nn.LogSoftmax()和nn.NLLLoss()两个函数 适用于分类
 
# training loop
for epoch in range(EPOCH):
    for i, (x, y) in enumerate(train_loader):
        batch_x = Variable(x)
        batch_y = Variable(y)
        output = cnn(batch_x) # 输入训练数据
        loss = loss_func(output, batch_y) # 计算误差 # 实际输出, 期望输出
        optimizer.zero_grad() # 清空上一次梯度
        loss.backward() # 误差反向传递 只需要调用.backward()即可
        optimizer.step() # cnn的优化器参数更新
# 训练
 
 
# 预测结果
# cnn.eval()
test_output = cnn(test_x[:10])
pred_y = torch.max(test_output, 1)[1].data.numpy().squeeze()
# torch.max(input, dim)函数  
# torch.max(test_output, 1)[1]  取出来indices 每行最大值的索引
# 输入 input是softmax函数输出的一个tensor  
# 输入 dim是max函数索引的维度0/1,0是每列的最大值,1是每行的最大值
# 输出 函数会返回两个tensor,第一个tensor是每行的最大值;第二个tensor是每行最大值的索引。
# squeeze()函数的功能是:从矩阵shape中,去掉维度为1的。例如一个矩阵是的shape是(5, 1),使用过这个函数后,结果为(5,)。
print(pred_y, 'prediction number')
print(test_y[:10], 'real number')
# 预测结果

RNN

#pytorch调用RNN代码
class RNN(nn.Module):
    def __init__(self, input_size, output_size, hidden_dim, n_layers):
        super(RNN, self).__init__()
        #隐藏层特征数量
        self.hidden_dim=hidden_dim
        '''
        input_size    – 输入x中预期特征的数量
		hidden_size   – 隐藏状态h的特征数量
		num_layers    - 循环层数。例如,设置 num_layers=2意味着将两个RNN 堆叠在一起形成一个堆叠的RNN,第二个RNN接收						    第一个RNN的输出并计算最终结果。默认值:1
		nonlinearity  — 隐藏层函数,可以是“tanh”或“relu”。默认值:'tanh'
		bias 		  - 如果为 False,则该层不使用偏差权重。默认值:真
		batch_first   - 输入特征是不是批量输入。默认值False
		dropout 	  - 是否要引入Dropout层,dropout概率等于dropout。默认值:0
		bidirectional —如果为真,则成为双向 RNN。默认值:假
		'''
        self.rnn = nn.RNN(input_size, hidden_dim, n_layers, batch_first=True)
        #全连接层
        self.fc = nn.Linear(hidden_dim, output_size)

    def forward(self, x, hidden):
        #批量输入大小
        batch_size = x.size(0)
        #批量输入input,隐藏层参数
        r_out, hidden = self.rnn(x, hidden)
        #维度转化
        r_out = r_out.view(-1, self.hidden_dim)  
        #全连接
        output = self.fc(r_out)
        return output, hidden

【参考资料】

RNN vs. CNN vs. 深度神经网络:比较与应用 - 知乎 (zhihu.com)

深度学习 --- 卷积神经网络CNN(LeNet-5网络详解)_zsffuture-百度飞桨星河社区 (csdn.net)

CNN | 05池化层_cnn池化层-CSDN博客

卷积神经网络(CNN)详细介绍及其原理详解 (qq.com) 【重点】

视频:【【循环神经网络】5分钟搞懂RNN,3D动画深入浅出】https://www.bilibili.com/video/BV1z5411f7Bm?vd_source=1eaeed589239e54203e51aff11bb3d44

RNN 的基本原理+pytorch代码_rnn pytorch-CSDN博客https://www.cnblogs.com/yh-blog/p/10052915.htmlRNN 的基本原理+pytorch代码_rnn pytorch-CSDN博客

https://www.cnblogs.com/yh-blog/p/10052915.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值