25
loading...
This website collects cookies to deliver better user experience
"And what is the use of a book", thought Alice, "without pictures or conversations?"
nltk
(Natural Language Toolkit) é um pacote para trabalhar com Processamento de Linguagem Natural (NLP) no Python. Por linguagem natural entende-se a linguagem usada no dia a dia na comunicação entre pessoas.nltk
possui muitos recursos para análise de texto e conheceremos alguns deles.sudo pip3 install -U nltk
nltk
possui um pacote com amostras de dados para uso, inclusive alguns do próprio projeto Gutenberg. A lista completa dos dados disponíveis pode ser acessada aqui. O pacote não vem habilitado por padrão, para instalá-lo, faça:>>> import nltk
>>> nltk.download()
usr/share/nltk_data
- diretório do Linux para armazenar dados que não serão modificados (mais informações aqui). Caso esteja utilizando Windows, a recomendação é salvar no diretório C:\nltk_data
e no Mac em /usr/local/share/nltk_data
.$ sudo python3 -m nltk.downloader -d /usr/local/share/nltk_data all
import
:>>> import nltk.corpus as corpus
corpus
possui exatamente isso, várias amostras de textos que podemos utilizar para análise. Usaremos o atributo gutenberg
para acessar alguns textos do projeto Gutenberg que carregamos com o download dos dados do nltk.>>> type(corpus.gutenberg)
<class 'nltk.corpus.reader.plaintext.PlaintextCorpusReader'>
corpus.gutenberg
é um atributo do tipo PlaintextCorpusReader
. Este objeto, segundo a documentação (acesse pelo comando help(corpus.gutenberg)
), é um leitor para corpus de texto plano - é assumido que parágrafos são divididos usando quebra de linha, as frases>>> corpus.gutenberg.fileids()
['austen-emma.txt', 'austen-persuasion.txt', 'austen-sense.txt', 'bible-k
jv.txt', 'blake-poems.txt', 'bryant-stories.txt', 'burgess-busterbrown.tx
t', 'carroll-alice.txt', 'chesterton-ball.txt', 'chesterton-brown.txt',
'chesterton-thursday.txt', 'edgeworth-parents.txt', 'melville-moby_dick.t
xt', 'milton-paradise.txt', 'shakespeare-caesar.txt', 'shakespeare-hamle
t.txt', 'shakespeare-macbeth.txt', 'whitman-leaves.txt']
fileids()
mostra os arquivos disponíveis. Para acessar o livro Alice no País das Maravilhas, usaremos o seu fileid
que é o carroll-alice.txt
através do método raw()
:>>> alice = corpus.gutenberg.raw('carroll-alice.txt')
>>> type(alice)
<class 'str'>
raw()
retorna uma string com todo o conteúdo do livro. Quem já trabalhou com strings conhece a dificuldade de trabalhar com estes objetos. Outros objetos do nltk
irão nos ajudar para conseguir analisar melhor este conteúdo.nltk
possui um módulo chamado tokenize
que facilita o processo de divisão de um texto. A função word_tokenize()
divide um texto por palavras e pontuações:from nltk.tokenize import word_tokenize
>>> texto = 'Hello, how are you?'
>>> word_tokenize(texto)
['Hello', ',', 'how', 'are', 'you', '?']
sent_tokenize()
:from nltk.tokenize import sent_tokenize
>>> texto = 'Hello, how are you? Fine, thanks!'
>>> sent_tokenize(texto)
['Hello, how are you?', 'Fine, thanks!']
line_tokenize()
:from nltk.tokenize import line_tokenize
>>> texto = 'Lorem ipsum dolor sit amet, amet blandit suscipit quam tellu
s vitae mauris, ut metus tellus, curabitur et elit, in volutpat, fringill
a aliquam. \nDonec cras tristique, quis eu. Ipsum integer quis sapien ves
tibulum wisi vel, scelerisque justo massa nulla tempor in, placerat ut se
m nunc ultrices ac, quis conubia.'
>>> line_tokenize(texto)
>>> ['Lorem ipsum dolor sit amet, amet blandit suscipit quam tellus vitae
mauris, ut metus tellus, curabitur et elit, in volutpat, fringilla aliqua
m.',
'Donec cras tristique, quis eu. Ipsum integer quis sapien vestibulum wis
i vel, scelerisque justo massa nulla tempor in, placerat ut sem nunc ultr
ices ac, quis conubia.']
gutenberg
, temos funções prontas como paras()
, sents()
e words()
que retornam o conteúdo do texto separados por parágrafos, sentenças e palavras, respectivamente. Você pode testar cada um deles:>>> paragrafos = corpus.gutenberg.paras('carroll-alice.txt')
>>> paragrafos
[[['[', 'Alice', "'", 's', 'Adventures', 'in', 'Wonderland', 'by', 'Lewi
s', 'Carroll', '1865', ']']], [['CHAPTER', 'I', '.'], ['Down', 'the', 'Ra
bbit', '-', 'Hole']], ...]
>>> sentencas = corpus.gutenberg.sents('carroll-alice.txt')
>>> sentencas
[['[', 'Alice', "'", 's', 'Adventures', 'in', 'Wonderland', 'by', 'Lewis'
, 'Carroll', '1865', ']'], ['CHAPTER', 'I', '.'], ...]
>>> palavras = corpus.gutenberg.words('carroll-alice.txt')
>>> palavras
['[', 'Alice', "'", 's', 'Adventures', 'in', ...]
>>> type(paragrafos)
<class 'nltk.corpus.reader.util.StreamBackedCorpusView'>
>>> type(sentencas)
<class 'nltk.corpus.reader.util.StreamBackedCorpusView'>
>>> type(palavras)
<class 'nltk.corpus.reader.util.StreamBackedCorpusView'>
StremBackedCorpusView
que representa uma visualização do corpus através de uma sequência de tokens iterável. Este objeto também possui métodos, como o count()
para contar o número de vezes que um elemento aparece na sequência de tokens.count()
para checar o número de vezes que determinados personagens são citados no texto. Por exemplo, se queremos saber quantas vezes a palavra "Alice" aparece, fazemos:>>> palavras.count('Alice')
396
>>> personagens = ['Alice', 'Rabbit', 'Caterpillar', 'Cat', 'Hatter', 'Do
rmouse', 'Hare', 'Queen', 'King', 'Gryphon' ]
>>> for p in personagens:
... print('{}: {}'.format(p, palavras.count(p)))
...
Alice: 396
Rabbit: 45
Caterpillar: 0
Cat: 26
Hatter: 55
Dormouse: 40
Hare: 31
Queen: 74
King: 61
Gryphon: 55
nltk
facilita essa visualização através da classe Text
.Text
funciona como um wrapper de uma sequência de tokens (como nossa variável palavras
) e ajuda na exploração de textos. Seus métodos executam várias análises e exibe seus resultados, como é o caso do método dispersion_plot()
, que plota um gráfico de dispersão. Primeiro precisamos de uma instância de Text com o conteúdo do livro, e obteremos através da variável palavras
:>>> palavras_text = nltk.Text(palavras)
>>> palavras_text.dispersion_plot(['Alice'])
palavras_text.dispersion_plot(personagens)
nltk
para determinar as palavras mais frequentes (especificamente tokens), que são usadas em um determinado texto. Para facilitar a visualização, vamos utilizar a classe FreqDist
que representa a distribuição dos valores que aparecem com maior frequência em uma amostra. Essa classe possui um método plot()
que recebe um número inteiro como parâmetro representando a quantidade dos valores que queremos mostrar. Vamos gerar um gráfico com as 20 palavras mais frequentes no>>> freq = nltk.FreqDist(palavras_text)
>>> freq.plot(20)
isalpha()
do objeto str
do próprio Python:>>> freq_sem_pontuacao = nltk.FreqDist(dict((word, freq) for word, freq i
n freq.items() if word.isalpha()))
>>> freq_sem_pontuacao.plot(20, title="20 palavras mais populares (sem po
ntuação)")
nltk
possui um recurso chamado de stopwords (palavras de parada). Vamos eliminar também essas stopwords.stopwords
:>>> stopwords = nltk.corpus.stopwords.words('english')
>>> freq_sem_pontuacao_e_sem_stopwords = nltk.FreqDist(dict((word, freq)
for word, freq in freq.items() if word not in stopwords and word.isalpha
()))
>>> freq_sem_pontuacao_e_sem_stopwords.plot(20, title="20 palavras mais p
opulares (sem stopwords ou pontuações)")
nltk
possui esse recurso.nltk
possui uma função chamada pos_tag()
que infere uma classe (substantivo, adjetivo, advérbio, verbo, etc..) para cada palavra. Como esta função recebe uma lista de tokens, vamos usar a função word_tokenize()
com o texto puro:>>> alice_txt = nltk.corpus.gutenberg.raw('carroll-alice.txt')
>>> words = nltk.word_tokenize(alice_txt)
>>> tags = nltk.pos_tag(words)
>>> tags
[('[', 'JJ'), ('Alice', 'NNP'),("'s", 'POS'), ('Adventures', 'NNS'), ('i
n', 'IN'), ('Wonderland', 'NNP'), ('by', 'IN'), ('Lewis', 'NNP'), ('Carro
ll', 'NNP'), ('1865', 'CD'), (']', 'NNP'), ('CHAPTER', 'NNP'), ('I', 'PR
P'), ('.', '.'), ('Down', 'RP'), ('the', 'DT'), ('Rabbit-Hole', 'JJ'), (
'Alice', 'NNP'), ('was', 'VBD'), ...
>>> nltk.help.upenn_tagset()
NNP
:>>> substantivos_proprios= []
>>> for word,tag in tags:
... if tag in ['NNP'] and word.isalpha():
... substantivos_proprios.append(word)
...
>>>
>>> freq_substantivos_proprios=nltk.FreqDist(substantivos_proprios)
>>> freq_substantivos_proprios.plot(20, title='20 substantivos próprios m
ais frequentes')
>>> mais_comuns = freq_substantivos_proprios.most_common(n=20)
>>> personagens_mais_comuns = []
>>> for nome,freq in mais_comuns:
... personagens_mais_comuns.append(nome)
...
>>> palavras_text.dispersion_plot(personagens_mais_comuns)
VB
:>>> verbos = []
>>> for word,tag in tags:
... if tag in ['VB']:
... verbos.append(word)
...
>>> freq_verbos=nltk.FreqDist(verbos)
>>> freq_verbos.plot(20, title='20 verbos mais frequentes')
>>> mais_comuns = freq_verbos.most_common(n=20)
>>> verbos_mais_comuns = []
>>> for nome,freq in mais_comuns:
... verbos_mais_comuns.append(nome)
...
>>> palavras_text.dispersion_plot(verbos_mais_comuns)
nltk
é um pacote bastante completo e possui subpacotes para analisar o sentimento de frases. Será que o texto possui mais sentenças que passam sentimentos negativos, positivos ounltk.sentiment
que possui o módulo vader
com diversas funcionalidade para obter métricas de sentimento de uma sentença. VADER
é acrônimo de Valence Aware Dictionary and Sentiment Reasoner, ou seja, um dicionário de valência e de raciocínio de sentimento. A palavra valência , em linguística, é o número de elementos gramaticais com os quais uma determinada palavra, especialmente um verbo, pode combinar em uma sentença.nltk
já fez todo este trabalho por nós. O código deste módulo pode ser acessado através deste link.SentimentIntensityAnalyzer
que nos dá uma pontuação de intensidade de sentimento de determinadas sentenças.>>> from nltk.sentiment.vader import SentimentIntensityAnalyzer
>>> sa = SentimentIntensityAnalyzer()
polarity_scores()
que vai gerar as pontuações. Vejamos um exemplo:>>> frase = 'Good job, nltk!'
>>> sa.polarity_scores(frase)
{'neg': 0.0, 'neu': 0.385, 'pos': 0.615, 'compound': 0.4926}
neg
(sentimento negativo), neu
(sentimento neutro), pos
(sentimento positivo) e compound
(sentimento dos três anteriores combinados). Esta pontuação é exatamente o cálculo da valência. vader
é muito utilizado para analisar sentimentos de posts em redes sociais. É extremamente rápido e não necessita de treinamento.>>> alice_txt = nltk.corpus.gutenberg.raw('carroll-alice.txt')
>>> sentencas = nltk.sent_tokenize(alice_txt)
>>> sentencas
>>> lista_pontuacoes = []
>>> lista_sentencas = []
>>> for sentenca in sentencas:
... lista_sentencas.append(sentenca)
... pontuacao = sa.polarity_scores(sentenca)
... lista_pontuacoes.append(pontuacao['compound'])
...
pandas
, uma biblioteca do Python bastante usada para análise de dados. Para instalar o pandas
, execute o código abaixo no terminal:$ pip3 install pandas
>>> import pandas as pd
>>> df = pd.DataFrame({'sentenca': lista_sentencas, 'pontuacao': lista_po
ntuacoes})
df
guarda um dataframe, um tipo de dado retangular que representa uma tabela com as colunas senteca
e pontuacao
. Cada linha dessa tabela, portanto, possui o valor da sentença e sua respectiva pontuação de análise de sentimento (no caso, a pontuação composta).head()
do dataframe:>>> df.head(10)
pandas
consegue selecionar isso muito facilmente. Uma sentença com sentimento negativo é aquela que possui pontuação menor do que 0 :>>> selecao_neg = df.pontuacao < 0
>>> negativas = df[selecao_neg]
>>> negativas.head(10)
negativas
. Vamos ver sua quantidade:>>> len(negativas)
394
>>> selecao_pos = df.pontuacao > 0
>>> positivas = df[selecao_pos]
>>> len(positivas)
443
>>> selecao_neu = df.pontuacao == 0
>>> neutras = df[selecao_neu]
>>> len(neutras)
788
>>> sentimentos = pd.DataFrame({'sentimentos':['negativo', 'neutro', 'pos
itivo'], 'quantidade':[len(negativas), len(neutras), len(positivas)]})
>>> sentimentos.plot(kind='bar', x='sentimentos', y='quantidade', color=[
'lightblue'], rot=0)