1========================================== 2Examplos para o processamento do portugu�s 3========================================== 4 5 >>> import nltk 6 7(NB. Este material parte do pressuposto de que o leitor esteja 8familiarizado com o livro do NLTK, dispon�vel em 9``http://nltk.org/index.php/Book``). 10 11Utilizando o Corpus MacMorpho Tagged 12------------------------------------ 13 14O NLTK inclui o corpus de not�cias para o portugu�s brasileiro com tags de partes do discurso 15MAC-MORPHO, que conta com mais de um milh�o de palavras de textos jornal�sticos extra�dos 16de dez se��es do jornal di�rio *Folha de S�o Paulo*, do ano de 1994. 17 18Podemos utilizar este corpus como uma seq��ncia de palavras ou de palavras com tags da 19seguinte maneira: 20 21 >>> nltk.corpus.mac_morpho.words() 22 ['Jersei', 'atinge', 'm\xe9dia', 'de', 'Cr$', '1,4', ...] 23 >>> nltk.corpus.mac_morpho.sents() 24 [['Jersei', 'atinge', 'm\xe9dia', 'de', 'Cr$', '1,4', 'milh\xe3o', 25 'em', 'a', 'venda', 'de', 'a', 'Pinhal', 'em', 'S\xe3o', 'Paulo'], 26 ['Programe', 'sua', 'viagem', 'a', 'a', 'Exposi\xe7\xe3o', 'Nacional', 27 'do', 'Zebu', ',', 'que', 'come\xe7a', 'dia', '25'], ...] 28 >>> nltk.corpus.mac_morpho.tagged_words() 29 [('Jersei', 'N'), ('atinge', 'V'), ('m\xe9dia', 'N'), ...] 30 31Tamb�m � poss�vel utiliz�-lo em chunks de frases. 32 33 >>> nltk.corpus.mac_morpho.tagged_sents() 34 [[('Jersei', 'N'), ('atinge', 'V'), ('m\xe9dia', 'N'), ('de', 'PREP'), 35 ('Cr$', 'CUR'), ('1,4', 'NUM'), ('milh\xe3o', 'N'), ('em', 'PREP|+'), 36 ('a', 'ART'), ('venda', 'N'), ('de', 'PREP|+'), ('a', 'ART'), 37 ('Pinhal', 'NPROP'), ('em', 'PREP'), ('S\xe3o', 'NPROP'), ('Paulo', 'NPROP')], 38 [('Programe', 'V'), ('sua', 'PROADJ'), ('viagem', 'N'), ('a', 'PREP|+'), 39 ('a', 'ART'), ('Exposi\xe7\xe3o', 'NPROP'), ('Nacional', 'NPROP'), 40 ('do', 'NPROP'), ('Zebu', 'NPROP'), (',', ','), ('que', 'PRO-KS-REL'), 41 ('come\xe7a', 'V'), ('dia', 'N'), ('25', 'N|AP')], ...] 42 43Estes dados podem ser utilizados para efetuar o treinamento de taggers (como nos 44exemplos abaixo para o Floresta treebank). 45 46 47Utilizando o Floresta Portuguese Treebank 48----------------------------------------- 49 50A distribui��o de dados do NLTK inclui o 51"Floresta Sinta(c)tica Corpus" na vers�o 7.4, dispon�vel em 52``http://www.linguateca.pt/Floresta/``. 53 54Como para a amostra do Penn Treebank, � poss�vel 55utilizar o conte�do deste corpus como uma seq��ncia de palavras com 56informa��es de tags, da seguinte maneira: 57 58 >>> from nltk.corpus import floresta 59 >>> floresta.words() 60 ['Um', 'revivalismo', 'refrescante', 'O', '7_e_Meio', ...] 61 >>> floresta.tagged_words() 62 [('Um', '>N+art'), ('revivalismo', 'H+n'), ...] 63 64As tags s�o constitu�das por certas informa��es sint�ticas, seguidas por 65um sinal 66de mais, seguido por tag costumeira de parte do discurso 67(part-of-speech). Vamos 68remover o conte�do que antecede o sinal de mais: 69 70 >>> def simplify_tag(t): 71 ... if "+" in t: 72 ... return t[t.index("+")+1:] 73 ... else: 74 ... return t 75 >>> twords = nltk.corpus.floresta.tagged_words() 76 >>> twords = [(w.lower(),simplify_tag(t)) for (w,t) in twords] 77 >>> twords[:10] # doctest: +NORMALIZE_WHITESPACE 78 [('um', 'art'), ('revivalismo', 'n'), ('refrescante', 'adj'), ('o', 'art'), ('7_e_meio', 'prop'), 79 ('\xe9', 'v-fin'), ('um', 'art'), ('ex-libris', 'n'), ('de', 'prp'), ('a', 'art')] 80 81E exibir de maneira mais apropriada as palavras com informa��es de tags: 82 83 >>> print ' '.join(word + '/' + tag for (word, tag) in twords[:10]) 84 um/art revivalismo/n refrescante/adj o/art 7_e_meio/prop ?/v-fin um/art ex-libris/n de/prp a/art 85 86Em seguida, vamos contar o n�mero de tokens de palavras e tipos, al�m de 87determinar qual a palavra mais comum: 88 89 >>> words = floresta.words() 90 >>> len(words) 91 211870 92 >>> fd = nltk.FreqDist(words) 93 >>> len(fd) 94 29425 95 >>> fd.max() 96 'de' 97 98Podemos tamb�m listar as 20 tags mais freq�entes, em ordem decrescente de 99freq��ncia: 100 101 >>> tags = [simplify_tag(tag) for (word,tag) in floresta.tagged_words()] 102 >>> fd = nltk.FreqDist(tags) 103 >>> fd.sorted()[:20] # doctest: +NORMALIZE_WHITESPACE 104 ['n', 'prp', 'art', 'v-fin', ',', 'prop', 'adj', 'adv', '.', 'conj-c', 'v-inf', 105 'pron-det', 'v-pcp', 'num', 'pron-indp', 'pron-pers', '\xab', '\xbb', 'conj-s', '}'] 106 107Tamb�m podemos ler o corpus agrupado por enunciados: 108 109 >>> floresta.sents() # doctest: +NORMALIZE_WHITESPACE 110 [['Um', 'revivalismo', 'refrescante'], ['O', '7_e_Meio', '\xe9', 'um', 'ex-libris', 111 'de', 'a', 'noite', 'algarvia', '.'], ...] 112 >>> floresta.tagged_sents() # doctest: +NORMALIZE_WHITESPACE 113 [[('Um', '>N+art'), ('revivalismo', 'H+n'), ('refrescante', 'N<+adj')], 114 [('O', '>N+art'), ('7_e_Meio', 'H+prop'), ('\xe9', 'P+v-fin'), ('um', '>N+art'), 115 ('ex-libris', 'H+n'), ('de', 'H+prp'), ('a', '>N+art'), ('noite', 'H+n'), 116 ('algarvia', 'N<+adj'), ('.', '.')], ...] 117 >>> floresta.parsed_sents() # doctest: +NORMALIZE_WHITESPACE 118 [Tree('UTT+np', [Tree('>N+art', ['Um']), Tree('H+n', ['revivalismo']), 119 Tree('N<+adj', ['refrescante'])]), Tree('STA+fcl', [Tree('SUBJ+np', 120 [Tree('>N+art', ['O']), Tree('H+prop', ['7_e_Meio'])]), Tree('P+v-fin', ['\xe9']), 121 Tree('SC+np', [Tree('>N+art', ['um']), Tree('H+n', ['ex-libris']), 122 Tree('N<+pp', [Tree('H+prp', ['de']), Tree('P<+np', [Tree('>N+art', ['a']), 123 Tree('H+n', ['noite']), Tree('N<+adj', ['algarvia'])])])]), Tree('.', ['.'])]), ...] 124 125Para ver uma �rvore de an�lise sint�tica, podemos utilizar o m�todo 126``draw()``, como no exemplo: 127 128 >>> psents = floresta.parsed_sents() 129 >>> psents[5].draw() # doctest: +SKIP 130 131 132Concord�ncia simples 133-------------------- 134 135A seguir, apresentamos uma fun��o que recebe uma palavra e uma 136quantidade determinada 137de contexto (medido em caracteres) e gera uma concord�ncia para a mesma. 138 139 >>> def concordance(word, context=30): 140 ... for sent in floresta.sents(): 141 ... if word in sent: 142 ... pos = sent.index(word) 143 ... left = ' '.join(sent[:pos]) 144 ... right = ' '.join(sent[pos+1:]) 145 ... print '%*s %s %-*s' %\ 146 ... (context, left[-context:], word, context, right[:context]) 147 148 >>> concordance("dar") # doctest: +SKIP 149 anduru , foi o suficiente para dar a volta a o resultado . 150 1. O P?BLICO veio dar a a imprensa di?ria portuguesa 151 A fartura de pensamento pode dar maus resultados e n?s n?o quer 152 Come?a a dar resultados a pol?tica de a Uni 153 ial come?ar a incorporar- lo e dar forma a um ' site ' que tem se 154 r com Constantino para ele lhe dar tamb?m os pap?is assinados . 155 va a brincar , pois n?o lhe ia dar procura??o nenhuma enquanto n? 156 ?rica como o ant?doto capaz de dar sentido a o seu enorme poder . 157 . . . 158 >>> concordance("vender") # doctest: +SKIP 159 er recebido uma encomenda para vender 4000 blindados a o Iraque . 160 m?rico_Amorim caso conseguisse vender o lote de ac??es de o empres?r 161 mpre ter jovens simp?ticos a ? vender ? chega ! } 162 Disse que o governo vai vender ? desde autom?vel at? particip 163 ndiciou ontem duas pessoas por vender carro com ?gio . 164 A inten??o de Fleury ? vender as a??es para equilibrar as fi 165 166Tagging de partes do discurso 167----------------------------- 168 169Vamos come�ar obtendo os dados dos enunciados marcados com tags e 170simplificando 171estas �ltimas como descrito anteriormente. 172 173 >>> from nltk.corpus import floresta 174 >>> tsents = floresta.tagged_sents() 175 >>> tsents = [[(w.lower(),simplify_tag(t)) for (w,t) in sent] for sent in tsents if sent] 176 >>> train = tsents[100:] 177 >>> test = tsents[:100] 178 179J� sabemos que ``n`` � a tag mais comum; desta forma, podemos criar um 180tagger por default 181que marque toda palavra como substantivo e, em seguida, avaliar seu 182desempenho: 183 184 >>> tagger0 = nltk.DefaultTagger('n') 185 >>> nltk.tag.accuracy(tagger0, test) 186 0.17690941385435169 187 188Como pode-se deduzir facilmente, uma em cada seis palavras � um 189substantivo. Vamos 190aperfei�oar estes resultados treinando um tagger unigrama: 191 192 >>> tagger1 = nltk.UnigramTagger(train, backoff=tagger0) 193 >>> nltk.tag.accuracy(tagger1, test) 194 0.85115452930728241 195 196E, em seguida, um tagger bigrama: 197 198 >>> tagger2 = nltk.BigramTagger(train, backoff=tagger1) 199 >>> nltk.tag.accuracy(tagger2, test) 200 0.86856127886323264 201 202Segmenta��o de frases 203--------------------- 204 205O Punkt � uma ferramenta para segmenta��o de frases ling�isticamente independente, o qual 206requer um treinamento em texto puro. 207O texto de origem (obtido do Floresta Portuguese Treebank) cont�m uma frase por linha. Podemos 208ler o texto, dividi-lo em fun��o de suas linhas e ent�o agrupar estas linhas utilizando 209espa�os. Desta forma as informa��es sobre quebras de frases ter�o sido descartadas; podemos 210ent�o dividir este material em dados para treinamento e para verifica��o: 211 212 >>> text = open('floresta.txt').read() 213 >>> lines = text.split('\n') 214 >>> train = ' '.join(lines[10:]) 215 >>> test = ' '.join(lines[:10]) 216 217� agora poss�vel treinar o segmentador de frases (ou tokenizador de frases) e utiliz�-lo em 218nossas frases de verifica��o. (Para exibir o texto em uma forma leg�vel, pode ser necess�rio 219converter o texto para o UTF-8, utilizando ``print sent.decode('latin-1').encode('utf-8')``.) 220 221 >>> stok = nltk.PunktSentenceTokenizer(train) 222 >>> for sent in stok.tokenize(test): 223 ... print sent 224 225 226As vers�es do NLTK a partir da 0.9b1 incluem um modelo treinado para a segmenta��o de frases 227em portugu�s, o qual pode ser carregado pela maneira a seguir. � mais r�pido carregar um modelo 228j� treinado do que repetir o treinamento do mesmo. 229 230 >>> stok = nltk.data.load('tokenizers/punkt/portuguese.pickle') 231 232Stemming 233-------- 234 235O NLTK inclui o stemmer para o portugu�s RSLP. Vamos demonstrar sua utiliza��o para algumas 236palavras em portugu�s: 237 238 >>> stemmer = nltk.stem.RSLPStemmer() 239 >>> stemmer.stem("copiar") 240 u'copi' 241 >>> stemmer.stem("paisagem") 242 u'pais' 243 244Stopwords 245--------- 246 247O NLTK inclui stopword ("palavras limite") para o portugu�s: 248 249 >>> stopwords = nltk.corpus.stopwords.words('portuguese') 250 >>> stopwords[:10] 251 ['a', 'ao', 'aos', 'aquela', 'aquelas', 'aquele', 'aqueles', 'aquilo', 'as', 'at\xe9'] 252 253A esta altura, � poss�vel utiliz�-las para filtrar textos. Vamos encontrar as palavras mais 254comuns (� exce��o das stopwords) e list�-las em ordem decrescente de freq��ncia: 255 256 >>> fd = nltk.FreqDist(w.lower() for w in floresta.words() if w not in stopwords) 257 >>> for word in fd.sorted()[:20]: 258 ... print word, fd[word] 259 , 13444 260 . 7725 261 ? 2369 262 ? 2310 263 ? 1137 264 o 1086 265 } 1047 266 { 1044 267 a 897 268 ; 633 269 em 516 270 ser 466 271 sobre 349 272 os 313 273 anos 301 274 ontem 292 275 ainda 279 276 segundo 256 277 ter 249 278 dois 231 279 280 281Codifica��es de caracteres 282-------------------------- 283 284O Python � capaz de lidar com todas a codifica��es de caracteres mais utilizada para o portugu�s, a 285ISO 8859-1 (ISO Latin 1). 286 287 >>> text = open('floresta.txt').read() 288 >>> text[:60] 289 'O 7 e Meio \xe9 um ex-libris da noite algarvia.\n\xc9 uma das mais ' 290 >>> print text[:60] 291 O 7 e Meio ? um ex-libris da noite algarvia. 292 ? uma das mais 293 >>> text[:60].decode('latin-1') 294 u'O 7 e Meio \xe9 um ex-libris da noite algarvia.\n\xc9 uma das mais ' 295 >>> text[:60].decode('latin-1').encode('utf-8') 296 'O 7 e Meio \xc3\xa9 um ex-libris da noite algarvia.\n\xc3\x89 uma das mais ' 297 >>> text[:60].decode('latin-1').encode('utf-8') 298 'O 7 e Meio \xc3\xa9 um ex-libris da noite algarvia.\n\xc3\x89 uma das mais ' 299 >>> text[:60].decode('latin-1').encode('utf-16') 300 '\xff\xfeO\x00 \x007\x00 \x00e\x00 \x00M\x00e\x00i\x00o\x00 \x00\xe9\x00 \x00u\x00m\x00 \x00e\x00x\x00-\x00l\x00i\x00b\x00r\x00i\x00s\x00 \x00d\x00a\x00 \x00n\x00o\x00i\x00t\x00e\x00 \x00a\x00l\x00g\x00a\x00r\x00v\x00i\x00a\x00.\x00\n\x00\xc9\x00 \x00u\x00m\x00a\x00 \x00d\x00a\x00s\x00 \x00m\x00a\x00i\x00s\x00 \x00' 301