我正在试验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());
}
}
答案 0 :(得分:2)
通常,表示数据对象(Tree,LexicalizedParser等)的Stanford NLP类是可序列化的,而代表处理器的类(StanfordCoreNLP,LexicalizedParserQuery,CRFClassifier)则不是。为了达到你所要求的目标,你需要制作许多可序列化的课程,而不是处理任何后果。
但是,我认为你的基本思想是错误的。 StanfordCoreNLP在这15秒内加载的东西主要是标准的java序列化对象。 NER分类器和解析器语法是标准的序列化Java对象。 (这些形式的一些事情不仅仅是二进制数据,包括POS标记器,主要是出于历史原因。)事实是,使用标准Java序列化加载大量对象并不是那么快......您可以在网上找到有关Java序列化速度以及替代方案速度比较的讨论。制作包含所有当前序列化对象的新的更大的序列化对象不能更快。 (你可以通过在一个连续的数据流中处理所有内容来获得一小部分,但除非你做额外的工作来标记不需要序列化的瞬态字段,否则几乎肯定会因序列化数据的增加而丢失结构。)
相反,我建议处理这个问题的关键是只支付一次加载系统的成本,然后在处理许多句子时将其保留在内存中。
答案 1 :(得分:1)