Пользовательская пометка с помощью nltk
Я пытаюсь создать небольшой англоязычный язык для задания задач. Основная идея состоит в том, чтобы разделить утверждение на глаголы и существительные-фразы, к которым должны относиться эти глаголы. Я работаю с nltk, но не получаю ожидаемых результатов, например:
>>> nltk.pos_tag(nltk.word_tokenize("select the files and copy to harddrive'"))
[('select', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('and', 'CC'), ('copy', 'VB'), ('to', 'TO'), ("harddrive'", 'NNP')]
>>> nltk.pos_tag(nltk.word_tokenize("move the files to harddrive'"))
[('move', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')]
>>> nltk.pos_tag(nltk.word_tokenize("copy the files to harddrive'"))
[('copy', 'NN'), ('the', 'DT'), ('files', 'NNS'), ('to', 'TO'), ("harddrive'", 'NNP')]
В каждом случае он не понимал, что первое слово (выбор, перемещение и копирование) предназначалось как глаголы. Я знаю, что могу создавать собственные теггеры и грамматики, чтобы обойти это, но в то же время я не решаюсь идти изобретать колесо, когда много этого материала выходит из моей лиги. Я особенно предпочел бы решение, в котором могли бы обрабатываться и неанглийские языки.
Так или иначе, мой вопрос один из:
Есть ли лучший теггер для этого типа грамматики?
Есть ли способ весить существующий теггер в сторону использования формы глагола чаще, чем форма существительного?
Есть ли способ тренировать теггер?
Есть ли лучший способ вообще?
Ответы
Ответ 1
Одним из решений является создание ручного UnigramTagger, который отсылается к тегере NLTK. Что-то вроде этого:
>>> import nltk.tag, nltk.data
>>> default_tagger = nltk.data.load(nltk.tag._POS_TAGGER)
>>> model = {'select': 'VB'}
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger)
Затем вы получаете
>>> tagger.tag(['select', 'the', 'files'])
[('select', 'VB'), ('the', 'DT'), ('files', 'NNS')]
Этот же метод может работать для неанглийских языков, если у вас есть соответствующий теггер по умолчанию. Вы можете обучать свои собственные тегеры с помощью train_tagger.py
из nltk-trainer и соответствующего корпуса.
Ответ 2
Ответ Джейкоба на месте. Однако, чтобы расширить его, вы можете обнаружить, что вам нужно больше, чем просто униграммы.
Например, рассмотрим три предложения:
select the files
use the select function on the sockets
the select was good
Здесь слово "select" используется как глагол, прилагательное и существительное соответственно. Агрегистр unigram не сможет моделировать это. Даже тегатор bigram не может справиться с этим, потому что два случая имеют одно и то же предыдущее слово (т.е. "The" ). Для правильного обращения с этим случаем вам понадобится триггер-теггер.
import nltk.tag, nltk.data
from nltk import word_tokenize
default_tagger = nltk.data.load(nltk.tag._POS_TAGGER)
def evaluate(tagger, sentences):
good,total = 0,0.
for sentence,func in sentences:
tags = tagger.tag(nltk.word_tokenize(sentence))
print tags
good += func(tags)
total += 1
print 'Accuracy:',good/total
sentences = [
('select the files', lambda tags: ('select', 'VB') in tags),
('use the select function on the sockets', lambda tags: ('select', 'JJ') in tags and ('use', 'VB') in tags),
('the select was good', lambda tags: ('select', 'NN') in tags),
]
train_sents = [
[('select', 'VB'), ('the', 'DT'), ('files', 'NNS')],
[('use', 'VB'), ('the', 'DT'), ('select', 'JJ'), ('function', 'NN'), ('on', 'IN'), ('the', 'DT'), ('sockets', 'NNS')],
[('the', 'DT'), ('select', 'NN'), ('files', 'NNS')],
]
tagger = nltk.TrigramTagger(train_sents, backoff=default_tagger)
evaluate(tagger, sentences)
#model = tagger._context_to_tag
Обратите внимание: вы можете использовать NLTK NgramTagger для обучения тегов с использованием произвольно большого количества n-граммов, но обычно вы не используете" t увеличивать производительность после триграмм.
Ответ 3
См. ответ Джейкоба.
В более поздних версиях (по крайней мере, nltk 3.2) nltk.tag._POS_TAGGER
не существует. Тегеры по умолчанию обычно загружаются в каталог nltk_data/taggers/, например:
>>> import nltk
>>> nltk.download('maxent_treebank_pos_tagger')
Использование выглядит следующим образом.
>>> import nltk.tag, nltk.data
>>> tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle'
>>> default_tagger = nltk.data.load(tagger_path)
>>> model = {'select': 'VB'}
>>> tagger = nltk.tag.UnigramTagger(model=model, backoff=default_tagger)
См. также: Как выполнить тегирование POS с помощью теггера POS NLTK в Python.
Ответ 4
Ответ Bud правильный. Кроме того, согласно эта ссылка,
если ваши пакеты nltk_data были правильно установлены, тогда NLTK знает, где они находятся в вашей системе, и вам не нужно передавать абсолютный путь.
Смысл, вы можете просто сказать
tagger_path = '/path/to/nltk_data/taggers/maxent_treebank_pos_tagger/english.pickle'
default_tagger = nltk.data.load(tagger_path)