You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spacy 3.0无配置文件实现早停、交叉验证与权重初始化设随机种子

Spacy文本分类:无配置文件实现早停、交叉验证与随机种子固定

1. 固定随机种子

在训练开始前,通过以下代码固定全局随机种子,确保权重初始化和训练过程的可复现性:

import spacy
import random
import numpy as np
import os

# 固定随机种子
SEED = 42
os.environ['PYTHONHASHSEED'] = str(SEED)
random.seed(SEED)
np.random.seed(SEED)
spacy.util.fix_random_seed(SEED)

2. 手动实现早停

在训练循环中跟踪验证集性能,设置patience参数(允许连续多少个epoch无性能提升),当触发条件时终止训练:

  • 记录最佳验证得分
  • 统计连续无提升的epoch数
  • 当计数超过patience时停止训练
  • 可选:保存性能最佳的模型

3. K折交叉验证

使用KFold拆分数据集,每次用K-1份数据训练,1份验证,循环完成所有折后计算平均性能。这里可以借助sklearn.model_selection.KFold实现数据拆分。


完整整合代码

import spacy
import random
import numpy as np
import os
from sklearn.model_selection import KFold
from spacy.training import Example

# ----------------------
# 1. 固定随机种子
# ----------------------
SEED = 42
os.environ['PYTHONHASHSEED'] = str(SEED)
random.seed(SEED)
np.random.seed(SEED)
spacy.util.fix_random_seed(SEED)

# 准备数据集(格式示例:[(文本, {"cats": {"类别1": 0, "类别2": 1}}), ...])
all_data = [...]  # 替换为你的完整数据集

# ----------------------
# 2. K折交叉验证设置
# ----------------------
K = 5  # 5折交叉验证
kf = KFold(n_splits=K, shuffle=True, random_state=SEED)
fold_scores = []

for fold_idx, (train_idx, val_idx) in enumerate(kf.split(all_data)):
    print(f"\n=== 第 {fold_idx+1}/{K} 折 ===")
    
    # 拆分训练和验证数据
    train_data = [all_data[i] for i in train_idx]
    val_data = [all_data[i] for i in val_idx]
    
    # 初始化Spacy文本分类模型
    nlp = spacy.blank("en")
    textcat = nlp.add_pipe("textcat", config={"exclusive_classes": True, "architecture": "simple_cnn"})
    
    # 添加标签
    labels = list(set([list(item[1]["cats"].keys())[0] for item in all_data]))
    for label in labels:
        textcat.add_label(label)
    
    # 初始化优化器
    optimizer = nlp.begin_training()
    
    # ----------------------
    # 3. 早停设置
    # ----------------------
    PATIENCE = 3  # 连续3个epoch无提升则停止
    best_val_score = 0.0
    no_improve_count = 0
    max_epochs = 25
    
    for epoch in range(max_epochs):
        losses = {}
        # 打乱训练数据
        random.shuffle(train_data)
        
        # 小批量训练
        batches = spacy.util.minibatch(train_data, size=8)
        for batch in batches:
            examples = []
            for text, annotations in batch:
                doc = nlp.make_doc(text)
                example = Example.from_dict(doc, annotations)
                examples.append(example)
            nlp.update(examples, sgd=optimizer, losses=losses)
        
        print(f"Epoch {epoch+1}, 训练损失: {losses['textcat']:.4f}")
        
        # 验证阶段
        val_score = nlp.evaluate(val_data)["textcat_f"]  # 取F1得分作为早停指标
        print(f"验证F1得分: {val_score:.4f}")
        
        # 早停逻辑
        if val_score > best_val_score:
            best_val_score = val_score
            no_improve_count = 0
            # 保存最佳模型
            nlp.to_disk(f"./best_model_fold_{fold_idx+1}")
        else:
            no_improve_count += 1
            if no_improve_count >= PATIENCE:
                print(f"连续{PATIENCE}个epoch无性能提升,提前停止训练")
                break
    
    fold_scores.append(best_val_score)
    print(f"第{fold_idx+1}折最佳F1得分: {best_val_score:.4f}")

# 输出交叉验证平均得分
print(f"\n=== 交叉验证结果 ===")
print(f"各折最佳F1得分: {[round(s,4) for s in fold_scores]}")
print(f"平均F1得分: {np.mean(fold_scores):.4f} ± {np.std(fold_scores):.4f}")

关键说明

  • 随机种子:通过全局设置确保模型初始化、数据拆分、训练过程的随机性完全可控,避免每次训练结果差异过大。
  • 早停:以验证集F1得分为指标,当连续指定次数epoch无提升时终止训练,避免过拟合,同时保存性能最优的模型。
  • 交叉验证:通过KFold将数据集拆分为K份,每份轮流作为验证集,最终取平均性能作为模型的可靠评估结果。

内容的提问来源于stack exchange,提问作者Pranjal Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 10:15:25