Redes Neurais e Filosofia da Linguagem

Por que as teorias de Wittgenstein são a base de toda a moderna PNL?

Massimo Belloni Blocked Unblock Seguir Seguindo 7 de janeiro

O Word Embeddings é provavelmente uma das ideias mais bonitas e românticas da história da inteligência artificial. Se Filosofia da Linguagem é o ramo da filosofia que explora a relação entre linguagem e realidade e como somos capazes de fazer conversas significativas compreenderem uma com a outra, esta técnica muito específica no Processamento de Linguagem Natural (PNL) moderna é, em certo sentido, a prova empírica das teorias de Ludwig Wittgenstein, um dos filósofos mais relevantes do século passado. Para Wittgenstein, o uso das palavras é um movimento em um jogo de linguagem social , interpretado pelos membros de uma comunidade que se entendem mutuamente. O significado de uma palavra depende de sua utilidade apenas em um contexto, e não apenas em uma relação de 1: 1 com um objeto mundial existente.

Para uma grande classe de casos em que empregamos a palavra “significado”, ela pode ser definida assim: o significado de uma palavra é seu uso na linguagem.

É claro que saber o significado exato de uma palavra é uma coisa complexa e envolve muitos aspectos diferentes: o objeto no mundo ao qual possivelmente se refere, que parte da fala (POS) é, se é uma expressão idiomática e todos os sabores que pode levar, e assim por diante. Todos esses aspectos, no final, podem ser resumidos em um único: saber usar.

O conceito de significado e por que um conjunto ordenado de caracteres tem uma certa conotação em um idioma não é apenas um interesse filosófico, mas é provavelmente o maior desafio que os especialistas em AI que trabalham com PNL enfrentam todos os dias. Como seres humanos falando inglês, é bastante trivial entender que um “cachorro” é um “animal” e que é mais parecido com um “gato” do que com um “golfinho”, mas esta tarefa está longe de ser fácil de ser resolvida de forma sistemática. caminho. Ajustando um pouco as teorias de Wittgenstein, podemos dizer que os cães são semelhantes aos gatos porque aparecem frequentemente nos mesmos contextos: é mais provável encontrar cães e gatos relacionados a palavras como “casa” e “jardim” do que palavras como “mar”. e "oceano". Essa mesma intuição é o núcleo do Word2Vec , uma das mais famosas e bem-sucedidas implementações de word embeddings. Se hoje as máquinas estão muito distantes de serem capazes de realmente entender textos longos e passagens, é indiscutível que a incorporação de palavras é a única técnica que permitiu que o campo desse o maior passo nessa direção na última década.

De BoW para Word2Vec

Um problema inicial em muitas tarefas relacionadas à Ciência da Computação é representar dados em uma forma numérica; palavras e frases são provavelmente o tipo de dados mais desafiador a ser representado dessa forma. Em nosso cenário, as palavras são selecionadas de um vocabulário composto por D palavras diferentes e cada palavra na coleção pode ser associada a um índice numérico i . A abordagem clássica utilizada durante décadas foi representar cada palavra como um vetor numérico de tamanho D, composto por todos os zeros, exceto por um 1 na posição i. Considere como exemplo um vocabulário composto apenas por 3 palavras: “cachorro”, “gato” e “golfinho” (D = 3). Cada palavra pode ser representada como um vetor de 3 tamanhos: “cachorro” corresponde a [1, 0, 0], “gato” a [0,1,0] e “golfinho”, obviamente, a [0, 0, 1 ]. Um documento, como uma extensão simples, pode ser representado como um vetor de tamanho D, em que cada elemento conta as ocorrências da i-ésima palavra no documento. Essa abordagem é chamada de Bag of Words (BOL) e tem sido usada há décadas.

BoW, na medida em que foi bem-sucedido nos anos 90, não possui o único recurso interessante sobre palavras: significado. Sabemos que duas palavras muito diferentes podem ter significados semelhantes, mesmo que sejam completamente diferentes do ponto de vista ortográfico. “Gato” e “cão” ambos representam animais de estimação, rei” e “rainha” têm o mesmo significado e apenas diferem para o gênero, “maçã” e "cigarro" não tem nada a ver com o outro. Sabemos disso, mas usando o modelo BoW todos têm a mesma distância no espaço vetorial, 1. O mesmo problema pode ser estendido aos documentos: usando o BoW, podemos dizer que dois documentos são semelhantes apenas se contiverem exatamente as mesmas palavras. um certo número de vezes. E aqui é onde o Word2Vec vem para ajudar, colocando em termos de Machine Learning muitas das discussões filosóficas que Wittgenstein fez em suas Investigações Filosóficas 60 anos antes.

Dado um dicionário de tamanho D, onde uma palavra é identificada por seu índice, o objetivo é aprender uma representação vetorial N-dimensionada para cada palavra com N << D. Idealmente, queremos que esse vetor de tamanho N seja denso e capaz de representar alguns aspectos de significado semântico-específicos. Por exemplo, nós idealmente queremos que cachorro” e “gato” tenham representações similares, enquanto “maçã” e “cigarro” muito distantes no espaço vetorial. Queremos ser capazes de fazer algumas operações algébricas básicas em vetores como king + woman-man = queen, ou que a distância entre o vetor representando “actor” e “atriz” é praticamente a mesma que a distância entre “prince” e "Princesa". Embora esses resultados sejam bastante utópicos, os experimentos mostram que os vetores obtidos via Word2Vec exibem propriedades muito próximas dessas.

O Word2Vec não aprende essas representações diretamente, mas as obtém como resultado secundário de uma tarefa de classificação não supervisionada. Um conjunto de dados NLP médio (chamado corpus) é composto por um conjunto de sentenças; cada palavra pertencente a uma frase aparece em um contexto de palavras circundantes. Objetivo do classificador é predizer uma palavra alvo dada suas palavras de contexto como entrada. Extrair uma frase como “um cachorro marrom está no jardim” as palavras [a, marrom, é, dentro, o, jardim] são fornecidas como entrada do modelo e a palavra de saída “cão” é a que será predita. Essa tarefa é considerada como aprendizado não supervisionado porque o corpus não precisa ser rotulado usando uma fonte externa de verdade: dado um conjunto de sentenças, é sempre possível criar exemplos positivos e negativos automaticamente. Considerando que "um cachorro marrom está no jardim" como um exemplo positivo, podemos criar muitas amostras negativas, como "um plano marrom está no jardim" ou "um marrom está no jardim", substituindo a palavra alvo "cachorro". com palavras aleatórias extraídas do conjunto de dados.

E agora está bem claro onde as teorias de Wittgenstein entram em cena: o contexto é crucial para aprender os embeddings, já que é crucial em suas teorias anexar significado. Da mesma forma que duas palavras têm significados semelhantes, elas terão representações similares (pequena distância no espaço N-dimensional) apenas porque elas freqüentemente aparecem em contextos similares. Assim, “gato” e “cachorro” acabarão tendo vetores próximos, porque eles aparecem frequentemente nos mesmos contextos: é útil para o modelo usar para eles embeddings semelhantes, porque é a coisa mais conveniente que pode fazer para ter um melhor desempenho na previsão do duas palavras dadas os seus contextos.

O artigo original propõe duas arquiteturas diferentes: CBOW e Skip-gram. Em ambos os casos, as representações de palavras são treinadas junto com a tarefa de classificação específica do sabor, fornecendo os melhores envoltórios vetoriais possíveis que maximizam o desempenho do modelo.

Figura 1 – Comparação de arquitetura entre CBOW e Skip-gram

CBOW significa Continuous Bag of Words, e seu objetivo é predizer corretamente uma palavra, dado seu contexto como entrada. Entradas e saídas são fornecidas como vetores de tamanho D e são projetadas em um espaço de tamanho N com pesos compartilhados. Os pesos usados para projetar vetores de tamanho D para os vetores internos de tamanho N são os encaixes que estamos procurando. Basicamente, o word embeddings é representado como uma matriz D x N, onde cada linha representa uma palavra do vocabulário. Todas as palavras de contexto são projetadas na mesma posição e suas representações de vetores são calculadas; portanto, a ordem das palavras não influencia a projeção.

Pular grama faz a mesma coisa, mas reverta: tentando prever as palavras de contexto C tomando como entrada a palavra alvo. O problema de prever múltiplas palavras de contexto pode ser reformulado como um conjunto de tarefas independentes de classificação binária, e o objetivo agora é prever a presença (ou ausência) de palavras de contexto.

Como regra geral, o skip-gram requer mais tempo para ser treinado e, muitas vezes, dá resultados um pouco melhores, mas, como de costume, aplicativos diferentes têm requisitos diferentes e é difícil prever com antecedência qual dos dois superará o outro. Para a simplicidade do conceito, treinar esse tipo de arquitetura é um grande pesadelo, devido à quantidade de dados e à capacidade computacional necessária para otimizar os pesos dos modelos. Felizmente, alguns embeddings de palavras pré-treinados podem ser encontrados on-line e é possível explorar o espaço vetorial – a parte mais engraçada – com apenas algumas linhas de código.

Possíveis melhorias: GloVe e fastText

No topo do clássico Word2Vec e seguindo mais ou menos a mesma abordagem, muitas melhorias possíveis foram propostas nos últimos anos. Os dois mais interessantes e comumente usados são o GloVe (da Universidade de Stanford) e o fastText (desenvolvido pelo Facebook), principalmente para as limitações do algoritmo original que eles destacam e tentam superar.

No artigo original de GloVe, os autores sublinham como o treinamento do modelo em um contexto local separado explora mal as estatísticas globais do corpus. O primeiro passo para superar esta limitação é criar uma matriz global X onde cada elemento i, j conta o número de vezes que a palavra j aparece no contexto da palavra i . A segunda maior contribuição deste artigo está em entender que essas probabilidades brutas por si só não são tão robustas na determinação do significado, introduzindo uma matriz de co-ocorrências a partir da qual certos aspectos do significado podem ser diretamente extraídos.

Considere duas palavras iej que exibem um aspecto particular de interesse; para concretude, suponha que estamos interessados no conceito de fase termodinâmica, para o qual podemos tomar i = ice e j = steam. A relação dessas palavras pode ser examinada estudando a razão de suas probabilidades de co-ocorrência com várias palavras de sondagem, k. Para as palavras k relacionadas ao gelo, mas não a vapor, digamos k = sólido, esperamos que a razão Pik / Pjk seja grande. Da mesma forma, para as palavras k relacionadas ao vapor, mas não ao gelo, digamos k = gás, a relação deve ser pequena. Para palavras como água ou moda, que estão relacionadas tanto ao gelo quanto ao vapor, ou a nenhuma delas, a razão deve estar próxima de uma.

Esta relação de probabilidades é agora o ponto de partida para aprender os embeddings. Queremos ser capazes de calcular representações que combinadas com uma função específica F mantém essa relação constante no espaço de incorporação.

Figura 2 – Fórmula mais geral para os envoltórios do GloVe

A função F e a dependência pela palavra k podem ser simplificadas e substituídas por exponenciais e vieses fixos, dando como resultado esta função de erro de mínimos quadrados J :

Figura 3 – Função de pontuação final para calcular os ingressos GloVe

A função f é uma função de pontuação que tenta não ponderar co-ocorrências muito freqüentes e raras, enquanto bi e bj são vieses usados para restaurar a simetria da função. Nos últimos parágrafos do artigo é mostrado como o treinamento deste modelo, no final, não é tão diferente do treinamento de um modelo clássico de Skip-gram, mesmo se os testes empíricos mostrarem como o GloVe supera tanto as implementações do Word2Vec.

O fastText, por outro lado, gera uma crítica completamente diferente ao Word2Vec: treinar um modelo a partir de um vetor codificado de tamanho único em tamanho D tem a desvantagem de ignorar a estrutura interna das palavras. Em vez de palavras de codificação simples que aprendem representações de palavras, o fastText propõe aprender representações para caracteres n-grams e representar palavras como a soma dos vetores n-grama. Por exemplo, com n = 3, a palavra “flor” é codificada como 6 diferentes 3 gramas [<fl, flo, baixo, owe, wer, er>] mais a sequência especial <flower>. Observe como os parênteses angulares são usados para indicar o início e o fim de uma palavra. Uma palavra é assim representada por seu índice no dicionário de palavras e pelo conjunto de n-gramas que contém, mapeados para inteiros usando uma função de hashing. Essa melhoria simples permite compartilhar as representações n-grama entre palavras e calcular os encaixes de palavras que não aparecem no corpus de treinamento.

Experimentos e possíveis aplicações

Como prometido, o uso desses encaixes é apenas uma questão de poucas linhas de código Python. Eu realizei alguns experimentos usando um modelo GloVe de 50 tamanhos treinado em 6 bilhões de palavras extraídas de sentenças recuperadas principalmente na Wikipedia e um FastText 300 treinado em Common Crawl (resultando em 600 bilhões de tokens). Neste parágrafo, os resultados de ambos são misturados apenas para provar os conceitos e para dar uma compreensão geral do tópico.

Antes de mais nada, queria testar algumas semelhanças básicas de palavras, a característica mais simples, porém importante, da incorporação de palavras. Como esperado, as palavras mais semelhantes à palavra “cachorro” são “gato” (0,92), “cachorro” (0,85), “cavalo” (0,79), “cachorro” (0,78) e “animal de estimação” (0,77). Note como a forma plural tem praticamente o mesmo significado que o singular. Novamente, para nós é bastante trivial dizer isso, mas para uma máquina é um fato completamente diferente. Agora comida: as palavras mais parecidas com “pizza” são “sanduíche” (0,87), “sanduíches” (0,86), “lanche” (0,81), “padaria” (0,79), “batata frita” (0,79) e “hambúrgueres” (0,78). Faz sentido, os resultados são satisfatórios e o modelo se comporta muito bem.

O próximo passo é tentar executar alguma álgebra básica no espaço vetorial para verificar se alguns dos comportamentos desejados foram aprendidos corretamente pelo nosso modelo. A palavra “atriz” (0,94) pode ser obtida como resultado da mulher + ator-homem, “rei” (0,86) como homem + rainha-mulher. De um modo geral, se significante-a: b = c: d, a palavra d deve ser obtida como d = b-a + c. Levando isso para o próximo nível, é inacreditável como essas operações vetoriais são capazes de descrever até mesmo aspectos geográficos: sabemos que Roma é a capital da Itália, já que Berlim é a capital da Alemanha, na verdade Berlim + Itália-Roma = Alemanha (0,88) e Londres + Alemanha-Inglaterra = Berlim (0,83).

E agora a parte mais engraçada, seguindo a mesma ideia, podemos tentar adicionar conceitos de subtração para ver o que acontece. Por exemplo, qual é o equivalente americano de pizza para os italianos? pizza + América-Itália = hambúrgueres (0,60), seguido por cheeseburgers (0,59). Desde que me mudei para a Holanda, sempre digo que esse país é uma mistura de três coisas: um pouco de capitalismo americano, o frio e a qualidade de vida suecos e, finalmente, uma pitada da exuberância napolitana . Ajustando um pouco o teorema original, removendo um pouco da precisão suíça, obtemos a Holanda (0,68) como EUA + Suécia + Nápoles-Suíça: bastante impressionante, para ser honesto.

Figura 4 – Para todos os leitores holandeses: leve isso como um elogio. OK?

Bons pontos de partida práticos para usar estes embeddings pré-treinados podem ser encontrados aqui e aqui . Gensim é uma biblioteca fácil e completa escrita em Python e tem algumas funções algébricas e de similaridade prontas para uso. Esses embeddings pré-treinados podem ser usados de diversas maneiras (e úteis), por exemplo, para melhorar o desempenho de analisadores de sentimento ou modelos de linguagem. Em vez de alimentar esses modelos (seja qual for a tarefa deles!) Com palavras codificadas com um clique a quente, usar esses vetores de tamanho N deve melhorar significativamente o desempenho. É claro que o treinamento de ad-hoc domain specific embeddings pode levar a desempenhos ainda melhores, mas novamente, o tempo e o esforço necessários para treinar esse tipo de arquitetura podem ser um pouco exagerados.