- 人工智能
- 大模型
- NLP
- 深度学习
- 预训练
- 微调
- RLHF
- 模型量化
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
导读
词法分析(Lexical Analysis)是自然语言处理(NLP)的基石任务之一:它把连续的中文文本切分为词语序列,并标注每个词的词性与专名类别,是分词、词性标注、命名实体识别等下游应用的基础能力。本文以 PaddleNLP 开源仓库中的 Lexical Analysis 教程 为骨架,结合仓库内 词法分析示例工程、Taskflow 一键预测实现 与 BiGruCrf 模型源码,系统讲解词法分析的任务定义、GRU+CRF 序列标注原理、数据格式与标签体系、从单卡/多卡训练到评估、模型导出、部署预测再到 Taskflow 一键调用的完整实战链路,帮助读者掌握一套可复现、可定制的中文词法分析方案。
词法分析任务概述
在编译原理中,词法分析(Lexical Analysis)是将字符序列转换为词法单元(token)序列的过程,是编译的第一阶段;在自然语言处理中,它同样是基础中的基础——中文没有天然的空格分词,必须由词法分析器完成"切词 + 打标"两项工作。
文档将词法分析的主要任务归纳为四类:
- Tokenization(分词):将连续字符序列切分为有意义的词;
- Removing whitespace/comments(去除空白与注释):过滤无信息量的噪音字符;
- Tracking line numbers(追踪行号):在代码分析场景记录 token 的原始位置;
- Generating symbol tables(生成符号表):为编译器/解释器维护标识符等符号信息。
其抽象数学表示为:
$$ T = Lex(S) $$
其中 $S$ 是输入字符串,$T$ 是输出的 token 序列。在 PaddleNLP 的中文 NLP 场景下,这条"从字符串到 token 序列"的映射具体落地为:输入一句中文,输出该句的切分结果(segs)与每个词的词性/专名标签(tags)。
中文词法分析的建模方式:GRU + CRF 序列标注
在 NLP 中,词法分析通常被建模为**序列标注(Sequence Labeling)**问题:为输入句子的每个"字"打上一个标签,标签的-B(Begin)/-I(Inside)后缀组合即可还原词边界与词类别。PaddleNLP 仓库中 词法分析示例工程 采用经典做法——两层双向 GRU 学习特征 + 一层 CRF 解码完成序列标注。
从 模型实现源码 可以看出完整的数据流:
def forward(self, inputs, lengths, labels=None): word_embed = self.word_embedding(inputs) # 1. 字 id -> 字向量 bigru_output, _ = self.gru(word_embed, sequence_length=lengths) # 2. 双向 GRU 特征 emission = self.fc(bigru_output) # 3. 线性层得到发射分数 if labels is not None: loss = self.crf_loss(emission, lengths, labels) # 训练:CRF 损失 return loss else: _, prediction = self.viterbi_decoder(emission, lengths) # 推理:Viterbi 解码 return prediction对应文档中描述的四步建模流程:
- 输入 one-hot 化:每个字以词典中的一个 id 表示;
- 字向量映射:one-hot 序列通过字表(
nn.Embedding,词向量维度emb_dim=128)转换为实向量表示的字向量序列; - 双向 GRU 特征学习:字向量序列作为输入送入
nn.GRU(num_layers=2,direction="bidirectional"),堆叠两层以增强学习能力,得到融合上下文的新特征序列; - CRF 序列标注:CRF 以 GRU 输出经线性层(
fc,输入维度hidden_size*2)得到的发射分数为输入,以标记序列为监督信号完成序列标注;推理时使用ViterbiDecoder全局搜索最优标签路径,而不是逐位置独立取最大值,从而显式建模标签间的转移约束(如-B后面必须跟同类型的-I)。
模型关键超参数及源码默认值如下表:
| 参数 | 默认值 | 含义 |
|---|---|---|
emb_dim | 128 | 字向量(word embedding)维度 |
hidden_size | 128 | 单层 GRU 隐层节点数(双向输出维度为 2×) |
emb_lr | 2.0 | Embedding 层学习率缩放系数 |
crf_lr | 0.2 | CRF 层学习率缩放系数 |
init_bound | 0.1 | 参数 Uniform 初始化的上下界 |
with_start_stop_tag | True | 是否启用 CRF 起止标签 |
CRF 部分复用了 PaddleNLP 的 LinearChainCrf 与 LinearChainCrfLoss,训练时计算 CRF 负对数似然损失,推理时通过ViterbiDecoder求最优路径;训练脚本中还使用 ChunkEvaluator(见 train.py 中的chunk_evaluator = ChunkEvaluator(label_list=label_vocab.keys(), suffix=True))按"块"统计 Precision / Recall / F1。
数据准备:下载示例数据与数据格式说明
进入 slm/examples/lexical_analysis 目录,执行以下命令即可下载并解压示例数据集(对应 download.py,其数据源为lexical_analysis_dataset_tiny.tar.gz小样本数据集):
python download.py --data_dir ./训练数据格式
训练数据(train.tsv/test.tsv)除首行为固定的text_a\tlabel开头外,其余每行由两列组成、以制表符分隔:
- 第一列:utf-8 编码的中文文本,字符之间以
\002分割; - 第二列:每个字对应的标注,同样以
\002分隔。
采用IOB2 标注体系:X-B表示类型为 X 的词的开始,X-I表示该词的持续,O表示不关注的字(在词性、专名联合标注中实际上不存在O)。示例数据(摘自 示例工程 README):
除\002了\002他\002续\002任\002十\002二\002届\002政\002协\002委\002员\002,\002马\002化\002腾\002,\002雷\002军\002,\002李\002彦\002宏\002也\002被\002推\002选\002为\002新\002一\002届\002全\002国\002人\002大\002代\002表\002或\002全\002国\002政\002协\002委\002员 p-B\002p-I\002r-B\002v-B\002v-I\002m-B\002m-I\002m-I\002ORG-B\002ORG-I\002n-B\002n-I\002w-B\002PER-B\002PER-I\002PER-I\002w-B\002PER-B\002PER-I\002w-B\002PER-B\002PER-I\002PER-I\002d-B\002p-B\002v-B\002v-I\002v-B\002a-B\002m-B\002m-I\002ORG-B\002ORG-I\002ORG-I\002ORG-I\002n-B\002n-I\002c-B\002n-B\002n-I\002ORG-B\002ORG-I\002n-B\002n-I从 数据读取源码 可以确认:load_dataset按\t切分字序列与标签序列,再用CHAR_DELIMITER = "\002"拆分并断言二者长度一致;convert_example通过word.dic/tag.dic/q2b.dic三个词典完成 token→id 转换,超过max_seq_len(默认 64)的部分截断,未登录字用"OOV"替换。
词性 / 专名标签体系
文档与示例 README 给出了完整的标签集合,包含24 个词性标签(小写字母)和4 个专名类别标签(大写字母):
| 标签 | 含义 | 标签 | 含义 | 标签 | 含义 | 标签 | 含义 |
|---|---|---|---|---|---|---|---|
| n | 普通名词 | f | 方位名词 | s | 处所名词 | t | 时间 |
| nr | 人名 | ns | 地名 | nt | 机构名 | nw | 作品名 |
| nz | 其他专名 | v | 普通动词 | vd | 动副词 | vn | 名动词 |
| a | 形容词 | ad | 副形词 | an | 名形词 | d | 副词 |
| m | 数量词 | q | 量词 | r | 代词 | p | 介词 |
| c | 连词 | u | 助词 | xc | 其他虚词 | w | 标点符号 |
| PER | 人名 | LOC | 地名 | ORG | 机构名 | TIME | 时间 |
需要注意:人名、地名、机构名、时间四类存在两套标签(PER/LOC/ORG/TIME与nr/ns/nt/t)。被标注为第二套(小写)标签的词,是模型判断为低置信度的人名、地名、机构名和时间词。开发者可以基于这两套标签,在四个类别的准确率与召回率之间做出自己的权衡。
模型训练:单卡与多卡
单卡训练
在 slm/examples/lexical_analysis 目录下执行(对应 train.py):
python train.py \ --data_dir ./lexical_analysis_dataset_tiny \ --model_save_dir ./save_dir \ --epochs 10 \ --batch_size 32 \ --device gpu \ # --init_checkpoint ./save_dir/final各参数释义如下:
--data_dir:数据集所在文件夹路径(需包含train.tsv、test.tsv、word.dic、tag.dic、q2b.dic);--model_save_dir:训练期间模型保存路径;--epochs:训练迭代轮数(默认 10);--batch_size:每次迭代每张卡上的样本数目;--device:训练设备,gpu表示使用 GPU,xpu表示使用百度昆仑卡,cpu表示使用 CPU(train.py 中实际限定为cpu/gpu);--init_checkpoint:模型加载路径,通过设置该参数可启动增量训练。
结合训练脚本源码,还有一组常用超参数值得关注:--base_lr(基础学习率,默认 0.001,作用于全网络,优化器为 Adam)、--crf_lr(CRF 层学习率比率,默认 0.2,对应模型构造参数crf_lr=args.crf_lr)、--emb_dim(词向量维度,默认 128)、--hidden_size(GRU 隐层节点数,默认 128)、--max_seq_len(最长序列字数,默认 64)、--logging_steps(日志间隔,默认 10)、--save_steps(保存 checkpoint 间隔,默认 100)、--do_eval(是否边训练边评估,默认 True)。训练时每save_steps步保存一次model_{global_step}.pdparams,并在评估 F1 超过历史最优时额外保存best_model.pdparams。
多卡训练
使用paddle.distributed.launch启动分布式训练:
python -m paddle.distributed.launch --gpus "0,1" train.py \ --data_dir ./lexical_analysis_dataset_tiny \ --model_save_dir ./save_dir \ --epochs 10 \ --batch_size 32 \ --device gpu \ # --init_checkpoint ./save_dir/final从 train.py 可以看到多卡支持的内在逻辑:paddle.distributed.get_world_size()大于 1 时调用paddle.distributed.init_parallel_env(),使用paddle.io.DistributedBatchSampler做分布式采样,且仅rank == 0的进程执行模型保存与评估。
模型评估
通过加载训练保存的模型,对测试集进行验证(对应 eval.py):
python eval.py --data_dir ./lexical_analysis_dataset_tiny \ --init_checkpoint ./save_dir/model_100.pdparams \ --batch_size 32 \ --device gpu其中./save_dir/model_100.pdparams是训练过程中保存的参数文件,请替换为实际得到的训练保存路径。评估基于ChunkEvaluator计算 Precision、Recall 与 F1,日志形如eval precision: 0.xx, recall: 0.xx, f1: 0.xx(具体实现见 train.py 中的evaluate函数,eval.py与其同构)。
模型导出与部署预测
动态图转静态图导出
训练结束后,可通过 export_model.py 将动态图参数导出为静态图参数:
python export_model.py --data_dir=./lexical_analysis_dataset_tiny --params_path=./save_dir/model_100.pdparams --output_path=./infer_model/static_graph_params--params_path:动态图训练保存的参数路径;--output_path:静态图参数导出路径。
从源码看,导出流程为:加载word.dic与tag.dic重建BiGruCrf,paddle.load载入权重后经paddle.jit.to_static转换,input_spec声明为[None, None]的int64token_ids与[None]的int64length,最后paddle.jit.save保存静态图模型。
Python 部署预测
导出模型后即可用于部署,deploy/predict.py 提供了 Python 部署预测示例。
开启 PIR(PaddlePaddle 3.0.0 默认):
python deploy/predict.py --model_file=infer_model/static_graph_params.json --params_file=infer_model/static_graph_params.pdiparams --data_dir lexical_analysis_dataset_tiny未开启 PIR:
python deploy/predict.py --model_file=infer_model/static_graph_params.pdmodel --params_file=infer_model/static_graph_params.pdiparams --data_dir lexical_analysis_dataset_tiny模型预测
对无标签数据可启动模型预测(对应 predict.py,读取infer.tsv并输出results.txt):
python predict.py --data_dir ./lexical_analysis_dataset_tiny \ --init_checkpoint ./save_dir/model_100.pdparams \ --batch_size 32 \ --device gpu得到类似输出:
(大学, n)(学籍, n)(证明, n)(怎么, r)(开, v) (电车, n)(的, u)(英文, nz) (什么, r)(是, v)(司法, n)(鉴定人, vn)预测结果的组装逻辑位于 data.py 的 parse_result:将模型输出的标签 id 序列还原为标签文本后,按-B开头、O边界拼接字符还原词语,并剥离-B/-I后缀得到词性/专名主类别,最终得到(词, 标签)序列。
Taskflow 一键预测与自定义模型
开箱即用的一键调用
如果不想走完整训练链路,PaddleNLP 提供了 Taskflow 工具对输入文本进行一键分词与词性标注,用法见 LacTask 实现 中的 usage 与 示例工程 README:
from paddlenlp import Taskflow lac = Taskflow("lexical_analysis") lac("LAC是个优秀的分词工具") ''' [{'text': 'LAC是个优秀的分词工具', 'segs': ['LAC', '是', '个', '优秀', '的', '分词', '工具'], 'tags': ['nz', 'v', 'q', 'a', 'u', 'n', 'n']}] ''' lac(["LAC是个优秀的分词工具", "三亚是一个美丽的城市"]) ''' [{'text': 'LAC是个优秀的分词工具', 'segs': ['LAC', '是', '个', '优秀', '的', '分词', '工具'], 'tags': ['nz', 'v', 'q', 'a', 'u', 'n', 'n']}, {'text': '三亚是一个美丽的城市', 'segs': ['三亚', '是', '一个', '美丽', '的', '城市'], 'tags': ['LOC', 'v', 'm', 'a', 'u', 'n']} ] '''任务默认路径为$HOME/.paddlenlp/taskflow/lexical_analysis/lac/,其中包含执行该任务所需的全部文件。从 源码 可以看到LacTask的resource_files_names声明了四个必需资源:model_state.pdparams(模型权重)、tag.dic(标签词典)、q2b.dic(全角/半角归一化词典)、word.dic(字词典),首次调用时自动下载。预处理阶段(_preprocess)会先用q2b.dic将半角字符归一为全角,再经word.dic转 id,OOV作为未登录字 id;推理时通过静态图 predictor 执行(_run_model),后处理(_postprocess)按-B/O边界还原词与标签,并支持_auto_splitter对超长文本自动切分(_max_seq_len = 512)、_auto_joiner拼接回原始输入。LacTask还支持batch_size、num_workers、split_sentence等 kwargs 参数。
通过 Taskflow 加载自定义模型
如果希望得到定制化的分词及标注结果,可以通过 Taskflow 加载自定义词法分析模型进行预测:用model_path指定用户自定义路径(示例 README 中写作task_path),自定义路径下的文件需与默认路径一致:
custom_task_path/ ├── model.pdparams ├── word.dic ├── tag.dic └── q2b.dic加载并预测:
from paddlenlp import Taskflow my_lac = Taskflow("lexical_analysis", model_path="./custom_task_path/")同时,LacTask.__init__还支持user_dict参数,配合 Customization 工具 实现用户自定义词典的强制切分(_custom.load_customization(self._user_dict)后在后处理阶段parse_customization修正切分与标注)。更多 Taskflow 用法可参考 Taskflow 文档。
预训练模型参考
如需直接使用已经预训练好的 LAC 模型完成词法分析任务,可参考 Lexical Analysis of Chinese 与 PaddleHub 分词模型(lac),而 PaddleNLP 仓库内的 Taskflowlexical_analysis任务即内置了 LAC 预训练权重(模型资源定义),开箱即用。
小结
本文以 PaddleNLP 的 Lexical Analysis 教程 为主线,完整串联了中文词法分析从任务定义、GRU+CRF 建模原理,到数据准备、标签体系、单卡/多卡训练、评估、动态图转静态图导出、部署预测、Taskflow 一键调用与自定义模型加载的端到端流程。读者既可以通过 slm/examples/lexical_analysis 示例工程从零训练自己的词法分析模型,也可以借助 Taskflow 一键预测 在几行代码内完成中文分词与词性标注,或基于自定义词典与自定义模型获得完全可控的切分与标注结果。
- 人工智能
- 大模型
- NLP
- 深度学习
- 预训练
- 微调
- RLHF
- 模型量化
【免费下载链接】PaddleNLP
Easy-to-use and powerful LLM and SLM library with awesome model zoo.
相关推荐
OpenDisplay网络安全加固:UDP 9001、Bonjour暴露面与防火墙配置完整指南
OpenDisplay网络安全加固:UDP 9001、Bonjour暴露面与防火墙配置完整指南 OpenDisplay 是一款免费开源的 Sidecar / D
音视频桌面应用【亲测免费】 LAC (Lexical Analysis for Chinese) 安装与使用指南
LAC Lexical Analysis for Chinese 安装与使用指南 1. 项目目录结构及介绍 在解压或克隆完成 LAC https://githu
NLP10分钟搞懂AISystem量化训练(QAT):从原理到部署实践
10分钟搞懂AISystem量化训练 QAT :从原理到部署实践 你还在为模型部署时精度下降发愁?想让INT8模型达到FP32性能却不知从何入手?本文将详解AI
文档教程人工智能
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考