5

我正在尝试使用 Stanford CoreNLP 库,并且我想序列化主要的 StanfordCoreNLP 管道对象,即使它抛出了 java.io.NotSerializableException。

全文:每当我运行我的实现时,将管道注释器和分类器加载到内存中大约需要 15 秒。最终进程在内存中大约有 600MB(很容易小到可以存储在我的案例中)。我想在第一次创建它之后保存这个管道,所以我可以稍后将它读入内存。

但是它会引发 NotSerializableException。我尝试制作一个实现 Serializable 的简单子类,但 StanfordCoreNLP 具有未实现此接口的注释器和分类器属性,并且我无法为所有它们创建子类。

是否有任何 Java 库可以序列化不实现 Serializable 的对象?我想它必须通过它的属性递归并对任何类似的对象做同样的事情。

我试过的序列化代码:

static StanfordCoreNLP pipeline;
static String file = "/Users/ME/Desktop/pipeline.sav";
    static StanfordCoreNLP pipeline() {
    if (pipeline == null) {
        try {
            FileInputStream saveFile = new FileInputStream(file);
            ObjectInputStream read = new ObjectInputStream(saveFile);
            pipeline = (StanfordCoreNLP) read.readObject();
            System.out.println("Pipeline loaded from file.");
            read.close();
        } catch (FileNotFoundException e) {
            System.out.println("Cached pipeline not found. Creating new pipeline...");
            Properties props = new Properties();
            props.put("annotators", "tokenize, ssplit, pos, lemma, ner, parse, dcoref");
            pipeline = new StanfordCoreNLP(props);
            savePipeline(pipeline);
        } catch (IOException e) {
            System.err.println(e.getLocalizedMessage());
        } catch (Exception e) {
            System.err.println(e.getLocalizedMessage());
        }
    }
    return pipeline;
}

static void savePipeline(StanfordCoreNLP pipeline) {
    try {
        FileOutputStream saveFile = new FileOutputStream(file);
        ObjectOutputStream save = new ObjectOutputStream(saveFile);
        save.writeObject(pipeline);
        System.out.println("Pipeline saved to file.");
        save.close();
    } catch (FileNotFoundException e) {
        System.out.println("Pipeline file not found during save.");
    } catch (IOException e) {
        System.err.println(e.getLocalizedMessage());
    }
}
4

2 回答 2

2

一般来说,代表数据对象的斯坦福 NLP 类(Tree、LexicalizedParser 等)是可序列化的,而代表处理器的类(StanfordCoreNLP、LexicalizedParserQuery、CRFClassifier)则不是。为了实现您的要求,您需要使许多类可序列化,而这些类不是可序列化的,并处理由此产生的任何后果。

但是,我认为您的基本思想是错误的。StanfordCoreNLP 在这 15 秒内加载的主要是标准的 java 序列化对象。NER 分类器和解析器语法是标准的序列化 java 对象。(有些东西不是这种形式,而只是二进制数据,包括 POS 标记器,主要是出于历史原因。)事实上,使用标准 Java 序列化加载大量对象并不是那么快......你可以在网上找到关于 Java 序列化速度以及替代方案速度比较的讨论。制作一个包含所有当前序列化对象的新的更大的序列化对象并不能让它更快。(通过将所有东西都放在一个连续的数据流中,您可能会获得一小部分,

相反,我建议处理这个问题的关键是只支付一次加载系统的成本,然后在处理许多句子时将其保存在内存中。

于 2012-09-06T05:25:19.123 回答
1

如果确实它不可序列化的唯一原因是它没有被标记为Serializable,那么您可能能够摆脱一些非默认的序列化策略。例如,您可以尝试JacksonXStream

也就是说,如果有一个很好的理由,它Serializable首先不是,这些策略可能会以有趣的方式打破。彻底测试!

于 2012-09-04T04:38:06.657 回答