卷积神经网络

目录

一、卷积神经网络应用领域

二、 卷积

1. 卷积神经网络与传统神经网络的不同

2. 那么到底卷积做了什么事情呢??什么是卷积??

3. 卷积特征值的计算方法

4. 得到特征图的表示

5. 卷积层涉及的参数

6. 特征图尺寸的计算

7. 参数共享

8.池化层的作用

9.整体网络架构

10.经典网络架构

11. 残差神经网络(Resnet) 

12.感受野

三、卷积神经网络实战 

1.导入包

2.读取数据

3. 构建网络

4. 训练网络

5.查看损失结果 


一、卷积神经网络应用领域

        CV领域发展
        应用:目标检测,分类检索,超分辨率重构,医学任务,无人驾驶,人脸识别...

        传统神经网络在特征提取上的问题:

             1. 权重参数矩阵大

             2. 过拟合风险大

二、 卷积神经网络

        1. 卷积神经网络与传统神经网络的不同

        大家可以参考神经网络(深度学习,计算机视觉,得分函数,损失函数,前向传播,反向传播,激活函数)icon-default.png?t=N7T8https://blog.csdn.net/JamesSwifte/article/details/136848838?spm=1001.2014.3001.5501来学习神经网络的有关知识。

        大家想一下,神经网络的输入是一个向量,即使数据原本是矩阵,也是将其拉成一长条。

        上图可以看出有4个特征输入,经过两个隐藏层,到达输出层。

        

        那么卷积神经网络输入不在是向量,不是一条,而是张量,是矩阵。

        

 从上图可以看出输入的张量,中间经过卷积层后面加上全连接网络也就是神经网络。

2. 那么到底卷积做了什么事情呢??什么是卷积??

大家联系神经网络提取特征的过程,经过隐藏层,将输入特征值增大,减小,特征数量增多,减少,最后学习到了特征,虽然人是看不出,读不懂这样的特征。那么卷积的作用也是提取特征,而且克服了神经网络的参数过多,容易过拟合的问题。

想象一下,一张图片有主次之分,有背景,有人物,把一张图片分成一块一块的(张量),每一块都有它的代表特征,怎么得到这个特征呢???

        引入卷积核(类似于神经网络中的权重参数矩阵)

                   卷积核在定义了大小后,初始化类似与神经网络中的权重参数矩阵,然后在迭代优化中(反向传播)更新,达到最佳的一组。

3. 卷积特征值的计算方法

        数据与卷积核是怎么来做运算呢?答案是做内积各自位置上的值相乘然后再相加。

上图的列子里:

3\times 0+3\times1+2\times2+...+3\times0+1\times1+2\times2=12

而且有3个颜色通道,每个颜色通道进行计算,最后相加。

 4. 得到特征图的表示

大家看上图的列子,用了一个5*5*3的卷积核得到了一个,特征图。一个特征图效果可能不好,那么想要得到多个特征图怎么做呢?答案是用多个5*5*3的卷积核。而且每个卷积核都不同,这样可以多尺度,多粒度进行特征提取。

而且为了提高提取特征的精确率,采用多次卷积的方式。

   5. 卷积层涉及的参数

1. 滑动窗口步长 很显然步长小:粒度细,特征丰富 步长大:粒度粗,特征少

2. 卷积核尺寸 一般3X3

3. 边缘填充 我们发现一个问题:当步长太长,边缘的点被利用的次数明显比在里面的点的次数少,那么是边缘的点就不重要了吗?不是,经过边缘填充,将边缘点变为中间点,多利用几次,一定程度上弥补了边界信息缺失的问题(一般加0)加一圈。

4. 卷积核的个数 增大特征丰富度,有几个核就可以得到几个通道的特征图

6. 特征图尺寸的计算

        在卷积后怎么计算卷积后的结果呢?即wight,hight,channel呢?

        卷积结果计算公式:

        Hight:H_2=\frac{H_1-F_H+2p}{S}+1\\ Wight:W_2=\frac{W_1-F_W+2p}{S}+1

         其中W_1,H_1表示输入的宽度,长度;W_2,H_2表示输出特征图的宽度,长度;F表示卷积核长和宽的大小;S表示滑动窗口的步长;P表示边界填充(加几圈)。

7. 参数共享

        采用卷积神经网络可以大大降低参数的数量。例如:一张32*32*1的灰度图,用神经网络由输入层1024个特征到第一隐藏层784个特征,中间的权重参数一个需要1024*784=8028816个。而采用卷积神经网络需要一个7*7的卷积核,所需的参数49个。

        那么如果对于每一区域的卷积核参数要不一样吗?如果不一样,那么参数就会像神经网络一样非常庞大。所以对每一个区域选择相同的卷积核。这就是参数共享。这是卷积神经网路非常重要的一个特点。

8.池化层的作用

        池化层的作用:并不是所有的特征都重要,选择一些留下来。这个操作不涉及矩阵的计算。

        池化方法:最大池化(选择该区域内最大值),最小池化(选择该区域内最小值),平均池化(该区域内平均值)

        经过实验人员的验证最大池化效果最好,一般选择最大池化方式。  

9.整体网络架构

        卷积的作用就是提取特征,所以和神经网络的隐藏层一样卷积层可以很多,但是唯一不同的是在卷积后,要加入全连接层,即神经网络的隐藏层后,再输出。而且卷积,非线性变换(relu),池化一般配套使用。

10.经典网络架构

做了解

11. 残差神经网络(Resnet) 

        深层网络遇到的问题:当卷积核的个数,网络的深度到达一定值后,网络的结果没有出现提升,反而越来越差。这是深度学习的末日,意思是深度学习就到此为止了吗?

        分析一下问题:当深度越深效果反而不好,是因为下一层特征提取是在上一层提取的特征上进行的,不能保证效果越来越好的。

        解决方案:有学的好的学的不好的,要保留学的好的,同时不能让学的不好的影响整体效果。

        残差神经网络:

在上图我们可看到残差网络在18层和34层在误差上比普通网络有明显的下降。

12.感受野

        在卷积神经网络中,感受野(Receptive Field)是指特征图上的某个点能看到的输入图像的区域,即特征图上的点是由输入图像中感受野大小区域的计算得到的。神经元感受野的值越大表示其能接触到的原始图像范围就越大,也意味着它可能蕴含更为全局,语义层次更高的特征;相反,值越小则表示其所包含的特征越趋向局部和细节。因此感受野的值可以用来大致判断每一层的抽象层次。
  卷积层(conv)和池化层(pooling)都会影响感受野,而激活函数层通常对于感受野没有影响,当前层的步长并不影响当前层的感受野,感受野和填补(padding)没有关系。
  公式求取的感受野通常很大,而实际的有效感受野(Effective Receptive Field)往往小于理论感受野,因为输入层中边缘点的使用次数明显比中间点要少,因此作出的贡献不同,所以经过多层的卷积堆叠后,输入层对于特征图点做出的贡献分布呈高斯分布形状。

 

        

三、卷积神经网络实战 

构建卷积神经网络

    卷积网络中的输入层与传统的神经网络有区别,需要重新设计,训练模块基本一致

1.导入包

import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
from torchvision import datasets,transforms
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline

2.读取数据

    分别构建训练集和测试集(验证集)

    DataLoader来迭代取数据

#定义超参数
input_size = 28 # 图像的总尺寸28*28
num_classes = 10 #标签的种类数
num_epochs = 3  #训练的总循环数
batch_size = 64 # 一个批次的大小,64张图片
#训练集
train_dataset = datasets.MNIST(root='./data',
                               train = True,
                               transform=transforms.ToTensor(),
                               download = True)

#测试集
test_dataset = datasets.MNIST(root='./data',
                               train = False,
                               transform=transforms.ToTensor(),
                               )

#构建batch数据
train_loader = torch.utils.data.DataLoader(
                                dataset = train_dataset,
                                batch_size = batch_size,
                                shuffle = True
)

test_loader = torch.utils.data.DataLoader(
                                dataset = test_dataset,
                                batch_size = batch_size,
                                shuffle = True
)

3. 构建网络

class CNN(nn.Module):
    def __init__(self):
        super(CNN,self).__init__()
        self.conv1 = nn.Sequential(   # 输入大小 (1,28,28)
            nn.Conv2d(
                in_channels = 1,          #灰度图 一个颜色通道
                out_channels = 16,        #要得到几个特征图
                kernel_size = 5,          #卷积核大小
                stride = 1,               #步长
                padding = 2,              #如果希望卷积后的大小跟原来一样,设置padding=(kernel_size-1)/2 if stride = 1
            ),
            nn.ReLU(),                    #激活函数
            nn.MaxPool2d(kernel_size=2),   #进行池化层操作(2x2 区域),输出结果为:(16,14,14)
        )
        self.conv2 = nn.Sequential(  
            nn.Conv2d(16,32,5,1,2),
            nn.ReLU(),                    #激活函数
            nn.MaxPool2d(2),   #进行池化层操作(2x2 区域),输出结果为:(32,7,7)
        )
        self.out = nn.Linear(32*7*7,10)    #全连接层得到结果
    
    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0),-1)           #flatten操作,结果为:(batch_size,32*7*7)
        output = self.out(x)
        return output

 4. 训练网络

#定义一个准确率作为评估标准
def accuracy(predictions,labels):
    pred = torch.max(predictions.data,1)[1]
    rights = pred.eq(labels.data.view_as(pred)).sum()
    return rights, len(labels)
#实例化
net = CNN()
#损失函数
criterion = nn.CrossEntropyLoss()
#优化器
optimizer = optim.SGD(net.parameters(),lr=0.01) # 定义优化器,普通的随机梯度下降算法
loss_num = []
#开始循环训练
for epoch in range(num_epochs):
    #当前epoch的结果保存下来
    train_rights = []
    for batch_idx,(data,target) in enumerate(train_loader):
        net.train()
        output = net(data)
        loss = criterion(output,target)
        loss_num.append(loss)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        right = accuracy(output,target)
        train_rights.append(right)

        if batch_idx % 100 == 0 :
            
            net.eval()
            val_rights = []

            for (data,target) in test_loader:
                output = net(data)
                right = accuracy(output,target)
                val_rights.append(right)


            #准确率计算
            train_r = (sum([tup[0] for tup in train_rights]),sum([tup[1] for tup in train_rights]))
            val_r = (sum([tup[0] for tup in val_rights]),sum([tup[1] for tup in val_rights]))
            
            print('当前epoch: {} [{}/{} ({:.0f}%)]      \t损失: {:.6f}\t训练集正确率: {:.2f}%\t测试集准确率: {:.2f}%'.format(
                epoch,batch_idx*batch_size,len(train_loader.dataset),
                100 * batch_idx / len(train_loader),
                loss.data,
                100 * train_r[0]/ train_r[1],
                100 * val_r[0] / val_r[1]
                )
            )

5.查看损失结果 

plt.figure(figsize=(10,4))
with torch.no_grad():
    plt.plot(loss_num[:])
plt.xlabel('iterion')
plt.ylabel('loss')
plt.show()

                                                                                                                                                                                                                                                                                                                                                                    

        

  • 19
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值