Transformers 中的 PP-LCNet:面向文档方向与表格分类的轻量 CNN 图像分类与骨干网络实战指南
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
PP-LCNet(PaddlePaddle Lightweight Convolutional Network)是百度 PaddlePaddle 团队推出的一族高效轻量卷积神经网络,在本文所述的 Hugging Face Transformers 集成版本中,它被定位为面向真实场景文档理解与 OCR 流程的图像分类模型与多尺度特征骨干网络,可同时服务服务端与边缘端部署。本指南以 docs/source/en/model_doc/pp_lcnet.md 为主线,结合仓库中该模型的配置、建模、图像预处理源码与测试用例,带你完整掌握 PP-LCNet 的三大应用模块、PPLCNetConfig全部可调参数、PPLCNetImageProcessor预处理管线,以及如何使用Pipeline与AutoModel完成单张/批量图像分类推理,并读懂它在 Auto API 中的接入方式与集成测试验证结果。
模型总览:轻量化与文档理解场景的定位
PP-LCNet 于 2026-03-13 被贡献集成进本仓库(见 pp_lcnet.md 顶部说明),其模型类型标识为pp_lcnet。官方定位是一族高效、轻量的卷积神经网络,面向真实世界的文档理解(document understanding)与 OCR 任务设计,在精度、速度与模型体积之间取得平衡,适用于服务端与边缘端两类部署环境。
在架构上,PP-LCNet 延续了 MobileNet 一族的"轻量"路线:主体由深度可分离卷积(Depthwise Separable Convolution)、可选的 Squeeze-and-Excitation(SE)通道注意力、以及硬 Swish(hardswish)激活构成,并且通过scale宽度缩放系数衍生出一族不同计算量的子模型(配置注释给出的典型取值为 0.25、0.5、1.0、1.5)。与通用图像分类网络不同,本仓库中的 PP-LCNet 权重主要服务于文档预处理链路的三个具体分类任务(详见下一节)。
三大应用模块:PP-LCNet 在 OCR 流程中的角色
按 Overview 的说明,PP-LCNet 针对不同文档处理需求提供三类主要变体,每个变体针对特定任务优化:
文档图像方向分类模块(Document Image Orientation Classification):主要用于判断文档图像的旋转方向,并通过后处理进行矫正。在文档扫描、证件照拍摄等过程中,设备可能因旋转而拍摄出各种朝向的图像,而标准 OCR 流程对这些图像的处理效果不佳。借助图像分类技术,可预先判定并调整包含文字区域的文档/证件朝向,从而提升 OCR 精度。仓库集成测试中的标签映射
{"0": "0", "1": "90", "2": "180", "3": "270"}(见 test_modeling_pp_lcnet.py)正是这种 0°/90°/180°/270° 四分类输出的直接体现。表格分类模块(Table Classification Module):是计算机视觉系统里负责对输入表格图像进行分类的关键部件,其性能直接影响整个表格识别流程的精度与效率。该模块通常接收表格图像作为输入,利用深度学习算法依据图像特征与内容将其归入预定义类别(如实线与无线表格),分类结果作为表格识别流水线的输入。
PPLCNetForImageClassification.forward的 docstring 示例即使用表格分类 checkpoint(输出类别如wireless_table)。文本行方向分类模块(Text Line Orientation Classification):主要判断文本行的方向并通过后处理矫正。与文档方向分类相似,在文档扫描、执照/证书拍摄等场景下采集设备可能发生旋转,产生各种朝向的文本行,标准 OCR 流程难以处理。该模块通过图像分类技术预先判定并调整文本行方向,提高 OCR 处理准确率。
可见,PP-LCNet 在 Hugging Face 生态中的定位并不是通用视觉大模型,而是OCR/文档理解前置处理链路的即用型小模型。
网络架构源码级拆解
本节依据建模源码 src/transformers/models/pp_lcnet/modeling_pp_lcnet.py(由 modular 源 modular_pp_lcnet.py 自动生成)展开。
宏观结构:stem + 5 个 stage 的多尺度下采样
PPLCNetEncoder(对应源码PPLCNetEncoder)先经过一个3×3、默认步长 2、输出通道由stem_channels × scale决定的 stem 卷积层,再依次串联 5 个PPLCNetBlockstage。默认block_configs在 configuration_pp_lcnet.py 中按"每行一个 stage、每个元组(kernel_size, in_channels, out_channels, stride, use_squeeze_excitation)"定义如下:
| Stage(源码注释) | blocks | 卷积核大小 | 通道变化 | stride | 是否使用 SE |
|---|---|---|---|---|---|
| Stage 1(blocks2) | 1 | 3 | 16 → 32 | 1 | 否 |
| Stage 2(blocks3) | 2 | 3 / 3 | 32 → 64 → 64 | 2 / 1 | 否 |
| Stage 3(blocks4) | 2 | 3 / 3 | 64 → 128 → 128 | 2 / 1 | 否 |
| Stage 4(blocks5) | 6 | 3、5、5、5、5、5 | 128 → 256(后 5 层保持 256) | 2 后接 1 | 否 |
| Stage 5(blocks6) | 2 | 5 / 5 | 256 → 512 → 512 | 2 / 1 | 是 / 是 |
从结构上可以推算:以224×224输入为例,stem(stride 2)后为 112,Stage2/3/4/5 各自的首层 stride 2 会依次将特征图下采样到 56、28、14、7,因此网络天然形成多分辨率金字塔——这也是它能承担通用骨干网络的原因。每个 stage 内部各层的通道数都会乘以scale后再经make_divisible处理为divisor的整数倍。配置类在初始化时还会据此自动生成depths = [len(blocks) for blocks in block_configs](默认即[1, 2, 2, 6, 2])与stage_names = ["stem", "stage1", ..., "stage5"]。
基础组件:卷积、深度可分离卷积与 SE 模块
单个普通卷积层PPLCNetConvLayer遵循Conv2d → BatchNorm2d → 激活的固定顺序,默认激活函数为hardswish。真正的轻量化核心是PPLCNetDepthwiseSeparableConvLayer,其前向流程为:
Depthwise Conv(3×3/5×5,groups=in_channels,可选 stride 2) → Squeeze-and-Excitation 模块(可选,按 block 配置开关) → Pointwise Conv(1×1,恢复/扩展到目标输出通道)这是 MobileNet、PP-LCNet 等轻量网络的共同手段:用"逐通道卷积 + 1×1 逐点卷积"解耦空间与通道混合,大幅削减参数量与计算量。SE 模块PPLCNetSqueezeExcitationModule则先以AdaptiveAvgPool2d(1)做全局压缩,再经过"channel → channel//reduction(ReLU)→channel(Hardsigmoid)"的两段 1×1 卷积恢复通道权重,最后与原特征做逐元素乘(残差式通道重标定),以极低成本提升模型对关键通道的关注能力。此外,该层继承自GradientCheckpointingLayer,支持梯度检查点训练;模型的supports_gradient_checkpointing = True、_can_compile_fullgraph = True,且_no_split_modules = ["PPLCNetDepthwiseSeparableConvLayer"]。
通道对齐与分类头
make_divisible(value, divisor=8)用于保证每层通道数都是divisor(默认 8)的整数倍,以利于在特定硬件上高效实现与资源利用——该工具函数与 MobileNetV2 复用的同一实现(见 modular 文件对make_divisible的复用导入)。
PPLCNetForImageClassification的分类头结构为:
AdaptiveAvgPool2d(1)全局平均池化;- 1×1 卷积将最后 stage 输出通道(
512 × scale经make_divisible对齐)扩展为class_expand(默认 1280)维; hardswish激活,并乘以(1 - hidden_dropout_prob)(默认hidden_dropout_prob=0.2,即推理期按 Dropout 保留率做确定性缩放);Flatten后接Linear(class_expand, num_labels)输出类别 logits(当num_labels > 0时)。
因此模型前向返回的是原始 logits,输出对象为BaseModelOutputWithNoAttention(last_hidden_state即分类 logits,同时可携带各 stagehidden_states)。
配置参数全解:PPLCNetConfig
PPLCNetConfig(configuration_pp_lcnet.py)继承BackboneConfigMixin与PreTrainedConfig,标注为@strict数据类:传入未知字段会报错,且validate_architecture()会强制block_configs恰好包含 5 个 stage,否则抛出ValueError。核心参数如下:
| 参数 | 默认值 | 含义与影响 |
|---|---|---|
scale | 1.0 | 各层通道维度的宽度缩放系数,用于在不改变整体架构的前提下调节模型尺寸与计算开销(如 0.25 / 0.5 / 1.0 / 1.5,对应 PP-LCNet 系列不同的 x 变体) |
block_configs | None | 每个 stage 中每个 block 的配置,元组为(kernel_size, in_channels, out_channels, stride, use_squeeze_excitation);为None时使用上表默认 PP-LCNet 结构 |
stem_channels | 16 | stem 层输出通道数 |
stem_stride | 2 | stem 卷积层步长 |
reduction | 4 | SE 模块中通道压缩的比例,用于降低参数与计算量 |
class_expand | 1280 | 分类头扩展层隐单元数,增强最终分类前的特征表达能力 |
divisor | 8 | 通道数对齐除数,保证参数(如通道维)为 8 的倍数 |
hidden_act | "hardswish" | 全网络激活函数 |
hidden_dropout_prob | 0.2 | 分类头处按保留率缩放的"确定性 dropout"比例 |
由于继承BackboneConfigMixin,还可通过out_features/out_indices指定骨干输出哪些 stage 的特征(对应stage_names中的stem、stage1…stage5)。典型实例化方式:
from transformers import PPLCNetConfig config = PPLCNetConfig(scale=0.5) # 半宽度的轻量变体 print(config.depths) # [1, 2, 2, 6, 2] print(config.stage_names) # ['stem', 'stage1', ..., 'stage5']从 Auto 映射(modeling_auto.py)看,pp_lcnet的配置类、分类模型与骨干模型分别映射为PPLCNetConfig、PPLCNetForImageClassification、PPLCNetBackbone。本仓库还同时存在同族后续版本pp_lcnet_v3、pp_lcnet_v4的独立模块,但本文聚焦基础版 PP-LCNet(见 auto_mappings.py)。
PPLCNetBackbone:多尺度特征提取骨干
PPLCNetBackbone(建模源码)将PPLCNetEncoder包装为特征金字塔式骨干:其num_features按 stem 与每个 stage 最后一个 block 的(缩放后)输出通道自动计算;前向时使用capture_outputs机制按PPLCNetBlock粒度记录各阶段hidden_states,再依据out_features(默认在测试中使用["stage2", "stage3", "stage4"],见 test_modeling_pp_lcnet.py)组装feature_maps,最终以BackboneOutput(feature_maps=..., hidden_states=...)返回。docstring 内置的最小示例:
>>> from transformers import PPLCNetConfig, PPLCNetBackbone >>> import torch >>> config = PPLCNetConfig() >>> model = PPLCNetBackbone(config) >>> pixel_values = torch.randn(1, 3, 224, 224) >>> with torch.no_grad(): ... outputs = model(pixel_values) >>> feature_maps = outputs.feature_maps >>> list(feature_maps[-1].shape)由于全网络不含任何注意力,has_attentions = False,输入名为主键pixel_values(main_input_name),输入模态为图像(input_modalities = ("image",))。
PPLCNetImageProcessor:面向文档图的预处理管线
图像处理器 image_processing_pp_lcnet.py 基于TorchvisionBackend实现(依赖torch/torchvision),为适配文档分类任务定义了一组明确默认值:
| 属性/默认值 | 值 | 说明 |
|---|---|---|
resample | 2(BILINEAR) | 缩放插值方式 |
do_resize/do_center_crop | True/True | 先等比缩放再中心裁剪 |
resize_short | 256 | 以短边为基准的目标边长 |
size | {"height": 256, "width": 256} | 缩放参考尺寸 |
crop_size | 224 | 中心裁剪尺寸(送入网络的边长) |
image_mean/image_std | [0.406, 0.456, 0.485]/[0.225, 0.224, 0.229] | 归一化均值/方差 |
size_divisor | 1 | 尺寸对齐除数 |
预处理链路的两个关键实现细节值得注意:
- 按短边等比缩放(保持宽高比):与常规
TorchvisionBackend缩放到固定尺寸不同,get_image_size会先按target_short_edge / min(height, width)计算缩放比例,对宽高同步缩放并四舍五入,可选地按size_divisor向上取整对齐,避免文档图像被拉伸变形(代码注释明确说明了这一差异)。 - RGB → BGR 通道重排:归一化完成后,处理器会将每个张量按
image[[2, 1, 0], :, :]重排为 BGR 通道顺序,与 PaddlePaddle 生态的输入约定保持一致。
处理过程还通过group_images_by_shape/reorder_images对同尺寸图像分组批量缩放再还原顺序,保证批处理时 resize/crop 的一致性。此外,类属性暴露了两个可覆盖参数resize_short与size_divisor(PPLCNetImageProcessorKwargs),预处理时可通过image_processor(images=..., resize_short=..., size_divisor=...)临时调整。
使用指南:图像分类推理
下面的示例完整继承自原文档,演示用Pipeline或AutoModel对文档图像进行方向分类,checkpoint 使用方向分类模型PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors(PaddlePaddle 组织在 Hub 上发布的 safetensors 权重)。
单张图像推理
用Pipeline一行创建分类器:
import requests from PIL import Image from transformers import pipeline model_path = "PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors" image_classifier = pipeline("image-classification", model=model_path, function_to_apply="none", device_map="auto") image = Image.open(requests.get("https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/img_rot180_demo.jpg", stream=True).raw) result = image_classifier(image) print(result)或使用AutoModelForImageClassification+AutoImageProcessor显式做前向:
import requests from PIL import Image from transformers import AutoImageProcessor, AutoModelForImageClassification model_path = "PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors" model = AutoModelForImageClassification.from_pretrained(model_path, device_map="auto") image_processor = AutoImageProcessor.from_pretrained(model_path) image = Image.open(requests.get("https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/img_rot180_demo.jpg", stream=True).raw) inputs = image_processor(images=image, return_tensors="pt").to(model.device) outputs = model(**inputs) predicted_label = outputs.logits.argmax(-1).item() print(model.config.id2label[predicted_label])批量图像推理
把单张 PIL 图像放进列表即可批量推理。Pipeline 写法:
import requests from PIL import Image from transformers import pipeline model_path = "PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors" image_classifier = pipeline("image-classification", model=model_path, function_to_apply="none", device_map="auto") image = Image.open(requests.get("https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/img_rot180_demo.jpg", stream=True).raw) result = image_classifier([image, image]) print(result)AutoModel 写法(注意按 batch 维度取 argmax 后逐个查id2label):
import requests from PIL import Image from transformers import AutoImageProcessor, AutoModelForImageClassification model_path = "PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors" model = AutoModelForImageClassification.from_pretrained(model_path, device_map="auto") image_processor = AutoImageProcessor.from_pretrained(model_path) image = Image.open(requests.get("https://paddle-model-ecology.bj.bcebos.com/paddlex/imgs/demo_image/img_rot180_demo.jpg", stream=True).raw) inputs = image_processor(images=[image, image], return_tensors="pt").to(model.device) outputs = model(**inputs) predicted_labels = outputs.logits.argmax(-1) for label_id in predicted_labels: label_id_scalar = label_id.item() label = model.config.id2label[label_id_scalar] print(label)配套注意事项
function_to_apply="none":PP-LCNet 分类头直接输出 logits(多类 softmax 交叉熵训练),Pipeline 中设置function_to_apply="none"即跳过 sigmoid/softmax 这类激活,直接以 logits 最大值对应类别,避免在分类任务上误套 sigmoid。device_map="auto":由 accelerate 自动分配设备,CPU 环境同样可用;若不用多设备加载,也可直接去掉该参数。- 图像预处理:推理前请务必配合
PPLCNetImageProcessor/AutoImageProcessor使用(等比缩放短边至 256、中心裁剪 224、归一化、RGB→BGR),以保证与官方权重训练/验证时的输入一致。 - 表格分类等其他任务:只需替换 checkpoint,例如模型 docstring 中使用
PaddlePaddle/PP-LCNet_x1_0_table_cls_safetensors可得到wireless_table(无线表格)之类的类别输出;方向分类与文本行方向分类的 checkpoint 用法完全相同。
Auto API 接入与集成测试验证
PP-LCNet 已完整接入 Transformers 的自动注册体系:
- 配置类映射(auto_mappings.py):
("pp_lcnet", "PPLCNetConfig"); - 图像处理器映射:
("pp_lcnet", {"torchvision": "PPLCNetImageProcessor"}); - 模型映射(modeling_auto.py):
("pp_lcnet", "PPLCNetForImageClassification")与("pp_lcnet", "PPLCNetBackbone")。
对应测试分布在 tests/models/pp_lcnet/:
- test_modeling_pp_lcnet.py 覆盖配置通用测试、骨干输出测试(要求
hidden_states数量为 stage 数 + 1,且各阶段通道数符合block_configs[i][-1][2] * scale)、float16/bfloat16/float32 混合精度推理,以及@slow集成测试; - 集成测试以
PaddlePaddle/PP-LCNet_x1_0_doc_ori_safetensors加载真实权重与官方 demo 图像,断言输出 logits 形状为(1, 4)且与参考 logits[[-0.3655, -1.0573, 2.4883, -1.0640]]在2e-2容差内一致,最终argmax落在类别 2(180°),可直接作为你在本地复现"文档旋转 180° 被判正"的验收基准; - test_image_processing_pp_lcnet.py 通过
ImageProcessingTestMixin校验预处理默认参数(如上表),并显式跳过 4 通道输入用例(该模型尚不支持 4 通道图像)。
由于模型在PipelineTesterMixin中注册的映射为{"image-classification": PPLCNetForImageClassification},因此 PP-LCNet 天然支持image-classification这一 Pipeline 任务。
API 速览
PPLCNetForImageClassification:带分类头的完整模型,输入pixel_values,输出 logits(last_hidden_state);PPLCNetConfig:模型配置类(支持 Backbone 的out_features/out_indices),关键参数见上文参数表;PPLCNetBackbone:特征提取骨干,输出feature_maps与hidden_states,适合做下游任务的视觉编码器;PPLCNetImageProcessor:PaddlePaddle文档类模型的专用图像处理器,核心方法是preprocess(等比缩放 + 中心裁剪 + 归一化 + RGB→BGR)。
对每个 API 的完整签名与 docstring,可直接查阅 pp_lcnet.md 中对应的[[autodoc]]章节,或浏览 models/pp_lcnet 目录下的源码。
【免费下载链接】transformers🤗 Transformers: the model-definition framework for state-of-the-art machine learning models in text, vision, audio, and multimodal models, for both inference and training.项目地址: https://gitcode.com/GitHub_Trending/tra/transformers
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考