java - "main"java.lang.OutOfMemoryError : Java heap space Error in Stanford Custom Entity Recognition Model training

标签 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)

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

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

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

这个堆空间是跟内存有关还是跟可用空间有关?

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

最佳答案

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

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

关于java - "main"java.lang.OutOfMemoryError : Java heap space Error in Stanford Custom Entity Recognition Model training,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56930903/

相关文章:

当在另一个可变参数方法中调用可变参数方法时,Java 可变参数不检测

linux - Linux 上的 DB2 Express

nlp - 如何处理我从 syntaxnet 获得的树?(conll 格式)

java - 字符串拆分并存储在 2 个不同的列表中

java - 从 C 转换为 Java

java - Java使用的内存远大于堆大小(或正确大小的Docker内存限制)

stanford-nlp - 配置 SUTime 使用自定义规则文件

python - stanford corenlp 不工作

java - 在线程之间传递可变数据

linux qt 更改监视器刷新频率