Data Science Machine Learning Python

NLP com scikit-learn

Fala galera do mundo dos dados, partiu NLP com scikit-learn! Hoje vamos falar sobre processamento de linguagem natural ou NLP (do inglês Natural Language Processing). Mas o que é esse NLP? O que é linguagem natural? Fica tranquilo, que vamos entender todos esses conceitos, os problemas relacionados a NLP. Logo depois dos conceitos, vamos ver como o python pode nos ajudar com isso. Seguimos na construção de modelos de Machine Learning (ML) com sklearn.

Vamos resolver um problema de classificação utilizando python e as técnicas de NLP. Se não sabe o que são os problemas de classificação confere o nosso último post da trilha de  modelos de machine learning (Classificação com scikit-learn). Sem mais enrolação, vamos começar falando o que é  processamento de linguagem natural. Partiu NLP com skearn!!!

O que é NLP?

O  processamento de linguagem natural ou NLP é a área de estudo que busca fazer com que a máquina possa compreender e simular a linguagem humana. Em outras palavras, é fazer o computador receber uma frase e ter uma “opinião” sobre ela.

Na ciência de dados e inteligência artificial a NLP tem áreas de estudos específicas, além disso é tratada com muito carinho pois é a chave para resolução de muitos problemas atuais. As soluções vão desde classificação de textos, como vamos ver hoje, até soluções mais complexas de análises de sentimentos. 

Chatbots e assistentes virtuais são outras soluções que estão em alta relacionadas a NLP. Os chatbots tem soluções simples, como respostas prontas relacionadas a um manual técnico de instruções, até soluções de interações de diálogos com seres humanos, como o famoso Watson da  IBM.

Como prever o futuro?
“Minha bola de cristal prever que IBM e Watson são o futuro!”

Dessa mesma forma estão os assistentes virtuais com reconhecimento de voz e interações dos mais diversos temas, por exemplo, a Siri do iPhone.

A nossa solução problema de hoje é pegar uma base de dados mercadológica classificada por departamento, vamos ensinar o algoritmo a classificar novos produtos para os departamentos treinados. Para que isso seja possível vamos ver algumas técnicas que são utilizadas para NLP. Vamos construir um processo para chegar a solução desse problema, com o conceito de cada etapa e como fazer utilizando a linguagem python.

Para começar vamos fazer a preparação dos dados.  

Preparação dos dados

A preparação de dados é muito importante para qualquer modelo de aprendizagem de máquina. Para os problemas de processamento de linguagem natural não é diferente, um bom tratamento do texto pode levar nosso modelo a resultados incríveis.

Nesse sentido vamos conhecer algumas ferramentas para nos auxiliar nesse processo, um conjunto de bibliotecas em python a plataforma NLTK, e uso de expressões regulares. NLTK (Natural Language Toolkit), se traduzido ao pé da letra, seria kit de ferramentas para linguagem natural, é uma plataforma que conta com um conjunto de bibliotecas para auxiliar no processamento da linguagem natural. Já as expressões regulares são uma forma de encontrar em textos cadeia de caracteres, seja para removê-los ou substituir.

Antes de mais nada, para começar o tratamento dos dados em python vamos, importar as bibliotecas necessárias, carregar os dados e criar uma nova coluna no dataframe para trabalhar os dados:

Importando bibliotecas

import pandas as pd
import nltk
from nltk.corpus import stopwords
nltk.download('stopwords')
nltk.download('punkt')
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer
from sklearn.svm import LinearSVC
from sklearn import metrics
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from wordcloud import WordCloud

Carregando dataset

df = pd.read_csv('https://raw.githubusercontent.com/dadosaocubo/nlp/master/base_mercadologica.csv')
df.head(2)

Criando uma nova coluna

df['nova_descricao'] = df['descricao'].copy()

Para o nosso problema vamos tratar nos dados, pontuação, acentuação, caracteres especiais, palavras vazias (stop words) e números, que são caracteres que interferem na análise do texto. Então vamos começar com pontuação e acentuação.

Pontuação e acentuação para NLP

A pontuação é sempre um ponto de atenção, ela pode auxiliar o entendimento de um texto. por exemplo a ?, que indica uma pergunta, ela pode atrapalhar, por exemplo, em um erro de digitação, ou ser irrelevante como no nosso exemplo, que para identificar produtos de mercado não precisamos de pontuação nos nomes dos itens.

Portantando vamos remover as pontuações das descrições dos itens, utilizando expressão regular com a linguagem python como podemos ver abaixo:

df['nova_descricao'] = df['nova_descricao'].str.replace('[,.:;!?]+', ' ', regex=True).copy()

A acentuação dos textos também podem ser removidas dos textos para evitar ruídos no processamento de textos, desde a mesma palavra estando com e sem pontuação no texto, até o uso de gírias e expressões coloquiais. Também vamos remover a acentuação das descrições dos itens do nosso problema mais em outro momento.

Agora vamos tratar a remoção de caracteres especiais.

Caracteres Especiais para NLP

Os caracteres especiais, por exemplo: #, $ e &, normalmente representam alguma simbologia ou marcações no texto. Dessa forma não agregam muito valor para o entendimento do texto.

Portantando vamos remover caracteres especiais das descrições dos itens, utilizando também expressão regular com a linguagem python como podemos ver abaixo:

df['nova_descricao'] = df['nova_descricao'].str.replace ('[/<>()|\+\-\$%&#@\'\"]+', ' ', regex=True).copy()

Sigamos para os tratamento do números.

Números para NLP

Os números devem ser mais um ponto de atenção na análise do texto. Em problemas de classificação de texto por exemplo, os números podem confundir os classificadores, diminuindo a assertividade dos mesmos.

Portantando para o nosso problema que é de classificação também, vamos remover os números das descrições dos itens, utilizando também expressão regular com a linguagem python como podemos ver abaixo:

df['nova_descricao'] = df['nova_descricao'].str.replace('[0-9]+', '', regex=True).copy()

Por fim da nossa preparação de dados para o nosso problema, vamos conhecer e tratar as stop words.

Stop Words para NLP

As palavras vazias ou stop words, como são mais conhecidas, são palavras que não agregam sentidos as frases, por exemplo, conjunções, artigos e pronomes. Não existe uma lista definitiva com essas palavras, como sempre essa análise vai depender do problema.

Vou mostrar a lista de stop words em português da biblioteca NLTK, que pode ser uma base inicial de partida.

# Lista com as 50 primeiras stop words da biblioteca NLTK
str(stopwords.words('portuguese')[:50])
 
['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é', 'isso', 'ela', 
 'entre', 'depois', 'sem', 'mesmo', 'aos', 'seus', 'quem']

Mas para o nosso problema vamos criar a nossa lista de stop words, devido a peculiaridade do nosso problema a maioria das palavras da biblioteca NLTK não consta na descrição dos itens mercadológicos. Agora vamos ver como construir uma lista de stop words em python:

# Criamos um objeto do tipo lista com todas as nossas stop words
stop_words = ['em','sao','ao','de','da','do','para','c','kg','un',
              'ml','pct','und','das','no','ou','pc','gr','pt','cm',
              'vd','com','sem','gfa','jg','la','1','2','3','4','5',
              '6','7','8','9','0','a','b','c','d','e','lt','f','g',
              'h','i','j','k','l','m','n','o','p','q','r','s','t',
              'u','v','x','w','y','z']

Após esse tratamento inicial, vamos agora preparar o texto para servir como input no modelo de aprendizagem de máquina. Vamos entender o que é a tokenização e a transformação desses tokens em vetores, assim sendo possível de ser interpretado pelo algoritmo.

Tokenização

A tokenização é a forma de separação do texto em tokens, ou seja, decompor o texto por cada termo. Essa técnica utiliza-se para contar palavras e realizar diversas análises de texto. Agora vamos ver um exemplo em python para ficar mais claro o entendimento.

frase = 'Texto exemplo tokenização'
nltk.word_tokenize(frase)
 
['Texto', 'exemplo', 'tokenização']

Agora que entendemos como é feita a tokenização, vamos transformar essa lista de tokens em vetores binários com a função CountVectorizer() do scikit-learn.

CountVectorizer

Essa função já faz o processo de tokenização e transforma os tokens em vetores, sem precisar usar a biblioteca do NLTK. O processo ocorre da seguinte forma, são identificada todas as palavras únicas no texto e transformados em vetores binários que identifica cada uma dessas palavras. Calma, esse processo é totalmente encapsulado para o usuário, mas agora você também sabe como funciona por trás das cortinas. Vamos criar a nossa função:

# Criação da função CountVectorizer
cvt = CountVectorizer(strip_accents='ascii', 
                      lowercase=True, 
                      stop_words=stop_words)

Parâmetros utilizados:

  • strip_accents – Remove acentuação do texto, como informado no item 2.1.
  • lowercase – Transforma todo o texto em caixa baixa.
  • stop_words – Remove a nossa lista de stop words.

Vamos ver um exemplo com 2 itens da nossa base para ficar fácil a compreensão.

# Seleção de dois itens da base de dados
exemplo_descricao = df['nova_descricao'][:2]
exemplo_descricao.values
 
array(['PASTA INT VITAPOWER  KG AMEND SHOT',
       'ESPONJA BETTANIN BRILHUS C '], dtype=object)
 
# Transformação dos dois itens em vetores binários
exemplo_descricao_cvt = cvt.fit_transform(exemplo_descricao)
exemplo_descricao_cvt.toarray()
 
array([[1, 0, 0, 0, 1, 1, 1, 1],
       [0, 1, 1, 1, 0, 0, 0, 0]])

Agora que ficou mais claro o entendimento, podemos aplicar em toda o nosso dataset.

X_cvt = cvt.fit_transform(df['nova_descricao'])

Dessa forma toda a coluna ‘nova_descricao’ vai ser transformada em vetores similar ao exemplo que vimos acima, que ficaram armazenados na variável X_cvt.

Para que os resultados do nosso modelo seja mais assertivo vamos colocar um pouco de estatística nos nossos vetores, que agora vão deixar de ser binários com a função TfidfTransformer() também do scikit-learn.

TfidfTransformer

A função TfidfTransformer() transforma as matrizes binárias acima em matrizes normalizadas com representações tf ou tf-idf, que são medidas estatísticas que mensuram a importância das palavras em um texto. Claro que essa é uma explicação bem simplista das funções tf e tf-idf, apenas para ser ter uma noção com o que estamos trabalhando. Vamos criar a nossa função TfidfTransformer:

# Criação da função TfidfTransformer
tfi = TfidfTransformer(use_idf=True)

Parâmetros utilizados:

  • use_idf – Seleciona a opção de normalização tf-idf.

Vamos pegar o exemplo que utilizamos acima e fazer a transformação para fixar o entendimento.

# Transformação dos exemplos com a normalização tf-idf
exemplo_descricao_tfi = tfi.fit_transform(exemplo_descricao_cvt)
exemplo_descricao_tfi.toarray()
 
array([[0.4472136 , 0.        , 0.        , 0.        , 
        0.4472136 , 0.4472136 , 0.4472136 , 0.4472136 ],
       [0.        , 0.57735027, 0.57735027, 0.57735027, 
        0.        , 0.        , 0.        , 0.        ]])

Agora que já sabemos como funciona, vamos aplicar em toda o nosso dataset.

X_tfi = tfi.fit_transform(X_cvt)

Dessa forma a variável X_cvt vai ser transformada em vetores normalizados com tf-idf similar ao exemplo que vimos acima, que ficaram armazenados na variável X_tfi.

Feito todas essas etapas de tratamento e transformações na descrição dos nosso itens, chegou a hora de dividir a nossa base em treino e teste para que possamos avaliar o modelo após o treinamento.

Divisão treino e teste

# A entrada será a transformação de vetores com a normalização tf-idf
entrada = X_tfi
# A saida será os departamentos
saida = df['departamento']
# Separando 20% dos dados para teste
X_train, X_test, y_train, y_test = train_test_split(entrada, 
                                                    saida, 
                                                    test_size=0.2)

Feita a divisão de dados em treino e teste, vamos agora criar o modelo para treinamento.

Modelo LinearSVC

O modelo LinearSVC é da família dos SVM (support vector machine), ou em português máquina de vetores de suporte em tradução livre. O SVM é uma técnica que pode ser utilizada para classificação no aprendizado supervisionado. Portanto para o nosso problema vamos usar o algoritmo LinearSVC para classificar os departamentos. Veremos a seguir com python como criar o modelo e treinar o mesmo.

# Criando modelo
clf = LinearSVC()
# Treinamento do modelo
clf.fit(X_train, y_train)

Agora que já temos o modelo treinado podemos fazer a predição com os dados que guardamos para teste e avaliar a performance do mesmo.

Predição e avaliação do modelo de NLP

# Realizando a predição
resultado = clf.predict(X_test)
# Avaliando o modelo
print('Acurácia: {:.2f}'.format(metrics.accuracy_score(y_test, resultado)))
 
Acurácia: 0.95

Avaliando apenas a acurácia do modelo, temos uma performance de cerca de 95% de acerto no classificador. No notebook que está disponível ao final do post, tem a avaliação mais completa do classificador com outras medidas como precisão, recall e F1 Score.

Por fim, criei uma função para classificar novos itens utilizando o modelo criado. Vamos ver como consumir esse modelo com novos dados.

Utilização do modelo de NLP

A função para utilização do modelo, recebe uma descrição e retorna o departamento para essa descrição, vejamos a função no código python abaixo.

def novo_item(descricao):
  novo_cvt = cvt.transform(pd.Series(descricao))
  novo_tfi = tfi.transform(novo_cvt)
  departamento = clf.predict(novo_tfi)[0]
  return departamento

Agora vamos criar 3 exemplos aleatórios para testar o modelo, vejamos o código python abaixo.

# Lista de exemplos de novos produtos
itens = ['FEIJÃO','AÇÚCAR','QUEIJO']
# Loop for para fazer a predição do departamento de novos produtos
for item in itens:
  print('Produto:', item, 'Departamento:', novo_item(item))

Produto: FEIJÃO Departamento: MERCEARIA SALGADA
Produto: AÇUCAR Departamento: MERCEARIA DOCE
Produto: QUEIJO Departamento: FRIOS

No final o nosso resultado mostrando (Produto: descrição informada Departamento: departamento previsto). Portanto, podemos ver a assertividade do nosso modelo na prática.

NLP com scikit-learn ao Cubo

Então, chegamos ao fim de mais um post, preparado com muito carinho para vocês. Vimos aqui todo um pipeline básico de um problema de NLP. Isso é só? Vou resolver todos os meus problemas de NLP? Nem de perto, dá para resolver alguns problemas sim! Como o que vimos aqui hoje. Mas NLP tem muita, muita, mas muita coisa. É uma área de estudos na ciência de dados que tem novidades sempre. 

Portanto aprofundar sempre os estudos, mais para frente vamos ter outros posts sobre NLP com técnicas mais avançadas. Espero que tenham curtido, não esqueça de deixar aquele feedback. 

Acesse AQUI o notebook completo que está lá no nosso GitHub, com todo esse código comentado e mais algumas dicas. Até a próxima,um abraço a todos e todas e se cuidem!

Referências

Conteúdos ao Cubo

Por fim, deixo algumas sugestões de conteúdos que você pode encontrar no Dados ao Cubo, sempre falando sobre o mundo dos dados.

Finalizo com um convite para você ser Parceiro de Publicação Dados ao Cubo e escrever o próximo artigo, compartilhando conhecimento para toda a comunidade de dados. Não esqueça de assinar a nossa Newsletter para ficar por dentro de todas as novidades. 

Gostou? Compartilhe!

Deixe um comentário

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *