从像素到汉字:OCR 模型是如何依靠 CNN “学会“识字的?

从像素到汉字:OCR 模型是如何依靠 CNN “学会“识字的? 这篇文章的灵感和方向来源于大佬苏剑林的博客分享https://spaces.ac.cn/archives/3774我只是扩写展开嘿嘿。本文将以 OCR光学字符识别系统为例拆解其中的 CNN 识别模块是如何被训练出来的——它怎样从 140 万张字形样本中自动学会看懂笔画、组合出特征、最终输出汉字概率。文中网络参数Filter 数量、尺寸等均为便于理解的示例实际应用中可灵活调整。一、OCR 系统的分工CNN 只负责认字不负责找字一套完整的 OCR 系统通常分为两大阶段┌─────────────────────────────────────────────────────────────┐ │ 第一阶段预处理找字 切字 │ │ ───────────────────────────────────────────────────────── │ │ 灰度聚类 → 生成 Mask → 连通域分析 → 裁剪归一化 │ │ 把整张大图切成一个个 32×32 的单字小图 │ └─────────────────────────────────────────────────────────────┘ ↓ ┌─────────────────────────────────────────────────────────────┐ │ 第二阶段CNN认字 │ │ ───────────────────────────────────────────────────────── │ │ 输入32×32 单字灰度图 │ │ 输出这是中字的概率 92%申字的概率 4%…… │ │ 靠 140 万张样本训练出来的认字大脑 │ └─────────────────────────────────────────────────────────────┘CNN 在 OCR 中的角色非常明确它不管字在图片的哪个位置、怎么切出来的它只接过一张已经框好的单字小图输出这个字是什么的概率分布。接下来我们就走进这个认字大脑的内部看看它是怎么被训练出来的。二、训练之前CNN 什么都不会在训练开始前CNN 里面的所有 Filter那些 3×3 的小窗口里面填的都是随机数。它就像一个刚出生的小孩看着一张中字的图片完全不知道这是什么。它的学习过程本质上是通过反向传播算法不断调整每个 Filter 里的数字让它在看到中字时输出高概率看到申字时输出低概率。三、输入对 CNN 来说一张字就是一张数字表格一张 32×32 的灰度单字图在 CNN 眼里是一个32×32 的矩阵每个格子是 0~255 的整数列0 列1 列2 列3 列4 行0: 255 255 255 255 255 ← 255 白色背景 行1: 255 255 0 255 255 ← 0 黑色笔画 行2: 255 255 0 255 255 行3: 255 255 0 255 255 行4: 255 255 255 255 255CNN 的所有操作都是在这张数字表格上进行的。四、卷积用小窗口扫描收集笔画证据4.1 Filter 是什么CNN 的核心组件叫Filter滤波器/卷积核是一个3×3 的小窗口里面填着可学习的数字。比如一个竖线检测器在训练初期是随机数训练后会变成类似这样Filter (训练后的竖线检测器): [-1, 2, -1] [-1, 2, -1] [-1, 2, -1]注意这些数字不是人设计的是 CNN 从 140 万张样本中自动学出来的。4.2 卷积 滑动窗口做点积Filter 从左上角开始一步一步向右、向下滑动每到一个位置就做逐元素相乘再相加output[i, j] Σ_m Σ_n input[im, jn] × filter[m, n]举个例子输入区域3×3中间一竖是黑色笔画255 0 255 255 0 255 255 0 255Filter竖线检测器-1 2 -1 -1 2 -1 -1 2 -1计算结果的绝对值很大说明 Filter 在这里检测到了竖线。4.3 Feature Map一张热力图Filter 滑过整张图后生成一张Feature Map特征图值很大的位置 → 该特征出现的地方值接近 0的位置 → 这里没有该特征第一层通常有几十个 Filter就会输出几十张 Feature Map分别检测竖线、横线、斜线、左边缘、右边缘等。五、池化把图缩小让网络不那么较真卷积之后接MaxPool 2×2输入: [120, 80] MaxPool → [150] [150, 90]保留 2×2 区域里的最大值其余扔掉。作用减少计算量图缩小一半后续计算量降为 1/4平移不变性字稍微歪一点、偏移几个像素池化后特征仍然保留抗噪小范围噪声被过滤六、层次化特征越深层越抽象CNN 的精髓在于逐层组合特征就像人类认字一样层级输入学到的特征类比人类认字Conv1原始像素 32×32低级特征竖线、横线、斜线、点先看笔画Pool1特征图尺寸缩小保留最强响应忽略细节Conv2缩小后的特征图中级特征十字交叉、口字框、偏旁再看结构Pool2特征图再次缩小进一步抽象Flatten多维特征图拉成一条证据向量整理线索FC Softmax证据向量输出各类别概率做出判断具体例子识别中字Conv1检测到有竖线“有横线”“有外框”Conv2组合出有十字交叉“有口字框”FC 层综合证据 → “十字交叉 口字框 很可能是『中』字”Softmax输出概率 → 中: 0.92, 申: 0.04, 田: 0.02……七、CNN 是怎么学会的—— 训练过程揭秘7.1 训练数据140 万张字卡要训练 CNN 认字需要准备大量带标签的单字图片图片内容标签各种字体的中字“中”各种字体的国字“国”各种字体的A“A”…………这些样本会经过数据增强随机旋转、缩放、加噪、模糊等让 CNN 见过各种变形的字提高泛化能力。7.2 前向传播猜一次把一张中字图片输入 CNN它随机初始化的大脑会胡乱猜第一次猜测中: 0.15, 申: 0.20, 田: 0.30, 甲: 0.35...显然错得很离谱。7.3 计算损失错得有多离谱用交叉熵损失函数Cross-Entropy Loss衡量预测与真实标签的差距Loss -log(预测为中的概率)如果预测中的概率只有 0.15Loss 就很大如果预测 0.92Loss 就很小。7.4 反向传播调整 Filter 里的数字这是训练的核心。通过链式法则把 Loss 的责任逐层往前推输出层错了 → 调整 FC 层的权重FC 层的误差 → 继续往前传调整 Flatten 之前的参数Conv2 层的误差 → 调整第二层的 Filter 数值Conv1 层的误差 → 调整第一层的 Filter 数值梯度下降公式新参数 旧参数 - 学习率 × (Loss 对参数的梯度)每一次调整都让 CNN 在下一次看到中字时输出中的概率稍微高一点点。7.5 重复 140 万次把 140 万张样本轮流喂给 CNN反复进行前向传播 → 算 Loss → 反向传播 → 更新参数经过成千上万轮Epoch训练后Filter 里的随机数逐渐被雕刻成有意义的模式某个 Filter 变成了竖线检测器某个 Filter 变成了横线检测器某个 Filter 变成了十字交叉检测器……最终CNN 从什么都不会变成了训练正确率 99.7%的认字专家。八、CNN 的两大核心机制8.1 局部连接只看邻居判断这里有没有竖线只需要看周围 3×3 的像素不需要看整张图。每个 Filter 只有 9 个参数相比全连接网络的每个神经元连所有像素参数量减少了几十倍。8.2 权重共享一把尺子量到底同一个 Filter 在整张图上滑动扫描所有位置共用同一组权重。无论竖线出现在左上角还是右下角同一个检测器都能抓到。九、常见误区澄清QCNN 的 Filter 数量、尺寸、层数是固定的吗A不是。这些都是超参数可根据任务灵活调整参数本文示例实际常见范围Filter 数量32, 6416 ~ 512Filter 尺寸3×31×1, 3×3, 5×5, 7×7网络深度4 层2 ~ 50 层输入尺寸32×3228×28, 64×64, 224×224本文用 32 个 Filter、3×3 等数字仅为方便讲解原理。实际搭建时这些数字完全可以根据数据量、计算资源和精度需求来调整。十、总结┌─────────────────────────────────────────────────────────────┐ │ OCR 系统完整流程 │ │ ───────────────────────────────────────────────────────── │ │ 整张大图 → 预处理找字、切字→ 32×32 单字图 │ │ ↓ │ │ CNN 认字大脑经 140 万样本训练 │ │ • Conv1学到竖线、横线等笔画检测器 │ │ • Pool1缩小图获得平移不变性 │ │ • Conv2学到十字交叉、口字框等组合特征 │ │ • Pool2 Flatten整理所有证据 │ │ • FC Softmax综合判断输出概率 │ │ ↓ │ │ 输出中字概率 92%申字概率 4%…… │ └─────────────────────────────────────────────────────────────┘核心思想OCR 里的 CNN 不是天生会认字而是从海量样本中通过反向传播一点点雕刻出 Filter 的权重。它逐层提取有没有竖线 → 有没有十字 → 像不像中字的证据链最终在输出层做概率投票。训练正确率 99.7% 的背后是 140 万张字卡、成千上万轮迭代、以及无数个梯度下降步骤的积累。最后有任何问题欢迎一起交流探讨