一、第一层卷积:学边缘
假设输入一张 28×28 灰度图(比如数字 5) 。
less
model.add(tf.layers.conv2d({
inputShape: [28, 28, 1],
filters: 32,
kernelSize: 3,
activation: 'relu'
}));
-
数据形状变化:
- 输入
[28, 28, 1]
- 输出
[26, 26, 32]
- 输入
-
含义:
- 卷积核像小眼睛在图像上扫,学习到"横线、竖线、斜线"。
- 32 个 filters = 32 种不同方向的边缘。
👉 类比:
就像小孩第一次看图画时,能分辨出哪里是"黑线"和"白底"。
二、第二层卷积:学纹理
less
model.add(tf.layers.conv2d({
filters: 64,
kernelSize: 3,
activation: 'relu'
}));
-
数据形状变化:
- 输入
[26, 26, 32]
- 输出
[24, 24, 64]
- 输入
-
含义:
- 组合前一层的线条 → 学到"曲线、角、网格纹理"。
- 64 种 filters = 更复杂的图案。
👉 类比:
像小孩第二次看画时,能分辨"这是弯弯的线条","这块像个三角形"。
三、第三层卷积:学局部物体
less
model.add(tf.layers.conv2d({
filters: 128,
kernelSize: 3,
activation: 'relu'
}));
-
数据形状变化:
- 输入
[24, 24, 64]
- 输出
[22, 22, 128]
- 输入
-
含义:
- 把纹理进一步组合成局部结构,比如:圆圈、半个数字形状。
- 128 种 filters = 更多局部特征检测器。
👉 类比:
小孩这时可以认出:"这个弯曲+竖线,像数字 5 的结构。"
四、Flatten:摊平特征
csharp
model.add(tf.layers.flatten());
-
数据形状变化:
- 输入
[22, 22, 128]
- 输出
[22*22*128] = [61952]
- 输入
-
含义:
- 把二维"特征图"变成一维向量。
- 相当于把"图像上的所有小块特征"变成"一个长长的特征列表"。
👉 类比:
就像把"拼图"的每块拆开排成一排,方便后面的大脑分析。
五、全连接层:组合特征
less
model.add(tf.layers.dense({units: 128, activation: 'relu'}));
-
输入/输出形状:
- 输入
[61952]
- 输出
[128]
- 输入
-
含义:
-
Dense 层像"大脑",把所有特征综合起来。
-
每个神经元会学一种组合方式,比如:
- 神经元 1:边缘+弯曲 → "像数字 3"
- 神经元 2:直线+横线 → "像数字 7"
-
👉 类比:
这一步就像大脑在判断"这个图像最像哪个数字"。
六、输出层:分类结果
less
model.add(tf.layers.dense({units: 10, activation: 'softmax'}));
-
输入/输出形状:
- 输入
[128]
- 输出
[10]
- 输入
-
含义:
-
10 个数值分别表示"属于数字 0--9 的概率"。
-
比如:
csharp[0.01, 0.02, 0.05, 0.80, 0.02, 0.05, 0.01, 0.02, 0.01, 0.01]
→ 表示这张图片是"3"的概率最大(80%)。
-
👉 类比:
小孩最后说:"这一定是数字 3!"
七、更多直观例子
-
如果你只用 1 层卷积 + Dense:
- 只能学到边缘,无法组合 → 分类效果差。
-
如果你用 3 层卷积:
- 能学到边缘 → 纹理 → 数字结构 → 效果好很多。
-
如果你用 8 层卷积:
- 模型能学到非常复杂的模式(比如"9"上面的圈 + 下面的竖线),但需要更多数据,否则会过拟合。
✅ 总结:
- 卷积层:从简单到复杂逐层学习特征。
- Flatten:把二维特征图摊平,变成可输入 Dense 的向量。
- 全连接层:整合所有特征,做最终分类。
- 输出层:用 Softmax 得到概率,给出最终结果。
👉 类比一句话:
卷积层像眼睛逐层看细节,Flatten 把眼睛看到的东西排好,全连接层像大脑整合后做判断。