本文正在参加「金石方案」

上一篇文章咱们简略介绍了 KNN、线性回归在核算机视觉中的运用,信任大家对机器学习的“从数据中学习”的思路有了必定的认识,接下来咱们切入到神经网络中去。

神经网络

神经网络简介

神经网络是深度学习算法的中心。 其名称和结构均遭到人脑的启示。

神经网络由节点层组成,包含一个输入层、一个或多个隐藏层和一个输出层。 每个节点也称为一个人工神经元,它们衔接到另一个节点,具有相关的权重和阈值。 假如任何单个节点的输出高于指定的阈值,那么该节点将被激活,并将数据发送到网络的下一层。 否则该节点不将数据传递到网络的下一层。

神经网络依托练习数据来学习和随时间推移进步本身精度,这些学习算法经过精度调优后就会成为核算机科学和人工智能领域中的强大东西,可支持咱们快速进行数据分类和分组。

神经网络的作业流程

从零速成计算机视觉(二)神经网络与卷积神经网络

每个独自的节点都进行“用输入数据、权重、阈值确认该节点的输出”这一作业,具体方法如下:

  1. 得到输入数据后,将输入数据乘对应的权重并累加。
  2. 经过激活函数传递输出,假如输出超越给定阈值(或许经过某种 check),则激活该节点,并将数据传递到网络中的下一层。
  3. 该节点的输出成为下一个节点的输入的一部分。

将数据从一层传递至下一层的这一进程可将此神经网络界说为前馈网络。

经过调整权重或阈值,可以从模型中得出不同的成果。模型会经过反向传达并运用梯度下降法调整其权重和差错,寻觅丢失函数的最小值。

卷积神经网络

之前说到的神经网络可以说是线性分类器的堆叠,只不过在中心加入非线性函数,对中心层发生的模板加权后得到终究的得分。核算机视觉中用到更多的神经网络结构是卷积神经网络。接下来咱们对卷积神经网络加以介绍。

什么是卷积神经网络

从零速成计算机视觉(二)神经网络与卷积神经网络
卷积神经网络(Convolutional Neural Network,CNN)是一种用于提取图画不同层次特征的多层神经网络,最早由Yann LeCun提出并应用在手写字体辨认中(MINST)。

卷积神经网络根本机制根据生物学上感触野,其首要思想为:只要视网膜上的特定区域(感触野)才干激活视觉神经元。

卷积神经网络首要应用于图画和视频分析任务中,比如图画分类、人脸辨认、物体辨认、图画分割等,其准确率远远超出了传统浅层神经网络。

接下来咱们紧扣“只要感触野才干激活视觉神经元”这一中心思想对卷积神经网络的算法细节进行介绍。

卷积神经网络的详细介绍

典型的卷积神经网络由输入层、卷积层、激活层、池化层、全衔接层与输出层组成。

即 INPUT-CONV-RELU-POOL-FC。

其间,卷积层、激活层与池化层一般组成多个卷积组以提取图画不同层次的特征,终究经过若干个全衔接层进行分类。

输入层

卷积神经网络可对灰度与 RGB 两类数字图画进行处理。

从零速成计算机视觉(二)神经网络与卷积神经网络

关于灰度图画,其像素取值范围为[0,255](“0”表明纯黑、“255”表明纯白、其间不同数字表明不同层次的灰色),神经网络中的输入可视为一个 MN1MN1 二维数字矩阵(M与N分别表明图画行数与列数)。

关于 RGB 图画,由于其像素色彩由红(R)、绿(G)、蓝(B)三原色的组合得到,因此在结构上由三个不同色彩重量的层次组成,神经网络的输入可视为一个 MN3MN3 三维数字矩阵。

卷积层

卷积层是构建卷积神经网络的中心层,网络中大部分的核算量都由它发生。卷积层首要用来提取不同层次的特征。

卷积层的参数是由一些可学习的滤波器(filter) 集合构成的。每个滤波器在宽度和高度上都比较小,但是深度和输入数据共同。

如下图所示,输入图画尺度为 3232332323,卷积核尺度为 55325532(55为由长度与宽度决定的感触野尺度、3为与输入图画通道或色彩重量层次、2为卷积核数量),输入图画经过卷积运算后将得到 222828128281 的特征图。

从零速成计算机视觉(二)神经网络与卷积神经网络

这个进程是经过卷积操作完成的。卷积就是对图画的不同部分矩阵和卷积核矩阵各个方位的元素相乘再相加运算。

如下图所示,假定图画为二维 3434 的矩阵,而卷积核是一个 2222 的矩阵。假如按逐像素(每次移动一个像素)卷积规则:

从零速成计算机视觉(二)神经网络与卷积神经网络

则首先对输入图左上角 2222 部分矩阵和卷积核矩阵进行卷积(即各个方位的元素相乘再相加)以得到输出矩阵 SSS0,0S_{0,0} 元素,其值为 aw+bx+ey+fza\times w+b\times x+e\times y+f\times z;然后卷积核向右平移一个像素以对(b,c,f,g)四个元素构成的矩阵进行卷积运算,从而可得到输出矩阵 SSS0,1S_{0,1} 元素值;同理可得出矩阵 SSS0,2S_{0,2}S1,0S_{1,0}S1,1S_{1,1}S1,2S_{1,2} 的值。终究矩阵 SS 即为得到的输出矩阵。

卷积经过以上方法对图画特征进行提取,不同的卷积核可以提取不同的图画特征,卷积后的输出矩阵为“特征图画”。

不同类型的卷积核对图画进行卷积后,可提取图画边际、棱角、含糊、杰出等图画特征的才能。不同层次的卷积层可提取输入图画不同层次的特征;低层卷积层倾向于提取图画底层、部分特征(如物体边际),而高层卷积层则可提取包含更丰厚语义信息的大局特征(如物体结构)。

激活层

卷积层首要对图画进行线性运算,关于非线性运算问题,一般需要使用激活层对卷积层的输出进行非线性映射。激活函数可以引进非线性因素,首要作用是供给神经网络的非线性建模才能。常用的激活函数如下图所示。

从零速成计算机视觉(二)神经网络与卷积神经网络

池化层

“池化”,即“下采样”,其意图在于:

  1. 对特征图进行紧缩处理以下降核算复杂度或减小模型的规划。
  2. 杰出首要特征或进步特征的鲁棒性。
  3. 在必定程度上控制过拟合。

从零速成计算机视觉(二)神经网络与卷积神经网络

池化操作包含平均池化与最大池化两种;如图所示,最大池化(Max Pooling)操作在特征图中求取 2222 区域内值的最大者作为原 2222 区域内值的表达,终究可得到右图所示的成果(步长为 22)。平均池化与之相似顾名思义。当然,窗口巨细是人工设置的,除此之外,池化层没有任何参数需要设置或练习。

全衔接层

全衔接层将最后的特征输出映射到线性可分的空间以完成分类或回归任务。即将获得的卷积(包含激活与池化等处理)成果转换为向量输入至分类器(如 Softmax 分类器)进行分类。

代码完成

导包

import torch
from torch import nn, optim
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision import datasets, transforms 
import torch.nn.functional as F
import matplotlib.pyplot as plt

生成数据

batch_size = 64
#预处理设置
data_tf = transforms.Compose(
    [transforms.ToTensor(),
     transforms.Normalize([0.5], [0.5])])
# 生成数据
train_dataset = datasets.MNIST(root='./data', train=True, transform=data_tf, download=True)
test_dataset = datasets.MNIST(root='./data', train=False, transform=data_tf)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False)

界说卷积神经网络

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5, 1) # 28+1-5 = 24
        self.conv2 = nn.Conv2d(20, 50, 5, 1)
        self.fc1 = nn.Linear(4*4*50, 500)
        self.fc2 = nn.Linear(500, 10)
	def forward(self, x):
        # x: 1 * 28 * 28
        x = F.relu(self.conv1(x))  # 24 * 24 * 20
        x = F.max_pool2d(x, 2, 2)  # 12 * 12 * 20
        x = F.relu(self.conv2(x))  # 8 * 8 * 50
        x = F.max_pool2d(x, 2, 2)  # 4 * 4 * 50
        x = x.view(-1, 4*4*50) 
        x = F.relu(self.fc1(x))
        x = self.fc2(x)
        return x
# 实例化模型 
net = CNN()

练习

# 界说丢失函数
Loss = nn.CrossEntropyLoss()
# 设置优化器
Opt = optim.SGD(net.parameters(), lr=0.02)
# 练习模型
T = 10
for epoch in range(T):
    Loss_Sum = 0.0 #累积练习差错
    Acc_Sum = 0.0 #累积练习精度
    for i, data in enumerate(train_loader, 1):
        img, label = data
        img = Variable(img)
        label = Variable(label)
        label_pred = net(img) #前向传达
        L = Loss(label_pred, label) #核算差错
        Loss_Sum  += L.data.numpy() #差错累积
        _, label_opt = torch.max(label_pred, 1) #求取预测概率对应的类别
        Acc_Sum += (label_opt == label).float().mean() #累积精度
        Opt.zero_grad() #梯度清零
        L.backward() #反向传达
        Opt.step() #更新参数
    #显现差错与精度变化
    if (epoch==0) | ((epoch+1) % 2 == 0):
        print('Epoch:[{}/{}], Loss: {:.4f}, Accuracy: {:.4f}'.format(epoch+1, T, Loss_Sum / i, Acc_Sum / i))

测试

net.eval()
Acc_Sum = 0.0 #累积精度
for i, data in enumerate(test_loader, 1):
    img, label = data
    img = Variable(img)
    label_pred = net(img)
    _, label_opt = torch.max(label_pred, 1)
    Acc_Sum += (label_opt == label).float().mean()  
print('Accuracy: {:.4f}'.format(Acc_Sum / i))