“主要” java.lang.OutOfMemoryError:Stanford自定义实体识别模型训练中的Java堆空间错误

时间:2019-07-08 08:18:40

标签: java linux stanford-nlp heap-memory

我正在尝试训练自定义NER模型以识别41个实体(训练集约有6000行)

当我尝试运行nlp site中提供的训练命令时:

java -cp stanford-ner.jar edu.stanford.nlp.ie.crf.CRFClassifier -prop austen.prop 

这是我面临的错误:

Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at edu.stanford.nlp.optimization.AbstractCachingDiffFunction.ensure(AbstractCachingDiffFunction.java:136)
        at edu.stanford.nlp.optimization.AbstractCachingDiffFunction.derivativeAt(AbstractCachingDiffFunction.java:151)
        at edu.stanford.nlp.optimization.QNMinimizer.evaluateFunction(QNMinimizer.java:1150)
        at edu.stanford.nlp.optimization.QNMinimizer.minimize(QNMinimizer.java:898)
        at edu.stanford.nlp.optimization.QNMinimizer.minimize(QNMinimizer.java:856)
        at edu.stanford.nlp.optimization.QNMinimizer.minimize(QNMinimizer.java:850)
        at edu.stanford.nlp.optimization.QNMinimizer.minimize(QNMinimizer.java:93)
        at edu.stanford.nlp.ie.crf.CRFClassifier.trainWeights(CRFClassifier.java:1935)
        at edu.stanford.nlp.ie.crf.CRFClassifier.train(CRFClassifier.java:1742)
        at edu.stanford.nlp.ie.AbstractSequenceClassifier.train(AbstractSequenceClassifier.java:785)
        at edu.stanford.nlp.ie.AbstractSequenceClassifier.train(AbstractSequenceClassifier.java:756)
        at edu.stanford.nlp.ie.crf.CRFClassifier.main(CRFClassifier.java:3011)

我尝试将-Xmx4096m添加到我的java命令中,以将最大堆空间指定为4GB(这是我的计算机中的最大可用空间),但仍然没有运气。

我还尝试添加-Xms1024m来指定最小堆空间,但没有不同的结果。

当我尝试使用该命令训练20个实体(1500行)的模型时,该命令完美运行,没有任何堆空间错误

此堆空间与RAM或可用空间有关吗?

我应该尝试在具有更多内存或存储空间的机器上进行培训吗?

1 个答案:

答案 0 :(得分:1)

如果您认为自己最终遇到了内存可用性问题,请参考斯坦福大学的指导原则(如果可以,请回头)。

  1. 最终,如果您具有大量功能和大量类,则需要大量内存来训练CRFClassifier。我们经常训练需要几GB RAM并习惯于键入java -mx4g.
  2. 的模型
  3. 您可以减少limited-memory quasi-Newton optimizer (L-BFGS)的内存。优化器保留许多过去的猜测,这些猜测用于近似Hessian。拥有更多的猜测可以使估计更加准确,并且优化速度更快,但是系统在优化过程中使用的内存在猜测数目中是线性的。这由参数qnSize指定。默认值为25。使用10完全足够。如果您内存不足,则仍然可以使用较小的值工作,即使只有2值。
  4. 降低CRF的顺序。我们通常只使用一阶CRF(maxLeft=1,并且没有一个特征引用答案类的特征超过一个-可以在任何距离之外都引用单词特征)。虽然代码支持任意顺序的CRF,但是构建第二,第三或第四阶CRF将大大增加内存使用量,通常是没有必要的。请记住:maxLeft指的是您的功能使用的类上下文的大小(即,它比集团的大小小一个)。一阶CRF仍然可以向左或向右任意偏远,以获取有关所观察到的数据上下文的信息。
  5. 减少生成的特征数量。要查看生成的所有功能,可以将属性printFeatures设置为true。然后,CRFClassifier将在当前目录中写入(可能很大)文件,列出为每个令牌位置生成的功能。当maxNGramLeng很大时,生成大量功能的选项包括useWordPairs和useNGrams。
  6. 减少模型中的类数。这可能会或可能不会,取决于您的建模要求是什么。但是时间复杂度与提升到集团规模的班级数量成正比。
  7. 使用标志useObservedSequencesOnly = true。这样一来,您就只能使用在训练数据中彼此相邻的标签序列来标记相邻的单词。对于某些类型的数据,实际上可以提供更好的准确性,而对于其他类型,则更糟。但是除非标签序列模式密集,否则它将减少您的内存使用。
  8. 当然,减少训练数据的数量也会减少所需的内存,但是如果您要训练最佳分类器,则不是很理想。不过,您可能会考虑扔掉其中没有实体的句子。
  9. 如果您担心运行时内存的使用,上述某些内容仍然适用(功能和类的数量,useObservedSequencesOnly和CRF的顺序),但除此之外,您还可以使用标志featureDiffThresh,例如featureDiffThresh = 0.05。在训练中,CRFClassifier将训练一个模型,将所有权重(绝对值)降至指定阈值以下的特征,然后训练第二个模型。因此,训练需要更长的时间,但是生成的模型在运行时更小,更快,并且通常在合理的阈值(例如0.05)下具有非常相似的性能。