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

自定义类经pickle/dill序列化后重启进程字典字段为空

跨进程加载Pickle的NgramModel实例丢失字典字段数据

我尝试序列化并永久存储自定义类NgramModel的实例,遇到如下问题:

  • 同一进程内完成序列化、存储、加载并使用时,所有字段均正常;
  • 结束进程后重新从pickle文件加载实例,context_options和ngram_count两个字典字段为空,但其他字段(如n、num_paragraphs等)完整正确。

正常运行的代码(同一进程内)

first_model = NgramModel(3, name="debug")

for paragraph in text:
    first_model.train(paragraph_to_sentences(text))
    # paragraph_to_sentences 用正则按标点分割文本为句子

print(first_model.context_options)
# 输出正常的counter字典

first_model = NgramModel.load_existing_model("debug")
# load_existing_model 加载pickle文件

print(first_model.context_options)
# 输出依然正常

重启进程后单独运行的代码(输出空counter)

first_model = NgramModel.load_existing_model("debug")

print(first_model.context_options)
# 输出空字典

问题根源

问题出在NgramModel类的属性定义上:context_options和ngram_count被设置为类级属性,而非实例级属性。

当你在实例中调用self.ngram_count.update()或修改self.context_options时,并没有为当前实例创建独立的属性,而是直接修改了类本身的共享属性。同一进程内类的状态会被保留,所以加载后能看到修改结果;但重启进程后,新进程的NgramModel类会重新初始化,这两个类属性回到初始空值,而pickle加载时不会覆盖类属性,导致实例使用的依然是类的空属性。

解决方案

在__init__方法中初始化这两个属性为实例级属性,确保每个实例拥有独立的字典数据:

修改后的NgramModel核心代码:

import os
import dill
from itertools import count
from collections import Counter
from os import path


class NgramModel:
    # 仅保留类型注解,不初始化类级数据
    context_options: dict[tuple, set[str]]
    ngram_count: Counter[tuple]
    n: int
    pickle_path: str
    num_paragraphs: int
    num_sentences: int

    def __init__(self, n: int, **kwargs):
        self.n = n
        self.pickle_path = NgramModel.pathify(kwargs.get('name', NgramModel.gen_pickle_name()))
        # 初始化实例专属属性
        self.context_options = {}
        self.ngram_count = Counter()
        self.num_paragraphs = 0
        self.num_sentences = 0

    # 其余方法保持不变...

修改后重新训练并序列化实例,重启进程加载后,context_options和ngram_count会正确加载保存的数据,不再为空。

内容的提问来源于stack exchange,提问作者David Tejuosho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:15:39