感知机框架
znlp 里有五个能力都建立在同一套感知机框架上:中文分词(CWS)、词性标注(POS)、命名实体(NER)、人名识别、拼音音节切分。框架本身是公开的,可以用自己的语料训练模型替换默认的。
包路径:dev.znlp.perceptron。
| 类型 | 作用 |
|---|---|
PerceptronModel |
运行时模型,持有特征集、标签数和参数数组,提供解码器 |
PerceptronInstance<E, InputSequence> |
训练与推理的抽象点,定义标签、特征提取、语料解析、评估 |
CharBasedPerceptronInstance |
字符级任务的基类,分词/NER/人名/拼音切分都继承它 |
PerceptronTrainer<E, InputSequence> |
训练器 |
PerceptronTrainModel |
训练产物,可压缩、可落盘、可转运行时模型 |
FeatureExtractor / CharDSLFeatureExtractor / FeatureTemplate |
特征模板 |
ViterbiPerceptronDecoder / OptimizedViterbiPerceptronDecoder / QuickPerceptronDecoder |
解码器 |
PerceptronModel
Section titled “PerceptronModel”// 构造new PerceptronModel( ImmutableFeatureSet featureSet, int labelCount, float[] parameter, boolean decodeQuickModel)
// 加载static PerceptronModel read(File file)static PerceptronModel readFromClasspath(String path)static PerceptronModel readFromNlpResource(NlpResourceLoader loader, String path)
// 使用model.getDecoder(); // 解码器model.getFeatureSet(); // 特征集decodeQuickModel 控制是否使用 QuickPerceptronDecoder——牺牲一点精度换取推理速度。
PerceptronTrainer<E, Input> trainer = new PerceptronTrainer<>(instance, workDir);
PerceptronTrainModel trainModel = trainer.train( trainFile, // 训练语料 evaluateFile, // 评估语料 iter, // 迭代轮数 threadNum, // 线程数 quickDecode // 是否用快速解码);workDir 用于存放中间产物,训练中断后可以复用。
PerceptronModel runtime = trainModel.toModel(); // 转运行时模型
trainModel.compress(ratio, threshold); // 参数压缩,减小模型体积
trainModel.saveModelBinFile(file, featureFormat); // 单文件 .bintrainModel.saveModelToDir(dir); // 目录式(feature.dat / parameter.bin / ...)
static PerceptronTrainModel m = PerceptronTrainModel.readModelFromDir(dir);目录式模型对应 data/dat/cws-model/{feature.dat, feature.txt, parameter.bin} 这种布局。compress 可以在模型过大时按比率和阈值裁剪低权重参数。
实现自己的 PerceptronInstance
Section titled “实现自己的 PerceptronInstance”这是复用框架的关键。需要实现:
| 方法 | 作用 |
|---|---|
getLables() |
标签集 |
getFeatureFun() |
返回 FeatureExtractor,定义特征模板 |
getAnnotateTextParser() |
把标注语料的一行解析成训练样本 |
getEvaluateFunction() |
评估函数 |
tansform(...) |
输入序列到特征序列的转换 |
字符级任务(分词、NER、人名、拼音切分)直接继承 CharBasedPerceptronInstance,能省掉大量样板代码。
参考实现:PosPerceptron.train 是最清晰的完整范例,它扫描语料确定标签集后交给 PerceptronTrainer。CWS、NER、人名的训练代码结构完全一致,可以照着改。
现成的运行时模型类
Section titled “现成的运行时模型类”不想训练、只想直接用模型时,这几个类提供了便捷的加载和推理入口:
CwsPerceptron(分词)
Section titled “CwsPerceptron(分词)”CwsPerceptron cws = Znlp.getService(CwsPerceptron.class);
List<String> words = cws.split("文本");
// 加载static CwsPerceptron load(NlpResourceLoader loader)static CwsPerceptron load(NlpResourceLoader loader, String modelDir)static CwsPerceptron loadFromDir(File dir)
// 工具方法:把 BMES 标签数组还原成词static List<String> labelsToWords(char[] text, int[] labels)默认模型目录常量是 znlp/cws-model。
Znlp.getService(CwsPerceptron.class) 拿到的是单例,模型只加载一次。仓库的 CwsPerceptronExample 就是这么用的——它不走流水线,直接调 cws.split,适合对比感知机分词和词典分词的效果差异。
PersonNamePerceptron(人名)
Section titled “PersonNamePerceptron(人名)”PersonNamePerceptron pn = Znlp.getPersonNamePerceptron();
List<String> names = pn.findPersonName("文本");List<String> names2 = pn.findPersonName(charArray);使用 BMEO 标注,常量 B=0 / M=1 / E=2 / O=3。模型资源 znlp/personname/nr-name.model。
PinyinSplitPerceptron(拼音切分)
Section titled “PinyinSplitPerceptron(拼音切分)”PinyinSplitPerceptron ps = Znlp.getService(PinyinSplitPerceptron.class);List<String> syllables = ps.split("nihaoshijie");模型资源 znlp/pinyin/pinyin-split.model。
PosPerceptron / NERPerceptron
Section titled “PosPerceptron / NERPerceptron”训练用的数据与工作目录
Section titled “训练用的数据与工作目录”仓库约定:
data/work/—— 训练工作目录,已有name-nr、ner-model、ner-model-dynamic、ner-model-new、pinyin-split、pos-model、pos.data等历史产物data/dat/—— 目录式模型(cws-model/、ner-model/)- 外部大数据集放在项目根的同级目录
znlp-data/,其中data_train/{name-nr, ner, pinyin-split}是训练语料,不随仓库分发(见根目录data-dir-meta.txt)