08 从 MLP 到 LeNet:为什么一个神经元不够?

第8讲 为什么一个神经元不够?

一个神经元已经能够接收输入、完成加权计算,并给出一个分类判断。看起来,它已经具备了最基础的"分类能力"。但只要问题稍微复杂一点,这种结构就会很快碰到明显的能力边界。

问题并不在于神经元太少,而在于:单个神经元本质上只能学出一条线性的分类边界。

如果任务本身足够简单,一条线就能把不同类别分开,那么一个神经元已经足够有效;但只要数据中的规律不再是线性的,单个神经元就会很快失去表达能力。


1. 一个神经元本质上能做什么?

把一个神经元写成最简单的形式,它做的事情其实非常直接:

z = w_1x_1 + w_2x_2 + b

然后再配合一个阈值或激活方式,把结果变成输出。

如果只从几何角度去理解,这意味着:

一个神经元本质上是在输入空间里学习一条线性边界。

  • 在二维平面里,它对应一条直线
  • 在三维空间里,它对应一个平面
  • 在更高维空间里,它对应一个超平面

因此,单个神经元擅长处理的问题通常具有共同特点:

  • 类别边界比较规整
  • 规律比较简单
  • 可以用一条线性边界描述

只要问题本身满足这些条件,一个神经元已经足够完成分类。


2. 线性可分时,一个神经元已经足够

先看一个最简单的情形:两类样本可以被一条直线清楚地分开。

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import font_manager

font_path = "..\..\\00-基础环境\simfang.ttf"  # 请确认该路径下有 simfang.ttf 文件
font_prop = font_manager.FontProperties(fname=font_path)
plt.rcParams["font.family"] = font_prop.get_name()
plt.rcParams["axes.unicode_minus"] = False  # 解决负号显示问题


class_0 = np.array([
    [0, 0],
    [1, 0],
    [0, 1],
    [1, 1]
])

class_1 = np.array([
    [3, 3],
    [4, 3],
    [3, 4],
    [4, 4]
])

plt.figure(figsize=(6, 6))
plt.scatter(class_0[:, 0], class_0[:, 1], color='tomato', s=100, label='Class 0')
plt.scatter(class_1[:, 0], class_1[:, 1], color='royalblue', s=100, label='Class 1')

# x_vals = np.linspace(-1, 5, 100)
# y_vals = x_vals
# plt.plot(x_vals, y_vals, 'k--', label='Linear Boundary')

plt.xlim(-1, 5)
plt.ylim(-1, 5)
plt.xlabel("x1")
plt.ylabel("x2")
plt.title("线性可分:一个神经元已经足够")
plt.legend()
plt.grid(alpha=0.3)
plt.show()

这个例子说明,一个神经元不是"能力太弱",而是在它适用的问题范围内,本来就已经足够有效。

真正的困难出现在:类别边界不再是一条直线的时候。


3. 圆形内外分类:为什么单个神经元难以处理这类问题?

为了把问题说得更直观,这里直接看一个非常具体的分类任务:

  • 圆内部的点是一类
  • 圆外部的点是另一类

这个规则并不复杂。因为只要看一个点离圆心的距离,就大致知道它属于哪一类:

  • 距离小,属于圆内
  • 距离大,属于圆外

从人的直觉看,这个问题并不难。

但这个例子恰好非常适合说明单个神经元的局限,因为它真正需要的边界不是直线,而是一条曲线。

先把这组数据画出来。

python 复制代码
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(42)
n_samples = 600

X = np.random.uniform(-2, 2, (n_samples, 2))
r = np.sqrt(X[:, 0] ** 2 + X[:, 1] ** 2)
y = (r > 1.0).astype(np.int64)   # 圆外为1,圆内为0

plt.figure(figsize=(6, 6))
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='tomato', s=20, label='Inner Circle (Class 0)')
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='royalblue', s=20, label='Outer Ring (Class 1)')
plt.title("圆形内外分类:原始数据分布")
plt.xlabel("x1")
plt.ylabel("x2")
plt.legend()
plt.axis("equal")
plt.grid(alpha=0.3)
plt.show()

从图上看,这个任务本身非常直观:

  • 中间的一团是一类
  • 外面的一圈是另一类

这也恰好把问题暴露得非常清楚:

如果模型只能画一条直线,那么无论怎么画,都不可能把"中间的一团"和"外面的一圈"完整分开。

更本质的限制在于:
单个神经元不是不会训练,而是它只能表示线性边界。


4. 单层线性模型在这个问题上的局限

为了把这个结论说得更明确,可以先用一个最简单的线性模型试试这个任务。

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
from sklearn.datasets import make_circles

# 生成环形数据(必须有!)
X, y = make_circles(n_samples=200, noise=0.05, factor=0.4, random_state=42)

# 训练线性模型
linear_model = LogisticRegression()
linear_model.fit(X, y)

# 构造网格,用于画决策边界
xx, yy = np.meshgrid(np.linspace(-2.5, 2.5, 300),
                     np.linspace(-2.5, 2.5, 300))
grid = np.c_[xx.ravel(), yy.ravel()]
probs = linear_model.predict_proba(grid)[:, 1].reshape(xx.shape)

plt.figure(figsize=(7, 6))
plt.contourf(xx, yy, probs, levels=50, cmap="coolwarm", alpha=0.6)

# ✅ 这里修复了语法错误!
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='tomato', s=50, label='Inner Circle (Class 0)')
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='royalblue', s=50, label='Outer Ring (Class 1)')

plt.contour(xx, yy, probs, levels=[0.5], colors='black', linewidths=2)

plt.title("单层线性模型在圆形内外分类上的决策边界")
plt.xlabel("x1")
plt.ylabel("x2")
plt.legend()
plt.axis("equal")
plt.show()

这张图会非常清楚地显示出:

单层线性模型最终学出来的,仍然只是一条近似直线的边界。它也许能把一部分样本分开,但不可能真正贴合"圆"这种结构。

这里的问题不是模型完全不会分类,而是:

它只能用错误的边界形式去逼近一个本来就不是线性的问题。


5. 多个神经元叠加后,能力为什么会发生变化?

圆形分类这个例子的重要性,不只是说明"单层线性模型学不出来",而是进一步揭示了一个更本质的事实:

多个神经元和多层结构的组合,可以开始逼近单个神经元无法表示的边界。

如果只用一个神经元,本质上只能学出一条线性边界。

但一旦引入多个神经元、隐藏层和非线性激活,模型就不再只能学一条线,而是能够把多个简单的线性变换一层层组合起来,逐步逼近更复杂的边界。

从这个角度看,多层网络的价值并不只是"层数更多",而是它让模型开始能够表示那些单个神经元无法表达的模式。圆形边界只是一个非常直观的例子。推广开来,现实中的很多问题本来就不是一个简单线性表达式能直接写清楚的,它们往往对应更复杂的曲线、分段结构,甚至更高维空间中的复杂几何形状。

因此,模型从单层走向多层,并不是为了"看起来更复杂",而是为了获得足够的表达能力,去处理这些更接近真实世界的问题。


6. 多层网络的能力从哪里开始变化?

多层网络真正带来的,不只是"层数变多",而是:

模型开始具备逐层构造更复杂表示的能力。

可以把这个过程理解成:

  • 第一层先学一些简单边界
  • 第二层再把这些简单边界组合起来
  • 后面的层继续在已有表示上构造更复杂的模式

从表达能力的角度看,关键变化不在于"更深"本身,而在于:

模型终于不再只能做一次线性切分,而是可以把多个简单变换组合起来。


7. 最少需要多少层,这个问题该怎么理解?

看到这里,一个很自然的问题是:

那到底最少需要多少层?

这个问题本身是合理的,而且值得说明一下。

对于像"圆形内外分类"这样的任务,可以明确的是:

  • 单层线性模型一定不够
  • 只要加入至少一层隐藏层,并配合非线性激活,模型就开始具备表示更复杂边界的能力

至于从理论上"最少需要多少个隐藏单元、多少层才能精确表示某一种边界",这是更细的理论问题。放在入门阶段,更重要的不是先追求严格证明,而是先看清一个本质变化:

从没有隐藏层,到至少有一层隐藏层,模型的表达能力已经发生了变化。

也就是说,这里的重点不是先回答"到底两层还是三层最优",而是先理解:

单层不够,多层开始有能力。


8. 这段圆形分类代码到底在说明什么?

如果直接看代码,很容易把注意力放到"网络有几层、每层几个神经元"这些细节上。

但这篇文章更重要的事情,是先把问题讲清楚。

整个案例其实是在做一个非常直接的对比实验:

  1. 先构造一个"边界明显不是直线"的问题
  2. 再用单层线性模型试一次
  3. 最后用一个最小 MLP 再试一次
  4. 通过决策边界图比较两者的表达能力

所以这段代码的核心目标不是追求最优结果,而是为了把下面这个问题说明白:

单层模型为什么不够,而多层模型为什么开始有能力。

也正因为如此,这里不需要一开始就把层数、隐藏层宽度、全连接维度调到"最优"。这篇文章的重点不是网络调参,而是先把核心问题讲清楚:

  • 单层为什么不够
  • 多层为什么开始有能力
  • 隐藏层和非线性为什么重要

只要这个问题先看清了,后面再去讨论更细的结构设置和隐藏层到底在学什么,就会顺很多。


9. 用一个最小 MLP 解决这个问题

下面这段完整代码,直接把"单层线性模型 vs 多层感知机 MLP"的对比放在一起。它的作用不是追求最优精度,而是把问题用图形方式讲透。

python 复制代码
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
import torch
import torch.nn as nn
import torch.optim as optim

# =========================
# 1. 生成圆形内外分类数据
# =========================
np.random.seed(42)
n_samples = 600

X = np.random.uniform(-2, 2, (n_samples, 2))
r = np.sqrt(X[:, 0] ** 2 + X[:, 1] ** 2)
y = (r > 1.0).astype(np.int64)   # 圆外为1,圆内为0

# =========================
# 2. 先画原始数据
# =========================
plt.figure(figsize=(6, 6))
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='tomato', s=20, label='Inner Circle (Class 0)')
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='royalblue', s=20, label='Outer Ring (Class 1)')
plt.title("圆形内外分类:原始数据分布")
plt.xlabel("x1")
plt.ylabel("x2")
plt.legend()
plt.axis("equal")
plt.grid(alpha=0.3)
plt.show()

# =========================
# 3. 定义画决策边界的函数
# =========================
def plot_decision_boundary(model, X, y, title, is_torch=False):
    xx, yy = np.meshgrid(np.linspace(-2.5, 2.5, 300),
                         np.linspace(-2.5, 2.5, 300))
    grid = np.c_[xx.ravel(), yy.ravel()]

    if is_torch:
        grid_tensor = torch.tensor(grid, dtype=torch.float32)
        with torch.no_grad():
            probs = model(grid_tensor).numpy().reshape(xx.shape)
    else:
        probs = model.predict_proba(grid)[:, 1].reshape(xx.shape)

    plt.figure(figsize=(7, 6))
    plt.contourf(xx, yy, probs, levels=50, cmap="coolwarm", alpha=0.6)
    plt.scatter(X[y == 0, 0], X[y == 0, 1], c='tomato', s=20, label='Inner Circle (Class 0)')
    plt.scatter(X[y == 1, 0], X[y == 1, 1], c='royalblue', s=20, label='Outer Ring (Class 1)')
    plt.contour(xx, yy, probs, levels=[0.5], colors='black', linewidths=2)

    plt.title(title)
    plt.xlabel("x1")
    plt.ylabel("x2")
    plt.legend()
    plt.axis("equal")
    plt.grid(alpha=0.3)
    plt.show()

# =========================
# 4. 单层线性模型(逻辑回归)
# =========================
linear_model = LogisticRegression()
linear_model.fit(X, y)

plot_decision_boundary(
    linear_model, X, y,
    title="单层线性模型在圆形内外分类上的决策边界"
)

# =========================
# 5. 多层感知机 MLP
# =========================
X_tensor = torch.tensor(X, dtype=torch.float32)
y_tensor = torch.tensor(y.reshape(-1, 1), dtype=torch.float32)

class SimpleMLP(nn.Module):
    def __init__(self):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(2, 16),
            nn.ReLU(),
            nn.Linear(16, 16),
            nn.ReLU(),
            nn.Linear(16, 1),
            nn.Sigmoid()
        )

    def forward(self, x):
        return self.net(x)

mlp = SimpleMLP()

criterion = nn.BCELoss()
optimizer = optim.Adam(mlp.parameters(), lr=0.01)

for epoch in range(1000):
    optimizer.zero_grad()
    outputs = mlp(X_tensor)
    loss = criterion(outputs, y_tensor)
    loss.backward()
    optimizer.step()

    if epoch % 200 == 0:
        print(f"Epoch {epoch}, Loss: {loss.item():.4f}")

plot_decision_boundary(
    mlp, X, y,
    title="多层感知机 MLP 在圆形内外分类上的决策边界",
    is_torch=True
)

祖冲之点了个赞,他说过可以用多边形逼近圆形。就把多边形看成是多个线性边界的组合。这说明,多层模型为什么开始有能力,是因为它开始可以表示更复杂的线性关系。

这个实验最值得看的不是某个具体数字,而是最后那两张图:

  • 单层模型只能给出一条线性边界
  • MLP 学出来的边界开始接近圆形

这说明,多层感知机之所以更强,不是因为它"更大",而是因为它真正开始具备了更复杂的表达能力。


10. 最容易混淆的几个点

10.1 一个神经元不够,只是因为参数太少

不完全是。

更根本的问题不是参数数量,而是单个神经元本质上只能表示线性关系。

10.2 只要多加几个神经元,就一定能解决问题

不一定。

如果结构上仍然没有形成真正的多层非线性表示,模型能力未必会有本质变化。

10.3 多层网络只是"更大"的单层网络

不是。

多层网络的关键不只是更大,而是可以形成中间表示和更复杂的组合关系。

10.4 圆形内外分类只是一个特殊例子

不是。

它的重要性恰恰在于:这个问题足够直观,能非常清楚地把"单层线性边界为什么不够、多层为什么开始有能力"这件事表现出来。


11. 总结

单个神经元能够完成最基础的分类决策,但它本质上仍然只是一个线性分类器。

这意味着,一旦问题中的规律超出了线性边界所能表达的范围,它就会遇到非常明确的能力上限。

圆形内外分类这个案例很好地说明了这一点:

  • 单层线性模型学不出圆形边界
  • 多层感知机 MLP 借助隐藏层和非线性,开始有能力逼近这种更复杂的结构

如果把全文压缩成一句话,可以概括为:

一个神经元不够,不是因为它太小,而是因为它只能学出一条线性的判断边界。

相关推荐
罗西的思考2 小时前
【OpenClaw】通过Nanobot源码学习架构---(2)外层控制逻辑
人工智能·机器学习
wdf80882 小时前
算力随行:UltraLAB便携工作站如何将多卡深度学习带入户外与现场
人工智能·深度学习·大模型推理·无人机影像
FluxMelodySun4 小时前
机器学习(二十八) 特征选择与常见的特征选择方法
人工智能·机器学习
Westward-sun.4 小时前
基于 OpenCV DNN 模块实现图像风格迁移
人工智能·神经网络·opencv·计算机视觉·dnn
Ferries4 小时前
《从前端到 Agent》系列|02:应用层-提示词工程 (Prompt Engineering)
前端·人工智能·深度学习
水中加点糖4 小时前
多模态数据标注平台LabelStudio——部署与智能标注体验
人工智能·机器学习·自动标注·数据标注·labelstudio·ai标注·标注平台
π....4 小时前
人工智能(AI) & 深度学习 毕设热门题目
人工智能·深度学习
机器学习之心6 小时前
Bayes-TCN-BiLSTM+SHAP分析,贝叶斯优化时间卷积双向长短期网络分类预测可解释性分析!Matlab代码
神经网络·tcn-bilstm·贝叶斯优化·shap分析
AI先驱体验官7 小时前
AI智能体赛道新机遇:2026机会与挑战深度解析
大数据·人工智能·深度学习·重构·aigc