Similaridade de produtos com dados heterogêneos

Rodrigo Peres
b2w engineering
Published in
12 min readMar 17, 2021

Em um contexto de comércio eletrônico que opera com estoque próprio(1P) e permite que parceiros anunciem itens próprios(3P), temos o cenário onde cada lojista envia as informações sobre os itens em seus catálogos para a nossa base de produtos, dados esses que são indexados e disponibilizados através da busca interna dos sites e via motores de busca, como o Google.

Acontece que o mesmo produto pode ser representado e cadastrado posteriormente de forma diferente por cada parceiro, como no exemplo a seguir:

Figura 1 — Exemplos de produtos

Como podemos ver, o mesmo produto cadastrado por parceiros distintos pode possuir títulos, descrição e ficha técnica diferentes, uns com mais e outros com menos informação, assim como a ordem das palavras pode mudar. A imagem das ofertas pode conter variações de tamanho, brilho, contraste, e até mesmo um ângulo completamente diferente.

As descrições podem ser curtas, repetir o título ou podem ser enormes chegando a 4.000 caracteres. Um outro fator muito importante que deixa a questão mais complexa são os atributos. Em alguns itens, temos uma ficha técnica consistente com uma boa quantidade de chaves de atributo e seus respectivos valores, porém em outros temos pouquíssimos atributos informados.

A partir disso, o objetivo principal desse projeto é agrupar todas as ofertas de um mesmo produto, ou seja, produtos idênticos terão a mesma página de navegação, agrupados em um mesmo ID de produto.

Isso possibilita que consigamos indicar para o cliente a melhor oferta, levando em conta características como preço do produto, frete e prazo de entrega para que ele consiga, por conta própria, navegar entre as opções existentes e fazer a sua própria decisão de compra de forma fluida.

Quando os produtos iguais não estão agrupados, temos a experiência de compra prejudicada, já que a busca a partir de um termo pode retornar o mesmo produto em várias páginas de produto diferentes.

Isso gera uma certa confusão principalmente ao usuário mais leigo no mundo digital, que pode imaginar que existam características diferentes para um produto que, na verdade, é o mesmo. Uma parcela desses clientes pode acabar não concluindo a compra por conta dessa dificuldade.

Outro fator é a necessidade de um trabalho de análise das informações por pessoas, caso queiramos agrupar produtos atualmente. Essa análise, mesmo tendo alta precisão, não é escalável para o volume do nosso sortimento.

Também há produtos que investimos dinheiro para serem divulgados via PPC (Pay-per-click), isso faz com que os anúncios patrocinados sejam exibidos em destaque, acima dos resultados orgânicos da busca ou do lado direito dos resultados da pesquisa.

Se todos os produtos iguais não estiverem em uma única página, existe a chance de estarmos divulgando um produto que não possui a nossa melhor condição para o cliente e, desse modo, ele pode optar por não visitar os nossos sites. Como primeira aplicação desse projeto, escolhemos trabalhar com dados do departamento de Livros.

Proposta de solução

Nossa abordagem para esse problema envolve processamento de linguagem natural (PLN), visão computacional (VC) e redes siamesas profundas (Deep Learning). Basicamente, temos um “ensemble” de dois modelos de machine learning e a aplicação de algumas regras de negócio em chaves de atributos selecionadas e nos preços, visando evitar principalmente agrupamentos incorretos (e caros para a companhia).

PLN pode ser definido como “um campo da Inteligência Artificial que proporciona às máquinas a habilidade de ler, entender e extrair valor das linguagens humanas” (LOPEZ YSE, 2019, tradução nossa).

Já a visão computacional é definida como um campo de estudo que busca desenvolver técnicas que ajudem os computadores a enxergar e entender o conteúdo de imagens digitais como fotos e vídeos (BRONLEE, 2019).

Temos também a rede siamesa profunda, que é um tipo de arquitetura de rede neural artificial profunda que possui duas estruturas idênticas, treinadas simultaneamente com pesos compartilhados (SHAH, KOPRU, RUVINI, 2018).

O projeto utiliza duas redes siamesas profundas, uma focada em texto que recebe como input os títulos dos produtos e outra voltada para a visão computacional, que recebe como entrada a primeira imagem de cada produto. Ao fim de cada rede, têm-se duas saídas com as probabilidades de similaridade por título e por imagem, como demonstra a imagem a seguir:

Figura 2 — Arquitetura dos modelos

Filtros de preços e atributos

Como forma de eliminarmos candidatos incorretos para os agrupamentos, construímos dois filtros. O primeiro foi voltado para a comparação entre os preços existentes em cada par de produtos e o segundo com um foco maior na comparação entre atributos selecionados. Atributos esses que podem variar conforme o departamento tratado.

  • Preços

Essa etapa do processo serve como uma série de validações que são feitas com o foco em preço, tanto do novo item que está chegando para fazer o match, como também para os valores presentes no destino indicado. O serviço terá como saída essas duas opções:

‘Suspeito’ — quando algum indício de problema for detectado;

‘Aceito’ — quando nenhum problema for detectado;

O primeiro passo será buscar e armazenar o preço do item origem, assim como o preço ou preços contidos no item destino. Só serão considerados preços de ofertas ativas ou canceladas, maiores do que zero. Dessa forma, caso o número de preços considerados válidos for igual a zero no item origem ou no item destino, o teste não é realizado e o par de produtos não avança para as etapas seguintes.

Para o caso onde temos 1 preço origem (PO) x 1 preço destino (PD), o teste irá pegar o valor de PD e criará um range que irá variar entre 30% para baixo e 30% para cima em relação a PD. Caso PO esteja dentro desse intervalo será apontado como aceito, caso contrário será marcado como valor suspeito.

Para o outro caso, onde temos 1 preço origem (PO) contra mais de 1 preço de destino (PN) — aqui entendido como uma lista —, o primeiro passo será a remoção dos outliers presentes na lista PN.

Esse trabalho será feito por meio do cálculo do z-score modificado que, ao invés de utilizar a média e o desvio padrão, fará uso da mediana e do desvio absoluto mediano, mais robusto para esse caso, gerando assim uma nova lista de preços sem dados sujos (PNL).

Com a lista sem os outliers, será aplicada a mesma lógica de range, formado dessa vez pelo menor preço da lista PNL, menos 30% de seu valor até o maior preço da lista PNL, mais 30% de seu valor. Caso o preço origem esteja dentro desse intervalo será aceito, caso contrário será marcado como valor suspeito.

  • Atributos

Os atributos cadastrados nos produtos podem ser utilizados no processo de matching de duas formas diferentes:

1 — sendo somados ao título do produto, tornando-o dessa forma mais completo;

2 — servindo como filtros no momento de comparação entre dois IDs diferentes.

Para livros estaremos, nesse primeiro momento, utilizando a segunda estratégia, com os atributos cadastrados servindo como uma espécie de filtro no processo de agrupamento de anúncios. Alguns atributos selecionados foram “autor” e “editora”.

Todos os valores de atributos passam por um tratamento visando remover espaçamentos desnecessários, caracteres especiais e pontuação, assim como a padronização em minúsculo.

A regra utilizada no momento é que, caso os pares de atributos estejam preenchidos, os seus valores têm que ser iguais. Caso sejam diferentes, esse match em potencial será descartado. Se algum dos valores ou os dois sejam nulos, o par segue para a próxima etapa.

Utilizamos essa regra para não limitarmos ao extremo o número de matchs, já que é notório que muitos parceiros não enviam dados sobre os produtos ou os enviam de forma não estruturada na descrição.

Rede siamesa de texto

  • Geração do dataset

Graças ao nosso catálogo, já havia exemplos de ofertas agrupadas, junções essas que passaram em parte por avaliação humana. Levando isso em consideração, utilizamos o histórico de ofertas agrupadas em um único PIT como exemplos de match correto.

Para os exemplos de match incorreto, utilizamos duas estratégias. Primeiramente, buscamos outros títulos de produtos de itens pertencentes à mesma estrutura mercadológica, porém com um ID e EAN diferentes. A outra estratégia foi a de gerar títulos errados de forma sintética, com o objetivo de dificultar o processo de aprendizado do modelo.

  • Extração de atributos com fasttext

A primeira rede siamesa citada é a de texto. Nela, basicamente temos como entrada dois títulos de produto e o label, informando se representam o mesmo item ou não.

Esses textos passam por um pré-processamento onde temos alguns processos de limpeza e normalização, visando remover determinadas pontuações e informações desnecessárias.

Após essa etapa, temos então os textos em forma limpa. Esses textos precisam ser convertidos em uma representação numérica e, para isso, utilizamos a técnica de word embedding (fastText) que é capaz de representar uma sequência de caracteres (N-grama) em vetores.

Visando a extração de atributos dos títulos de forma otimizada, optamos por não utilizar um modelo pré-treinado, mas sim treinar um novo modelo fastText com dados de e-commerce para obter um resultado melhor.

Para mais informações sobre a normalização dos textos e os parâmetros utilizados para treinar o modelo fastText com dados de e-commerce, acesse:

https://allanbatista.github.io/fasttext-ecommerce.github.io/

Para cada título que é passado, nós temos uma saída de numpy array (21, 128). A sentença é limitada em até 21 palavras e cada palavra representa um vetor de números, caso o título possua menos do que 21 palavras, o vetor é completado com zeros.

  • Treinamento

Para o treinamento do modelo, utilizamos 1.194.635 pares de títulos. O treinamento foi até a época 37. Como cláusula de parada, utilizamos o valor de loss do dataset de validação com uma paciência de 5 épocas, e utilizamos somente o modelo que teve o menor erro no conjunto de dados de validação. O modelo possui o total de 5.805.825 parâmetros e todos eles estavam como treináveis. Utilizamos uma máquina com 8 CPUs, 64GB e uma GPU NVIDIA TESLA V100.

  • Output

Após as inferências no modelo fastText, temos dois vetores que representam numericamente os títulos. Esse par é enviado junto com o label para a rede siamesa profunda, responsável por aprender o nível de similaridade entre os títulos informados. Essa rede tem como saída um valor que representa a similaridade entre os vetores, quanto mais próximo de 1 mais similar e quanto mais próximo de 0 menos similar.

Rede siamesa de imagem

  • Geração do dataset

Para geração do dataset na rede siamesa de imagens, seguimos uma abordagem parecida com a de texto. Para os exemplos incorretos, selecionamos imagens de outros produtos da mesma estrutura mercadológica, porém com o EAN diferente, garantindo a diferença entre os itens.

Já para os exemplos corretos, usamos a imagem do produto como principal e a duplicamos para formar o par. Para que os exemplos corretos não ficassem exatamente iguais, utilizamos uma etapa de Data Augmentation, adicionando pequenas diferenças no par de imagens como brilho, contraste e rotação.

  • Extração de atributos com InceptionResNetV2

Similar a rede de texto, temos uma segunda rede siamesa profunda, voltada para as imagens dos produtos. Como input, utilizamos a primeira imagem (principal) de cada item para comparação. O formato escolhido foi de 224 x 224 x 3, levando em conta os valores que representam uma imagem colorida e também por ser um formato adotado em vários modelos pré-treinados, como por exemplo a ResNet50V2.

Diferentemente do fastText de word embeddings utilizado para extração de atributos dos textos, utilizamos uma outra abordagem para as imagens. Nesse caso, estamos utilizando o modelo InceptionResNetV2 como forma de criar vetores a partir das imagens.

Essa abordagem possui alguns problemas de antemão. Caso utilizássemos o modelo pré-treinado sem nenhuma modificação, o output não seria do formato que nos interessa, já que previamente esse modelo foi treinado com outro objetivo em relação ao nosso.

Outra alternativa seria refazer o treinamento completo dessa rede, porém com novos dados de imagens que representassem livros, o que seria extremamente custoso.

Visando resolver essa questão, escolhemos utilizar um meio termo, onde deixamos as camadas iniciais da rede congeladas para aproveitarmos o que já foi aprendido e reduzir a complexidade e tempo de treinamento pelo modelo, trabalhando somente as camadas finais com os nossos dados na intenção de realizar um fine tuning com dados do nosso universo de e-commerce.

  • Treinamento

Para o treinamento do modelo, utilizamos 1.716.627 pares de imagens no formato 224 x 224, durando até a época 39. Assim, como no modelo de texto, utilizamos como call back a função do early stopping do keras aplicada loss de validação. O modelo possui o total de 55.981.985 parâmetros, sendo 6.457.649 treináveis. Também aqui utilizamos uma máquina com 8 CPU, 64GB e uma GPU NVIDIA TESLA V100.

  • Output

A rede de similaridade entre imagens também possui como saída um número que representa o nível de similaridade entre as duas figuras. Desse modo, podemos utilizar a média entre as taxas das duas redes e assim conseguimos um único grau de similaridade para os produtos. Nas duas redes siamesas a função erro utilizada foi a Binary Crossentropy.

Resultados

Visando realizar a etapa de teste dos dois modelos, foram usados dados que que não estavam no treinamento e validação anteriormente. A composição desse dataset foi a seguinte:

Quadro 1 — Dados utilizados para teste

Importante destacar que, a partir das predições dos modelos, podemos ter dois casos de erro, um dando o falso negativo que acontece quando deixamos de agrupar produtos iguais e outro, onde o falso positivo ocorre quando agrupamos cadastros diferentes em uma mesma página de produto.

Levando em conta a visão de negócio, o mais interessante para o momento é priorizarmos a precisão, ou seja, só agruparmos itens quando tivermos uma alta taxa de confiança. Após fazermos as inferências nos modelos, tivemos os seguintes resultados demonstrados a seguir:

Figura 3 — Resultados segmentados após inferências
Figura 4 — Métricas após inferências

Vários valores de threshold foram testados, assim como diferentes combinações entre a similaridade de título e de imagem. Ao fim, tomamos a decisão de fazermos a média entre os valores preditos de cada modelo e selecionamos o threshold de 0.99.

Acima ou igual a esse valor, consideramos como match correto e abaixo como match incorreto. Esse limite possibilita a realização de uma boa quantidade de matchs entre os disponíveis com uma baixa taxa de erro.

Conforme apontado na Figura 4 com o threshold de 0.99, conseguimos atingir a acurácia de 99,97% nos casos classificados como corretos e 64,71% nos classificados como incorretos.

Com isso, temos uma quantidade de falsos positivos representando 0.03% e a de falsos negativos 35.29%. Dado o problema que temos, é preferível sacrificarmos alguns matchs corretos em troca de uma maior precisão (reduzindo os falsos positivos).

Com o objetivo de fazermos uma nova checagem das métricas, decidimos selecionar uma parcela dos nossos dados e passar em todo o processo descrito ao longo do artigo, apontado na figura abaixo:

Figura 5 — Fluxo de predição para um item

A partir de um produto e seu título, selecionamos possíveis candidatos, passamos os pares de produto nas validações de preço e de atributos e, por fim, fizemos as inferências nos modelos com os títulos e as imagens. Ao final desse processo, foi feita a validação manual de 2.090 exemplos. O resultado foi o seguinte:

Figura 6 — Métricas após inferências

Da mesma forma que o caso anterior, o nosso principal objetivo é evitar ao máximo erros quando afirmamos que um par de produtos é igual.

Nesse segundo caso, além do ensemble dos modelos, também aplicamos algumas regras de negócio como os filtros de preços e atributos e, dessa forma, todos os 823 casos apontados como match correto foram validados como certos após uma avaliação manual. Já sobre os 1.267 exemplos apontados como incorretos, 1.044 (82.39%) realmente eram incorretos.

Conclusão

Como falado, esse é um projeto que visa solucionar o problema de agrupamento ou matching de produtos a partir de machine learning, tendo como objetivo a geração de uma taxa de similaridade entre os itens.

A primeira aplicação desse projeto foi feita no departamento de Livros e as técnicas utilizadas, assim como as métricas atingidas, foram demonstradas ao longo do texto.

Conclui-se que a rede siamesa profunda, em conjunto com aplicações de processamento de linguagem natural, visão computacional e certas heurísticas de validação são uma técnica útil para o problema de produtos iguais, sendo representados de formas diferentes.

Como perspectiva, temos algumas estratégias em mente que podem ser utilizadas visando a melhoria desse projeto, como treinarmos somente uma rede siamesa que contemple dados textuais e das imagens.

Outra abordagem complementar é que, a partir de um modelo de feature extraction aplicado na área destinada à descrição dos produtos, possamos utilizar esses novos atributos para gerarmos títulos mais complexos e com mais qualidade, levando assim a melhora da performance geral.

Referências

Se você busca uma oportunidade de desenvolvimento, trabalhando com inovação em um negócio de alto impacto, acesse o portal B2W Carreiras! Nele, você consegue acessar todas as vagas disponíveis. Venha fazer parte do nosso time!

--

--