stanford coreNLP 使用脚本处理许多文件

stanford coreNLP process many files with a script

更新

dir=/Users/matthew/Workbench
for f in $dir/Data/NYTimes/NYTimesCorpus_4/*/*/*/*.txt; do
    [[ $f == *.xml ]] && continue # skip output files
    java -cp "*" -Xmx2g edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,pos,lemma,ner,parse,dcoref -filelist "$f" -outputDirectory .  
done

这个似乎效果更好,但我遇到了 io exception file name too long 错误,这是怎么回事,如何解决?

我猜文档中的其他命令不起作用


我试图使用此脚本通过 Stanford CoreNLP 处理我的语料库,但我一直收到错误

Could not find or load main class .Users.matthew.Workbench.Code.CoreNLP.Stanford-corenlp-full-2015-01-29.edu.stanford.nlp.pipeline.StanfordCoreNLP

这是脚本

dir=/Users/matthew/Workbench
for f in $dir/Data/NYTimes/NYTimesCorpus_3/*/*/*/*.txt; do
    [[ $f == *.xml ]] && continue # skip output files
    java -mx600m -cp $dir/Code/CoreNLP/stanford-corenlp-full-2015-01-29/stanford-corenlp-VV.jar:stanford-corenlp-VV-models.jar:xom.jar:joda-time.jar:jollyday.jar:ejml-VV.jar -Xmx2g /Users/matthew/Workbench/Code/CoreNLP/stanford-corenlp-full-2015-01-29/edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit -file "$f" -outputDirectory $dir/Data/NYTimes/NYTimesCorpus_3/*/*/*/. 
done

斯坦福 NER 的一个非常相似的,看起来像这样:

dir=/Users/matthew/Workbench
for f in $dir/Data/NYTimes/NYTimesCorpus_3/*/*/*/*.txt; do
    [[ $f == *_NER.txt ]] && continue # skip output files
    g="${f%.txt}_NER.txt"
    java -mx600m -cp $dir/Code/StanfordNER/stanford-ner-2015-01-30/stanford-ner-3.5.1.jar edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier $dir/Code/StanfordNER/stanford-ner-2015-01-30/classifiers/english.all.3class.distsim.crf.ser.gz -textFile "$f" -outputFormat inlineXML > "$g"
done

我不明白为什么我总是收到那个错误,看来我已经正确指定了所有路径。

我知道有一个选项-filelist parameter [which] points to a file whose content lists all files to be processed (one per line).

但我不知道这在我的情况下究竟如何工作,因为我的目录结构看起来像这样 $dir/Data/NYTimes/NYTimesCorpus_3/*/*/*/*.txt,其中有许多文件要处理。

也可以动态指定 -outputDirectory 他们在文档中说 You may specify an alternate output directory with the flag 但它似乎会被调用一次然后是静态的,这对我来说是一场噩梦。

我想也许我可以写一些代码来做到这一点,但也行不通,这是我试过的:

public static void main(String[] args) throws Exception 
{

    BufferedReader br = new BufferedReader(new FileReader("/home/matthias/Workbench/SUTD/nytimes_corpus/NYTimesCorpus/2005/01/01/1638802_output.txt"));
    try 
    {
        StringBuilder sb = new StringBuilder();
        String line = br.readLine();

        while (line != null) 
        {

            sb.append(line);
            sb.append(System.lineSeparator());
            line = br.readLine();
        }
        String everything = sb.toString();
        //System.out.println(everything);

        Annotation doc = new Annotation(everything);

        StanfordCoreNLP pipeline;

        // creates a StanfordCoreNLP object, with POS tagging, lemmatization,
        // NER, parsing, and coreference resolution
        Properties props = new Properties();

        // configure pipeline
        props.put(
                  "annotators", 
                  "tokenize, ssplit"
                  );

        pipeline = new StanfordCoreNLP(props);

        pipeline.annotate(doc);

        System.out.println( doc );

    }
    finally 
    {
        br.close();
    }

}

到目前为止,使用 Stanford CoreNLP 处理大量文件的最佳方法是安排一次加载系统 - 因为在完成任何实际文档处理之前加载所有各种模型需要 15 秒或更长时间,具体取决于您的计算机- 然后用它处理一堆文件。您更新中的内容不会这样做,因为 运行ning CoreNLP 在 for 循环内。一个好的解决方案是使用 for 循环制作一个文件列表,然后在文件列表上一次 运行 CoreNLP。文件列表只是一个文本文件,每行一个文件名,所以你可以按照你想要的方式制作它(使用脚本,编辑器宏,自己输入),你可以并且应该在 运行宁 CoreNLP。对于您的示例,根据您的更新示例,以下内容应该有效:

dir=/Users/matthew/Workbench
for f in $dir/Data/NYTimes/NYTimesCorpus_3/*/*/*/*.txt; do
    echo $f >> filelist.txt
done
# You can here check that filelist.txt has in it the files you want
java -cp "*" -Xmx2g edu.stanford.nlp.pipeline.StanfordCoreNLP -annotators tokenize,ssplit,pos,lemma,ner,parse,dcoref -filelist filelist
# By default output files are written to the current directory, so you don't need to specify -outputDirectory .

关于早期尝试的其他说明:

  • -mx600m 不是 运行 完整 CoreNLP 管道(直接通过解析和 coref)的合理方式。它所有模型的总和太大了。 -mx2g 可以。
  • 上面的最佳方法并没有完全扩展到 NER 的情况。 Stanford NER 不采用 -filelist 选项,如果您使用 -textFiles 则文件将连接起来并成为一个输出文件,您可能不希望这样。目前,对于 NER,您可能需要在 for 循环中 运行 它,就像在您的脚本中那样。
  • 我还没有完全理解你是如何得到错误的Could not find or load main class .Users.matthew.Workbench.Code.CoreNLP.Stanford-corenlp-full-2015-01-29.edu.stanford.nlp.pipeline.StanfordCoreNLP,但这是因为你把一个字符串(文件名?)像那样(可能用斜杠而不是句点)放在java 命令需要一个 class 名称。在那个地方,应该只有 edu.stanford.nlp.pipeline.StanfordCoreNLP 就像你更新的脚本或我的那样。
  • 您不能在对 CoreNLP 的一次调用中获得动态 outputDirectory。通过使用两个嵌套的 for 循环对 CoreNLP per directory 进行一次调用,您可以获得我认为您想要的相当有效的效果。外层 for 循环将遍历目录,内层循环从该目录中的所有文件中生成一个文件列表,然后在对 CoreNLP 的一次调用中进行处理,并根据输入目录写入适当的输出目录在外部 for 循环中。比我有更多时间或 bash-fu 的人可以尝试写那个....
  • 您当然也可以编写自己的代码来调用 CoreNLP,但是您需要自己负责扫描输入目录并写入适当的输出文件。你所拥有的看起来基本上没问题,除了行 System.out.println( doc ); 不会做任何有用的事情 - 它只是打印出你开始的测试。你需要这样的东西:

    PrintWriter xmlOut = new PrintWriter("outputFileName.xml");
    pipeline.xmlPrint(doc, xmlOut);