Package nltk :: Package stem :: Module rslp
[hide private]
[frames] | no frames]

Source Code for Module nltk.stem.rslp

  1  #!/usr/bin/python 
  2  # -*- coding: utf-8 -*- 
  3   
  4  # Natural Language Toolkit: RSLP Stemmer 
  5  # 
  6  # Copyright (C) 2001-2008 NLTK Project 
  7  # Author: Tiago Tresoldi <[email protected]> 
  8  # URL: <http://nltk.org> 
  9  # For license information, see LICENSE.TXT 
 10   
 11  # This code is based on the algorithm presented in the paper "A Stemming 
 12  # Algorithm for the Portuguese Language" by Viviane Moreira Orengo and 
 13  # Christian Huyck, which unfortunately I had no access to. The code is a 
 14  # Python version, with some minor modifications of mine, to the description 
 15  # presented at http://www.webcitation.org/5NnvdIzOb and to the C source code 
 16  # available at http://www.inf.ufrgs.br/~arcoelho/rslp/integrando_rslp.html. 
 17  # Please note that this stemmer is intended for demostration and educational 
 18  # purposes only. Feel free to write me for any comments, including the 
 19  # development of a different and/or better stemmer for Portuguese. I also 
 20  # suggest using NLTK's mailing list for Portuguese for any discussion. 
 21   
 22  # Este código é baseado no algoritmo apresentado no artigo "A Stemming 
 23  # Algorithm for the Portuguese Language" de Viviane Moreira Orengo e 
 24  # Christian Huyck, o qual infelizmente não tive a oportunidade de ler. O 
 25  # código é uma conversão para Python, com algumas pequenas modificações 
 26  # minhas, daquele apresentado em http://www.webcitation.org/5NnvdIzOb e do 
 27  # código para linguagem C disponível em 
 28  # http://www.inf.ufrgs.br/~arcoelho/rslp/integrando_rslp.html. Por favor, 
 29  # lembre-se de que este stemmer foi desenvolvido com finalidades unicamente 
 30  # de demonstração e didáticas. Sinta-se livre para me escrever para qualquer 
 31  # comentário, inclusive sobre o desenvolvimento de um stemmer diferente 
 32  # e/ou melhor para o português. Também sugiro utilizar-se a lista de discussão 
 33  # do NLTK para o português para qualquer debate. 
 34   
 35  import nltk.data 
 36   
 37  from api import * 
 38   
39 -class RSLPStemmer(StemmerI):
40 """ 41 A stemmer for Portuguese. 42 """
43 - def __init__ (self):
44 self._model = [] 45 46 self._model.append( self.read_rule("step0.pt") ) 47 self._model.append( self.read_rule("step1.pt") ) 48 self._model.append( self.read_rule("step2.pt") ) 49 self._model.append( self.read_rule("step3.pt") ) 50 self._model.append( self.read_rule("step4.pt") ) 51 self._model.append( self.read_rule("step5.pt") ) 52 self._model.append( self.read_rule("step6.pt") )
53
54 - def read_rule (self, filename):
55 rules = nltk.data.load('nltk:stemmers/rslp/' + filename, format='raw').decode("utf8") 56 lines = rules.split("\n") 57 58 lines = [line for line in lines if line != u""] # remove blank lines 59 lines = [line for line in lines if line[0] != "#"] # remove comments 60 61 # NOTE: a simple but ugly hack to make this parser happy with double '\t's 62 lines = [line.replace("\t\t", "\t") for line in lines] 63 64 # parse rules 65 rules = [] 66 for line in lines: 67 rule = [] 68 tokens = line.split("\t") 69 70 # text to be searched for at the end of the string 71 rule.append( tokens[0][1:-1] ) # remove quotes 72 73 # minimum stem size to perform the replacement 74 rule.append( int(tokens[1]) ) 75 76 # text to be replaced into 77 rule.append( tokens[2][1:-1] ) # remove quotes 78 79 # exceptions to this rule 80 rule.append( [token[1:-1] for token in tokens[3].split(",")] ) 81 82 # append to the results 83 rules.append(rule) 84 85 return rules
86
87 - def stem(self, word):
88 word = word.lower() 89 90 # the word ends in 's'? apply rule for plural reduction 91 if word[-1] == "s": 92 word = self.apply_rule(word, 0) 93 94 # the word ends in 'a'? apply rule for feminine reduction 95 if word[-1] == "a": 96 word = self.apply_rule(word, 1) 97 98 # augmentative reduction 99 word = self.apply_rule(word, 3) 100 101 # adverb reduction 102 word = self.apply_rule(word, 2) 103 104 # noun reduction 105 prev_word = word 106 word = self.apply_rule(word, 4) 107 if word == prev_word: 108 # verb reduction 109 prev_word = word 110 word = self.apply_rule(word, 5) 111 if word == prev_word: 112 # vowel removal 113 word = self.apply_rule(word, 6) 114 115 return word
116
117 - def apply_rule(self, word, rule_index):
118 rules = self._model[rule_index] 119 for rule in rules: 120 suffix_length = len(rule[0]) 121 if word[-suffix_length:] == rule[0]: # if suffix matches 122 if len(word) >= suffix_length + rule[1]: # if we have minimum size 123 if word not in rule[3]: # if not an exception 124 word = word[:-suffix_length] + rule[2] 125 break 126 127 return word
128
129 -def demo():
130 from nltk import stem 131 stemmer = stem.RSLPStemmer() 132 133 # white-space tokenizer friendly text; text taken from the first paragraph 134 # of Erico Verissimo's "Música ao Longe" 135 text = u""" 136 Clarissa risca com giz no quadro-negro a paisagem que os alunos devem copiar . 137 Uma casinha de porta e janela , em cima duma coxilha . Um coqueiro do lado 138 ( onde o nosso amor nasceu - pensa ela no momento mesmo em que risca o troco 139 longo e fino ) . Depois , uma estradinha que corre , ondulando como uma cobra 140 , e se perde longe no horizonte . Nuvens de fiz do céu preto , um sol redondo 141 e gordo , chispando raios , árvores , uma lagoa com marrecos nadando ... 142 """ 143 144 tokens = text.split() 145 146 for token in tokens: 147 word = token 148 stem = stemmer.stem(token) 149 150 print "%16s - %16s" % (word, stem)
151 152 if __name__ == "__main__": 153 demo() 154