Determinando a Relevância de Produtos num Sistema de Buscas Usando Machine Learning

Uma das tarefas mais importantes para um site de comércio eletrônico é garantir que o usuário encontre o produto que está buscando. Isto inclui um sistema de buscas que retorne produtos relevantes. Nesta competição a CrowdFlower, uma plataforma especializada na coleta de dados, disponibilizou dados sobre buscas por produtos, e a mediana da pontuação de relevância dada por três pessoas para cada um.

O objetivo era criar um modelo que pudesse calcular a relevância de um produto para uma determinada frase de busca.

Dados

Foram disponibilizados cerca de 10 mil registros para treino, e 20 mil para teste. Nestes registros havia a frase de busca, o título e a descrição do produto, a mediana da relevância e a variância da relevância atribuída pelos usuários.

Nos exemplos de teste havia uma parcela de registros “falsos”, que não eram utilizados para calcular a performance, mas foram colocados para evitar classificação humana.

Métrica

A métrica de avaliação foi o Quadratic Weighted Kappa. Ela mede a discordância entre dois “avaliadores”. Neste caso, media a discordância entre a pontuação dada pelo modelo e a pontuação dada por humanos. Ela é sensível não apenas à precisão, mas também à distribuição da pontuação. Em tese, uma atribuição de pontos aleatória resultaria num Kappa de 0, e uma concordância total, em Kappa igual a 1. Existem casos em que o Kappa se torna negativo.

Processamento dos Dados

Texto

A transformação básica do texto do título e da descrição é fazer uma bag of words. Em sua forma mais simples é uma matriz cujas linhas são os exemplos (documentos) e as colunas são palavras (termos). O valor de cada célula é o número de vezes que a palavra aparece naquele documento.

Uma transformação mais avançada é pegar esta matriz e fazer algumas operações utilizando a frequência dos termos em cada documento, e também no corpo de documentos. Esta é chamada de TF-IDF. Neste caso, os termos com maior presença dentro de um documento específico recebem um peso maior, mas que é descontado por um fator inversamente proporcional à presença dele em outros documentos.

Simplificando: palavras raras que aparecem bastante em um documento recebem maior peso, e palavras frequentes, que aparecem em todos os documentos, se tornam menos importantes.

Fora isso, é importante determinar um limite mínimo de vezes que a palavra deve aparecer no corpo de documentos, para diminuir o ruído.

Neste caso, a melhor representação que encontrei foi treinar uma matriz baseada apenas nos títulos, e outra apenas na descrição. Alguns participantes sugeriram treinar nos dois ao mesmo tempo, mas como se trata de um problema de busca, acredito que seja importante diferenciá-los.

SVD – Latent Semantic Analysis

Como você já deve imaginar, a matriz de documentos fica enorme, e é bastante esparsa. Isso dificulta o uso com alguns modelos não lineares. Neste caso existe a opção de reduzir a dimensionalidade usando o SVD. Este algoritmo de álgebra linear basicamente encontra os componentes principais da matriz de documentos, onde há maior variação. Isso reduz a dimensionalidade do problema, mas pode causar perda de informação.

Nestes casos de NLP eles acabam funcionando bem, porque filtram um pouco o ruído dos dados. Aplicar o SVD à matriz TF-IDF te dá uma representação conhecida como Latent Semantic Analysis. A interpretação é que cada componente obtido se refere a um “conceito” representado pelos documentos. Ele também é bastante usado para visualizar os documentos num espaço com menores dimensões.

Na competição utilizei SVD para reduzir a dimensionalidade da matriz TF-IDF antes de alimentá-la aos modelos.

Outros atributos

Além dos atributos acima, criei outros que pareciam fazer sentido, e alguns que encontrei em trabalhos acadêmicos relacionados. O mais importante deles foi a porcentagem de palavras da busca que estavam no título. Além disso, criei atributos baseados na similaridade média entre um produto e os outros da mesma frase de busca, e também a contagem de vezes que a frase de busca aparece nos dados.

Uma parte importante foi codificar cada frase de busca com one hot. Ou seja, para cada uma delas criei uma coluna que possuía o número 1 caso ela estivesse presente, e o número 0 caso contrário. Fiz isso para ajudar o modelo a capturar variações próprias de cada frase de busca.

Regressão ou Classificação?

Existiam duas maneiras de encarar essa tarefa: considerar cada nível da mediana como uma classe, sendo assim um problema de classificação, ou considerar como um problema de regressão e arredondar as previsões.

Num primeiro momento achei mais adequado tratar como regressão, mas como o Kaggle queria as previsões arredondadas, acabei criando vários modelos de classificação e não tive tempo de testar a outra alternativa.

Com a classificação temos duas opções: usar a classe prevista pelo modelo, ou utilizar as probabilidades de cada classe para fazer uma média ponderada para obter a pontuação. A primeira alternativa se mostrou melhor neste caso.

Modelos

SVM

Os melhores modelos foram obtidos usando SVM. Ele é um dos modelos mais utilizados para classificação de texto, então não é surpresa que tenha boa performance.

O melhor modelo individual, utilizando os componentes do SVD e os outros atributos, atingia um Kappa de 0,672 na validação cruzada, e 0,654 na LB.

Random Forest

Um dos meus modelos preferidos, mas normalmente não são a melhor opção para dados esparsos em altas dimensões. De qualquer maneira, após vários testes, consegui 0,6695 na validação cruzada, e 0,6508 na LB usando uma matriz TF-IDF junto com os outros atributos.

Uma razão que pode ajudar a explicar o fato dela se comportar melhor com a matriz TF-IDF do que com a matriz do SVD é que este é um método que reduz a variância, então acaba sendo robusto diante de muitos atributos, desde que uma parcela deles seja relevante para a previsão.

Gradient Boosted Trees

Apesar deste modelo também não ser muito recomendado para uso com dados esparsos em altas dimensões, decidi treinar vários modelos “fracos” e fazer o stacking usando as previsões deles e os outros atributos, que não envolviam a representação das palavras.

Os modelos do stacking tinham uma média de 0,60 Kappa na validação.

A pontuação deste modelo ficava por volta de 0,624 na LB. Mas a intenção real com ele era ter um modelo diferente do SVM para fazer o ensemble.

Pós Processamento

Em todas as soluções de Top 10 que eu li, havia um detalhe em comum: o pós processamento das previsões. As equipes usaram métodos especiais para fazer arredondamento, multiplicando por coeficientes, ou determinando pontos de corte diferentes para a previsão de cada “classe”.

Em um dos casos, o time ordenou as previsões e, de acordo com a proporção de cada classe nos dados de treino, arredondou as previsões. Kappa é uma métrica preocupada com a distribuição das previsões, então isso acabou ajudando.

O mais próximo que cheguei de um ajuste nas previsões foi utilizar a média geométrica em vez da média simples para o ensemble. Os modelos costumavam superestimar a relevância dos produtos, e ela puxava as previsões para a classes mais baixas.

Ensemble e Overfitting

No fim, fiz uma média geométrica com meus melhores modelos. O ensemble era formado por vários SVMs, uma Random Forest e um GBT.

Apesar de não ser uma prática recomendável, principalmente em casos com uma quantidade de dados pequena como esta competição, utilizei a LB para validar o ensemble. Isso acabou fazendo com que eu escolhesse o meu segundo melhor ensemble, mesmo assim acabei no Top 5% da competição.

Deixe uma resposta

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