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);
更新
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);