CofeehousePy/nlpfr/nltk/test/portuguese.doctest_latin1

301 lines
12 KiB
Plaintext

==========================================
Examplos para o processamento do português
==========================================
>>> import nltk
(NB. Este material parte do pressuposto de que o leitor esteja
familiarizado com o livro do NLTK, disponível em
``http://nltk.org/index.php/Book``).
Utilizando o Corpus MacMorpho Tagged
------------------------------------
O NLTK inclui o corpus de notícias para o português brasileiro com tags de partes do discurso
MAC-MORPHO, que conta com mais de um milhão de palavras de textos jornalísticos extraídos
de dez seções do jornal diário *Folha de São Paulo*, do ano de 1994.
Podemos utilizar este corpus como uma seqüência de palavras ou de palavras com tags da
seguinte maneira:
>>> nltk.corpus.mac_morpho.words()
['Jersei', 'atinge', 'm\xe9dia', 'de', 'Cr$', '1,4', ...]
>>> nltk.corpus.mac_morpho.sents()
[['Jersei', 'atinge', 'm\xe9dia', 'de', 'Cr$', '1,4', 'milh\xe3o',
'em', 'a', 'venda', 'de', 'a', 'Pinhal', 'em', 'S\xe3o', 'Paulo'],
['Programe', 'sua', 'viagem', 'a', 'a', 'Exposi\xe7\xe3o', 'Nacional',
'do', 'Zebu', ',', 'que', 'come\xe7a', 'dia', '25'], ...]
>>> nltk.corpus.mac_morpho.tagged_words()
[('Jersei', 'N'), ('atinge', 'V'), ('m\xe9dia', 'N'), ...]
Também é possível utilizá-lo em chunks de frases.
>>> nltk.corpus.mac_morpho.tagged_sents()
[[('Jersei', 'N'), ('atinge', 'V'), ('m\xe9dia', 'N'), ('de', 'PREP'),
('Cr$', 'CUR'), ('1,4', 'NUM'), ('milh\xe3o', 'N'), ('em', 'PREP|+'),
('a', 'ART'), ('venda', 'N'), ('de', 'PREP|+'), ('a', 'ART'),
('Pinhal', 'NPROP'), ('em', 'PREP'), ('S\xe3o', 'NPROP'), ('Paulo', 'NPROP')],
[('Programe', 'V'), ('sua', 'PROADJ'), ('viagem', 'N'), ('a', 'PREP|+'),
('a', 'ART'), ('Exposi\xe7\xe3o', 'NPROP'), ('Nacional', 'NPROP'),
('do', 'NPROP'), ('Zebu', 'NPROP'), (',', ','), ('que', 'PRO-KS-REL'),
('come\xe7a', 'V'), ('dia', 'N'), ('25', 'N|AP')], ...]
Estes dados podem ser utilizados para efetuar o treinamento de taggers (como nos
exemplos abaixo para o Floresta treebank).
Utilizando o Floresta Portuguese Treebank
-----------------------------------------
A distribuição de dados do NLTK inclui o
"Floresta Sinta(c)tica Corpus" na versão 7.4, disponível em
``http://www.linguateca.pt/Floresta/``.
Como para a amostra do Penn Treebank, é possível
utilizar o conteúdo deste corpus como uma seqüência de palavras com
informações de tags, da seguinte maneira:
>>> from nltk.corpus import floresta
>>> floresta.words()
['Um', 'revivalismo', 'refrescante', 'O', '7_e_Meio', ...]
>>> floresta.tagged_words()
[('Um', '>N+art'), ('revivalismo', 'H+n'), ...]
As tags são constituídas por certas informações sintáticas, seguidas por
um sinal
de mais, seguido por tag costumeira de parte do discurso
(part-of-speech). Vamos
remover o conteúdo que antecede o sinal de mais:
>>> def simplify_tag(t):
... if "+" in t:
... return t[t.index("+")+1:]
... else:
... return t
>>> twords = nltk.corpus.floresta.tagged_words()
>>> twords = [(w.lower(),simplify_tag(t)) for (w,t) in twords]
>>> twords[:10] # doctest: +NORMALIZE_WHITESPACE
[('um', 'art'), ('revivalismo', 'n'), ('refrescante', 'adj'), ('o', 'art'), ('7_e_meio', 'prop'),
('\xe9', 'v-fin'), ('um', 'art'), ('ex-libris', 'n'), ('de', 'prp'), ('a', 'art')]
E exibir de maneira mais apropriada as palavras com informações de tags:
>>> print ' '.join(word + '/' + tag for (word, tag) in twords[:10])
um/art revivalismo/n refrescante/adj o/art 7_e_meio/prop ?/v-fin um/art ex-libris/n de/prp a/art
Em seguida, vamos contar o número de tokens de palavras e tipos, além de
determinar qual a palavra mais comum:
>>> words = floresta.words()
>>> len(words)
211870
>>> fd = nltk.FreqDist(words)
>>> len(fd)
29425
>>> fd.max()
'de'
Podemos também listar as 20 tags mais freqüentes, em ordem decrescente de
freqüência:
>>> tags = [simplify_tag(tag) for (word,tag) in floresta.tagged_words()]
>>> fd = nltk.FreqDist(tags)
>>> fd.sorted()[:20] # doctest: +NORMALIZE_WHITESPACE
['n', 'prp', 'art', 'v-fin', ',', 'prop', 'adj', 'adv', '.', 'conj-c', 'v-inf',
'pron-det', 'v-pcp', 'num', 'pron-indp', 'pron-pers', '\xab', '\xbb', 'conj-s', '}']
Também podemos ler o corpus agrupado por enunciados:
>>> floresta.sents() # doctest: +NORMALIZE_WHITESPACE
[['Um', 'revivalismo', 'refrescante'], ['O', '7_e_Meio', '\xe9', 'um', 'ex-libris',
'de', 'a', 'noite', 'algarvia', '.'], ...]
>>> floresta.tagged_sents() # doctest: +NORMALIZE_WHITESPACE
[[('Um', '>N+art'), ('revivalismo', 'H+n'), ('refrescante', 'N<+adj')],
[('O', '>N+art'), ('7_e_Meio', 'H+prop'), ('\xe9', 'P+v-fin'), ('um', '>N+art'),
('ex-libris', 'H+n'), ('de', 'H+prp'), ('a', '>N+art'), ('noite', 'H+n'),
('algarvia', 'N<+adj'), ('.', '.')], ...]
>>> floresta.parsed_sents() # doctest: +NORMALIZE_WHITESPACE
[Tree('UTT+np', [Tree('>N+art', ['Um']), Tree('H+n', ['revivalismo']),
Tree('N<+adj', ['refrescante'])]), Tree('STA+fcl', [Tree('SUBJ+np',
[Tree('>N+art', ['O']), Tree('H+prop', ['7_e_Meio'])]), Tree('P+v-fin', ['\xe9']),
Tree('SC+np', [Tree('>N+art', ['um']), Tree('H+n', ['ex-libris']),
Tree('N<+pp', [Tree('H+prp', ['de']), Tree('P<+np', [Tree('>N+art', ['a']),
Tree('H+n', ['noite']), Tree('N<+adj', ['algarvia'])])])]), Tree('.', ['.'])]), ...]
Para ver uma árvore de análise sintática, podemos utilizar o método
``draw()``, como no exemplo:
>>> psents = floresta.parsed_sents()
>>> psents[5].draw() # doctest: +SKIP
Concordância simples
--------------------
A seguir, apresentamos uma função que recebe uma palavra e uma
quantidade determinada
de contexto (medido em caracteres) e gera uma concordância para a mesma.
>>> def concordance(word, context=30):
... for sent in floresta.sents():
... if word in sent:
... pos = sent.index(word)
... left = ' '.join(sent[:pos])
... right = ' '.join(sent[pos+1:])
... print '%*s %s %-*s' %\
... (context, left[-context:], word, context, right[:context])
>>> concordance("dar") # doctest: +SKIP
anduru , foi o suficiente para dar a volta a o resultado .
1. O P?BLICO veio dar a a imprensa di?ria portuguesa
A fartura de pensamento pode dar maus resultados e n?s n?o quer
Come?a a dar resultados a pol?tica de a Uni
ial come?ar a incorporar- lo e dar forma a um ' site ' que tem se
r com Constantino para ele lhe dar tamb?m os pap?is assinados .
va a brincar , pois n?o lhe ia dar procura??o nenhuma enquanto n?
?rica como o ant?doto capaz de dar sentido a o seu enorme poder .
. . .
>>> concordance("vender") # doctest: +SKIP
er recebido uma encomenda para vender 4000 blindados a o Iraque .
m?rico_Amorim caso conseguisse vender o lote de ac??es de o empres?r
mpre ter jovens simp?ticos a ? vender ? chega ! }
Disse que o governo vai vender ? desde autom?vel at? particip
ndiciou ontem duas pessoas por vender carro com ?gio .
A inten??o de Fleury ? vender as a??es para equilibrar as fi
Tagging de partes do discurso
-----------------------------
Vamos começar obtendo os dados dos enunciados marcados com tags e
simplificando
estas últimas como descrito anteriormente.
>>> from nltk.corpus import floresta
>>> tsents = floresta.tagged_sents()
>>> tsents = [[(w.lower(),simplify_tag(t)) for (w,t) in sent] for sent in tsents if sent]
>>> train = tsents[100:]
>>> test = tsents[:100]
Já sabemos que ``n`` é a tag mais comum; desta forma, podemos criar um
tagger por default
que marque toda palavra como substantivo e, em seguida, avaliar seu
desempenho:
>>> tagger0 = nltk.DefaultTagger('n')
>>> nltk.tag.accuracy(tagger0, test)
0.17690941385435169
Como pode-se deduzir facilmente, uma em cada seis palavras é um
substantivo. Vamos
aperfeiçoar estes resultados treinando um tagger unigrama:
>>> tagger1 = nltk.UnigramTagger(train, backoff=tagger0)
>>> nltk.tag.accuracy(tagger1, test)
0.85115452930728241
E, em seguida, um tagger bigrama:
>>> tagger2 = nltk.BigramTagger(train, backoff=tagger1)
>>> nltk.tag.accuracy(tagger2, test)
0.86856127886323264
Segmentação de frases
---------------------
O Punkt é uma ferramenta para segmentação de frases lingüisticamente independente, o qual
requer um treinamento em texto puro.
O texto de origem (obtido do Floresta Portuguese Treebank) contém uma frase por linha. Podemos
ler o texto, dividi-lo em função de suas linhas e então agrupar estas linhas utilizando
espaços. Desta forma as informações sobre quebras de frases terão sido descartadas; podemos
então dividir este material em dados para treinamento e para verificação:
>>> text = open('floresta.txt').read()
>>> lines = text.split('\n')
>>> train = ' '.join(lines[10:])
>>> test = ' '.join(lines[:10])
É agora possível treinar o segmentador de frases (ou tokenizador de frases) e utilizá-lo em
nossas frases de verificação. (Para exibir o texto em uma forma legível, pode ser necessário
converter o texto para o UTF-8, utilizando ``print sent.decode('latin-1').encode('utf-8')``.)
>>> stok = nltk.PunktSentenceTokenizer(train)
>>> for sent in stok.tokenize(test):
... print sent
As versões do NLTK a partir da 0.9b1 incluem um modelo treinado para a segmentação de frases
em português, o qual pode ser carregado pela maneira a seguir. É mais rápido carregar um modelo
já treinado do que repetir o treinamento do mesmo.
>>> stok = nltk.data.load('tokenizers/punkt/portuguese.pickle')
Stemming
--------
O NLTK inclui o stemmer para o português RSLP. Vamos demonstrar sua utilização para algumas
palavras em português:
>>> stemmer = nltk.stem.RSLPStemmer()
>>> stemmer.stem("copiar")
u'copi'
>>> stemmer.stem("paisagem")
u'pais'
Stopwords
---------
O NLTK inclui stopword ("palavras limite") para o português:
>>> stopwords = nltk.corpus.stopwords.words('portuguese')
>>> stopwords[:10]
['a', 'ao', 'aos', 'aquela', 'aquelas', 'aquele', 'aqueles', 'aquilo', 'as', 'at\xe9']
A esta altura, é possível utilizá-las para filtrar textos. Vamos encontrar as palavras mais
comuns (à exceção das stopwords) e listá-las em ordem decrescente de freqüência:
>>> fd = nltk.FreqDist(w.lower() for w in floresta.words() if w not in stopwords)
>>> for word in fd.sorted()[:20]:
... print word, fd[word]
, 13444
. 7725
? 2369
? 2310
? 1137
o 1086
} 1047
{ 1044
a 897
; 633
em 516
ser 466
sobre 349
os 313
anos 301
ontem 292
ainda 279
segundo 256
ter 249
dois 231
Codificações de caracteres
--------------------------
O Python é capaz de lidar com todas a codificações de caracteres mais utilizada para o português, a
ISO 8859-1 (ISO Latin 1).
>>> text = open('floresta.txt').read()
>>> text[:60]
'O 7 e Meio \xe9 um ex-libris da noite algarvia.\n\xc9 uma das mais '
>>> print text[:60]
O 7 e Meio ? um ex-libris da noite algarvia.
? uma das mais
>>> text[:60].decode('latin-1')
u'O 7 e Meio \xe9 um ex-libris da noite algarvia.\n\xc9 uma das mais '
>>> text[:60].decode('latin-1').encode('utf-8')
'O 7 e Meio \xc3\xa9 um ex-libris da noite algarvia.\n\xc3\x89 uma das mais '
>>> text[:60].decode('latin-1').encode('utf-8')
'O 7 e Meio \xc3\xa9 um ex-libris da noite algarvia.\n\xc3\x89 uma das mais '
>>> text[:60].decode('latin-1').encode('utf-16')
'\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'