链载Ai

标题: spaCy中文分句模型微调秘籍,从数据准备到模型评测,一学就会! [打印本页]

作者: 链载Ai    时间: 昨天 21:23
标题: spaCy中文分句模型微调秘籍,从数据准备到模型评测,一学就会!

spaCy中文分句模型微调秘籍,从数据准备到模型评测,一学就会

🎯 文章目标

本次文章配套代码地址:https://github.com/li-xiu-qi/XiaokeAILabs/tree/main/datas/spacy_finetune

后续可能会微调一个专门用来分块的模型,感兴趣的同学欢迎联系我或者给项目一个star哦,仓库地址:https://github.com/li-xiu-qi/spacy_chuking

📋 目录



🚁 前言

在实际 NLP 项目中,中文分句往往是文本处理的第一步,但 spaCy 默认的分句效果在面对特殊标点、缩写、省略号、对话等复杂情况时,常常难以满足高精度需求。很多同学会问:spaCy 到底有哪些分句方案?如何选择最适合自己的分句方式?能不能既高效又智能地实现分句,甚至扩展到更复杂的文本分块?

本教程将系统梳理 spaCy 的分句原理与工程实现,带你从最基础的规则分句(Sentencizer)、到可训练的 senter 组件、再到依存句法驱动的 DependencyParser,逐步深入每种方案的优缺点和适用场景。你不仅能学会如何微调 spaCy 分句模型,还能理解不同模型结构(CNN/Transformer)的本质区别,掌握如何根据实际需求灵活选择 pipeline 组件。更重要的是,本文还将带你思考如何将分句思想扩展到 RAG 等智能分块场景,助力你的文本处理系统更上一层楼。

🧠 spaCy句子分割理论与工程基础补充

1. 句子边界检测(SBD)在NLP中的基础性作用

句子边界检测(Sentence Boundary Detection, SBD)是自然语言处理(NLP)中的基础模块,其准确性直接影响分词、词性标注、依存句法、命名实体识别等下游任务。SBD的难点在于标点符号的歧义性(如缩写、小数点、省略号等),这使得“遇到句号就分割”远远不够,必须结合上下文、词性、大小写等多维特征。现代NLP通常将SBD视为一个分类问题,针对每个潜在边界点,利用统计学习或神经网络模型进行判别。

SBD主流方法简述

多语言与领域适应性

不同语言和专业领域(如医学、法律、金融)对SBD有不同挑战。spaCy支持多语言和可定制微调,能适应多样化场景。

2. spaCy三大句子分割策略对比

组件
可训练
速度
准确率
依存信息
适用场景
DependencyParser
需要依存句法的复杂NLP任务
senter
只需分句,需高精度
Sentencizer
极快
低-中
规则明确、格式规范的文本

在实际应用中,Sentencizer 是 spaCy 提供的基于规则的分句器,它无需任何训练和标注数据,只依赖简单的标点规则(如句号、问号、感叹号等)进行分句,非常适合规则明确、对分句精度要求不高的场景。你只需在 pipeline 里加上sentencizer组件即可直接使用。例如:

importspacy
nlp = spacy.blank("zh")
nlp.add_pipe("sentencizer")
doc = nlp("今天天气很好。我想去公园。你呢?")
forsentindoc.sents:
print(sent.text)

Sentencizer 开箱即用,无需训练,适合快速分句需求。

选择建议:

在 spaCy 的 senter 组件中,默认采用的是 CNN(如 HashEmbedCNN)结构实现。你也可以通过修改 config 文件,切换为 transformer 或其他结构,但默认就是 CNN。CNN 结构需配置 window_size,决定每个 token 能看到的上下文范围;而 transformer 结构无需配置窗口,能自动建模全局上下文(只受最大 token 长度限制)。如果你的分句任务主要依赖于局部标点和短距离上下文,CNN结构即可满足需求且效率高;如果文本结构复杂、长距离依赖明显,或希望获得更强的泛化能力,建议优先尝试Transformer结构。

此外,spaCy 的 senter 或 transformer+senter 组件在推理时,是将整段文本(如一整个句子或段落)分词后,作为一个整体输入模型,而不是每次只输入几个单词。spaCy 会自动处理超长文本的切分,最大 token 数由 transformer 模型决定(如 512)。这意味着 spaCy senter/transformer 是“整段文本分词后一起输入模型”,不是每次只输入3或5个词(窗口大小)。

parser 组件的分句原理

当 pipeline 里有 parser(依存句法分析器)时,spaCy 会先预测每个 token 的依存关系,构建依存树,再结合规则自动判断句子边界(如遇到 ROOT 节点、特定标点等)。这种方式能处理复杂句法结构,比单纯靠标点分句更智能。例如:“他说:你去吧,然后回来。”,parser 能识别“你去吧”是独立分句,即使没有明显句号。

spaCy 默认的句法依存分析器(parser)最早是基于 CNN+特征嵌入(HashEmbedCNN)和动态过渡系统(transition-based parser)实现的。但在新版 spaCy(v3 及以后),parser 也可以用 transformer 作为特征提取器(tok2vec),即“transformer+transition-based parser”结构。你可以在 config 文件里选择 tok2vec 用 CNN 还是 transformer。

总结来说,spaCy 的依存分析器既可以用 CNN,也可以用 transformer,取决于你的配置。

如果你用 transformer+senter 进行句子分割,通常不需要再依赖句法依存分析(parser)来分句。transformer+senter 已经能利用全局上下文和强大的特征表达能力,通常分句效果比传统 CNN 更好,适合复杂文本。senter 组件专门为句子边界识别而设计,训练目标就是分句,不依赖依存结构。只有在你还需要做依存句法分析(比如后续要用依存树做信息抽取、关系抽取等任务)时,才需要加 parser 组件。

🗺️ 整体流程概览

  1. 🛠️ 环境准备
  2. 🖊️ 数据准备与标注
  3. 🔄 数据格式转换
  4. ⚙️ 配置文件初始化
  5. 🏋️‍♂️ 模型训练(标准/Transformer)
  6. 🧪 模型推理与效果展示

🪄 微调难度说明

微调 spaCy 的句子分割器相对简单,主要流程包括数据准备、配置文件初始化、模型训练和评估。spaCy 已经为我们封装了大部分底层实现细节。我们只需准备好特定格式的数据(如 jsonl 或 spacy 格式),并通过简单的配置文件指定训练参数,无需手动编写复杂的深度学习训练代码。整个微调流程高度自动化,极大降低了上手门槛,下面从环境配置开始,注意不要使用过高的python版本,否则会导致一些库的兼容问题。

🛠️ 环境准备

建议使用 Python 3.10 及以下版本。推荐新建虚拟环境,并安装 spaCy 及相关依赖:

python -m venv .venv
source.venv/bin/activate
pip install -r tests/requirements.txt

📑 数据准备与格式说明

训练数据需为 spaCy 支持的 jsonl 或 spacy 格式。每条数据应包含文本及句子边界标注。

具体可以参考下面的示例:

{"text":"今天天气很好。我想去公园。","tokens": ["今天天气","很","好","。","我","想","去","公园","。"],"sent_starts": [true,false,false,false,true,false,false,false,false]}
{"text":"小明喜欢看书,也喜欢运动。你呢?","tokens": ["小明","喜欢","看书",",","也","喜欢","运动","。","你","呢","?"],"sent_starts": [true,false,false,false,false,false,false,false,true,false,false]}

这里的数据格式是 spaCy 句子分割器(senter)训练所需的 jsonl 格式,每一行为一个 JSON 对象,包含两个字段:

举例说明:

{"text": "今天天气很好。我想去公园。", "tokens": ["今天天气", "很", "好", "。", "我", "想", "去", "公园", "。"], "sent_starts": [true, false, false, false, true, false, false, false, false]}

字段解释:

例如,上面例子中:

这样 spaCy 就能根据sent_starts信息,学习如何在中文文本中正确分句。


🔄 jsonl 转 spaCy 格式脚本

如果你需要将上述 jsonl 格式的数据转换为 spaCy 所需的 .spacy 格式,可以参考如下脚本:

importspacy
fromspacy.tokensimportDoc, DocBin
importjson

nlp = spacy.blank("zh")
doc_bin = DocBin()

withopen("senter_train.jsonl","r", encoding="utf-8")asf:
forlineinf:
example = json.loads(line)
tokens = example["tokens"]
sent_starts = example["sent_starts"]
iflen(tokens) != len(sent_starts):
raiseValueError(f"tokens 数与 sent_starts 不一致:{tokens}\nsent_starts:{sent_starts}")
doc = Doc(nlp.vocab, words=tokens)
fori, tokeninenumerate(doc):
token.is_sent_start = sent_starts[i]
doc_bin.add(doc)

doc_bin.to_disk("senter_train.spacy")
print("已生成 senter_train.spacy ")

脚本会读取 jsonl 文件,生成 spaCy 训练所需的二进制数据文件(.spacy)。其作用是:将标注了句子起始信息的 jsonl 格式数据,转换为 spaCy 训练所需的二进制格式(.spacy文件),用于训练 spaCy 的句子分割器(senter)。

Doc是 spaCy 的核心数据结构之一,表示经过分词和注解的一段文本。本质上是一个“文档对象”,包含分词后的 token 列表及各种语言学特征(如词性、句法、实体等)。

在本脚本中,Doc对象的创建方式如下:

doc = Doc(nlp.vocab, words=tokens)

nlp.vocab:当前语言环境的词汇表(vocab),支持 spaCy 的各种词汇特性。words=tokens:分词后的 token 列表(字符串列表),每个元素对应文本中的一个 token。

这样创建的Doc对象包含了自定义的分词结果,后续可为每个 token 设置句子起始标记(is_sent_start),用于训练 spaCy 的句子分割模型。

DocBin是 spaCy 提供的高效二进制序列化工具,用于批量存储和管理多个Doc对象。它可将大量Doc文档对象打包成一个二进制文件(如.spacy),便于模型训练和分发。

在本脚本中,DocBin对象的创建方式如下:

doc_bin = DocBin()

每处理好一个Doc,通过doc_bin.add(doc)加入容器。最后用doc_bin.to_disk("senter_train.spacy")一次性保存为 spaCy 训练所需的二进制格式文件。

🖨️ 读取 .spacy 文件并打印每个 doc 的句子分割结果

你可以用下面的代码快速验证 .spacy 文件中的分句效果:

importspacy
fromspacy.tokensimportDocBin

# 读取 .spacy 文件并打印每个 doc 的句子分割结果
nlp = spacy.blank("zh")
doc_bin = DocBin().from_disk("senter_train.spacy")
docs = list(doc_bin.get_docs(nlp.vocab))

fori, docinenumerate(docs):
print(f"Doc{i+1}:")
forsentindoc.sents:
print(f" 句子:{sent.text}")
print("-"*20)

输出:

Doc 1:
句子: 今天天气 很 好 。
句子: 我 想 去 公园 。
--------------------
Doc 2:
句子: 小明 喜欢 看书 , 也 喜欢 运动 。
句子: 你 呢 ?
--------------------

这样可以直接看到每个 doc 的分句效果,方便检查数据标注和格式是否正确。

在上面代码中,get_docs(nlp.vocab)的作用是:

简而言之,get_docs(nlp.vocab)就是“用当前的词汇表,把二进制数据还原成 spaCy 的文档对象列表”,是 spaCy 官方推荐的标准用法。

⚙️ 配置文件初始化

spaCy 训练依赖 config 文件。推荐用命令自动生成:

python -m spacy init config config.cfg --pipeline senter --lang zh

📝 config 文件定义了训练流程、模型结构、超参数,更多可选的参数请看官方文档等。

运行后会输出一个内容大概是这样的config.cfg文件:

[paths]
train = null
dev = null
vectors = null
init_tok2vec = null

[system]
gpu_allocator = null
seed = 0

[nlp]
lang ="zh"
pipeline = ["senter"]
batch_size = 1000
disabled = []
before_creation = null
after_creation = null
after_pipeline_creation = null
vectors = {"@vectors":"spacy.Vectors.v1"}

[nlp.tokenizer]
@tokenizers ="spacy.zh.ChineseTokenizer"
segmenter ="jieba"

[components]

[components.senter]
factory ="senter"
overwrite =false
scorer = {"@scorers":"spacy.senter_scorer.v1"}

[components.senter.model]
@architectures ="spacy.Tagger.v2"
nO = null
normalize =false

[components.senter.model.tok2vec]
@architectures ="spacy.HashEmbedCNN.v2"
pretrained_vectors = null
width = 12
depth = 1
embed_size = 2000
window_size = 1
maxout_pieces = 2
subword_features =true

[corpora]

[corpora.dev]
@readers ="spacy.Corpus.v1"
path =${paths.dev}
max_length = 0
gold_preproc =false
limit= 0
augmenter = null

[corpora.train]
@readers ="spacy.Corpus.v1"
path =${paths.train}
max_length = 0
gold_preproc =false
limit= 0
augmenter = null

[training]
dev_corpus ="corpora.dev"
train_corpus ="corpora.train"
seed =${system.seed}
gpu_allocator =${system.gpu_allocator}
dropout = 0.1
accumulate_gradient = 1
patience = 1600
max_epochs = 0
max_steps = 20000
eval_frequency = 200
frozen_components = []
annotating_components = []
before_to_disk = null
before_update = null

[training.batcher]
@batchers ="spacy.batch_by_words.v1"
discard_oversize =false
tolerance = 0.2
get_length = null

[training.batcher.size]
@schedules ="compounding.v1"
start = 100
stop = 1000
compound = 1.001
t = 0.0

[training.logger]
@loggers ="spacy.ConsoleLogger.v1"
progress_bar =false

[training.optimizer]
@optimizers ="Adam.v1"
beta1 = 0.9
beta2 = 0.999
L2_is_weight_decay =true
L2 = 0.01
grad_clip = 1.0
use_averages =false
eps = 0.00000001
learn_rate = 0.001

[training.score_weights]
sents_f = 1.0
sents_p = 0.0
sents_r = 0.0

[pretraining]

[initialize]
vectors =${paths.vectors}
init_tok2vec =${paths.init_tok2vec}
vocab_data = null
lookups = null
before_init = null
after_init = null

[initialize.components]

[initialize.tokenizer]
pkuseg_model = null
pkuseg_user_dict ="default"

🏋️‍♂️ 训练模型

基于默认的模型进行训练

训练集和验证集都用同一份数据,因为我们这里是示例:

python -m spacy train config.cfg \
--paths.train data/senter_train.spacy \
--paths.dev data/senter_train.spacy \
--output output_model

训练过程会输出日志,最终模型在output_model/model-best

🤖 使用 Transformer 训练

如果你希望用 transformer 结构进行句子分割微调,可以使用如下命令(需准备好 transformer 配置文件 config_trf.cfg)。

使用 GPU 训练:

python -m spacy train config_trf.cfg \
--gpu-id 0 \
--paths.train data/senter_train.spacy \
--paths.dev data/senter_train.spacy \
--output output_model_trf

使用 CPU 训练:

python -m spacy train config_trf.cfg \
--paths.train data/senter_train.spacy \
--paths.dev data/senter_train.spacy \
--output output_model_trf

📝 Transformer 配置文件示例

下面是一个 spaCy Transformer 配置文件(config_trf.cfg)示例,适用于中文句子分割任务,并附有详细注释:

# [paths] 部分用于定义关键文件的路径,在训练时通过命令行传入。
[paths]
train = null
dev = null
vectors = null
init_tok2vec = null

# [system] 部分用于配置训练的硬件和可复现性。
[system]
# gpu_allocator: 设置使用的GPU内存分配器。
# "pytorch" 是推荐值。设为 null 或 none 则使用CPU。
gpu_allocator = pytorch
# seed: 随机种子,用于确保每次训练结果的可复现性。
seed = 0

# [nlp] 部分是流水线(pipeline)的核心配置。
[nlp]
lang = "zh"
# pipeline: 定义组件的处理顺序。这里,文本会先经过 transformer 组件,
# 然后其输出会作为 senter 组件的输入。顺序至关重要。
pipeline = ["transformer", "senter"]
# batch_size: 一次处理的文本数量。可根据内存大小调整。
batch_size = 1000
disabled = []
before_creation = null
after_creation = null
after_pipeline_creation = null

[nlp.tokenizer]
# @tokenizers: 指定中文分词器。
@tokenizers = "spacy.zh.ChineseTokenizer"
segmenter = "jieba"

# ===================================================================
# 组件 (Components) 配置
# ===================================================================
[components]

# [components.transformer] 定义了 Transformer 组件本身。
[components.transformer]
factory = "transformer"

[components.transformer.model]
@architectures = "spacy-transformers.TransformerModel.v3"
# name: 指定要使用的 Hugging Face Hub 上的预训练模型。
# 例如 "bert-base-chinese" 或 "hfl/chinese-roberta-wwm-ext"。
# spaCy 会在首次运行时自动下载。
name = "bert-base-chinese"
tokenizer_config = {"use_fast": true}

# [components.senter] 定义了句子切分器 (Sentence Recognizer)。
[components.senter]
factory = "senter"
overwrite = false
scorer = {"@scorers":"spacy.senter_scorer.v1"}

[components.senter.model]
@architectures = "spacy.Tagger.v2"
nO = null
normalize = false

[components.senter.model.tok2vec]
# @architectures: 指定 tok2vec (token-to-vector) 的架构。
# "TransformerListener" 是一个特殊组件,它本身不产生向量,
# 而是“监听”并直接使用上游 "transformer" 组件生成的、带有上下文信息的向量。
@architectures = "spacy-transformers.TransformerListener.v1"
grad_factor = 1.0
# pooling: 定义如何将一个词的多个子词(word-piece)的向量聚合成一个单一向量。
# "reduce_mean.v1" 表示使用平均值策略。
pooling = {"@layers":"reduce_mean.v1"}

# ===================================================================
# 语料库 (Corpora) 配置
# ===================================================================

[corpora]

[corpora.dev]
@readers = "spacy.Corpus.v1"
path = ${paths.dev}
max_length = 0
gold_preproc = false
limit = 0
augmenter = null

[corpora.train]
@readers = "spacy.Corpus.v1"
path = ${paths.train}
max_length = 0
gold_preproc = false
limit = 0
augmenter = null

# ===================================================================
# 训练 (Training) 配置
# ===================================================================
[training]
dev_corpus = "corpora.dev"
train_corpus = "corpora.train"
seed = ${system.seed}
gpu_allocator = ${system.gpu_allocator}
# dropout: 在训练期间随机丢弃一部分神经元,是防止过拟合的常用技巧。
dropout = 0.1
# accumulate_gradient: 梯度累积。如果显存不足,可设为 >1 的整数(如2, 4)。
# 这会用更多训练时间来换取更低的显存消耗。
accumulate_gradient = 1
# patience: 早停机制。如果在连续 1600 步内模型性能都没有提升,训练将自动停止。
patience = 1600
max_epochs = 0
# max_steps: 最大训练步数。若设为 0,则由 max_epochs 控制训练长度。
max_steps = 20000
# eval_frequency: 每训练多少步,就在开发集上评估一次性能。
eval_frequency = 200
frozen_components = []
annotating_components = []
before_to_disk = null
before_update = null

[training.batcher]
# @batchers: 定义如何将数据打包成批次 (batch)。
# "spacy.batch_by_words.v1" 会尽量让每个批次包含差不多数量的词。
@batchers = "spacy.batch_by_words.v1"
discard_oversize = false
tolerance = 0.2
get_length = null

[training.batcher.size]
# @schedules: 定义批次大小的变化策略。
# "compounding.v1" 表示批次大小从 start 值平滑增长到 stop 值。
@schedules = "compounding.v1"
start = 100
stop = 1000
compound = 1.001
t = 0.0

[training.logger]
@loggers = "spacy.ConsoleLogger.v1"
progress_bar = true

[training.optimizer]
@optimizers = "Adam.v1"
beta1 = 0.9
beta2 = 0.999
L2_is_weight_decay = true
L2 = 0.01
grad_clip = 1.0
use_averages = false
eps = 0.00000001
# learn_rate: 学习率。对于 Transformer 微调,一个较小的值(如 2e-5)是很好的起点。
learn_rate = 2e-5

[training.score_weights]
# sents_f: 评估时使用的主要分数,这里是句子切分的 F1-score。
sents_f = 1.0
sents_p = 0.0
sents_r = 0.0

[pretraining]

# [initialize] 部分用于在训练开始前初始化组件。
[initialize]
vectors = null
init_tok2vec = null
vocab_data = null
lookups = null
before_init = null
after_init = null

[initialize.components]

如需自定义 transformer 预训练模型、分词方式,可在此基础上修改。

🤔 Transformer 预训练模型选择建议

🛠️ 关键超参数调优指南

合理选择模型和调优超参数,有助于在硬件资源允许的前提下获得最佳分句效果。

⚡ 使用 transformer 结构通常能获得更好的效果,但对显存和硬件要求更高。 根据我的本地环境测试,GPU为A6000,代码如果使用cpu训练cnn版本的模型,大概1分钟内可以完成训练,而训练transformer版本的模型需要使用GPU训练大概几分钟,如果是CPU可能需要十几分钟。不过本次文章的超参数是我乱设置的,实际训练的时候建议调整一下。

🧪 模型推理与效果展示

训练完成后,可以直接加载模型进行分句推理。下面分别演示如何加载标准模型和 transformer 结构训练的模型,并输出分句结果:

importspacy

# 加载标准模型
test_text ="今天天气很好。我想去公园。"
nlp = spacy.load("output_model/model-best")
doc = nlp(test_text) # 直接用pipeline处理原始文本
print("标准模型分句结果(spaCy自带分词+完整pipeline):")
print("ipeline 组件:", nlp.pipe_names)
fortokenindoc:
print(token.text, token.is_sent_start)
print("\n分句结果:")
forsentindoc.sents:
print(sent.text)

# 加载 transformer 结构训练的模型
nlp_trf = spacy.load("output_model_trf/model-best")
doc_trf = nlp_trf(test_text) # 直接用pipeline处理原始文本
print("\nTransformer 模型分句结果(spaCy自带分词+完整pipeline):")
print("ipeline 组件:", nlp_trf.pipe_names)
fortokenindoc_trf:
print(token.text, token.is_sent_start)
print("\n分句结果:")
forsentindoc_trf.sents:
print(sent.text)

输出:

标准模型分句结果(spaCy自带分词+完整pipeline):
Pipeline 组件: ['senter']
今天天气 True
很 False
好 False
。 False
我 True
想 False
去 False
公园 False
。 False

分句结果:
今天天气很好。
我想去公园。

Transformer 模型分句结果(spaCy自带分词+完整pipeline):
Pipeline 组件: ['transformer','senter']
今天天气 True
很 False
好 False
。 False
我 True
想 False
去 False
公园 False
。 False

分句结果:
今天天气很好。
我想去公园。

上述代码会分别输出标准模型和 transformer 微调模型的分句效果,便于直观对比模型分割效果。

📝 代码说明

下面通过一个实际代码示例,帮助理解 nlp、doc、pipe_names、token、sents 的用法:

importspacy

# 加载模型
nlp = spacy.load("output_model/model-best")

# nlp 对象:可以直接处理原始文本
text ="小明喜欢看书,也喜欢运动。你呢?"
doc = nlp(text)

# pipe_names:查看 pipeline 组件
print("ipeline 组件:", nlp.pipe_names) # 例如 ['transformer', 'senter']

# doc 对象:结构化文本,支持遍历 token
print("所有 token:")
fortokenindoc:
print(f"{token.text}\t是否句子起始:{token.is_sent_start}")

# token 对象:每个 token 的属性
first_token = doc[0]
print(f"第一个 token:{first_token.text}, 是否句子起始:{first_token.is_sent_start}")

# sents:遍历分句结果
print("\n分句结果:")
forsentindoc.sents:
print(sent.text)

输出如下:

Pipeline 组件: ['senter']
所有 token:
小明 是否句子起始: True
喜欢 是否句子起始: False
看书 是否句子起始: False
, 是否句子起始: False
也 是否句子起始: False
喜欢 是否句子起始: False
运动 是否句子起始: False
。 是否句子起始: False
你 是否句子起始: True
呢 是否句子起始: False
? 是否句子起始: False
第一个 token: 小明, 是否句子起始: True

分句结果:
小明喜欢看书,也喜欢运动。
你呢?

如果换成transformer模型,那么输出结果会变成这样:

Pipeline 组件: ['transformer','senter']
所有 token:
小明 是否句子起始: True
喜欢 是否句子起始: False
看书 是否句子起始: False
, 是否句子起始: False
也 是否句子起始: False
喜欢 是否句子起始: False
运动 是否句子起始: False
。 是否句子起始: False
你 是否句子起始: True
呢 是否句子起始: False
? 是否句子起始: False
第一个 token: 小明, 是否句子起始: True

分句结果:
小明喜欢看书,也喜欢运动。
你呢?

通过这个例子可以直观理解 spaCy 推理流程中各对象的作用和输出。

📈 微调效果与评估

微调后,模型能更准确地识别句子边界,减少误分割和漏分割。例如,能更好地处理缩写、省略号、特殊标点、特殊表达等情况。实际效果可通过在自有数据集上的评估指标(如准确率、召回率、F1 分数等)体现。

如果你需要对分句模型进行评测,推荐的做法如下:

  1. 准备评测集






欢迎光临 链载Ai (https://www.lianzai.com/) Powered by Discuz! X3.5