30u30 中文导读 / 30 天目录 / 第 28 天

第 28 天 · 从零手写卷积网络,算清每一个维度

第 5 单元CS231n: Convolutional Neural Networks for Visual RecognitionFei-Fei Li, Andrej Karpathy, Justin Johnson et al.课程(Stanford University) · 2015
这是导读,不是翻译。先用 10 分钟拿到这篇论文的思想地图,再去读 原论文 →,去原仓库的 28_CS231n/ 目录 → 动手写代码。
给孩子讲:这一天有 10 岁孩子能听懂的讲义,带猜字游戏和动手活动,可打印。打开儿童讲义 → · PDF 简体 · PDF 繁體

一句话

CS231n 是斯坦福 2015 年开设的深度学习视觉课,由李飞飞和 Karpathy 首批主讲。它从 k 近邻和线性分类器讲起,一直讲到卷积网络、训练技巧和经典架构,并要求学生用 numpy 手写前向传播和反向传播。

论文讲了什么

CS231n 不是论文,而是一门课程,包括讲义、课件、录像和 3 次编程作业。课程目标是让学生能从零实现、调试和训练卷积神经网络,而不只是会调用框架。本日的核心阅读材料是公开讲义 cs231n.github.io。

讲义分为 3 个模块:

卷积层一节最值得精读。它解释了两个关键设计:

讲义用 AlexNet 第一层算了一笔账。输入是 227×227×3,用 96 个 11×11 的滤波器,步长 4,输出 55×55×96,共 290,400 个神经元。每个神经元有 363 个权重和 1 个偏置。如果不共享参数,总参数超过 1 亿。共享之后,只剩 34,944 个参数。

输出尺寸由一个公式决定:(W − F + 2P) / S + 1。W 是输入宽度,F 是滤波器大小,P 是填充,S 是步长。结果不是整数时,这组超参数就不合法。

讲义还介绍了 im2col 技巧:把每个感受野拉成矩阵的一列,卷积就变成一次大矩阵乘法,可以调用高度优化的 BLAS 库。代价是内存,因为重叠区域的像素被复制了多次。

架构案例部分逐层计算了 VGGNet:总共约 1.38 亿参数,一张图前向传播约需 93 MB 内存。大部分内存花在前几层卷积,大部分参数集中在第一个全连接层,约 1.03 亿个。

3 次作业把这些知识落到代码:

关键概念

卷积层(Convolutional layer)
用一组小滤波器在输入上滑动,每个位置计算点积,得到特征图。局部连接和参数共享让它的参数量远少于全连接层。
感受野(Receptive field)
一个神经元在输入图像上能“看到”的区域。叠 3 层 3×3 卷积,感受野等于 1 层 7×7 卷积,但参数更少,非线性更多。
池化层(Pooling layer)
在小窗口内取最大值来缩小空间尺寸。最常用 2×2 窗口、步长 2,丢弃 75% 的激活值。池化层没有可学习参数。
im2col
把每个感受野展开成矩阵的一列,卷积就变成矩阵乘法。它运算速度快,但重叠像素被复制多次,内存占用会成倍增加。
批归一化(Batch normalization)
对每层的激活按小批量做标准化,再学习一个缩放系数和一个偏移量。它让网络对初始化不敏感,并允许使用更大的学习率。
迁移学习(Transfer learning)
先在 ImageNet 这类大数据集上预训练,再把网络当作特征提取器,或在小数据集上微调。新数据越少、越接近原数据,需要重新训练的层越少。

历史位置:为什么值得读

2012 年 AlexNet(第 8 天)赢得 ImageNet 竞赛,深度学习在视觉领域爆发,但当时几乎没有系统的教材。CS231n 在 2015 年冬季学期首次开课,由李飞飞和她的博士生 Karpathy 主讲,2016 年 Justin Johnson 加入。课程录像和讲义在网上广泛传播,被全世界的自学者使用。

这门课的影响来自“手写一切”的教学方式。学生要用 numpy 写出每一层的前向传播和反向传播,再用数值梯度检查结果。Karpathy 的观点是:反向传播是一个会“泄漏”的抽象,不理解它,就无法调试梯度消失、ReLU 死亡这类问题。这种风格后来延续到他的 micrograd 项目和 “Neural Networks: Zero to Hero” 视频系列。

在清单里,本课程把第 8–12 天串成一个整体。AlexNet(第 8 天)和 ResNet(第 9–10 天)是讲义里的架构案例。扩张卷积(第 11 天)和 dropout(第 12 天)在讲义里都有对应小节。读完本课程,再回看这几篇论文,会更清楚它们各自改进了哪一环。

学前准备

在原仓库怎么学

  1. README.md:看本日的内容安排和文件清单。
  2. setup.py:运行它,检查依赖是否可用。
  3. implementation.py:按顺序读。先读 conv_forward_naive,再读 im2col 和 conv_forward_im2col,然后读 pool_forward、relu、fc_forward、softmax 和 cross_entropy_loss。最后读 SimpleCNN 类和 count_conv_params。
  4. data/README.md:了解本日使用的 CIFAR-10 数据集。
  5. train_minimal.py:用 SGD 在 CIFAR-10 上训练 SimpleCNN。首次运行会自动下载数据集。
  6. visualization.py:画第一层滤波器、各层激活图和空间尺寸的逐层变化。
  7. notebook.ipynb:在笔记本里逐步运行上面的流程。
  8. exercises/:做 5 个练习,依次是嵌套循环版卷积前向、最大池化的前向和反向、计算各层输出尺寸、统计网络参数量、特征可视化。答案在 exercises/solutions/。

做完仓库练习后,建议去 cs231n.github.io 完成官方作业 2 的卷积网络部分。官方作业要求写反向传播并做梯度检查,覆盖面更完整。

今天再看

CS231n 的方法论仍然有效,部分技术内容已经过时。

容易卡住的地方

延伸阅读