记录一下
编者按:最近小编在搜集CNN卷积计算方面的资料,希望能出一份清晰明了的图文列表,但即便是在CNN介绍已经泛滥的今天,一篇好的、简单易懂的博客文章都是那么稀缺。今天,小编就先编译加州大学洛杉矶分校学生Adit Deshpande的几篇入门文章,希望能给新手读者带来帮助。
简介
单从字面上看,卷积神经网络这个词听起来就像是生物学和数学的诡异组合,里面可能还掺了一点计算机科学的意味,但这种神经网络一直在为计算机视觉领域默默贡献着最具影响力的创新。2012年是神经网络蓬勃发展的第一年,Alex Krizhevsky利用它们在当年的ImageNet竞赛中赢得了胜利,把分类错误率从原来的26%降低到了15%,这在当时简直是惊天之举。
从那之后,许多公司开始把深度学习纳入自家的核心产品中:Facebook把神经网络用于自动标记算法,Google把神经网络用于图像搜索,亚马逊把它们用于商品推荐,Pinterest把它们用于主页的个性化,而Instagram则开始用神经网络改进搜索架构。
而在这些神经网络中,应用最为广泛的就是今天我们要聊的CNN。以图像处理为例,我们来看看CNN是怎么帮助进行图像分类的。
输入和输出
图像分类指的是输入一张图像后,神经网络输出一个关于这个图像的类,或是图像属于某类的概率的任务。对于人类而言,这是我们从出生那一刻起就开始不断学习的技能之一,而且随着年龄的增长,人们处理这种任务会越来越轻松自然。
无需二次思考,我们就能快速无缝识别身处的环境和周围的所有物体。当看到一幅图或是观察周围环境时,我们几乎是下意识地调用以往学习的所有知识,为场景中的各个对象一一打上标签。
我们看到的 vs. 计算机看到的
但计算机不同。我们把图像输入计算机后,它“看”到的其实是一组像素值。这些像素值的数量会根据图像的大小和分辨率发生改变,如果输入图像是一张JPG格式的彩色图像,它的像素为480×480,那么计算机得到的数组就是480×480×3(这里3表示RGB值)。
这个数组里的每一个值都介于0—225之间,描述了对应像素的强度。虽然这些值对分类任务来说毫无意义,但它们是计算机可以用的唯一输入。这就带出了另一个更直白的图像分类任务描述:它其实是把像素值数组作为输入,然后输出图像属于某一类的具体概率,如80%(猫)、15%(狗)、5%(鸟)。
我们想让计算机做什么
既然知道了理想的输入和输出,那我们面临的下一个问题就是如何让计算机解决这个任务。我们希望它能区分所有图像,然后找出狗之所以是狗、猫之所以是猫的独特特征。这是人类的本能反应。当我们看到包含狗的图像时,如果图像里出现了一些明确的识别特征,如狗爪子和四条小短腿,我们可以迅速将其归类。
同样的,计算机分辨猫狗的做法是观察边缘、曲线等低层次特征,然后把这些放进一系列卷积层中进一步提取更多抽象概念。当然,这只是CNN进行图像分类的一般概述,在下一节中我们会具体说明。
在开始正题前,我们先来探讨一下“卷积神经网络”这个词。当你第一次接触这个术语时,你会不会觉得这应该是神经科学或生物学方面的东西?其实这种感觉是正确的,CNN是生物学家对动物的视觉研究成果的一个衍生物。
视觉皮层中存在一块对视野特定区域尤为敏感的细胞。1962年,Hubel和Wiesel对视觉神经细胞做了一个实验,实验表结果明,只有在存在特定方向边缘的情况下,大脑中的一些神经细胞个体才会响应。他们发现所有这些神经细胞都位于一个柱状结构中,而且能产生视觉感知。这种在特定任务的系统内部寻找特定组件的思想正是如今许多计算机任务的核心,它也是CNN背后的基础。
让我们回到CNN,简而言之,它的一般流程就是:输入图像——卷积层、非线性层、池化层(下采样)、完全连接层——输出分类/概率。那么这些层分别都做了什么呢?
第一层 - 数学视角
CNN的第一层是一个卷积层。我会假装你还记得神经网络的输入和输出分别是什么,所以在这里我们假设输入图像是一张像素为32×32的彩色JPG,相应的,CNN的输入就是一个32×32×3的像素值数组。那么作为第一层的卷积层究竟有什么用?如下图所示,我们可以把卷积层想象成一个发光的手电筒,它从左上角开始检查,光照范围是5×5。现在,想象一下用手电筒一块块检查完所有区域。
在机器学习术语中,这个手电筒是filter(neuron/kernel),每次照亮的这块5×5的区域是receptive field(感受野)。filter也是一个数组(权重/参数),而且深度必须和输入图像深度一致,这样才能确保计算。在我们的例子中,filter的具体尺寸就是5×5×3。
随着手电筒从左上角开始逐渐照亮周围区域,图像正在卷积,这时filter的数组会与原图像像素值数组相乘(计算点积),在我们的例子中,它需要进行75次乘法运算,然后把这些乘积相加得到一个值。检查完第一块5×5后,让我们把手电筒往右挪一个像素继续计算点积,之后继续往右挪一个像素,以此类推。
已知原输入是32×32×3,filter尺寸5×5×3,当手电筒扫完整片区域后,最后我们在隐藏层获得的是一个28×28×1的数组(窗口逐格挪动,边界少2;3个颜色通道合并成1个)。它也被称为activation map(加激活函数)或feature map。
注:如果这里我们用了两个5×5×3的filter,那最后的映射结果会是28×28×2。filter越多,空间维度保留地越好。
第一层 - 高层次的视角
知道了具体的数学计算步骤后,我们似乎还是不清楚卷积层的作用,所以这里我们从高层次的视角再看一遍。
每个filter都可以被看作是特征标识符( feature identifiers),这里的特征指的是直线边缘、曲线、黑白等,它们是每个图像的都具备的最简单的特征。假设我们有一个7×7×3的能检测曲线的filter,它会给带有曲线像素结构的区域更高数值。(请忽略filter的深度,只把它看成一个数组)
上图就是这个filter的可视化,它在曲线区域赋予了更高的权重,因此当图像感受野和它相乘时,相应区域的值会很高。
假设输入图像是一只小老鼠的简笔画。当filter从左上角开始卷积时,窗口先接触到老鼠尾部。请记住一点,我们必须计算filter与图像原始像素数组和乘积。
这个圆润的曲线和filter的理想曲线形状相似,相乘后,它们产生了一个很大的值。
但是,如果这时我们把窗口移到老鼠头部,输出结果就很差了。我们要注意一点,就是filter的输出是个activation map(必定要ReLu一下),所以在这个只包含一个filter的简单示例中,第一个卷积层在图像左上角的区域得到了高值,而对右上角不会有激活反应。这就起到了“过滤”的效果。
当然这只是一个filter,一个只能分辨向右弯曲的曲线的filter,在真实实践中,我们可以设置大量不同的filter来获得更全面的activation map,如检测直线的、色彩的。
注:这里的曲线、直线、色彩都是假设,事实上我们并不清楚CNN捕捉的特征是什么,我们只能从数据中看出它有没有得到新特征,切勿认为计算机看到的就等同于人眼看到的。
CS 231N课程
越来越深的网络
现在在一些经典CNN架构中,卷积层之间偶尔也会出现一些其他层,感兴趣的读者可以去了解一下这些层分别是什么,或者分别有什么作用,但总的来说,它们的出现都是为了增强神经网络的稳定性并控制过拟合。从某种角度上说,CNN一般长这样:
常规的CNN包含两个卷积层就够了,一些更高级的可能会存在多个卷积层的情况。就上图而言,最后一个完全连接层是非常重要的,但我们把它放到下一节再介绍,先聊聊之前的各个步骤。把图像输入神经网络后,第一个卷积层输出的是activation map,这时网络提取到了图像中的一些低层次特征,就像人类眼中的边缘和曲线。
用ReLu激活后,CNN把activation map输入第二个卷积层,在这里,filter过滤的就是activation map中的特征,这是一个从低层次特征中提取高层次特征的过程,虽然我们不知道计算机看到了什么,但如果拿人类学习来类比,这一步可以被理解为从之前看到的边缘、曲线中找出能组成半圆、正方形的线条组合。
卷积层越多,我们能提取到的高层次特征就越多,神经网络对像素空间就越敏感。反过来看,这时网络复杂度也高了,容易产生过拟合。
全连接层
有了高层次特征,现在我们就能品尝CNN的精华——全连接层了。无论之前是卷积层的输出还是ReLu、池化层的输出,全连接层基本只接受一个输入,并输出一个N维向量,其中N是必须从中选择的分类数。如果你想要分类手写数字,这时N就是10,因为有10个数字。
这个N维向量中的每个数字代表属于某个类别的概率。例如,如果全连接层的输出是[0 .1 .1 .75 0 0 0 0 .05],那么图像是1的概率就是10%,图像是2概率是10%,图像是3的概率是75%,图像是9的概率则是5%(注意:还有其他方法可以表示输出,这里只展示softmax方法)。
简而言之,全连接层的作用就是观察前一层的输出(一般是包含高层次特征的activation map),然后确定哪些特征与特定类最相关。以人类类比,如果要辨别图像里的是不是狗,我们会注意里面有没有爪子、四肢;如果要辨别是不是鸟,翅膀和喙就特别重要。全连接层会赋予这些相关性更强的特征更多权重,以便当我们计算权重和上一层之间的乘积时,我们可以得到图像属于不同类别的正确概率。
训练
最后就到了CNN最重要的部分——训练了。在阅读前文时,我们可能有诸多疑惑:filter是怎么知道自己要找哪些低层次特征的?全连接层又是怎么筛选activation map的?计算机能自动选取filter中的权重吗?很显然,这一切都是由经典的反向传播来实现的。
在我们刚出生的时候,一切都是新的,我们不知道什么是狗,也不知道什么是鸟。同样的,当一个CNN被刚写出来的时候,它的世界也才刚起步,所有数值都是随机选取的,filter不知道自己要筛选什么特征,全连接层也无法在activation map里放大有效信息。而随着年龄的增长,我们的父母和老师逐渐向我们展示了这个多彩的世界,以及和它紧密相关的诸多标签。训练就是CNN学习的过程,通过查看数据集中成千上万的图片,神经网络也能慢慢从中捕捉到特征,并学会正确分类。
反向传播由4个不同步骤组成:正向传递、损失函数、反向传递和权重更新。
正向传递时,我们输入一张图像,一个尺寸为32×32×3的像素值数组,然后将其传递给整个网络。在我们的第一个训练示例中,由于所有权重/filter值都是随机初始化的,因此输出结果可能类似[.1 .1 .1 .1 .1 .1 .1 .1 .1],它在分类上“不偏不倚”。
损失函数开启了“反向”的第一步。当网络现有权重无法提取低层次特征时,这就意味着它没法得出合理的分类结果。但是记住一点,我们用的是训练数据,它包含图像和标签两种信息,这就意味着我们能用损失函数计算预测标签和真实标签的差异,差异越小,CNN预测正确的可能性就越大,性能也越好。损失函数有很多,但其中最常用的MSE(均方误差):
既然目的是把损失值降到最低,那这就成了一个优化问题——找出对输出影响最大的输入,也就是dL / dW,其中W是特定层的权重。
现在,我们要做的是通过网络进行反向传递,确定哪些权重对损失影响最大,并找到调整它们的方法从而减少损失。一旦我们计算出这个导数,我们就会进入最后一步,权重更新。
学习率(learning rate)是一个可以自定义调整的超参数,它影响着着CNN的收敛速度。如果学习率过大,权重更新的幅度就很大,这时CNN能快速收敛,但它也带来一个问题,就是权重的精度不够,无法得出最优解。
正向传递、损失函数、反向传递和权重更新的过程构成一轮训练迭代。CNN会对参与训练的每组图像(batch)进行进行固定次数的迭代。一旦你完成了最后一个训练样本的参数更新,这时网络的性能更好了,各层的权值也终于调整正确了。