2013-01-23 13 views
21

Chciałbym funkcję biblioteki Pythona, która tłumaczy/konwertuje na różne części mowy. Czasami należy wyjść kilka słów (na przykład „koder” i „kod” są zarówno rzeczowniki od czasownika „kodu”, jeden jest przedmiotem drugiej znajduje się obiekt)Konwersja słów między czasownikami/rzeczownikami/przymiotnikami

# :: String => List of String 
print verbify('writer') # => ['write'] 
print nounize('written') # => ['writer'] 
print adjectivate('write') # => ['written'] 

ja głównie dbają o czasowników < => rzeczowniki , dla programu do robienia notatek chcę napisać. tj. mogę napisać "antagoniści kofeiny A1" lub "kofeina jest antagonistą A1" i przy pomocy NLP może to oznaczać to samo. (Wiem, że to nie jest łatwe i że zajmie NLP, które analizuje i nie tylko taguje, ale chcę zhakować prototyp).

podobne pytania ... Converting adjectives and adverbs to their noun forms (ta odpowiedź łodygi tylko w dół do POS korzeniowego. Chcę, aby przejść pomiędzy POS).

ps nazywa konwersji w językoznawstwie http://en.wikipedia.org/wiki/Conversion_%28linguistics%29

+1

ja nie wiem, czy może to zrobić, ale spójrz na NLTK. http://nltk.org/ –

+0

Jak poradzisz sobie z niejednoznacznymi sprawami? Na przykład "diguise" może być albo czasownikiem, albo rzeczownikiem, w zależności od kontekstu. –

+0

jest ok: 'nounize ('przebranie') == ['przebranie']' i 'verbify ('przebranie') == ['przebranie']' i 'przymiotnik ('przebranie') == ['ukryte'] ' –

Odpowiedz

3

Rozumiem, że to nie robi nie odpowiadaj na całe twoje pytanie, ale odpowiada na dużą jego część. Chciałbym sprawdzić http://nodebox.net/code/index.php/Linguistics#verb_conjugation Ta biblioteka python jest w stanie koniugować czasowniki i rozpoznać, czy słowo jest czasownikiem, rzeczownikiem lub przymiotnikiem.

Przykład Kod

print en.verb.present("gave") 
print en.verb.present("gave", person=3, negate=False) 
>>> give 
>>> gives 

można również klasyfikować słowa.

print en.is_noun("banana") 
>>> True 

Pobieranie jest na górze linku.

+0

tak, widziałem to tutaj, ale to tylko robi rzeczy wewnątrz (nie poprzez) POS http://stackoverflow.com/questions/3753021/using-nltk-and-wordnet-how-do-i-convert-simple-tense -verb-into-its-present-past? rq = 1 –

3

Jednym ze sposobów może być użycie słownika słów z ich znacznikami POS i mapowaniem formuł. Jeśli uzyskasz lub utworzysz taki słownik (co jest całkiem możliwe, jeśli masz dostęp do konwencjonalnych danych słownika, ponieważ wszystkie słowniki wyświetlają znaczniki POS słowa, jak również formularze podstawowe dla wszystkich pochodnych formularzy), możesz użyć czegoś takiego:

def is_verb(word): 
    if word: 
     tags = pos_tags(word) 
     return 'VB' in tags or 'VBP' in tags or 'VBZ' in tags \ 
       or 'VBD' in tags or 'VBN' in tags: 

def verbify(word): 
    if is_verb(word): 
     return word 
    else: 
     forms = [] 
     for tag in pos_tags(word): 
      base = word_form(word, tag[:2]) 
      if is_verb(base): 
       forms.append(base) 
     return forms 
12

To bardziej heurystyczne podejście. Właśnie zakodowałem to tak, by wyglądało na styl. Używa metody derivationally_related_forms() z wordnetu. Wprowadziłem nounify. Domyślam się, że działa analogicznie. Z tego co ja badanych działa całkiem dobrze:

from nltk.corpus import wordnet as wn 

def nounify(verb_word): 
    """ Transform a verb to the closest noun: die -> death """ 
    verb_synsets = wn.synsets(verb_word, pos="v") 

    # Word not found 
    if not verb_synsets: 
     return [] 

    # Get all verb lemmas of the word 
    verb_lemmas = [l for s in verb_synsets \ 
        for l in s.lemmas if s.name.split('.')[1] == 'v'] 

    # Get related forms 
    derivationally_related_forms = [(l, l.derivationally_related_forms()) \ 
            for l in verb_lemmas] 

    # filter only the nouns 
    related_noun_lemmas = [l for drf in derivationally_related_forms \ 
          for l in drf[1] if l.synset.name.split('.')[1] == 'n'] 

    # Extract the words from the lemmas 
    words = [l.name for l in related_noun_lemmas] 
    len_words = len(words) 

    # Build the result in the form of a list containing tuples (word, probability) 
    result = [(w, float(words.count(w))/len_words) for w in set(words)] 
    result.sort(key=lambda w: -w[1]) 

    # return all the possibilities sorted by probability 
    return result 
2

Oto funkcja, która teoretycznie jest w stanie przerobić słowa między rzeczownik/czasownik/przymiotnik/przysłówek formie zaktualizowanej że od here (oryginalnie napisany przez bogs, ja uwierzyć) do zgodności z nltk 3.2.5 teraz, że synset.lemmas i sysnset.name są funkcje.

from nltk.corpus import wordnet as wn 

# Just to make it a bit more readable 
WN_NOUN = 'n' 
WN_VERB = 'v' 
WN_ADJECTIVE = 'a' 
WN_ADJECTIVE_SATELLITE = 's' 
WN_ADVERB = 'r' 


def convert(word, from_pos, to_pos):  
    """ Transform words given from/to POS tags """ 

    synsets = wn.synsets(word, pos=from_pos) 

    # Word not found 
    if not synsets: 
     return [] 

    # Get all lemmas of the word (consider 'a'and 's' equivalent) 
    lemmas = [] 
    for s in synsets: 
     for l in s.lemmas(): 
      if s.name().split('.')[1] == from_pos or from_pos in (WN_ADJECTIVE, WN_ADJECTIVE_SATELLITE) and s.name().split('.')[1] in (WN_ADJECTIVE, WN_ADJECTIVE_SATELLITE): 
       lemmas += [l] 

    # Get related forms 
    derivationally_related_forms = [(l, l.derivationally_related_forms()) for l in lemmas] 

    # filter only the desired pos (consider 'a' and 's' equivalent) 
    related_noun_lemmas = [] 

    for drf in derivationally_related_forms: 
     for l in drf[1]: 
      if l.synset().name().split('.')[1] == to_pos or to_pos in (WN_ADJECTIVE, WN_ADJECTIVE_SATELLITE) and l.synset().name().split('.')[1] in (WN_ADJECTIVE, WN_ADJECTIVE_SATELLITE): 
       related_noun_lemmas += [l] 

    # Extract the words from the lemmas 
    words = [l.name() for l in related_noun_lemmas] 
    len_words = len(words) 

    # Build the result in the form of a list containing tuples (word, probability) 
    result = [(w, float(words.count(w))/len_words) for w in set(words)] 
    result.sort(key=lambda w:-w[1]) 

    # return all the possibilities sorted by probability 
    return result 


convert('direct', 'a', 'r') 
convert('direct', 'a', 'n') 
convert('quick', 'a', 'r') 
convert('quickly', 'r', 'a') 
convert('hunger', 'n', 'v') 
convert('run', 'v', 'a') 
convert('tired', 'a', 'r') 
convert('tired', 'a', 'v') 
convert('tired', 'a', 'n') 
convert('tired', 'a', 's') 
convert('wonder', 'v', 'n') 
convert('wonder', 'n', 'a') 

Jak widać poniżej, nie działa tak dobrze. Nie można przełączać się między przymiotnikami i przysłówkami (mój konkretny cel), ale daje to ciekawe wyniki w innych przypadkach.

>>> convert('direct', 'a', 'r') 
[] 
>>> convert('direct', 'a', 'n') 
[('directness', 0.6666666666666666), ('line', 0.3333333333333333)] 
>>> convert('quick', 'a', 'r') 
[] 
>>> convert('quickly', 'r', 'a') 
[] 
>>> convert('hunger', 'n', 'v') 
[('hunger', 0.75), ('thirst', 0.25)] 
>>> convert('run', 'v', 'a') 
[('persistent', 0.16666666666666666), ('executive', 0.16666666666666666), ('operative', 0.16666666666666666), ('prevalent', 0.16666666666666666), ('meltable', 0.16666666666666666), ('operant', 0.16666666666666666)] 
>>> convert('tired', 'a', 'r') 
[] 
>>> convert('tired', 'a', 'v') 
[] 
>>> convert('tired', 'a', 'n') 
[('triteness', 0.25), ('banality', 0.25), ('tiredness', 0.25), ('commonplace', 0.25)] 
>>> convert('tired', 'a', 's') 
[] 
>>> convert('wonder', 'v', 'n') 
[('wonder', 0.3333333333333333), ('wonderer', 0.2222222222222222), ('marveller', 0.1111111111111111), ('marvel', 0.1111111111111111), ('wonderment', 0.1111111111111111), ('question', 0.1111111111111111)] 
>>> convert('wonder', 'n', 'a') 
[('curious', 0.4), ('wondrous', 0.2), ('marvelous', 0.2), ('marvellous', 0.2)] 

nadzieja jest w stanie uratować komuś trochę problemów