Comment appliquer l'apprentissage métrique à distance au problème de la rue à la boutique

Commençons par une définition du problème de la rue au magasin: identifier un article de mode dans une image utilisateur et le trouver dans une boutique en ligne. Avez-vous déjà vu quelqu'un dans la rue et vous vous êtes dit: «Waouh, c’est une belle robe, je me demande où je peux l’acheter? Mais pour moi, c'était une tâche difficile d'essayer des techniques d'apprentissage métriques à distance. J'espère que vous le trouverez intéressant aussi.

Ensemble de données

Premièrement, nous avons besoin d'un ensemble de données pour cela. En fait, je suis venu à cette idée après avoir découvert qu'il y avait des tonnes d'images prises par des utilisateurs sur Aliexpress. Et je me suis dit «Waouh, je peux faire une recherche par image en utilisant ces données, juste pour le fun, bien sûr». J’ai décidé de miser sur le top des vêtements pour femmes pour plus de simplicité.

Voici la liste des catégories que j'ai utilisées pour la mise au rebut:

  • Les robes
  • Blouses et chemises
  • Sweats à capuche et sweatshirts
  • Chandails
  • Vestes et manteaux

J'ai utilisé des demandes et BeautifulSoup pour la mise au rebut. Les images du vendeur peuvent être obtenues à partir de la page principale de l'article, mais pour les images de l'utilisateur, nous devons consulter les pages de commentaires. Il y a quelque chose appelé "couleurs" sur la page de l'article. La couleur peut être simplement un élément d'une autre couleur ou même complètement d'autres éléments. Nous allons donc considérer les différentes couleurs comme des éléments différents.

Vous pouvez trouver le code que j'ai utilisé pour obtenir toutes les informations sur un élément (il en cache encore plus que ce dont nous avons besoin pour notre tâche) par le lien https://github.com/movchan74/street_to_shop_experiments/blob/master/get_item_info.py.

Tout ce dont nous avons besoin est de parcourir les pages de recherche de chaque catégorie, de prendre les URL de tous les éléments et d’utiliser la fonction ci-dessus pour obtenir les informations sur chaque élément.

Enfin, nous aurons deux séries d'images pour chaque article: des images provenant d'un vendeur (URL du champ pour chaque élément initem ["couleurs"]) et des images des utilisateurs (imgs de champ pour chaque élément initem ["feedbacks"]).

Pour chaque couleur, nous avons une seule image d'un vendeur, mais il peut s'agir de plus d'une image pour chaque couleur d'un utilisateur (parfois, il n'y a aucune image pour la couleur).

Génial! Nous avons des données. Cependant, le jeu de données collecté est bruyant:

  • Il y a des images bruyantes de la part des utilisateurs (photos de boîtes d'emballage, de textures ou seulement d'une partie d'un article, d'articles non emballés, de photos sans rapport).
Exemples de bruit dans les images de l'utilisateur.

Pour atténuer ce problème, j'ai classé 5000 images en deux catégories: les bonnes images et les images de bruit. Au début, mon plan était de former un classificateur pour deux catégories et de l'utiliser pour nettoyer le jeu de données. Mais plus tard, j'ai décidé de laisser cette idée pour un travail futur et je viens d'ajouter des images nettoyées aux ensembles de test et de validation.

  • Le deuxième problème est qu'il existe des articles vendus par plusieurs vendeurs. Les vendeurs ont même parfois les mêmes images (ou des images légèrement modifiées). Mais comment y faire face? Le moyen le plus simple est de ne rien faire et d'utiliser un algorithme robuste pour l'apprentissage métrique à distance. Cela peut toutefois affecter la validation car nous pouvons avoir le même élément dans les données de validation et d'apprentissage. Cela conduit donc à une fuite de données. Une autre méthode consiste à utiliser quelque chose pour trouver des images similaires (ou même identiques) et les fusionner en un seul élément. Nous pouvons utiliser le hachage perceptuel pour trouver des images identiques (comme phash ou whash) ou former un modèle sur des données bruitées et appliquer le modèle pour trouver des images similaires. J'ai choisi la deuxième option car elle permet de fusionner des images même légèrement modifiées.

Apprentissage métrique à distance

La perte de triplet est l’une des méthodes d’apprentissage métrique à distance les plus populaires:

où max (x, 0) est la fonction de charnière, d (x, y) est la fonction de distance entre x et y, F (x) est un réseau neuronal profond, M est la marge, a est l'ancre, p est le positif. point, n est le point négatif.

F (a), F (p), F (n) sont des points situés dans un espace de grande dimension (imbrications) produits par un réseau de neurones profonds. Il est à noter que les embeddings doivent souvent être normalisés pour avoir une unité de longueur, c'est-à-dire, || x || = 1, afin d’être robuste aux changements d’éclairage et de contraste et à la stabilité de l’entraînement. L'ancre et les échantillons positifs appartiennent à la même classe, l'échantillon négatif est l'instance d'une autre classe.

Ainsi, l’idée principale de la perte de triplet est de séparer les imbrications de la paire positive (ancre et positive) des imbrications de la paire négative (ancre et négative) par une marge de distance M.

Mais comment sélectionner le triplet (a, p, n)? Nous pouvons simplement sélectionner des échantillons au hasard sous forme de triolet, mais cela pose les problèmes suivants. Tout d'abord, il n'y a pas de triplets possibles. Cela signifie que nous avons besoin de beaucoup de temps pour parcourir tous les triplés possibles. Mais en réalité, nous n’avons pas besoin de le faire, car après quelques répétitions d’entraînement, il y aura beaucoup de triplets qui ne violent pas la contrainte de triplet (donnez zéro perte). Cela signifie que ces triplés sont inutiles pour une formation.

L’un des moyens les plus courants de sélection de triolets est l’exploitation minière négative:

La sélection des négatifs les plus difficiles peut, dans la pratique, conduire à de mauvaises minima locaux au début de la formation. Plus précisément, il peut en résulter un modèle réduit (c.-à-d. F (x) = 0). Afin d'atténuer cela, nous pouvons utiliser une extraction négative semi-dure.

Les échantillons négatifs semi-durs sont plus éloignés de l'ancre que l'échantillon positif, mais ils sont toujours durs (non respect de la contrainte de triplet) car ils se trouvent à l'intérieur de la marge M.

Conditions pour un triplet avec échantillon négatif semi-dur

Il existe deux méthodes pour générer des échantillons négatifs semi-durs (et durs): en ligne et hors ligne.

  • En ligne signifie que nous sélectionnons de manière aléatoire des échantillons de l'ensemble de données de train sous forme de mini-lot et sélectionnons des triplets à partir des échantillons qu'il contient. Cependant, nous avons besoin d'une taille de mini-lot importante pour la méthode en ligne. Ce n'est pas possible dans mon cas car je n'ai qu'un seul GTX 1070 avec 8 Go de RAM.
  • Dans la méthode hors ligne, nous devons arrêter l'entraînement après un certain temps, prévoir l'intégration d'un nombre d'échantillons, sélectionner des triplets et entraîner le modèle avec ces triplets. Cela signifie que nous devons faire passer en avant deux fois mais que c’est le prix de la méthode hors ligne.

Bien! Nous pouvons déjà commencer à former le modèle avec la perte de triplet et l'extraction négative semi-dure hors ligne. Mais! Il y a toujours un «mais» dans ce monde imparfait. Il nous faut encore une astuce pour résoudre avec succès le problème de la rue au magasin. Notre tâche est de trouver l’image du vendeur la plus proche de celle de l’utilisateur. Cependant, les images du vendeur ont généralement une qualité bien meilleure (en termes d’éclairage, de caméra, de position) que les images d’utilisateur, nous avons donc deux domaines: les images du vendeur et les images d’utilisateur. Pour obtenir un modèle efficace, nous devons réduire l’écart entre ces deux domaines. Ce problème s'appelle adaptation de domaine.

Gauche: image de l'utilisateur, droite: image du vendeur

Je propose une technique très simple pour réduire les écarts de domaine: sélectionnons les ancres dans les images du vendeur, les échantillons positifs et négatifs dans les images des utilisateurs. C'est tout! Simple mais efficace.

la mise en oeuvre

Pour mettre en œuvre mes idées et expérimenter rapidement, j'ai utilisé la bibliothèque Keras avec le backend Tensorflow.

J'ai choisi le modèle Inception V3 comme base CNN pour mon modèle. Comme d'habitude, j'ai initialisé CNN avec des pondérations ImageNet. J'ai ajouté deux couches entièrement connectées après la mise en commun globale avec la normalisation L2 à la fin du réseau. La taille de l'intégration est 128.

Nous devons également implémenter la fonction de triple perte. Nous passons l'ancre, les échantillons positifs / négatifs sous forme de mini-lots simples et les divisons en 3 tenseurs à l'intérieur de la fonction de perte. La fonction distance est la distance euclidienne au carré.

Et compiler le modèle:

Résultats expérimentaux

Résultats de récupération. Première colonne - requête (image de l’utilisateur), 5 prochaines - images du vendeur les plus similaires.

La performance est mesurée en termes de rappel à K (R @ K).

Voyons comment calculer R @ K. L’image de chaque utilisateur provenant du jeu de validation a été utilisée comme requête et nous devons trouver l’image du vendeur correspondant. Nous prenons une image de requête, calculons le vecteur d’incorporation et cherchons les voisins les plus proches de ce vecteur parmi les vecteurs de toutes les images du vendeur. Nous utilisons non seulement les images du vendeur provenant du jeu de validation, mais également celles du train, car cela permet d’augmenter le nombre de distracteurs et rend notre tâche plus ardue.

Nous avons donc une image de requête et une liste des images du vendeur les plus similaires. S'il existe une image de vendeur correspondante dans les K images les plus similaires, nous retournons 1 pour cette requête, sinon nous renvoyons 0. Nous devons maintenant le créer pour l'image de chaque utilisateur dans l'ensemble de validation et trouver une moyenne des scores de chaque requête. Ce sera R @ K.

Comme je l’ai dit précédemment, j’ai nettoyé la petite quantité d’images de l’utilisateur des images bruitées. J'ai donc mesuré la qualité du modèle sur deux ensembles de données de validation: l'ensemble de validation complet et un sous-ensemble d'images uniquement nettes.

R @ K pour les données de validation

Les résultats sont loin d'être idéaux, il y a beaucoup de choses à faire:

  • Nettoyez les images de l'utilisateur du bruit. J'ai déjà fait le premier pas dans cette direction en nettoyant un petit ensemble.
  • Fusionner les éléments plus précisément (au moins dans le jeu de validation).
  • Réduire l'écart de domaine. Je suppose que cela peut être fait par une augmentation spécifique à un domaine (par exemple, une augmentation de l'éclairage) et en utilisant des méthodes spécialisées (comme celle-ci https://arxiv.org/abs/1409.7495).
  • Appliquez une autre technique d'apprentissage métrique à distance. J'ai essayé celui-ci https://arxiv.org/abs/1703.07464, mais cela fonctionne moins bien dans mon cas.
  • Recueillir plus de données bien sûr.

Démo, code et modèle formé

J'ai fait une démonstration du modèle. Vous pouvez le vérifier ici: http://vps389544.ovh.net:5555/. Vous pouvez télécharger votre propre image pour la recherche ou utiliser une image aléatoire à partir du jeu de validation.

Code et modèle formé: https://github.com/movchan74/street_to_shop_experiments

Merci d'avoir lu. Si vous appréciez cet article, faites-le moi savoir en applaudissant. Si vous souhaitez plus d'informations, vous pouvez communiquer avec moi sur LinkedIn.