CNN--卷积神经网络的学习

简述

卷积神经网络是一种经典的前馈神经网络,主要受生物学中的感受野的概念提出。感受野在生物体中广泛存在,一个感受野连接多个感受器细胞,这些感受器细胞共同决定了感受野是否兴奋。通过感受野的机制,生物体传入的信号数量会大大降低,同时也能很好的对输入信号进行特征提取。

基本概念

感受器与感受野

  • 感受器
    感受器即卷积核,在图像处理中也称为算子。一个卷积核包含与输入图像通道数目相同的过滤器,一个卷积核产生一个特征图。
  • 感受野
    特征图上的某个点能看到的输入图像的区域,即输入图像中每次与感受器进行运算的区域。
  • 特征图
    输入图像与卷积核运算的结果称为特征分布图,简称特征图。
    卷积核保留了原图的局部特征信息,保留了局部特征的强弱和位置信息,如图像处理中利用算子对边,点进行提取,边点就是图像的部分特征。
  • 卷积
    利用特征(卷积核)进行局部特征提取,并得到特征分布图(特征图)的过程,使得图像特征具有了一定的平移不变性。多个通道的特征图通过1*1卷积可以实现通道维度的改变,同时也实现了多个通道信息的汇聚。
  • 池化
    在允许损失少量信息的情况下,对特征图进行下采样。使得图像特征获得了一定的平移不变性;使得特征图的维度减小。
    在这里插入图片描述

卷积运算

卷积核数=特征图数,与通道数无关,多通道最终要进行求和合成一个特征图。

单通单核卷积

输入1通道,输出1通道
在这里插入图片描述

单通道多核卷积

输入1通道,输出2通道
在这里插入图片描述

多通道单核卷积

输入3通道,输出1通道
在这里插入图片描述

多通道多核卷积

输入3通道,输出2通道

边界与步长

VALID边界

只利用有效数据,不进行填补。
在这里插入图片描述

SAME边界

需要进行边界填充,需注意代码中padding=1指四周填充1像素。
填充不允许只在一端填充,不允许在中间插入填充,只允许在两端都填充。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

实例代码

使用Fashion-mnist数据集进行训练,网络结构与LeNet一致,但在6通道卷积为16特征图时,进行了完全相连,而不是论文中的部分相连。
在这里插入图片描述

import torch
from torch import nn
import torch.nn.functional as F
import numpy as np
from sklearn.metrics import accuracy_score
from torchvision import datasets
from torch.utils.data import TensorDataset,DataLoader
from torchvision import transforms as T 

class CNN(nn.Module):
    def __init__(self):
        super().__init__()
        #卷积:输入1,6核,输出6特征图
        self.conv1 = nn.Conv2d(1,6,(5,5),stride=1,padding=2)
        #池化:平均值池化
        self.pool1 = nn.AvgPool2d((2,2),stride=2)
        #卷积:输入6,16核,输出16特征图
        self.conv2 =  nn.Conv2d(6,16,(5,5),stride=1)
        #池化:平均值池化
        self.pool2 = nn.AvgPool2d((2,2),stride=2)
        #全连接:占成一维,输出120
        self.linear1 = nn.Linear(16*5*5,120)
        #全连接
        self.linear2= nn.Linear(120,84)
        self.linear3 = nn.Linear(84,10)

    def forward(self,input):
        output =F.relu(self.conv1(input))

        output = self.pool1(output)

        output = F.relu(self.conv2(output))

        output = self.pool2(output)

        output = F.relu(self.linear1(output.reshape((output.shape[0],-1))))

        output = F.relu(self.linear2(output))
        
        output = self.linear3(output)
        
        return output
    
    def fit(self,train,test):
        opt = torch.optim.SGD(self.parameters(), lr=0.01)#参数优化器
#         train_ds =  TensorDataset(x,y)  #优化x,y同步
        train_dl = DataLoader(train,batch_size = 100,shuffle = True) #优化小批量梯度,每次切等大小
        test_dl = DataLoader(test,batch_size = len(test),shuffle = True)
        epoch = 100
        acc = 0
        
        for i in range(epoch):
            sum_loss = 0
            for x,y in train_dl:

                predic_y = self(x)
                
                loss =torch.nn.functional.cross_entropy(predic_y,y)#分类任务,交叉熵
                loss.backward()
                #更新参数
                opt.step()
                opt.zero_grad()
                sum_loss+=loss
                
            print(sum_loss)
            for m,n in test_dl:
                 acc = accuracy_score(torch.argmax(self(m),axis = 1),n)
                    
            print('epoch%d:acc%.3f'%(i,acc))
                  
        return acc
    
    def predict(self,x):
        return torch.argmax(self(x),axis = 1)

#格式化变换
compose = T.Compose([
T.ToTensor(),
T.Normalize(mean=(0.5,),std =(0.5,))
])
#导入数据
train = datasets.FashionMNIST(root='./',download=False,transform = compose)               
test = datasets.FashionMNIST(root='./',download=False,transform = compose,train = False)
cnn = CNN()
cnn.fit(train,test)

# import matplotlib.pyplot as plt

# for image,label in test:
#     plt.title(label)
#     plt.imshow(image,cmap= 'gray')
#     plt.show()
                  
#部分结果
epoch95:acc0.888
tensor(119.9276, grad_fn=<AddBackward0>)
epoch96:acc0.895
tensor(119.1850, grad_fn=<AddBackward0>)
epoch97:acc0.891
tensor(119.0791, grad_fn=<AddBackward0>)
epoch98:acc0.891
tensor(118.1900, grad_fn=<AddBackward0>)
epoch99:acc0.889
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值