Использование универсального набора тегов NLTK с неанглийскими корпусами

Я использую NLTK (3.0.4-1) в Python 3.4.3+, и я хотел бы обработать некоторые помеченные корпуса, используя универсальный набор тегов (который мне пришлось установить), , как описано в книге NLTK, глава 5.

Я могу получить доступ к любому из этих корпусов с их исходным набором тегов PoS, например:

from nltk.corpus import brown, cess_esp, floresta

print(brown.tagged_sents()[0])
[('The', 'AT'), ('Fulton', 'NP-TL'), ('County', 'NN-TL'), ('Grand', 'JJ-TL'), ('Jury', 'NN-TL'), ('said', 'VBD'), ('Friday', 'NR'), ('an', 'AT'), ('investigation', 'NN'), ('of', 'IN'), ("Atlanta's", 'NP$'), ('recent', 'JJ'), ('primary', 'NN'), ('election', 'NN'), ('produced', 'VBD'), ('``', '``'), ('no', 'AT'), ('evidence', 'NN'), ("''", "''"), ('that', 'CS'), ('any', 'DTI'), ('irregularities', 'NNS'), ('took', 'VBD'), ('place', 'NN'), ('.', '.')]

print(cess_esp.tagged_sents()[0])
[('El', 'da0ms0'), ('grupo', 'ncms000'), ('estatal', 'aq0cs0'), ('Electricité_de_France', 'np00000'), ('-Fpa-', 'Fpa'), ('EDF', 'np00000'), ('-Fpt-', 'Fpt'), ('anunció', 'vmis3s0'), ('hoy', 'rg'), (',', 'Fc'), ('jueves', 'W'), (',', 'Fc'), ('la', 'da0fs0'), ('compra', 'ncfs000'), ('del', 'spcms'), ('51_por_ciento', 'Zp'), ('de', 'sps00'), ('la', 'da0fs0'), ('empresa', 'ncfs000'), ('mexicana', 'aq0fs0'), ('Electricidad_Águila_de_Altamira', 'np00000'), ('-Fpa-', 'Fpa'), ('EAA', 'np00000'), ('-Fpt-', 'Fpt'), (',', 'Fc'), ('creada', 'aq0fsp'), ('por', 'sps00'), ('el', 'da0ms0'), ('japonés', 'aq0ms0'), ('Mitsubishi_Corporation', 'np00000'), ('para', 'sps00'), ('poner_en_marcha', 'vmn0000'), ('una', 'di0fs0'), ('central', 'ncfs000'), ('de', 'sps00'), ('gas', 'ncms000'), ('de', 'sps00'), ('495', 'Z'), ('megavatios', 'ncmp000'), ('.', 'Fp')]

print(floresta.tagged_sents()[0])
[('Um', '>N+art'), ('revivalismo', 'H+n'), ('refrescante', 'N<+adj')]

Пока все хорошо, но когда я использую параметр tagset='universal' для доступа к упрощенной версии тегов PoS, он работает только для корпуса Brown.

print(brown.tagged_sents(tagset='universal')[0])
[('The', 'DET'), ('Fulton', 'NOUN'), ('County', 'NOUN'), ('Grand', 'ADJ'), ('Jury', 'NOUN'), ('said', 'VERB'), ('Friday', 'NOUN'), ('an', 'DET'), ('investigation', 'NOUN'), ('of', 'ADP'), ("Atlanta's", 'NOUN'), ('recent', 'ADJ'), ('primary', 'NOUN'), ('election', 'NOUN'), ('produced', 'VERB'), ('``', '.'), ('no', 'DET'), ('evidence', 'NOUN'), ("''", '.'), ('that', 'ADP'), ('any', 'DET'), ('irregularities', 'NOUN'), ('took', 'VERB'), ('place', 'NOUN'), ('.', '.')]

При доступе к корпусам на испанском и португальском языках я получаю длинную цепочку ошибок и LookupError исключение.

print(cess_esp.tagged_sents(tagset='universal')[0])
---------------------------------------------------------------------------
LookupError                               Traceback (most recent call last)
<ipython-input-6-4e2e43e54e2d> in <module>()
----> 1 print(cess_esp.tagged_sents(tagset='universal')[0])

[...]

LookupError: 
**********************************************************************
  Resource 'taggers/universal_tagset/unknown.map' not found.
  Please use the NLTK Downloader to obtain the resource:  >>>
  nltk.download()
  Searched in:
    - '/home/victor/nltk_data'
    - '/usr/share/nltk_data'
    - '/usr/local/share/nltk_data'
    - '/usr/lib/nltk_data'
    - '/usr/local/lib/nltk_data'
    - ''
**********************************************************************

Среди сопоставлений, расположенных в моем каталоге taggers/universal_tagset, я могу найти сопоставления для испанского (es-cast3lb.map) и португальского (pt-bosque.map), но у меня нет файла unknown.map. Есть идеи, как это решить?

Заранее спасибо :-)


person user1983822    schedule 12.12.2015    source источник


Ответы (1)


Это интересный вопрос. NLTK реализует сопоставление с универсальным набором тегов только для фиксированной коллекции корпусов с помощью фиксированных карт, которые вы нашли в nltk_data/taggers/universal_tagset/. За исключением нескольких особых случаев (которые включают обработку коричневого корпуса, как если бы он был назван en-brown), правилом является поиск файла сопоставления с тем же именем, что и набор тегов, используемый для вашего корпуса. В вашем случае для набора тегов установлено значение «unknown», поэтому вы видите это сообщение.

Теперь вы уверены, что «отображение для испанского языка», то есть карта es-cast3lb.map, действительно соответствует набору тегов для вашего корпуса? Я бы точно не стал предполагать, что это так, поскольку любой проект может создавать свой собственный набор тегов и правила для использования. Если это тот же набор тегов, который использует ваш корпус, у вашей проблемы есть простое решение:

  • Когда вы инициализируете свой читатель корпуса, например cess_esp, добавьте в конструктор параметр tagset="es-cast3lb". При необходимости, например для корпусов, уже загруженных NLTK с tagset="unknown", вы можете переопределить набор тегов после инициализации следующим образом:

    cess_esp._tagset = "es-cast3lb"
    

Это сообщает читателю корпуса, какой набор тегов используется в корпусе. После этого указание tagset="universal" должно привести к применению выбранного сопоставления.

Если этот набор тегов на самом деле не подходит для вашего корпуса, ваша первая задача - изучить документацию по набору тегов для вашего корпуса и создать соответствующее сопоставление с универсальным набором тегов; как вы, наверное, видели, формат довольно тривиален. Затем вы можете запустить свое отображение, отбросив его в nltk_data/taggers/universal_tagset. Добавление ваших собственных ресурсов в область nltk_data - это определенно хакерство, но если вы зайдете так далеко, я рекомендую вам внести свою карту набора тегов в nltk ... что решит проблему взлома постфактум.

Изменить: Итак (согласно комментариям) это правильный набор тегов, но только 1-2-буквенные теги POS находятся в словаре сопоставления (остальная часть тега предположительно описывает особенности изменяемых слов). Вот быстрый способ расширить словарь сопоставления на лету, чтобы вы могли видеть универсальные теги:

import nltk
from nltk.corpus import cess_esp
cess_esp._tagset = "es-cast3lb"

nltk.tag.mapping._load_universal_map("es-cast3lb")  # initialize; normally loaded on demand
mapdict = nltk.tag.mapping._MAPPINGS["es-cast3lb"]["universal"] # shortcut to the map

alltags = set(t for w, t in cess_esp.tagged_words())
for tag in alltags:
    if len(tag) <= 2:   # These are complete
        continue
    mapdict[tag] = mapdict[tag[:2]]

Это отбрасывает информацию о соглашении. Если вы предпочитаете украсить им «универсальные» теги, просто установите mapdict[tag] на mapdict[tag[:2]]+"-"+tag[2:].

Я бы сохранил этот словарь в файл, как описано выше, чтобы вам не приходилось пересчитывать сопоставление каждый раз, когда вы загружаете свой корпус.

person alexis    schedule 13.12.2015
comment
Спасибо за ответ, он дал мне несколько интересных советов, как решить эту проблему. es-cast3lb.map явно намеревается быть отображением для испанского корпуса. Проблема здесь в том, что, хотя исходные теги обычно длиннее двух символов (например, nccs000, vmip3s0), отображение связывает только начальную подстроку тегов с их универсальными аналогами (nc -> NOUN, vm -> VERB), и оно работает только для двух символов. теги (cs -> CONJ). Думаю, мне нужно настроить код самостоятельно или попытаться создать исчерпывающий список тегов. - person user1983822; 15.12.2015
comment
Да, у греческих корпусов тоже есть такая проблема. Для подхода с исчерпывающим списком попробуйте следующее: alltags = set(t for w,t in cess_esp.tagged_words()). Затем вы можете автоматически сгенерировать полную карту на основе префикса. (Если их слишком много, лучшим решением будет, вероятно, настроить модуль сопоставления тегов ...) - person alexis; 15.12.2015
comment
@user, если этот ответ решил вашу проблему, вы должны принять его, щелкнув большую галочку рядом с ответом; это помечает ваш вопрос как решенный. - person alexis; 19.12.2015