Natural Language Processing com a biblioteca spaCy

Ao procurar por NLP analysis no Google a impressão é de que análise de sentimento é a única coisa que se pode explorar em textos. Existe um mundo de possibilidades, e conhecer as ferramentas que temos à disposição é uma ótima maneira de aguçar a criatividade.

Visando isso, nesse texto vamos conhecer algumas métricas usadas para analisar textos e explorá-las através de exemplos, utilizando a biblioteca spaCy.

➗ Tokenization

Uma boa forma de começar a analisar o texto é o separando em unidades menores. O nome desse processo é tokenization, que basicamente significa separar o texto em palavras.

No spaCy você utiliza models, que são tipo os ‘cérebros treinados’ de cada língua. A biblioteca ainda não tem um model para Português :(, só para Inglês e Alemão.

import spacy
nlp = spacy.load('en') #o model
raw_text = "Seven years after the death of his wife, Mill was invited to contest Westminster. His feeling on the conduct of elections made him refuse to take any personal action in the matter, and he gave the frankest expression to his political views, but nevertheless he was elected by a large majority. He was not a conventional success in the House; as a speaker he lacked magnetism. But his influence was widely felt."
parsedData = nlp(raw_text) #pronto, o texto já tá separado em tokens

Ao passar o texto para o model ele já o separa em tokens e computa várias outras propriedades.

word = parsedData[0]
print(word.text, word.lower_)
>>> Seven seven

A lista de todas as propriedades que o model computa pode ser encontrada aqui.

🗣 Part-of-speech tagging

Lembra na escola quando a gente tinha que identificar quem era o substantivo, o verbo e os adjetivos nas frases? Em NLP esse processo se chama part-of-speech tagging. É a boa e velha análise gramatical.

O model já fez essa análise, que pode ser acessada pela propriedade.pos_ de cada token.

for i,word in enumerate(parsedData):
print(word.text, word.pos_)
if i > 5:
break
>>> Seven NUM
years NOUN
after ADP
the DET
death NOUN
of ADP
his ADJ

Aqui a gente pode ver a lista com o significado de cada uma dessas tags.

Existe também uma tag mais elaborada, que pode ser acessada pela propriedade .tag_ Essa tag contém informações sobre a estrutura morfológica da palavra.

word = parsedData[10] #a palavra 'was'
print("original:",word.text)
print("POS tag:",word.pos_)
print("fine grainned POS tag:", word.tag_)
>>> original: was
POS tag: VERB
fine grainned POS tag: VBD
# VBD significa: VerbForm=fin Tense=past

Massa, né?

📌 Named Entity Recognition (NER)

Esse processo busca identificar categorias como nomes de pessoas, organizações, locais, porcentagens, valores monetários, e por ai vai. Essas categorias podem ser pré-definidas por nós, então dependendo do texto podemos criar nossas próprias entidades.

Pra variar, o model também já computou isso pra a gente na propriedade .ent_type_. Vamos ver quantas entidades nosso texto tem:

for word in parsedData:
if word.ent_type_:
print(word.text, word.ent_type_)
>>> Seven DATE
years DATE
Mill PERSON
Westminster PERSON
House ORG

🔪 Syntactic Parsing

Syntactic parsing é o processo de representar as dependências do texto através das relações entre os tokens. Por exemplo: um artigo está ligado a um substantivo, um advérbio modifica um verbo, e por ai vai.

O Explosion AI criou uma ferramenta linda para visualizar essas dependências, o Dependency Visualizer.

As dependências da primeira frase do nosso texto

O atributo para ter acesso à dependência sintática de cada token é o .dep_

for word in parsedData:
print(word.text, word.dep_)
>>> Seven nummod
years nsubjpass
after prep
the det
death pobj
of prep
[...]

Existem várias formas de navegar pela árvore sintática. Aqui na documentação eles explicam tudo que pode ser feito. É possível encontrar um verbo e o sujeito dele, por exemplo.

Aqui tem uma lista com o significado de cada tag da análise sintática e nesse site aqui eles explicam mais o significado de cada termo.


Agora vamos ver funcionalidades do spaCy que nos ajudam a trabalhar com as métricas que vimos até aqui.

✅ Rule-based matching

Esse rule-based matching permite a criação de regras utilizando os atributos e flags dos tokens. Isso pode ser bem interessante nos casos onde a gente tá trabalhando em um corpus sobre um domínio específico.

Por exemplo, eu quero encontrar todos os sujeitos nominais do texto:

from spacy.attrs import DEP
from spacy.matcher import Matcher
matcher = Matcher(nlp.vocab)
# http://universaldependencies.org/en/dep/nsubj.html
matcher.add_pattern("SujeitoNominal", [ {DEP:'nsubj'}])
doc = nlp(raw_text)
matches = matcher(doc)
for ent_id, label, start, end in matcher(doc):
print(doc[start:end].text)
>>> feeling
he
He
he

Ainda é possível:

↗️ Word vectors

Para computar as similaridades entre palavras uma técnica comum é representá-las através de vetores. A forma mais famosa de treinar esses vetores é com a família de algoritmos do word2vec.

Com o spaCy é fácil trabalhar com vetores porque as classes Lexeme, Token, Span e Doc têm uma propriedade .vector . Vamos testar isso vendo as similaridades entre um cachorro, um gato e um cavalo.

my,dog,and_,cat,and__,horse = nlp(u'my dog and cat and horse')
print(cat.similarity(dog))
print(cat.similarity(horse))
print(dog.similarity(horse))
>>> 0.801685428714
0.484733507195
0.624627638895

📈 E a análise se sentimento?

Na documentação eles mostram como conectar um modelo de deep learning no spaCy. Em um outro post vamos explorar mais essa funcionalidade.

E é isso! Com essas coisinhas já dá pra a gente brincar e analisar textos. Nesse gist você encontra o notebook que eu usei nessa tour. 😄

Anúncios

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s