我在使用OpenNLP
的模型构建插件
来创建一个更好的NER模型。根据这个帖子,我使用了markg发布的代码:
public class ModelBuilderAddonUse { private static List<String> getSentencesFromSomewhere() throws Exception { List<String> list = new ArrayList<String>(); BufferedReader reader = new BufferedReader(new FileReader("D:\\Work\\workspaces\\default\\UpdateModel\\documentrequirements.docx")); String line; while ((line = reader.readLine()) != null) { list.add(line); } reader.close(); return list; } public static void main(String[] args) throws Exception { /** * 建立一个文件来存储句子 */ File sentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\sentences.text"); /** * 建立一个文件来存储你想要保留的NER命中(基于概率) */ File knownEntities = new File("D:\\Work\\workspaces\\default\\UpdateModel\\knownentities.txt"); /** * 建立一个黑名单文件来存储你不想要的NER命中(也可以基于概率) */ File blacklistedentities = new File("D:\\Work\\workspaces\\default\\UpdateModel\\blentities.txt"); /** * 建立一个文件来写入你的标注句子 */ File annotatedSentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\annotatedSentences.txt"); /** * 建立一个文件来写入你的模型 */ File theModel = new File("D:\\Work\\workspaces\\default\\UpdateModel\\nl-ner-person.bin");//------------创建多个文件写入器来将你的结果和句子写入文件 FileWriter sentenceWriter = new FileWriter(sentences, true); FileWriter blacklistWriter = new FileWriter(blacklistedentities, true); FileWriter knownEntityWriter = new FileWriter(knownEntities, true);//设置一些阈值来决定将命中写入哪里,你可以完全不使用这些阈值... double keeperThresh = .95; double blacklistThresh = .7; /** * 像 usual 一样加载你的模型 */ TokenNameFinderModel personModel = new TokenNameFinderModel(new File("D:\\Work\\workspaces\\default\\UpdateModel\\nl-ner-person.bin")); NameFinderME personFinder = new NameFinderME(personModel); /** * 对你拥有的句子进行通常的NER */ for (String s : getSentencesFromSomewhere()) { sentenceWriter.write(s.trim() + "\n"); sentenceWriter.flush(); String[] tokens = s.split(" ");//最好使用分词器 Span[] find = personFinder.find(tokens); double[] probs = personFinder.probs(); String[] names = Span.spansToStrings(find, tokens); for (int i = 0; i < names.length; i++) { //你可能有比这更好的启发式方法来确保从默认模型中获得好的命中 if (probs[i] > keeperThresh) { knownEntityWriter.write(names[i].trim() + "\n"); } if (probs[i] < blacklistThresh) { blacklistWriter.write(names[i].trim() + "\n"); } } personFinder.clearAdaptiveData(); blacklistWriter.flush(); knownEntityWriter.flush(); } //刷新并关闭所有写入器 knownEntityWriter.flush(); knownEntityWriter.close(); sentenceWriter.flush(); sentenceWriter.close(); blacklistWriter.flush(); blacklistWriter.close(); /** * 这是插件将使用这些文件(按原样)来创建新模型的地方。你应该不需要再次运行第一部分,只需现在调整已知实体和黑名单文件,然后再次运行下面的方法,直到你得到一些不错的结果(一个不错的模型)。 */ DefaultModelBuilderUtil.generateModel(sentences, knownEntities, blacklistedentities, theModel, annotatedSentences, "person", 3); }}
它也能运行,但我的输出在以下位置停止:
标注的句子:1862 已知实体:58 使用1862个标注构建模型 读取训练数据...
但在帖子中的示例中应该继续如下:
使用5的截止值索引事件 计算事件计数...完成。561755事件 索引...完成。排序和合并事件...完成。将561755事件减少到127362。完成索引。合并索引数据进行训练...完成。 事件标记数:127362 结果数:3 谓词数:106490...完成。
有谁能帮我解决这个问题,让我能生成一个模型?我已经搜索了很多,但找不到任何好的文档。非常感谢你的帮助。
回答:
像这样修正你的训练数据文件路径:
File sentences = new File("D:/Work/workspaces/default/UpdateModel/sentences.text");
而不是
File sentences = new File("D:\\Work\\workspaces\\default\\UpdateModel\\sentences.text");
更新
这是我如何使用的,通过将文件添加到项目文件夹中。试试这样 –
File sentences = new File("src/training/resources/CreateModel/sentences.txt");
这应该会有所帮助。