≡ edrone Blog
You've successfully subscribed to edrone
Great! Next, complete checkout for full access to edrone
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.
Success! Your billing info is updated.
Billing info update failed.

O que é Word2Vec

Word2Vec é um método de Aprendizado de Máquina para construir um modelo de linguagem baseado em ideias de Aprendizado Profundo. No entanto, a rede neural usada aqui é um tanto superficial (tem apenas uma camada escondida).

Marcin Lewek
Marcin Lewek

O objetivo principal desta série de artigos sobre Word2Vec é mostrar que o Processamento de Linguagem Natural (PLN) não é algo tão complicado – Word2Vec é como o "Hello, world!" do PLN. Porém, é preciso um pouco mais de trabalho além de escrever algumas linhas de código. Aqui vamos discutir:

  1. De onde surgiu a ideia do Word2Vec.
  2. Como o Word2Vec funciona.
  3. Como você pode fazer uma versão simplificada do Word2Vec.

Pequenos esclarecimentos antes de começarmos

Para os propósitos deste artigo, não é tão importante que você entenda os detalhes das diferenças entre Inteligência Artificial, Aprendizado de Máquina (Machine Learning) e Aprendizado Profundo (Deep Learning). No entanto, estes termos muitas vezes são confundidos e usados como sinônimos, o que quase sempre está errado. Para esclarecer:

  1. O Aprendizado Profundo (Deep Learning) lida com um tipo específico de Rede Neural (redes neurais profundas, com muitas camadas, ou redes rasas que contêm muitos dados de entrada e nós interdependentes).
  2. O Deep Learning é uma área de estudo inserida na área de Aprendizado de Máquina (Machine Learning).
  3. O Machine Learning, por sua vez, faz parte da área de Inteligência Artificial.

Neste artigo, vamos construir um modelo de linguagem baseado em ideias de Aprendizado Profundo, usando métodos de Aprendizado de Máquina.

Diferenças entre Inteligência Artificial, Aprendizado de Máquina e Aprendizado Profundo

Uma breve revisão histórica do Aprendizado de Máquina

A primeira onda de popularidade do Aprendizado de Máquina veio entre 2005 e 2012. A segunda onda, por vezes chamada de Revolução do Aprendizado Profundo, veio em 2012. Outro período importante foi a invenção do Word2Vec (e seus clones: Doc2Vec, Nodes2Vec), que aconteceu entre 2013 e 2015. A onda mais recente, na qual ainda estamos, começou em 2017 com a invenção do BERT (e também GPT, T5).


Resumindo a AVA: escopo da P&D
A assistente de compra virtual fornecida pela AVA conduzirá conversas naturais e improvisadas — usando uma linguagem natural, com todo coloquialismo e significado compreensível apenas por humanos — com clientes de lojas online.

Hipótese Distribucional

Word2Vec é uma técnica de Processamento de Linguagem Natural (PLN) baseada em uma tese popularizada por John Rupert Firth no fim da década de 1950. Esta tese diz que cada palavra é caracterizada, e até certo ponto definida, pelas outras palavras em seu entorno.

Firth, por sua vez, baseou sua teoria na ideia de Zellig Sabbettai Harris, publicada em 1954, de que "palavras que ocorrem em contextos semelhantes tendem a ter significados semelhantes". Se pensarmos bem, é uma ideia surpreendentemente certeira. A Hipótese Distribucional é a base para a Semântica Estatística e, embora tenham se originado na Linguística, estes assuntos têm atraído muita atenção nas áreas de ciências cognitivas e Aprendizado de Máquinas.

Posicionamento das palavras no corpus de textos: a base da Semântica Computacional

Juntando tudo: quanto mais uma palavra "A" aparecer no mesmo contexto que outras palavras específicas (por exemplo, "B", "C", "D" e "E"), mais próximo será o significado de todas estas palavras. O contexto, neste caso, depende do critério de quem estiver fazendo a análise. Pode ser a mesma frase, o mesmo parágrafo, ou – mais provável quanto o assunto é PLN – o mesmo trecho que usamos para analisar o corpus do texto.

Modelo Skip-Gram de Word2Vec
Representação do modelo Skip-Gram em ação, que discutiremos mais adiante.

Você poderia presumir que, quanto maior o texto, mais precisas serão as previsões, o que está corretíssimo. O tamanho do trecho, no entanto, é uma escolha do analista. Aqui, maior nem sempre é melhor.


Buscar é falar – Seriam as conversas e os buscadores a mesma coisa?
Geralmente, as lojas virtuais não se preocupam muito com seus campos de busca. Elas tratam os buscadores como algo finalizado, completo. É uma pena, visto que os motores de busca estão em constante desenvolvimento, e os clientes há tanto tempo alienados hoje têm expectativas muito mais elevadas.

Então, por onde devemos começar ao analisarmos um texto? Primeiro, precisamos fazer o texto ser compreensível para computadores. O nome Word2Vec ("Word to Vector") já indica – precisamos traduzir palavras em vetores.

OK, e o que são vetores? Um vetor, em programação, serve para armazenar variáveis de um mesmo tipo. Para facilitar a compreensão, entenda "vetor" como uma sequência unidimensional de elementos. No caso do Word2Vec, atribuímos uma lista de valores numéricos a cada palavra original presente no texto.

Pré-processamento de dados

É sempre mais fácil explicar usando exemplos, então vamos acompanhar o passo a passo usando um pequeno corpus apresentado a seguir. Mas antes, um pequeno aviso a respeito da linguagem de programação que usaremos para este exercício:

Usaremos a linguagem de programação Python para lidar com os conceitos de Aprendizado de Máquina. Se você domina esta linguagem, sugerimos continuar a leitura com um ambiente preparado e seu editor de texto favorito à mão.

Se você nunca usou Python, não se preocupe. A instalação é gratuita e fácil. eu usei o Spyder como ambiente de desenvolvimento integrado. Após instalar estas ferramentas, basta copiar e colar os códigos apresentados e testar os processos por conta própria.

Além disso, não tem problema se o código for incompreensível para você. Não é necessário entender como o código funciona para entender como o Word2Vec funciona. Foque apenas no resultado :)

Vamos criar um corpus!

Para este exemplo, nosso corpus terá apenas duas frases:

edrone is awesome. The first CRM for eCommerce and AI fueled marketing machine.

Código:

tiny_corpus = ['edrone is awesome', 
               'The first CRM for eCommerce and AI fueled marketing machine']
print(tiny_corpus,'\n')

Resultado:

['edrone is awesome', 
 'The first CRM for eCommerce and AI fueled marketing machine'] 

O uso de letras maiúsculas e minúsculas faz diferença, então precisamos deixar tudo em minúsculas (apresentado abaixo para mostrar os estágios de tokenização):

Código:

# LOWER CASE
tiny_corpus_lowered = [sentence.lower() for sentence in tiny_corpus]
print(tiny_corpus_lowered,'\n')

Resultado:

['edrone is awesome', 
 'the first crm for ecommerce and ai fueled marketing machine'] 

Agora vamos dividir as frases em palavras separadas.

Código:

# TOKENIZATION
tiny_corpus_lowered_tokenized = [sentence.split() for sentence in tiny_corpus_lowered]
print(tiny_corpus_lowered_tokenized,'\n')

Resultado:

[['edrone', 'is', 'awesome'], 
['the', 'first', 'crm', 'for', 'ecommerce', 'and', 'ai', 'fueled', 'marketing', 'machine']]

A esta altura, o pré-processamento está quase pronto. Agora vamos construir um dicionário para o nosso pequeno corpus.

Como você pode ter percebido, a lista de palavras foi inicialmente dividida em uma lista bidimensional (matriz). Para criar o dicionário, vamos primeiro organizá-la em uma lista de palavras originais em ordem alfabética, e depois transformá-la em uma lista unidimensional.

Código:

# DICTIONARY
words = [word for sentence in tiny_corpus_lowered_tokenized for word in sentence]
print(sorted(words),'\n') 

unique_words = list(set(words))

Resultado:

['ai', 'and', 'awesome', 'crm', 'ecommerce', 'edrone', 
 'first', 'for', 'fueled', 'is', 'machine', 'marketing', 'the'] 

Agora vamos criar o dicionário, concluindo o processo de pré-processamento!

Código:

# ASSIGN TO DICTIONARY
id2word = {nr: word for nr, word in enumerate(unique_words)}
print(id2word,'\n')

word2id = {word: id for id, word in id2word.items()}
print(word2id,'\n')

Resultado:

{0: 'is', 1: 'ai', 2: 'first', 3: 'ecommerce', 4: 'the', 
 5: 'fueled', 6: 'machine', 7: 'for', 8: 'awesome', 
 9: 'and', 10: 'marketing', 11: 'crm', 12: 'edrone'} 

{'is': 0, 'ai': 1, 'first': 2, 'ecommerce': 3, 'the': 4, 
 'fueled': 5, 'machine': 6, 'for': 7, 'awesome': 8, 
 'and': 9, 'marketing': 10, 'crm': 11, 'edrone': 12} 

Codificação Distribuída (One-Hot Encoding)

O processo de transformar palavras em vetores está quase concluído. Agora vamos atribuir um vetor a cada palavra da lista. Confira o código abaixo, e mais adiante discutiremos o resultado.

Código:

# ONE HOT ENCODING
from pprint import pprint
import numpy as np

num_word = len(unique_words)
word2one_hot = dict()

for i in range(num_word):
  zero_vec = np.zeros(num_word)
  zero_vec[i] = 1
  word2one_hot[id2word[i]] = list(zero_vec)
  
# RESULT
pprint(word2one_hot)

Resultado:

{'ai': 
 [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],

 'and': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0],
 
 'awesome': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0],
 
 'crm': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0],
 
 'ecommerce': 
 [0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'edrone': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0],
 
 'first': 
 [0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'for': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'fueled': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'is': 
 [1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'machine': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0],
 
 'marketing': 
 [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0],
 
 'the': 
 [0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}

E pronto!

Como você pode ver, cada palavra única tem seu próprio vetor. Estes vetores não são como os que você aprendeu nas aulas de física. Eles não fazem sentido fisicamente, pois estão em um espaço de 13 dimensões, tornando-os impossíveis de serem imaginados. Felizmente, não precisamos fazer isso. Para simplificar:

  1. Cada palavra original em nosso texto representa uma dimensão.
  2. Cada vetor é representado por zeros ("0.0") e apenas um "1.0".
  3. Cada "1.0" aparece em uma posição diferente.

Ou seja, se nosso texto fosse composto por 100 palavras originais, cada vetor seria composto por 99 "0.0" e apenas um "1.0", e cada "1.0" estaria em uma posição diferente para cada palavra. Esta convenção permite que os computadores processem palavras facilmente.

E como os vetores são processados? Você aprenderá isso na parte 2!

Enquanto isso, aqui está o código completo para você explorar:


tiny_corpus = ['edrone is awesome', 
               'The first CRM for eCommerce and AI fueled marketing machine']
print(tiny_corpus,'\n')

# LOWER CASE
tiny_corpus_lowered = [sentence.lower() for sentence in tiny_corpus]
print(tiny_corpus_lowered,'\n')

# TOKENIZATION
tiny_corpus_lowered_tokenized = [sentence.split() for sentence in tiny_corpus_lowered]
print(tiny_corpus_lowered_tokenized,'\n')

# DICTIONARY
words = [word for sentence in tiny_corpus_lowered_tokenized for word in sentence]
print(sorted(words),'\n') 

unique_words = list(set(words))

# ASSIGN TO DICTIONARY
id2word = {nr: word for nr, word in enumerate(unique_words)}
print(id2word,'\n')

word2id = {word: id for id, word in id2word.items()}
print(word2id,'\n')

# ONE HOT ENCODING
from pprint import pprint
import numpy as np

num_word = len(unique_words)
word2one_hot = dict()

for i in range(num_word):
  zero_vec = np.zeros(num_word)
  zero_vec[i] = 1
  word2one_hot[id2word[i]] = list(zero_vec)
  
# RESULT
pprint(word2one_hot)

Tutorials & GuidesArtificial intelligenceMachine learningDeep learningNLPPythonWord2vec

Marcin Lewek

Digital marketer and copywrier specialized in Artificial Intelligence, design, and digital marketing itself. Science, and holistic approach enthusiast, after-hours musician, and sometimes actor.