🧠 第五章 深度学习算法
📄 一句话概括

同心圆两类数据,线性模型测试集 0.378——基本等于瞎猜; 加一层 8 个 tanh 神经元,测试集跳到 0.967,参数量只从 2 涨到 33。

📝 本节和前面几节的关系

上一章讲的机器学习算法都要人先想好特征。这一章讲深度学习,核心区别只有一条:特征也让它自己学。

一、「深」指的是层数,不是参数量

深度学习的「深」是指网络里有不止一层非线性变换,不是参数多。 Demo 的对比很干脆:线性模型 2 个参数,两层网络 33 个参数。参数量差 16 倍,但成绩差得更多。 关键不在参数,在中间那层 tanh。 线性模型只能画一条直线(高维叫超平面),而两类数据是套在一起的同心圆,一条直线怎么摆都分不开。 中间那 8 个神经元做了一件事:把平面「掰弯」。掰弯之后,原来套着的两圈就变成能切开的两块。

二、实测:0.378 对 0.967

数据是 300 个点,内圈 171 个、外圈 129 个,内圈半径约 0.45、外圈从 0.55 到 1.0,中间只隔 0.1。 线性模型:训练集 0.405、测试集 0.378。比瞎猜(0.5)还低——因为它找到的那条线方向完全反了。 两层网络:训练集 0.986、测试集 0.967。参数量 33 个,训练 1500 轮。 注意训练集和测试集只差 0.019,说明没有过拟合。33 个参数对 300 个样本,这个比例是安全的。

三、损失怎么下来的

训练过程打了 11 个点:第 0 轮损失 0.6912,第 150 轮 0.6350,第 300 轮 0.4459, 第 600 轮 0.1616,第 900 轮 0.1064,第 1499 轮 0.0682。 曲线不是一条直线往下,而是「先慢、中间快、后面又慢」——前 150 轮几乎没动,那是在调整方向; 300 到 600 轮掉得最快;后面是精修。 这种形状在深度学习里非常典型。看到「前几百轮损失不动」不要急着调参,很可能只是还没找到方向。

四、什么时候该上深度学习

不是所有问题都值得上。判断标准有三条: 1. 规律说不清。同心圆这种还好,人脸、语音、自然语言,人根本写不出规则。 2. 数据够多。33 个参数的玩具网络要 300 个样本,真实网络几千万参数就要几十万条。 3. 有算力。这一节 1500 轮跑了几十毫秒,是因为网络只有 33 个参数。 三条缺一条,传统方法往往更划算。 上一章那个「手工特征 + 逻辑回归」在 20 条样本时就是 1.000——知识塞进去,比让机器学便宜得多。

五、动手 Demo:同心圆:一条直线分不开,两层网络能分开

生成 300 个同心圆分布的点;先用最小二乘拟合一个线性分类器; 再手写一个 2→8→1 的两层网络(tanh 激活、手算反向传播、1500 轮梯度下降); 对比两者的训练集与测试集准确率、参数量,并打出损失下降过程。

inner = r < 0.45
rad = np.where(inner, 0.45 * np.sqrt(r / 0.45),
                0.55 + 0.45 * (r - 0.45) / 0.55)
X = np.column_stack([rad * np.cos(ang), rad * np.sin(ang)])

h = np.tanh(X @ W1 + b1)          # 中间层:把平面掰弯
p = H.sigmoid(h @ W2 + b2)

g = (p - yy) / len(X)             # 反向传播第一步
gh = (g @ W2.T) * (1 - h ** 2)    # tanh 的导数
W1 -= lr * (X.T @ gh)

实跑输出:

--------------------------------------------------------------------
同心圆:一条直线分不开,两层网络能分开
--------------------------------------------------------------------
  数据                     同心圆两类,300 个点(内圈 171/外圈 129)
  两层网络结构             2 → 8 → 1,tanh 激活,1500 轮

  模型                 训练集   测试集   参数量
  --------------------------------------------
  线性(一个超平面)    0.405    0.378        2
  两层网络              0.986    0.967       33

  训练损失下降过程:
    第    0 轮   0.6912
    第  150 轮   0.6350
    第  300 轮   0.4459
    第  450 轮   0.2424
    第  600 轮   0.1616
    第  750 轮   0.1264
    第  900 轮   0.1064
    第 1050 轮   0.0929
    第 1200 轮   0.0827
    第 1350 轮   0.0747
    第 1499 轮   0.0682

  线性模型错在哪           它只会画一条直线,而两类是套在一起的
  外圈内圈半径             约 0.55 与 0.45,中间只隔 0.1

  「深」不是堆参数,是多了一层【非线性变换】。
  中间那 8 个 tanh 神经元把平面掰弯了,所以能套住内圈。
  这就是深度学习的最小理由——表达力,不是算力。

参数量那一列值得记:线性 2 个,两层 33 个(2×8+8+8+1)。 深度学习的第一印象常是「参数巨多」,但这个例子里 33 个就够了。 准确率对比:线性 0.405 / 0.378,两层 0.986 / 0.967。 线性那个比瞎猜还低,因为它找到的线方向是反的。 损失那一列从 0.6912 降到 0.0682,中间 300 到 600 轮掉得最快。 前 150 轮几乎没动,这在真实训练里很常见。 注意这个 Demo 里的反向传播是手写的,包括 tanh 的导数 1 - h²。 写错这一项,损失照样会降,只是降不到最低——所以下一篇专门做一次梯度检验。

30 秒实验

  1. 把中间层从 8 个神经元改成 2 个,看还能不能分开同心圆。
  2. 把激活函数从 tanh 换成 relu,重跑,看损失曲线形状变不变。
  3. 想一想:为什么「参数量少」不代表「模型简单」?

常见误区

  1. 「深度就是参数多」——本例 33 个参数就解决了线性模型解决不了的问题。
  2. 「层数越多越好」——每多一层,需要的数据和算力都跟着涨。
  3. 「损失不降就是学不动」——前几百轮不动很常见,是在找方向。
自测三问(点开对答案) 1. 「深」指的是什么? —— 指网络里有不止一层非线性变换,不是指参数数量。 2. 为什么线性模型在这个任务上比瞎猜还差? —— 它只能画一条直线,而两类是套着的;找到的那条线方向正好反了。 3. 中间那层 tanh 到底做了什么? —— 把输入空间掰弯,让原本套在一起的两类变得可分。

深度学习跟机器学习到底差在哪?下一节用同一批数据把两条路各跑一遍。

相关笔记