GATE записывает идентификатор аннотации как функцию

Мне было интересно, может ли кто-нибудь помочь мне здесь. Я думаю, что это может быть полезно для всех, кто пытается проводить машинное обучение в GATE (общая архитектура для текстовой инженерии). Таким образом, в основном для проведения машинного обучения мне сначала нужно добавить некоторый код в несколько файлов jape, чтобы мой выходной файл XML распечатывал значение идентификатора аннотации как функцию. Пример приведен ниже:

<Annotation Id="1491" Type="Person" StartNode="288" EndNode="301">
<Feature>
  <Name className="java.lang.String">id</Name>
  <Value className="java.lang.String">1491</Value>
</Feature>

(Обратите внимание, что значение функции 1491 соответствует идентификатору аннотации = "1491". Это то, что я хочу.)

ЗАЧЕМ МНЕ ЭТО НУЖНО: я провожу машинное обучение на простом текстовом документе, который изначально не содержит аннотаций. Я использую учебный курс за июнь 2012 года, который находится на веб-сайте GATE, в качестве руководства при этом. Я специально следую учебному пособию Модуль 11: Отношения (он находит трудовые отношения между человеком и организацией). Я использую корпус из 93 предварительно аннотированных документов для обучения, а затем применяю изученный модуль к своему документу. Но сначала я прогоняю свой документ через ANNIE. Он создает множество аннотаций и функций, но не все, что мне нужно для машинного обучения. Путем проб/ошибок и исследований я узнал, что мой аннотированный документ должен содержать функции с идентификатором аннотации для каждого типа «Лицо» и «Организация». Я понимаю, что файл конфигурации (relations-config.xml), который используется в пакетном обучении PR, ищет функции идентификатора для типов «Лицо» и «Организация». Он не будет работать, если эти функции ID отсутствуют. Поэтому я добавляю это вручную, а затем запускаю его в режиме машинного обучения «ПРИЛОЖЕНИЕ». Это работает довольно хорошо. Однако я явно не хочу каждый раз вручную добавлять функции id в мой XML-файл.

ЧТО Я ПОНЯЛ С КОДОМ ВОРОТ: Я считаю, что нашел файлы кода (final.jape, org_context.jape и name_context.jape), которые мне нужно изменить, чтобы они могли добавить эту функцию идентификатора в каждую аннотацию, содержащую «Person». " и "Организация". Я не очень хорошо понимаю язык, который использует GATE (я инженер-механик, а не инженер-программист), и, вероятно, поэтому я не могу этого понять (ха!). В любом случае, я могу ошибаться, и мне может понадобиться добавить еще несколько строк, чтобы файл jape работал правильно, но я чувствую, что довольно точно определил его. Есть две секции кода, которые похожи, но немного отличаются, и в настоящее время являются бичом моего существования. Первый проходит через цикл итератора, второй - нет. Я скопировал / вставил эти 2 ниже со строкой, указывающей WHAT_DO_I_PUT_HERE, которая указывает, где, по моему мнению, лежит моя проблема и решение. Я был бы очень признателен, если кто-то может помочь мне с тем, что мне нужно написать, чтобы получить мой результат.

Спасибо! - Тодд

//////////// Первый раздел кода /////////////////

Rule: PersonFinal
Priority: 30
//({JobTitle}
//)?
(
 {TempPerson.kind == personName}
)
:person
--> 
{
gate.FeatureMap features = Factory.newFeatureMap();
gate.AnnotationSet personSet = (gate.AnnotationSet)bindings.get("person");
gate.Annotation person1Ann = (gate.Annotation)personSet.iterator().next();


gate.AnnotationSet firstPerson = (gate.AnnotationSet)personSet.get("TempPerson");
if (firstPerson != null && firstPerson.size()>0)
{
  gate.Annotation personAnn = (gate.Annotation)firstPerson.iterator().next();
  if (personAnn.getFeatures().containsKey("gender")) features.put("gender", personAnn.getFeatures().get("gender"));
}
  features.put("id", WHAT_DO_I_PUT_HERE.getId().toString());
  features.put("rule1", person1Ann.getFeatures().get("rule"));
  features.put("rule", "PersonFinal");
outputAS.add(personSet.firstNode(), personSet.lastNode(), "Person", features);
outputAS.removeAll(personSet);
}

//////////// Второй раздел кода /////////////////

Rule:OrgContext1
Priority: 1
// company X
// company called X

(
 {Token.string == "company"}
 (({Token.string == "called"}|
   {Token.string == "dubbed"}|
   {Token.string == "named"}
  )
 )?
)
( 
 {Unknown.kind == PN}
)
:org
-->
{
gate.AnnotationSet org = (gate.AnnotationSet) bindings.get("org");
gate.FeatureMap features = Factory.newFeatureMap();
features.put("id", WHAT_DO_I_PUT_HERE.getId().toString());
features.put("rule ", "OrgContext1");
outputAS.add(org.firstNode(), org.lastNode(), "Organization", features);
outputAS.removeAll(org);
}

person user2929055    schedule 28.10.2013    source источник
comment
Я считаю, что вам не следует изменять библиотеку, так как ваш код будет несовместим с любыми будущими версиями.   -  person Lajos Arpad    schedule 29.10.2013


Ответы (2)


Вы не можете получить доступ к идентификатору аннотации, пока не будет создана фактическая аннотация. Мое решение этой проблемы:

Rule:PojemId
(
 {PojemD}
):pojem
--> 
{
    AnnotationSet matchedAnns = bindings.get("pojem");  
    Annotation ann = matchedAnns.get("PojemD").iterator().next();

    FeatureMap pojemFeatures = ann.getFeatures();
    gate.FeatureMap features = Factory.newFeatureMap();
    features.putAll(pojemFeatures);
    features.put("annId", ann.getId()); 

    inputAS.remove(ann); 
    Integer id = outputAS.add(matchedAnns.firstNode(), matchedAnns.lastNode(), "PojemD", features);  
    features.put("id", id); 
}
person isixtova    schedule 24.02.2015

Это довольно просто. Вы должны пометить аннотацию на правой стороне (RHS) правила какой-либо меткой (token_match в моем примере ниже), а затем на левой стороне ( LHS) правила, просто получите соответствующую переменную AnnotationSet формы bindings и выполните итерацию по аннотациям (обычно в ней есть только одна аннотация) и скопируйте соответствующие идентификаторы в выходные данные.

Phase: Main
Input: Token 

Rule: WriteTokenID
(
  ({Token}):token_match
)    
-->
{
  AnnotationSet as = bindings.get("token_match");
  for (Annotation a : as) 
  {
    FeatureMap features = Factory.newFeatureMap();
    features.put("origTokenId", a.getId());
    outputAS.add(a.getStartNode(), a.getEndNode(), "NewToken", features);   
  }
}

В своем коде вы, вероятно, захотите пометить {TempPerson.kind == personName} и {Unknown.kind == PN} как-то так, как показано ниже.

(
 ({TempPerson.kind == personName}):temp_person
)
:person

и

(
 {Token.string == "company"}
 (({Token.string == "called"}|
   {Token.string == "dubbed"}|
   {Token.string == "named"}
  )
 )?
)
( 
 ({Unknown.kind == PN}):unknown_org
)
:org

И они используют bindings.get("temp_person") и bindings.get("unknown_org") соответственно.

person dedek    schedule 22.09.2014