PaddleSpeech 标点恢复(Punctuation Restoration)实战:一行命令为 ASR 文本智能补全标点
2026/9/23 12:03:42 网站建设 项目流程

PaddleSpeech 标点恢复(Punctuation Restoration)实战:一行命令为 ASR 文本智能补全标点

【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleSpeech

标点恢复(Punctuation Restoration)是语音识别(ASR)系统的常见后处理步骤,负责为没有标点的原始转录文本自动补全标点,从而提升文本可读性并为后续自然语言处理(NLP)任务提供更高质量的输入。本文将基于 PaddleSpeech 官方 demo(demos/punctuation_restoration/README_cn.md)展开,结合仓库内 CLI 与模型源码,完整讲解如何通过单条命令或数行 Python 代码为原始文本恢复标点,并深入剖析其基于 ERNIE 的模型实现、输入预处理与推理全链路,帮助你在实际项目中快速接入标点恢复能力。

标点恢复在语音识别链路中的位置

语音识别系统直接输出的往往是没有任何标点的纯文本流(例如“今天的天气真不错啊你下午有空吗我想约你一起去吃饭”)。这样的文本对人类读者不友好,也会影响分词、命名实体识别、机器翻译等下游 NLP 任务的准确率。标点恢复的作用就是为这类原始文本自动插入句号、逗号、问号、感叹号等标点,属于 ASR 后处理(post-processing)中的关键一环。

在 PaddleSpeech 中,标点恢复以text任务的形式提供,其 CLI 命令为paddlespeech text,Python 侧对应的执行器为TextExecutor(定义于 paddlespeech/cli/text/infer.py)。从源码看,TextExecutor继承自BaseExecutor(paddlespeech/cli/executor.py),遵循preprocess → infer → postprocess的标准三段式执行框架。

环境安装

使用该 demo 前需要先安装 PaddleSpeech。项目提供了 easy、medium、hard 三种安装方式,可参考仓库内的安装文档按需选择:

  • easy:使用 pip 直接安装预编译包,适合快速体验;
  • medium:在虚拟环境中从源码安装,适合开发调试;
  • hard:在 Docker 等隔离环境中完整编译安装,适合深度定制。

无论选择哪种方式,标点恢复功能本身只需要 PaddlePaddle 与 PaddleSpeech 两个核心依赖即可运行。

准备输入

标点恢复 demo 的输入是通过参数传递的、特定语言的原始文本字符串(目前官方预训练模型以中文zh为主)。输入文本应为不含标点的连续字符序列,例如:

今天的天气真不错啊你下午有空吗我想约你一起去吃饭

使用方法

命令行方式(推荐)

安装完成后,直接执行单条命令即可完成标点恢复:

paddlespeech text --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭

执行后终端输出:

[2021-12-14 19:50:22,200] [ INFO] [log.py] [L57] - Text Result: 今天的天气真不错啊!你下午有空吗?我想约你一起去吃饭。

查看全部可用参数:

paddlespeech text --help

各参数含义如下(与源码 paddlespeech/cli/text/infer.py#L39-L91 中的 argparse 定义一一对应):

参数说明默认值
input原始文本(必填)None
task子任务,当前仅支持puncpunc
model文本模型类型ernie_linear_p7_wudao
lang模型语言zh
config文本任务的配置文件,不设置时使用预训练模型内置配置None
ckpt_path模型参数文件,不设置时自动下载预训练模型None
punc_vocab标点恢复任务的标点词表文件None
device执行推理的设备当前环境下 paddlepaddle 的默认 device
-d/--job_dump_result将任务结果保存到文件False
-v/--verbose提升当前任务日志输出级别False

其中taskchoices仅为['punc'](infer.py#L43-L46),lang可选['zh', 'en'](infer.py#L59-L61),model的可选项由预训练模型注册表中的 key 动态生成(infer.py#L47-L55)。

自定义模型参数的使用

当你不使用默认的预训练模型,而是希望加载自己训练的模型时,可以同时指定configckpt_pathpunc_vocab三个参数,例如:

paddlespeech text \ --input 今天的天气真不错啊你下午有空吗我想约你一起去吃饭 \ --model ernie_linear_p3_wudao \ --config /path/to/model_config.json \ --ckpt_path /path/to/model_state.pdparams \ --punc_vocab /path/to/punc_vocab.txt

从源码 infer.py#L109-L124 可以看到,当三者均为None时,执行器会根据模型名-任务-语言拼出的 tag(如ernie_linear_p7_wudao-punc-zh)自动从资源表中定位并下载预训练模型;否则会将传入路径转换为绝对路径后直接加载。

Python API 方式

在 Python 脚本中,通过TextExecutor几行代码即可完成相同功能:

import paddle from paddlespeech.cli.text import TextExecutor text_executor = TextExecutor() result = text_executor( text='今天的天气真不错啊你下午有空吗我想约你一起去吃饭', task='punc', model='ernie_linear_p7_wudao', lang='zh', config=None, ckpt_path=None, punc_vocab=None, device=paddle.get_device()) print('Text Result: \n{}'.format(result))

输出:

Text Result: 今天的天气真不错啊!你下午有空吗?我想约你一起去吃饭。

TextExecutor.__call__的完整签名定义于 infer.py#L307-L317,参数含义与命令行一致。该方式特别适合将标点恢复嵌入到你自己的 ASR 后处理流水线中。

预训练模型列表

PaddleSpeech 为标点恢复任务提供了以下可直接被命令行与 Python API 使用的预训练模型:

模型语言标点类型数
ernie_linear_p3_wudaozh3(,。?)
ernie_linear_p7_wudaozh7(,。!?、:;)

这些模型在 paddlespeech/resource/pretrained_models.py#L1077-L1120 的text_dynamic_pretrained_models注册表中登记,包含下载 URL、MD5 校验值以及包内三个关键文件的相对路径:

  • cfg_pathckpt/model_config.json,模型结构配置;
  • ckpt_pathckpt/model_state.pdparams,模型权重;
  • vocab_filepunc_vocab.txt,标点词表(每行一个标点字符)。

两者唯一的区别在于输出层预测的标点类别数:p3仅区分逗号、句号、问号 3 类,p7进一步细分为逗号、句号、感叹号、问号、顿号、冒号、分号 7 类,可覆盖更丰富的标点粒度。此外注册表中还包含一个ernie_linear_p3_wudao_fast-punc-zh变体,其 tokenizer 使用更轻量的ernie-3.0-mini-zh(见 infer.py#L195-L200),推理速度更快。

深入源码:模型结构与推理流程

模型结构:ErnieLinear

标点恢复的核心模型是ErnieLinear(paddlespeech/text/models/ernie_linear/ernie_linear.py),它本质上是基于 ERNIE 预训练模型的 Token 分类器(Token Classification)

class ErnieLinear(nn.Layer): def __init__(self, num_classes=None, pretrained_token='ernie-1.0', cfg_path=None, ckpt_path=None, **kwargs): super(ErnieLinear, self).__init__() if cfg_path is not None and ckpt_path is not None: # 从本地 checkpoint 加载 self.ernie = ErnieForTokenClassification.from_pretrained( os.path.dirname(cfg_path)) else: # 从预训练 token 初始化,num_classes 为标点类别数 self.ernie = ErnieForTokenClassification.from_pretrained( pretrained_token, num_labels=num_classes, **kwargs) self.num_classes = self.ernie.num_labels self.softmax = nn.Softmax()

forward中,模型对输入序列中的每个 token 输出一个分类 logits,经 Softmax 后得到该位置属于“无标点”或某个具体标点类别的概率分布:

def forward(self, input_ids, token_type_ids=None, position_ids=None, attention_mask=None): y = self.ernie(input_ids, token_type_ids=token_type_ids, attention_mask=attention_mask, position_ids=position_ids) y = paddle.reshape(y, shape=[-1, self.num_classes]) logits = self.softmax(y) return y, logits

推理三段式流程

TextExecutor的推理过程严格遵循preprocess → infer → postprocess三段式:

1. preprocess:文本清洗与分词

_clean_text(infer.py#L205-L210)先将输入转为小写,并用正则剔除除字母、数字、中文之外的字符,再进一步移除标点词表中除首位外的所有标点符号,确保送入模型的输入是“干净”的无标点文本。随后用 ERNIE tokenizer 按字符切分并转换为input_idsseg_ids(token_type_ids)与seq_len

tokenized_input = self.tokenizer( list(clean_text), return_length=True, is_split_into_words=True) self._inputs['input_ids'] = tokenized_input['input_ids'] self._inputs['seg_ids'] = tokenized_input['token_type_ids'] self._inputs['seq_len'] = tokenized_input['seq_len']

2. infer:模型前向推理

@paddle.no_grad()下将输入张量送入ErnieLinear,对每个 token 取 logits 的 argmax 得到预测类别下标:

logits, _ = self.model(input_ids, seg_ids) preds = paddle.argmax(logits, axis=-1).squeeze(0)

3. postprocess:标点回填

将模型预测的每个位置类别与 token 对齐,类别下标为 0 表示不加标点,非 0 时在 token 后拼接对应标点词表中的字符:

for t, l in zip(tokens, labels): text += t if l != 0: # Non punc. text += self._punc_list[l]

值得注意的细节是,标点词表在加载时每行一个标点字符,第 0 位语义上代表“无标点”(空格占位),因此模型输出类别下标l直接作为self._punc_list的索引即可回填正确的标点。

资源自动下载机制

configckpt_pathpunc_vocab均为None时,执行器按模型-任务-语言拼出 tag 并在资源表中查找(infer.py#L109-L120):

tag = '-'.join([model_type, task, lang]) # 例如 ernie_linear_p7_wudao-punc-zh self.task_resource.set_task_model(tag, version=None) self.cfg_path = os.path.join(self.task_resource.res_dir, self.task_resource.res_dict['cfg_path']) self.ckpt_path = os.path.join(self.task_resource.res_dir, self.task_resource.res_dict['ckpt_path']) self.vocab_file = os.path.join(self.task_resource.res_dir, self.task_resource.res_dict['vocab_file'])

也就是说,首次运行时 PaddleSpeech 会自动从 CDN 下载ernie_linear_p7_wudao-punc-zh.tar.gz并校验 MD5,解压后自动定位模型配置、权重与标点词表,对用户完全透明。

进阶:模型训练与评估(选读)

如果你需要针对特定领域(如法律、医疗等标点习惯特殊的文本)训练自己的标点恢复模型,PaddleSpeech 在paddlespeech/text/exps/ernie_linear/下提供了完整的训练、测试脚本:

  • paddlespeech/text/exps/ernie_linear/train.py:训练入口,支持多卡分布式训练,训练过程中以CrossEntropyLoss为损失函数、macro F1-score作为训练/验证指标(见 ernie_linear_updater.py 中的update_coreevaluate_core);
  • paddlespeech/text/exps/ernie_linear/test.py:模型测试;
  • paddlespeech/text/exps/ernie_linear/punc_restore.py:标点恢复推理工具;
  • paddlespeech/text/exps/ernie_linear/avg_model.py:多 checkpoint 权重平均。

训练数据的组织方式可参考 paddlespeech/text/models/ernie_linear/dataset.py 中的PuncDatasetPuncDatasetFromErnieTokenizer:训练文本按空格切分为 token 序列,相邻的“词 + 标点”构成监督信号,标点词表首位的空格字符(" ")作为“无标点”标签。自训练模型训练完成后,即可通过前面介绍的自定义参数方式接入推理。

总结

标点恢复是提升 ASR 转录文本可读性、为下游 NLP 任务铺路的关键后处理环节。通过 PaddleSpeech,你既可以用一条paddlespeech text命令快速完成中文标点恢复,也可以在 Python 中以TextExecutor形式将其嵌入既有流水线;仓库同时开放了基于 ERNIE 的完整训练链路,支持按需定制。从源码看,其实现以 ERNIE Token 分类为核心,配以“文本清洗 → 分词 → 分类 → 标点回填”的简洁流程,部署与二次开发都非常轻量。

相关代码与文档索引:

  • Demo 说明:demos/punctuation_restoration/README_cn.md
  • CLI 执行器:paddlespeech/cli/text/infer.py
  • 模型实现:paddlespeech/text/models/ernie_linear/ernie_linear.py
  • 数据与训练:paddlespeech/text/models/ernie_linear/dataset.py、paddlespeech/text/exps/ernie_linear/train.py
  • 预训练模型注册表:paddlespeech/resource/pretrained_models.py

【免费下载链接】PaddleSpeechEasy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation and Keyword Spotting. Won NAACL2022 Best Demo Award.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleSpeech

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询