2015-07-28 2 views
2

Я создал парсер java с использованием NLP Stanford Core. Я нахожу проблему в получении согласованных результатов с объектом CORENLP. Я получаю разные типы объектов для одного и того же входного текста. Мне кажется, что это ошибка в CoreNLP. Если вы заметили, что кто-то из пользователей StanfordNLP столкнулся с этой проблемой и нашел обходное решение для этого. Это мой класс службы, который я создаю и использую повторно.Stanford Core NLP: Тип сущности не детерминированный

class StanfordNLPService { 
     //private static final Logger logger = LogConfiguration.getInstance().getLogger(StanfordNLPServer.class.getName()); 
     private StanfordCoreNLP nerPipeline; 
     /* 
      Initialize the nlp instances for ner and sentiments. 
     */ 
     public void init() { 
      Properties nerAnnotators = new Properties(); 
      nerAnnotators.put("annotators", "tokenize,ssplit,pos,lemma,ner"); 
      nerPipeline = new StanfordCoreNLP(nerAnnotators); 


     } 

     /** 
     * @param text    Text from entities to be extracted. 

     */ 
     public void printEntities(String text) { 

      //  boolean tracking = PerformanceMonitor.start("StanfordNLPServer.getEntities"); 
      try { 

       // Properties nerAnnotators = new Properties(); 
       // nerAnnotators.put("annotators", "tokenize,ssplit,pos,lemma,ner"); 
       // nerPipeline = new StanfordCoreNLP(nerAnnotators); 
       Annotation document = nerPipeline.process(text); 
       // a CoreMap is essentially a Map that uses class objects as keys and has values with custom types 
       List<CoreMap> sentences = document.get(CoreAnnotations.SentencesAnnotation.class); 

       for (CoreMap sentence : sentences) { 
        for (CoreLabel token : sentence.get(CoreAnnotations.TokensAnnotation.class)) { 
         // Get the entity type and offset information needed. 
         String currEntityType = token.get(CoreAnnotations.NamedEntityTagAnnotation.class); // Ner type 
         int currStart = token.get(CoreAnnotations.CharacterOffsetBeginAnnotation.class); // token offset_start 
         int currEnd = token.get(CoreAnnotations.CharacterOffsetEndAnnotation.class);  // token offset_end. 
         String currPos = token.get(CoreAnnotations.PartOfSpeechAnnotation.class);   // POS type 
         System.out.println("(Type:value:offset)\t" + currEntityType + ":\t"+ text.substring(currStart,currEnd)+"\t" + currStart); 
        } 
       } 
      }catch(Exception e){ 
       e.printStackTrace(); 

      } 
     } 

    } 
Discrepancy result: type changed from MISC to O from the initial use. 
Iteration 1: 
(Type:value:offset) MISC: Appropriate 100 
(Type:value:offset) MISC: Time 112 
Iteration 2: 
(Type:value:offset) O: Appropriate 100 
(Type:value:offset) O: Time 112 
+0

Я дополнительно протестировал и обнаружил, что проблема существует, даже если экземпляр CoreNLP воссоздан для каждого вызова. –

+0

Существует вызов StanfordCoreNLP.clearAnnotatorPool(), который решает эту проблему, но это дорого, поскольку оно перезагружает классификаторы, которые занимают около 5 секунд. –

ответ

0

Я просмотрел код некоторых, а вот возможный способ решения этой проблемы:

Что вы можете сделать для решения этой задачи загружается каждый из трех сериализованных CRF с использованиемKnownLCWords, установленным в false, и сериализуйте их снова. Затем поставьте новые сериализованные CRF на ваш StanfordCoreNLP.

Вот команда для загрузки сериализованную ХПН с useKnownLCWords значение ЛОЖЬ, а затем сбрасывать его снова:

Java -mx600m -cp «* :.» edu.stanford.nlp.ie.crf.CRFClassifier -loadClassifier классификаторы/english.all.3class.distsim.crf.ser.gz -useKnownLCWords false -serializeTo классификаторы/new.english.all.3class.distsim.crf.ser.gz

Поместите любые имена, которые вы хотите явно!Эта команда предполагает, что вы находитесь в stanford-corenlp-full-2015-04-20/и имеете классификаторы каталогов с сериализованными CRF. При необходимости измените настройки.

Эта команда должна загрузить сериализированную ХПН, переопределить с useKnownLCWords значение ЛОЖЬ, а затем повторно дамп ХПН в new.english.all.3class.distsim.crf.ser.gz

Тогда в вашем Исходный код:

nerAnnotators.put("ner.model","comma-separated-list-of-paths-to-new-serialized-crfs"); 

Пожалуйста, дайте мне знать, если это работает или если он не работает, и я могу смотреть глубже в это!

+0

Спасибо, что посмотрели на это. В моем случае я использую объект StanfordCoreNLP. Есть ли способ опубликовать свойство CRFClassifier через StanfordCoreNLP, например classifier.useKnownLCWords, и установить значение. –

+0

В основном объект StanfordCoreNLP имеет объект NERClassifierCombiner, который имеет список CRF. CRF - это то, что нужно, чтобы useKnownLCWords устанавливался в false, поэтому я думаю, что, вероятно, это не способ сделать то, что вы хотите, хотя я не уверен в этом! – StanfordNLPHelp

+0

Когда я смотрю ClassifierCombiner, он загружает CRF только своими путями, поэтому он не загружает их с помощью каких-либо пропеллеров. Я думаю, что проще всего было бы просто создать новые CRF в том виде, как я предложил выше. – StanfordNLPHelp

0

После выполнения некоторых исследований я обнаружил, что проблема связана с методом ClassifierCombiner.classify(). Один из baseClassifiers edu/stanford/nlp/models/ner/english.conll.4class.distsim.crf.ser.gz, загруженный по умолчанию, в какой-то момент возвращает другой тип. Я пытаюсь загрузить только первую модель для решения этой проблемы.

Проблема заключается в следующем область кода

CRFClassifier.classifyMaxEnt()

int[] bestSequence = tagInference.bestSequence(model); Line 1249 

ExactBestSequenceFinder.bestSequence() возвращает другую последовательность для для вышеуказанной модели для того же ввод при вызове несколько раз.

Не уверен, что для этого требуется исправление кода или некоторые изменения конфигурации модели. Любое дополнительное понимание оценено.

2

Вот ответ от РЭК FAQ:

http://nlp.stanford.edu/software/crf-faq.shtml

ли ЧПО детерминированным? Почему результаты изменяются для одних и тех же данных?

Да, базовый CRF детерминирован. Если вы применяете NER к одному и тому же предложению более одного раза, во второй раз можно получить разные ответы. Причиной этого является то, что NER помнит, видел ли он слово в нижнем регистре раньше.

Точный способ использования этой функции в функции формы слова, который рассматривает слова типа «Браун» по-разному, если он раньше или не видел «коричневого» в качестве нижнего регистра. Если это так, форма слова будет «Начальная верхняя, видна всего в нижнем регистре», а если нет, форма слова будет «Начальная верхняя, не видна всего в нижнем регистре».

Эта функция может быть отключена в последних версиях с флагом -useKnownLCWords ложных

+0

Большое спасибо. Как вы используете этот флаг? должен ли я изменить все три файла modelxxx.prop или есть способ передать эту информацию в общих для всех моделей с помощью конструктора StanfordCoreNLP ?. Также я не вижу это свойство в файлах свойств моделей, хотя AbstractSequenceClassifier.reinit() имеет эту проверку в последней версии 3.5.2, но я вижу, что значение устанавливается равным true для всех трех моделей даже после того, как я добавьте этот флаг во все 3 модели. Нужно ли добавлять любую другую конфигурацию? или это версия, в которой работает это свойство? –

+0

См. Ниже возможное решение вашей проблемы. – StanfordNLPHelp

Смежные вопросы