Примечание Принимая программу с NLTK и Wordnet не работает, сообщение об ошибке говорит, что это из-за Wordnet - PullRequest
0 голосов
/ 24 апреля 2018

Я пытаюсь создать программу на python, которая будет делать заметки в отрывке, который я ввожу.Он отсортирует первое и последнее предложение абзаца и предложения с датами и числами.Затем он заменит некоторые слова синонимами и избавится от ненужных прилагательных.Я знаю общие вещи с python, но я новичок в nltk и WordNet.Я запустил программу-прототип, которая заменит слова в предложении всеми случайными синонимами, однако я продолжаю получать сообщение об ошибке, которое говорит, что с WordNet что-то не так.Я думаю, что установил это правильно, но я могу ошибаться.Вот мой код:

import random
import sys
from nltk.corpus import wordnet

print('Enter your passage')
Passage = sys.stdin.readline()
PassageList = Passage.split(' ')
wordCounter = 0
syns = []

def maxInt(list):
    i = 0
    for x in list:
    i += 1
return i



for x in PassageList:
    syns = wordnet.synsets(PassageList[wordCounter])
    synLength = maxInt(syns)
    PassageList[wordCounter] == syns[0]
    print(PassageList[wordCounter])
    wordCounter += 1

Вот ошибка, которую я продолжаю получать:

Traceback (most recent call last):
  File "C:\Users\shoob\Documents\Programs\Python\Programs\NoteTake.py",   line 22, in <module>
    PassageList[wordCounter] == syns[0]
  File "C:\Users\shoob\AppData\Local\Programs\Python\Python36-32\lib\site-packages\nltk\corpus\reader\wordnet.py", line 198, in __eq__
    return self._name == other._name
   AttributeError: 'str' object has no attribute '_name'

Если вы можете помочь в любом случае, это очень мне поможет.: -D

Ответы [ 2 ]

0 голосов
/ 25 апреля 2018

In Longer

Другой ответ был скорее о НЛП, но вот пошаговое руководство по вашему коду в OP и посмотрите, что происходит.

Соглашения Python

Во-первых, некоторые соглашения кода Python.Обычно имена переменных CamelCase не являются фактическими переменными, а являются объектами класса, поэтому избегайте использования таких переменных, как Passage.

. Кроме того, используя более подходящие имена переменных, вместо PassageList вы можете называть их словами.

Например,

import random
import sys
from nltk.corpus import wordnet

print('Enter your passage')
passage = sys.stdin.readline()

# The passage.split() is aka word tokenization
# note you've skipped sentence tokenization, 
# so it doesn't fit the goal of getting first and last sentence 
# that you've described in the OP
words = passage.split(' ') 

Коллекции - это ваш друг

Далее, в нативном Python есть встречные объекты, которые вы можете использовать и которые помогут вам в некоторой оптимизации.и более читаемый код.Например,

from collections import Counter
word_counter = Counter()

Взгляните на https://docs.python.org/3/library/collections.html

Синсеты не являются синонимами

Как объясняется в другом ответе, WordNet индексируется по значениям (иначеsynsets) и они не являются синонимами.Чтобы получить синонимы, вы можете использовать функцию Synset.lemma_names().Но они действительно ограничены, и вам придется пройти через процесс WSD, прежде чем узнаете, какие имена наборов из какого набора синтаксиса можно выбрать из любого неоднозначного слова.

Кроме того, explicit is better than implicit, использование понятных человеку имен переменных помогаетмного понимания и улучшения кода, поэтому вместо syn = [] используйте synonyms = [].

В противном случае, действительно неясно, что хранит syn.

Не следует злоупотреблять функциями

Независимо от неправильного отступа, неясно, какую функцию здесь пытаются достичь,Вы просто добавляете 1 к каждому элементу в списке, что по сути является функцией длины, поэтому вы можете просто использовать len(x).

def maxInt(list):
    i = 0
    for x in list:
        i += 1
    return i

x = [1,2,3,4,5]
maxInt(x) == len(x)

Для последовательного доступа к элементу из списка просто зацикливайте

Двигаясь дальше, мы видим, что вы странным образом перебираете каждое слово в списке слов отрывка.

Упрощаете свой ОП,

Passage = sys.stdin.readline()
PassageList = Passage.split(' ')
wordCounter = 0

for x in PassageList:
    syns = wordnet.synsets(PassageList[wordCounter])

Вымог бы легко сделать:

from nltk.corpus import wordnet as wn

passage =sys.stdin.readline()
words = passage.split(' ')
for word in words:
    synsets_per_word = wn.synsets(word)

Просто используйте len ()

Чтобы проверить номер.наборов для данного слова вместо

synLength = maxInt(syns)

вы можете просто сделать:

from nltk.corpus import wordnet as wn

passage =sys.stdin.readline()
words = passage.split(' ')
for word in words:
    synsets_per_word = wn.synsets(word)
    num_synsets_per_word = len(synsets_per_word)

Теперь к тревожной строке

Строка:

PassageList[wordCounter] == syns[0]

При правильном соглашении по именованию переменных мы имеем:

word == synsets_per_word[0]

Теперь это запутанная часть, левая часть - word типа str.И вы пытаетесь сравнить его с synsets_per_word[0] типа nltk.corpus.wordnet.Synset.

Donc Voila

Таким образом, при сравнении двух переменных с различным типом всплывает AttributeError ...

Большой вопрос - чего вы пытаетесь достичь здесь??Я предполагаю, что вы думаете, что synset является объектом str, но, как уже было объяснено, это объект Synset, а не строка, и даже если вы получаете lemma_names из Synset, это список строк иа не str, который можно сравнить по эквивалентности с str.

Итак, как вы решаете проблему

Сначала прочитайте о NLP, Python и о том, что WordNet API может делать вNLTK.

Затем переопределите задачу, поскольку WordNet не поможет вам с помощью неоднозначных слов.

0 голосов
/ 25 апреля 2018

Короче

Ваш проект немного чересчур амбициозен.

Кроме того, попробуйте задать более конкретные вопросы по Stackoverflow. Сосредоточьтесь на том, чтобы узнать, что не так, и объясните, какая помощь вам потребуется. Это поможет людям помочь вам лучше.

В длинном

Давайте попробуем разбить ваши требования:

Я пытаюсь создать программу на python, которая будет делать заметки в отрывке, который я ввожу.

Не уверен, что это действительно означает ...

Будет отсортировано первое и последнее предложение абзаца ...

Оригинальный код в оригинальном сообщении (OP) не имеет никаких проверок на даты / цифры.

Во-первых, вам нужно определить что такое предложение?

  • Что считается границей предложения?
  • Как вы собираетесь обнаруживать предложения из абзаца.

Возможно, nltk.sent_tokenize поможет:

from nltk import sent_tokenize

text = """Gwaha-ju (과하주; 過夏酒; literally "summer-passing wine") is a traditional Korean fortified rice wine. The refined rice wine cheongju (also called yakju) is fortified by adding the distilled spirit soju to produce gwaha-ju. Gwaha-baekju was first mentioned in Sanga Yorok, a mid-15th century cookbook, but the rice wine was made without fortification. The earliest recorded recipe for fortified gangha-ju appears in Eumsik dimibang, a 1670 cookbook.  Other Joseon books that mention the fortified rice wine include Jubangmun, Chisaeng yoram, Yeokjubangmun, Eumsikbo, Sallim gyeongje, Jeungbo sallim gyeongje, Gyuhap chongseo, and Imwon gyeongjeji."""

sent_tokenize(text)

... и предложения с датами и числами.

Хммм .. вот как насчет проверки цифр в строке каждого предложения:

from nltk import sent_tokenize

text = """Gwaha-ju (과하주; 過夏酒; literally "summer-passing wine") is a traditional Korean fortified rice wine. The refined rice wine cheongju (also called yakju) is fortified by adding the distilled spirit soju to produce gwaha-ju. Gwaha-baekju was first mentioned in Sanga Yorok, a mid-15th century cookbook, but the rice wine was made without fortification. The earliest recorded recipe for fortified gangha-ju appears in Eumsik dimibang, a 1670 cookbook.  Other Joseon books that mention the fortified rice wine include Jubangmun, Chisaeng yoram, Yeokjubangmun, Eumsikbo, Sallim gyeongje, Jeungbo sallim gyeongje, Gyuhap chongseo, and Imwon gyeongjeji."""

for sent in sent_tokenize(text):
    if any(ch for ch in sent if ch.isdigit()):
        print(sent)

Затем он заменит некоторые слова ...

Тогда вам нужно определить что такое слово?

  • Как вы определяете границу слова?
  • Это не будет одинаковым для разных языков

Может быть с nltk.word_tokenize, например,

from nltk import sent_tokenize, word_tokenize

text = """Gwaha-ju (과하주; 過夏酒; literally "summer-passing wine") is a traditional Korean fortified rice wine. The refined rice wine cheongju (also called yakju) is fortified by adding the distilled spirit soju to produce gwaha-ju. Gwaha-baekju was first mentioned in Sanga Yorok, a mid-15th century cookbook, but the rice wine was made without fortification. The earliest recorded recipe for fortified gangha-ju appears in Eumsik dimibang, a 1670 cookbook.  Other Joseon books that mention the fortified rice wine include Jubangmun, Chisaeng yoram, Yeokjubangmun, Eumsikbo, Sallim gyeongje, Jeungbo sallim gyeongje, Gyuhap chongseo, and Imwon gyeongjeji."""

for sent in sent_tokenize(text):
    if any(ch for ch in sent if ch.isdigit()):
        print(word_tokenize(sent))

Затем некоторые слова заменяются синонимами,

Не уверен, какое слово вы хотите заменить синонимами, и какие синонимы вы выберете. Но обратите внимание, что WordNet не совсем хороший тезаурус.

Каждое слово имеет разные значения, и в WordNet связаны только значения, а не слова, см. https://stackoverflow.com/a/19383914/610569

например. дано слово "вино":

from nltk.corpus import wordnet as wn

for synset in wn.synsets('wine'): # each meaning for the word, aka. synset
    print(synset)
    print('Words with same meaning:', synset.lemma_names(), '\n')

Как узнать, какой набор / значение использовать?

Это открытый вопрос. Он также известен как Устранение неоднозначности слов (WSD) .

Если вы просто сгладите и будете использовать названия лемм всех синтаксисов, «синонимы» или замена, которую вы хотите сделать, не будут иметь смысла. Например.

from itertools import chain

from nltk.corpus import wordnet as wn
from nltk import sent_tokenize, word_tokenize

text = """Gwaha-ju (과하주; 過夏酒; literally "summer-passing wine") is a traditional Korean fortified rice wine. The refined rice wine cheongju (also called yakju) is fortified by adding the distilled spirit soju to produce gwaha-ju. Gwaha-baekju was first mentioned in Sanga Yorok, a mid-15th century cookbook, but the rice wine was made without fortification. The earliest recorded recipe for fortified gangha-ju appears in Eumsik dimibang, a 1670 cookbook.  Other Joseon books that mention the fortified rice wine include Jubangmun, Chisaeng yoram, Yeokjubangmun, Eumsikbo, Sallim gyeongje, Jeungbo sallim gyeongje, Gyuhap chongseo, and Imwon gyeongjeji."""

for sent in sent_tokenize(text):
    if any(ch for ch in sent if ch.isdigit()):
        for word in word_tokenize(sent):
            lemma_names = set(chain(*[synset.lemma_names() for synset in wn.synsets(word)]))
            # If you just flatten and use the lemma names of all synset, 
            # the "synonyms" or replacement you want to make won't make sense.
            print(word, '\t', lemma_names)

... и избавиться от бесполезных прилагательных.

Хммм, для этого потребуется еще один фрагмент POS-тегов вызова процесса NLP, и он не идеален.

Возможно, вы можете попробовать nltk.pos_tag, но не ожидайте слишком многого от него (с точки зрения точности), например,

from itertools import chain

from nltk.corpus import wordnet as wn
from nltk import sent_tokenize, word_tokenize, pos_tag

text = """Gwaha-ju (과하주; 過夏酒; literally "summer-passing wine") is a traditional Korean fortified rice wine. The refined rice wine cheongju (also called yakju) is fortified by adding the distilled spirit soju to produce gwaha-ju. Gwaha-baekju was first mentioned in Sanga Yorok, a mid-15th century cookbook, but the rice wine was made without fortification. The earliest recorded recipe for fortified gangha-ju appears in Eumsik dimibang, a 1670 cookbook.  Other Joseon books that mention the fortified rice wine include Jubangmun, Chisaeng yoram, Yeokjubangmun, Eumsikbo, Sallim gyeongje, Jeungbo sallim gyeongje, Gyuhap chongseo, and Imwon gyeongjeji."""

for sent in sent_tokenize(text):
    if any(ch for ch in sent if ch.isdigit()):

        for word, tag in pos_tag(word_tokenize(sent)):
            if not tag.startswith('JJ'): # JJ* refers to adjective.
                print(word)
        print('-----')

Я знаю общие вещи с python, но я новичок в nltk и WordNet. Я запустил программу-прототип, которая заменит слова в предложении всеми случайными синонимами,

Так держать! Не отчаивайтесь, и я думаю, что начинать с цели создания приложения - не самое подходящее место для начала работы с NLP, попробуйте вместо этого:

однако я получаю сообщение об ошибке, в котором говорится, что с WordNet что-то не так. Я думаю, что установил это правильно, но я могу ошибаться.

Да, с установкой все в порядке.

Возможно, использование WordNet API в NLTK поможет вам понять, как и что может делать WordNet: http://www.nltk.org/howto/wordnet.html

Кроме того, улучшение базового Python и понимание, почему происходит AttributeError, очень помогло бы =)

...