letreiro brilhante embaixo de uma janela

Mineração de texto: python para descobrir emoções

O que as pessoas pensam sobre a sua empresa, ou sobre a empresa que você trabalha?

Há um tempo, comecei a estudar um conteúdo dentro do aprendizado de máquina conhecido como análise de texto — ou mineração de emoções. Este campo tenta identificar emoções em texto.

Por exemplo: hoje estou feliz.

Quem for ler esta frase perceberá que trata-se de uma frase de alegria, entretanto como fazer o computador entender que esta frase é uma frase de felicidade?

A resposta é mais ou menos simples: utilizando o aprendizado de máquina. Essa pergunta tem um peso ainda maior quando falamos do mundo corporativo.

Imagina escanear a reação de um montante grande de pessoas e, com isso, acelerar uma tomada de decisão, como uma automação, que tem uma influência direta sobre o business?

Ou sobre o customer success.

Bem, hoje nós falaremos sobre como usar a mineração de emoção, por meio de texto e utilizando a linguagem Python.  

Vamos lá? 🙂

10 Livros de Python para ser um especialista

Mineração de emoções nas redes sociais

Se pararmos para pensar as pessoas nunca se comunicaram tanto por redes sociais como hoje. Seja facebook, Twitter, Instagram entre outras redes sociais.

As pessoas demonstram seus sentimentos e suas vontades via redes sociais.

Então, poderíamos usar como ‘termômetro’ para saber se nossa empresa está sendo bem falada ou não estas redes sociais. Certo?  

Um bom começo para nosso estudo será o Twitter, já que o mesmo dispõe de uma API para desenvolvedores para coletar tweets, a chamada tweepy.

Sim, esta biblioteca está disponível para Python, que será a linguagem utilizada no meu exemplo, como já adiantei.

Imagine o seguinte cenário. Trabalhamos em uma empresa que produz “capinha de celular” e desejamos saber o que as pessoas comentam sobre nossos produtos.

Com isso podemos criar uma campanha de marketing para lançar um produto novo, ou detectar alguma falha já existente e corrigi-la.

>>Leitura Recomendada:
Leia nosso artigo sobre Python Microsservices

Mas como catalogar emoções?

Segundo o psicólogo Paul Ekman existem seis tipos de emoções básicas que são:

  1. Surpresa
  2. Alegria
  3. Tristeza
  4. Medo
  5. Desgosto ou nojo
  6. Raiva

Porém, para o nosso caso decidimos catalogar as frases em duas emoções que são: alegria e raiva.

Se uma frase for de alegria, para nós, significa, que a pessoa está feliz com o produto. Mas, se uma frase for de raiva significa que a pessoa está descontente com nosso produto.

Mineração de texto usando python na prática

Para fins didáticos separei em seções os passos da construção do algoritmo de machine learning para que possamos classificar as frases como sendo de alegria, ou de raiva.

Imagine que já coletamos os tweets e agora partiremos para o pré-processamento das nossas frases coletadas.

base = [(‘Essa capinha de celular é muito boa’, ‘alegria’),
        (‘Gostei muito desta capinha de celular’, ‘alegria’),
        (‘Capinha maravilhosa’, ‘alegria’),
        (‘Que capinha bonita’, ‘alegria’),
        (‘Abaixo do esperado’, ‘raiva’),
        (‘Não gostei’, ‘raiva’),
        (‘Desbotou na primeira semana’, ‘raiva’),
  (‘Olha só essa capinha! ‘, ‘alegria’),
        (‘Material de baixa resistência’, ‘raiva’),
        (‘Custo benefício excelente’, ‘alegria’),
        (‘A foto é diferente do produto’, ‘raiva’)]

Usaremos este banco de dados com 11 frases para o entendimento ficar mais claro, porém a lógica será a mesma para uma quantidade maior de frases.

O “pulo do gato” é mapear a maior quantidade de frases similares entre si, que expressam esses dois sentimentos.

Antes de começarmos o pré-processamento precisaremos instalar a biblioteca nltk.

Para isso podemos utilizar o comando pip install nltk no prompt de comando (mais sobre a biblioteca nltk aqui)

Após instalar, precisamos fazer o download de algumas coleções da biblioteca nltk, para isso abrimos o prompt de comando, digitamos python e quando aparecer:

 >>> 

importaremos a biblioteca nltk

 >>> import nltk 

e em seguida digitamos o seguinte comando

 >>> nltk.download() 

Então, será aberta esta tela:

Agora basta fazer o download do all-corpora. Feito, isso vamos para o pré-processamento das frases.

Pré-processamento

Em qualquer idioma existem palavras que não agregam muito sentido a frases como por exemplo: “a”, “as”, “e”, “de”, “das” e etc… essas palavras na biblioteca nltk* são conhecidas como StopWords.

Então, sim, estas palavras podem gerar algum tipo de ruído indesejável para nossas análises posteriores.

*conjunto de bibliotecas para PLN (processamento de linguagem natural simbólica e estatística) em Python

Outra coisa que podemos fazer nessa mesma etapa é retirar o sufixo e o prefixo das palavras e ficar apenas com seu radical. Observe as palavras:

Carro

Carrinho

Carrão

As três palavras dizem respeito a algum tipo de carro, então o que podemos fazer é retirar o sufixo da palavra e ficar apenas com seu radical.

Isto é, carr.

Iremos fazer isso com todas as nossas palavras, porém, ao fazermos isso, podemos perder um pouco de informação.

Isso quer dizer que retirar uma Stopword, sufixo e prefixo tem um certo custo e devemos analisar se vale a pena ou não fazer esse processo.

Criando o algoritmo de mineração de texto

Vamos voltar à biblioteca nltk:

import nltk
stopwords=nltk.corpus.stopwords.words(‘portuguese’)

Esse pacote contém radicais de várias línguas assim como Stopwords, e o que rola é que elas variam de língua para língua, então precisamos referenciar o português na segunda linha.

Agora teremos uma lista com as stopwords se fizermos o comando:

 print(stopwords) 

Receberemos uma lista com as stopwords em português parecida com essa:

 ['de', 'a', 'o', 'que', 'e', 'é', 'do', 'da', 'em', 'um', 'para', 'com', 'não', 'uma', 'os', 'no', 'se', 'na', 'por', 'mais', 'as', 'dos', 'como', 'mas', 'ao', 'ele', 'das', 'à', 'seu', 'sua', 'ou', 'quando', 'muito', 'nos', 'já', 'eu', 'também', 'só', 'pelo', 'pela', 'até', ,....,'teríamos', 'teriam'] 

Agora criaremos a função que faz o processamento que falamos anteriormente:

 
def fazstemmer(texto):
    stemmer = nltk.stem.RSLPStemmer()
    frasessstemming = []
    for (palavras, emocao) in texto:
        comstemming = [str(stemmer.stem(p))
                       for p in palavras.split() if p not in stopwords]
        frasessstemming.append((comstemming, emocao))
    return frasessstemming
 
 
frasescomstemming = fazstemmer(base)
print(frasescomstemming)

E como resultado temos o seguinte :

[([‘ess’, ‘cap’, ‘celul’, ‘boa’], ‘alegria’), ([‘gost’, ‘dest’, ‘cap’, ‘celul’], ‘alegria’), ([‘cap’, ‘maravilh’], ‘alegria’), ([‘que’, ‘cap’, ‘bonit’], ‘alegria’), ([‘abaix’, ‘esper’], ‘raiva’), ([‘não’, ‘gost’], ‘raiva’), ([‘desbot’, ‘prim’, ‘seman’], ‘raiva’), ([‘olh’, ‘capinha!’], ‘alegria’), ([‘mater’, ‘baix’, ‘resist’], ‘raiva’), ([‘cust’, ‘benefici’, ‘excel’], ‘alegria’), ([‘a’, ‘fot’, ‘difer’, ‘produt’], ‘raiva’)]

Perceba acima, por exemplo, a primeira frase que era:

“Está capa de celular é o máximo”

…que na função ficou:

“est cap celul máx”

Mas, perceba que as frases estão organizadas em tuplas contendo a frase e a emoção, então o que faremos agora é uma função que organiza somente as palavras em uma lista:

def buscapalavras(frases):
    todaspalavras = []
    for (palavras, emocao) in frases:
        todaspalavras.extend(palavras)
    return todaspalavras
 
frasescomstemming = fazstemmer(base)
print(frasescomstemming)

E como resultado teremos a seguinte lista:

[‘ess’, ‘cap’, ‘celul’, ‘boa’, ‘gost’, ‘dest’, ‘cap’, ‘celul’, ‘cap’, ‘maravilh’, ‘que’, ‘cap’, ‘bonit’, ‘abaix’, ‘esper’, ‘não’, ‘gost’, ‘desbot’, ‘prim’, ‘seman’, ‘olh’, ‘capinha!’, ‘mater’, ‘baix’, ‘resist’, ‘cust’, ‘benefici’, ‘excel’, ‘a’, ‘fot’, ‘difer’, ‘produt’]

Agora que temos nossa lista de radicais iremos calcular a frequência com que eles aparecem:

def buscafrequencia(palavras):
    palavras = nltk.FreqDist(palavras)
    return palavras
frequencia = buscafrequencia(palavras)

E agora vamos criar um dicionário de palavras únicas. Isso vai produzir um efeito de excluir as palavras repetidas.

Para você entender melhor, pense em um dicionário de gramática, no dicionário há apenas palavras únicas, então é isso que faremos aqui, com a seguinte função:

def busca_palavrasunicas(frequencia):
    freq = frequencia.keys()
    return freq
 
palavrasunicas = busca_palavrasunicas(frequencia)
print(palavrasunicas)

E como resultado teremos:

 dict_keys(['ess', 'cap', 'celul', 'boa', 'gost', 'dest', 'maravilh', 'que', 'bonit', 'abaix', 'esper', 'não', 'desbot', 'prim', 'seman', 'olh', 'capinha!', 'mater', 'baix', 'resist', 'cust', 'benefici', 'excel', 'a', 'fot', 'difer', 'produt']) 

Agora utilizaremos uma função chamada extraipalavras.

O objetivo desta função é classificá-las como True,se estiverem dentro da nossa lista de palavras únicas, ou False se ela não está em nossa lista de palavras únicas.

def extrai_palavras(documento):
    doc = set(documento)
    caracteristicas = {}
    for palavras in palavrasunicas:
        caracteristicas[‘%s’ % palavras] = (palavras in doc)
    return caracteristicas

Exemplo:

caracteristicasfrase = extrai_palavras([‘am’, ‘nov”dia’,’ess’,’celul’,’boa’])
print(caracteristicasfrase)
{‘ess’: True, ‘cap’: False, ‘celul’: True, ‘boa’: True, ‘gost’: False, ‘dest’: False, ‘maravilh’: False, ‘que’: False, ‘bonit’: False, ‘abaix’: False, ‘esper’: False, ‘não’: False, ‘desbot’: False, ‘prim’: False, ‘seman’: False, ‘olh’: False, ‘capinha!’: False, ‘mater’: False, ‘baix’: False, ‘resist’: False, ‘cust’: False, ‘benefici’: False, ‘excel’: False, ‘a’: False, ‘fot’: False, ‘difer’: False, ‘produt’: False}

A função extraipalavras fez a seguinte comparação:

As palavras que estão em nossa lista de palavras únicas foram classificadas como True e as que não estão em nossa lista de palavras únicas foram classificadas como False.

Agora chamaremos uma função da biblioteca nltk passando como parâmetros a função extraipalavras e nossas frases já processadas:

basecompleta = nltk.classify.apply_features(extrai_palavras,frasescomstemming)

Agora vamos testar a basecompleta na nossa primeira frase:

 ('Essa capinha de celular é muito boa', 'alegria')


print(basecompleta[0]) 

E como resultado teremos:  

({‘ess’: True, ‘cap’: True, ‘celul’: True, ‘boa’: True, ‘gost’: False, ‘dest’: False, ‘maravilh’: False, ‘que’: False, ‘bonit’: False, ‘abaix’: False, ‘esper’: False, ‘não’: False, ‘desbot’: False, ‘prim’: False, ‘seman’: False, ‘olh’: False, ‘capinha!’: False, ‘mater’: False, ‘baix’: False, ‘resist’: False, ‘cust’: False, ‘benefici’: False, ‘excel’: False, ‘a’: False, ‘fot’: False, ‘difer’: False, ‘produt’: False}, ‘alegria’)

Esta função retorna as nossas frases mostrando quais palavras estão contidas ou não nelas.

Quando imprimimos a basecompleta[0] recebemos uma tupla, onde o primeiro item é um dicionário com nossas palavras únicas marcadas como True ou False.

As palavras marcadas como True  são as palavras que estão na frase ‘Essa capinha de celular é muito boa’. 

Já o segundo item da tupla é o alvo, ou seja, como essa frase foi classificada.

Agora vamos construir nossa tabela de probabilidade  com a biblioteca nltk.

 classificador = nltk.NaiveBayesClassifier.train(basecompleta) 

Agora podemos imprimir as etiquetas das frases, que aqui são apenas duas: alegria e raiva

 print(classificador.labels()) 

E com isso, teremos:

 ['alegria', 'raiva'] 

Ainda podemos imprimir mais informações sobre nossa tabela de probabilidade, com o seguinte comando:

 print(classificador.show_most_informative_features(5))



Most Informative Features
                     cap = False        raiva : alegri =      2.6 : 1.0
                   celul = False        raiva : alegri =      1.4 : 1.0
                    baix = False        alegri : raiva =      1.2 : 1.0
                   seman = False        alegri : raiva =      1.2 : 1.0
                   mater = False        alegri : raiva =      1.2 : 1.0 

O que esta tabela mostra é:

  • Quando a palavra cap é False, ou seja, não aparece na frase, a probabilidade da frase ser de raiva é 2.6 vezes maior do que de ser de alegria.
  • Quando a palavra celul é False, ou seja, não aparece na frase, a probabilidade da frase ser de raiva é de 1.4 vezes mais do que de ser de alegria.
  • Quando à palavra baix é False, ou seja, não aparece na frase, a probabilidade da frase ser de alegria é de 1.2 vezes mais do que de ser de alegria.

e assim por diante;

>>Leitura Recomendada:
Os 5 melhores frameworks de Python

Adicionando novas frases ao algoritmo de mineração

Agora iremos testar nosso algoritmo com uma nova frase:

teste= “Capinha legal! Gostei

Então, vamos criar uma lista vazia que recebe somente os radicais da nossa frase teste:

teste = ‘Capinha legal! Gostei’
testestem = []
stemmer = nltk.stem.RSLPStemmer()
for (palavras) in teste.split():
    comstem = [p for p in palavras.split()]
    testestem.append(str(stemmer.stem(comstem[0])))
print(testestem)

E como resultado teremos:

[‘cap’, ‘legal!’, ‘gost’]

E, por fim, vamos ver como algoritmo classifica nossa nova frase:

 nova_frase = extrai_palavras(testestem)
 
distribuicao = classificador.prob_classify(nova_frase)
print('-----------------------')
for classe in distribuicao.samples():
    print("%s: %f" % (classe, distribuicao.prob(classe))) 

E o resultado é:

alegria: 0.941693
raiva: 0.058307 

Ou seja, a probabilidade dessa frase ser de alegria é de 0.9416 ou de 94,16%.

Caso você tenha ficado com alguma dúvida, ou queira ver o algoritmo completo o link para o código completa está no meu GitHub.

>>Leitura Recomendada:
Os algoritmos de machine learning

Próximos passos

Agora que construímos um algoritmo podemos fazer coletas semanais por uma ou duas horas, classificá-las e, com isso, podemos fazer desde uma simples contagem do tipo das frases que coletamos.

Isto é, podemos ver quantas são de alegria e quantas são de raiva. Também podemos aplicar outras métricas próprias da empresa.

Podemos também criar grupos do porquê as pessoas sentem raiva do nosso produto e fazer uma outra mineração para clusterizar as frases de raiva, atacando os problemas que são mais recorrentes.

Enfim, a partir daqui as possibilidades são infinitas.

Espero ter ajudado a sua empresa! 🙂



Compartilhar
You May Also Like