Portuguese (Português) translation by Erick Patrick (you can also view the original English article)
É provável que todos já pegamos livros gigantescos e vimos índices ao final deles. Com um capa dura, é bom ter algo como um índice para navegar rapidamente à pagina desejada. Recentemente, publiquei um livro curto e, ao tentar criar o índice, a tarefa parece bem complicada, mesmo o livro sendo curto. O livro ainda não um índice, infelizmente.
Se tem acompanhado nossos artigos, perceberá que escrevo, basicamente, sobre Python e como ele pode ajudar-nos a resolver diferentes problems de forma simples. Então, vejamos como criar o índice de um livro usando Python.
Sem mais delongas, comecemos!
O Que É o Índice de um Livro?
Tenho certeza que a maioria de nós sabe o que é o índice de um livro, mas, gostaria de esclarecer o conceito.
O índice de um livro é uma coleção de palavras e/ou frases que são consideradas importantes para o licro, junto de suas localizações no livro. O índice não contém todas palavras/frases do livro. O motivo é explicado na próxima seção.
O Que Torna Um Índice de Livro Bom?
E se tivéssemos um índice que pudéssemos encontrar o local de cada palavra ou frase num livro? Essa não seria a melhor escolha de índice? Errado!
O índice escolhido ou um que seria considerado bom é aquele que aponta as palavras e frases importantes no livro. Talvez se pergunte o porque disso. Vejamos um exemplo. Digamos que temos um livro consistindo da seguinte sentença:
My book is short
O que aconteceria se tentássemos indexar cada palavra e frase nessa pequena sentença, assumindo que o local seja a posição da palavra na sentença? Esse seria o índice que teríamos nesse caso:
1 |
my book is short: 1 |
2 |
my book is: 1 |
3 |
my book: 1 |
4 |
my: 1 |
5 |
short: 4 |
6 |
is short: 3 |
7 |
is: 3 |
8 |
book is short: 2 |
9 |
book is: 2 |
10 |
book: 2 |
Do exemplo acima, podemos ver que tal índice seria maior que o próprio livro! Assim, um índice bom seria aquele que contém palavras e frases importantes para o leitor.
Configuração
Natural Language Toolkit (NLTK)
No tutorial, usaremos a biblioteca Natural Language Toolkit (NLTK), usada para trabalhar com dados em linguagem natural. Como mencionado na documentação, NLTK é considerada "uma maravilhosa ferramenta para ensinar e trabalhar em linguística computacional usando Python" e "uma maravilhosa biblioteca para brincar com linguagem natural".
Escrevemos esse tutorial usando uma máquina rodando Ubuntu e os passos para instalar NLTK nessa seção serão relevantes para esse Sistema Operacional. Mas, não se preocupe, podemos encontrar os passos para instalar NLTK em outros sistemas no site da NLTK.
Para instalar NLTK, usaremos pip. Se não tivermos pip
instalado, podemos instalá-lo usando o comando de terminal a seguir:
sudo easy_install3 pip
Para garantir que temos pip instalado, digitemos o seguinte:
pip --version
Deveríamos ter como retorno algo assim:
pip 8.1.2 from /usr/local/lib/python3.5/dist-packages/pip-8.1.2-py3.5.egg (python 3.5)
Agora, para instalar NLTK, apenas executemos o comando abaixo no terminal.
sudo pip install -U nltk
Podemos testar a isntalação do nltk
digitando python e então importando nltk no terminal. Se virmos ImportError: No module named nltk
, esse tópico pode ajudá-lo.
Arquivo de Teste
Agora, precisamos um arquivo de teste (livro) pra usarmos na criação do índice. Usaremos o livro A Taxa de Mudança da Taxa de Mudança por EFF. Podemos baixar o arquivo de texto do livro desse Dropbox. Podemos, claro, usar qualquer livro, apenas precisamos algo para trabalhar nesse tutorial.
Programa
Comcemos com a parte interessante do tutorial, o programa que nos ajudará a formar o índice do livro. A primeira coisa que queremos fazer é achar a frequência das palavras no livro. Mostramos como fazer isso em outro tutorial, mas mostraremos como fazer usando a biblioteca NLTK.
Podemos fazê-lo assim:
1 |
import nltk, collections |
2 |
from nltk.collocations import * |
3 |
|
4 |
frequencies = collections.Counter() |
5 |
with open('bigd10.txt') as book: |
6 |
read_book = book.read() |
7 |
words = nltk.word_tokenize(read_book) |
8 |
|
9 |
for w in words: |
10 |
frequencies[w] += 1 |
11 |
|
12 |
print (frequencies) |
Ao executarmos o programa, perceberemos que teremos uma lista bem grande de palavras e suas frequêcias.
Antes de continuar, analisemos um pouco esse código. Nessa linha:
1 |
frequencies = collections.Counter() |
Tentamos usar a função Counter()
para obter a frequência da palavra no livro (quantas vezes ela apareceu no livro).
word_tokenize
, por outro lado, divite as sentenças em suas partes constituintes. Vejamos um exemplo simples para ver como word_tokenize
funciona:
1 |
from nltk.tokenize import word_tokenize |
2 |
sentence = 'My name is Abder. I like Python. It\'s a pretty nice programming language' |
3 |
print (word_tokenize(sentence)) |
O retorno do script assim é:
['My', 'name', 'is', 'Abder', '.', 'I', 'like', 'Python', '.', 'It', "'s", 'a', 'pretty', 'nice', 'programming', 'language']
Nós então iteramos pelas palavras e achamos a frequência de cada uma delas.
Que tal frases (combinação de palavras)? Elas são chamadas de colocações (sequência de palavras que aparecem juntas frequentemente). Exemplo de colocação é bigramas, que é uma lista de par de palavras. De forma similar são os trigramas (combinação de três palavras) e por aí vai (n-grams).
Digamos que queremos extrair os bigramas do livro. Podemos fazê-lo assim:
1 |
bigram = nltk.collocations.BigramAssocMeasures() |
2 |
finder = BigramCollocationFinder.from_words(words) |
3 |
finder.apply_freq_filter(2) |
O número 2
em apply_freq_filter()
diz para ignorar todos os bigramas que ocorrem duas ou menos vezes no livro.
Se quisermos os 30
mais frquentes bigramas do livro, podemos usar o seguinte código:
1 |
print (finder.nbest(bigram.pmi, 30)) |
Por fim, se quisermos encontrar a localização, que em nosso caso seria onde a palavra ou frase ocorre no livro (não a página do livro), podemos fazer o seguinte:
1 |
print (read_book.index('computer')) |
2 |
print (read_book.index('Assisted Reporting')) |
As declarações acima retornam a localização da palavra em uma sentença, similar ao que vimos no exemplo da curta sentença no início do tutorial.
Juntando Tudo
Juntemos tudo que aprendemos em um único script Python. O script abaixo lerá o livro e retornar a frequência das palavras, junto dos 30 mais frequentes bigramas no livro, fora a localização de uma palavra e uma frase no livro:
1 |
import nltk, collections |
2 |
from nltk.collocations import * |
3 |
|
4 |
frequencies = collections.Counter() |
5 |
with open('bigd10.txt') as book: |
6 |
read_book = book.read() |
7 |
words = nltk.word_tokenize(read_book) |
8 |
|
9 |
for w in words: |
10 |
frequencies[w] += 1 |
11 |
|
12 |
bigram = nltk.collocations.BigramAssocMeasures() |
13 |
finder = BigramCollocationFinder.from_words(words) |
14 |
finder.apply_freq_filter(2) |
15 |
|
16 |
print ('Those are the words and their frequency of occurrence in the book:') |
17 |
print (frequencies) |
18 |
print ('#################################################################') |
19 |
print ('Those are the 30 most bigrams occurring in the book:') |
20 |
print (finder.nbest(bigram.pmi, 30)) |
21 |
print (read_book.index('computer')) |
22 |
print (read_book.index('Assisted Reporting')) |
Conclusão
Como vimos no tutorial, mesmo o menor texto pode ser bem complciado ao criar um índice para ele. Vimos também que uma forma automatizada de construção de índice ótimo pode não ser viável.
Fomos capazes de resolver esse problema usando Python e a biblioteca NLTK, onde pegamos as melhores palavras e frases para o índice do livro, baseados nas suas frequências (i.e, importância) no livro.
Claro, há mais o que podemos fazer com NLTK, como visto na documentação da biblioteca. Também podemos ir mais a fundo, se quisermos, com o livro Processamento de Linguagem Natural com Python.