Найдите продукты, похожие на определенный продукт, используя изображение и название продуктов.

Описание проблемы:

Shopee — это ведущая онлайн-платформа электронной коммерции, которая позволяет пользователям покупать и продавать товары в Интернете. Он специализируется на электронной коммерции и ведет свой бизнес в основном в странах Южной Азии. Клиенты ценят простой, безопасный и быстрый процесс онлайн-покупок, адаптированный к их региону. Компания также обеспечивает надежную оплату и материально-техническую поддержку, а также функцию Гарантия самой низкой цены на тысячи перечисленных товаров Shopee. В этом конкурсе они открывают изображения продуктов с названиями/описаниями и ожидают, что специалисты по машинному обучению создадут модели, которые идентифицируют похожие продукты на основе изображений и описаний.

Исследование данных:

Posting_id: уникальный идентификатор для каждой публикации/продукта.

Изображение: имя файла изображения.

Image_phash: воспринимаемый хэш изображения.

Заголовок: описание этого изображения.

Label_group: код группы, к которой принадлежит продукт.

В трейн 34250 постов и некоторые посты имеют похожие файлы изображений, фаш и заголовки. Существует 11014 групп меток. Товары, принадлежащие группе label_group, похожи. Например,

Эти три разных продукта, которые принадлежат к группе этикеток, похожи, и это видно по изображениям этих трех продуктов.

Может ли label_group рассматриваться как наземная реальность или наземная истина? Нет

Рассмотрим Image_phash. Мы можем заметить, что приведенные ниже точки данных имеют один и тот же phash изображения, но они принадлежат к разным группам меток.

Когда я проверил изображения, они оказались похожими продуктами.

Мы можем ясно видеть, что вышеуказанные 3 продукта похожи и принадлежат к разным группам этикеток. Так можно ли считать фальшивые изображения истинной правдой? Нет

Из этого обсуждения на kaggle видно, что у непохожих товаров может быть один и тот же фэш изображения. Кроме того, есть публикации с одинаковыми/похожими изображениями или описаниями, но принадлежащие к разным группам ярлыков или имеющие разный фэш изображения.

Переходя к заголовку сообщений, давайте посмотрим, какие слова наиболее часто встречаются в заголовках данных о поездах с использованием облака слов.

Мы можем ясно видеть, что многие слова здесь не английские слова. Пройдите эту дискуссию на Kaggle, где с помощью Google Translate было изучено и замечено, что английский, индонезийский, малайский и немецкий языки являются наиболее используемыми языками, и это очевидно, потому что Shopee ведет свой бизнес в основном в странах Южной Азии. Также мы можем наблюдать числа в наиболее часто встречающихся словах. Номера не должны удаляться из заголовков во время предварительной обработки, потому что числа могут значительно описывать и различать продукты.

Сколько слов в заголовках?

Сколько уникальных слов присутствует в заголовках?

С помощью гистограмм количества слов и количества уникальных слов мы можем наблюдать, что в заголовках нет повторяющихся слов. Логично, что в названии продуктов обычно нет ни часто повторяющихся слов, ни стоп-слов. Я не заметил каких-либо стоп-слов в Word Cloud.

Переходя к изображениям,

from tensorflow.keras.preprocessing.image import load_img,img_to_array
# dimension of squared images
dims=[]
for img in tqdm(train.image.unique()):
path='Data/train_images/'+img
img_arr=img_to_array(load_img(path))
if img_arr.shape[0]==img_arr.shape[1]:
dims.append(img_arr.shape[0])
print('Number of unique Images: {}'.format(train.image.unique().shape[0]))
print('Number of squared Images: {}'.format(len(dims)))

Было замечено, что около 96% изображений в поезде являются квадратными изображениями, а более 56% изображений имеют размеры 640x640 и 1024x1024.

Формулировка проблемы машинного обучения:

Эта проблема не имеет оснований, и ее следует решать с помощью неконтролируемого подхода. Используя заголовки/описания, мы можем векторизовать их, используя базовые подходы, такие как TFIDF, Word2Vec/Glove, а также можем использовать BERT и различные варианты BERT (DistilBERT, SentenceBERT и т. д.) для получения вложений. После получения вложений мы можем сделать векторы единичными векторами и вычислить произведение DOT (Косинусное сходство) с другими векторами/вложениями. Приведение векторов/вложений к единичной длине гарантирует, что произведение DOT (косинусное сходство) находится между +1 и -1, поскольку теперь оно зависит только от угла между векторами/вложениями. Если косинусное сходство равно +1, то угол разделения между векторами равен 0 градусов (Cos(0)=+1), что, в свою очередь, означает, что они идентичны, а если косинусное сходство равно -1, то угол разделения между векторами составляет 180 градусов. (Cos(180)=-1), что, в свою очередь, означает, что они являются самыми непохожими векторами.

Точно так же встраивание изображений также можно выполнять с помощью сверточных нейронных сетей, и процесс вычисления сходства такой же, как описано выше. Мы также можем использовать Евклидово расстояние в качестве меры сходства, но, поскольку я уже создаю векторы/эмбеддинги как единичные векторы, евклидово расстояние пропорционально косинусному расстоянию. Нам нужно установить порог решения для продукта Косинусного сходства/DOT, чтобы получить совпадения для продукта, и этот оптимальный порог можно определить во время работы над проблемой.

Показатель эффективности:

Показателем производительности этой задачи является средний балл F1 по публикациям. Это означает, что оценка F1 вычисляется для каждого продукта с использованием его соответствий, и берется среднее значение всех продуктов.

Продукт ArcFace Loss/Arc Margin:

Справочный документ: https://arxiv.org/pdf/1801.07698.pdf

  1. ArcFace является модификацией Softmax, чтобы потери зависели только от косинусного подобия (точечный продукт) между вектором признаков и вектором весов. Возьмем, к примеру, сигмоид. Мы знаем, что сигмовидная функция равна 1/(1+exp-(W.X+b)), где X — вектор признаков, W — вес, а b — член смещения. Давайте рассмотрим, что плоскость проходит через начало координат, т.е. для простоты смещение = 0. Теперь Sigmoid=1/(1+exp-(W.X)).
  2. Мы знаем, что точка(W,X)=||W||.||X||.Cos(угол между ними). Мы вычисляем это и рассматриваем это как оценку вероятности и рассчитываем потери с этим. Что, если мы сделаем W и X единичными векторами? Потери зависят только от угла между этими векторами. То есть, если угол меньше (более похож на косинус), потери меньше, и во время обучения модель обновляет веса таким образом, чтобы уменьшить угол между W и X для конкретной метки класса.
  3. В дополнение к этому, что, если мы добавим некоторый угол к реальному? Даже если угол меньше, поскольку мы добавляем определенный угол и делаем вектор менее косинусным, модель пытается уменьшить добавленный угол во время обучения, что, в свою очередь, обновляет веса посредством обратного распространения таким образом, что фактический угол уменьшается. Мы просто усложняем обучение, что приводит к лучшему обучению, чем на самом деле.
  4. Этот процесс зависимости потерь от угла (подобие косинуса) и добавления к нему дополнительного угла для повышения эффективности обучения называется ArcFace-Additive Angular Margin Loss.
class ArcFace(tf.keras.layers.Layer):
# Implementation reference from https://github.com/lyakaap/Landmark2019-1st-and-3rd-Place-Solution/blob/master/src/modeling/metric_learning.py
def __init__(self, n_classes, scale, margin, **kwargs):
super(ArcFace, self).__init__(**kwargs)
self.n_classes = n_classes
self.scale = scale
self.margin = margin
self.cos_m = tf.math.cos(margin)
self.sin_m = tf.math.sin(margin)
def get_config(self):
config = super().get_config().copy()
config.update({'n_classes': self.n_classes,'scale': self.scale,'margin': self.margin})
return config
def build(self, input_shape):
super(ArcFace, self).build(input_shape[0])
self.W = self.add_weight(
name='W',
shape=(int(input_shape[0][-1]), self.n_classes),
initializer='glorot_uniform',
dtype='float32',
trainable=True,
regularizer=None)
def call(self, inputs):
X, y = inputs
y = tf.cast(y, dtype=tf.int32)
# Normalizing vectors( Unit Vectors ) to make dot product depend only on angle between vectors.
cosine = tf.matmul(
tf.math.l2_normalize(X, axis=1),
tf.math.l2_normalize(self.W, axis=0)
)
# Sin(angle)^2 + Cos(angle)^2 = 1
sine = tf.math.sqrt(1.0 - tf.math.pow(cosine, 2))
# Cos(angle+margin)=Cos(angle)*Cos(margin)-Sin(angle)*Sin(margin)
phi = cosine * self.cos_m - sine * self.sin_m
one_hot = tf.cast(tf.one_hot(y, depth=self.n_classes),dtype=cosine.dtype)
output = (one_hot * phi) + ((1.0 - one_hot) * cosine)
output *= self.scale
return output
view raw ArcFace_1.py hosted with ❤ by GitHub

Лучшее решение:

IDF +BERT(ArcFace) + EfficientNet B3(ArcFace): Отправка

Наилучшая частная оценка 0,72 — это сочетание текстовых и графических моделей/встраивания. EfficientNet B3 (на основе изображений) был обучен с использованием ArcFace с переменным запасом. Здесь маржа добавляется в каждом сценарии, но варьируется в зависимости от угла между характеристикой и весами. Маржа больше, когда угол мал, и наоборот.

class ArcFace(tf.keras.layers.Layer):
# Implementation reference from https://github.com/lyakaap/Landmark2019-1st-and-3rd-Place-Solution/blob/master/src/modeling/metric_learning.py
def __init__(self, n_classes, scale, margin, **kwargs):
super(ArcFace, self).__init__(**kwargs)
self.n_classes = n_classes
self.scale = scale
self.margin = margin
self.cos_m = tf.math.cos(margin)
self.sin_m = tf.math.sin(margin)
# Cos(180-margin)
self.threshold = tf.math.cos(math.pi - margin)
# let margin=30 degress =0.52 radians, then minimum_margin= sin(180-30)*0.52 = 0.26
self.minimum_margin = tf.math.sin(math.pi - margin) * margin
def get_config(self):
config = super().get_config().copy()
config.update({'n_classes': self.n_classes,'scale': self.scale,'margin': self.margin})
return config
def build(self, input_shape):
super(ArcFace, self).build(input_shape[0])
self.W = self.add_weight(
name='W',
shape=(int(input_shape[0][-1]), self.n_classes),
initializer='glorot_uniform',
dtype='float32',
trainable=True,
regularizer=None)
def call(self, inputs):
X, y = inputs
y = tf.cast(y, dtype=tf.int32)
# Normalizing vectors( Unit Vectors ) to make dot product depend only on angle between vectors.
cosine = tf.matmul(
tf.math.l2_normalize(X, axis=1),
tf.math.l2_normalize(self.W, axis=0)
)
# Sin(angle)^2 + Cos(angle)^2 = 1
sine = tf.math.sqrt(1.0 - tf.math.pow(cosine, 2))
# Cos(angle+margin)=Cos(angle)*Cos(margin)-Sin(angle)*Sin(margin)
phi = cosine * self.cos_m - sine * self.sin_m
# Smaller the angle between feature vector and weight vector, larger the margin and vice versa
# let theta be angle between feature vector and weight vector
# let theta=20 degrees, phi= Cos(30)-minimum_margin = 0.606. angle=inv_cos(0.606)= 52 degrees --> margin_added= 22 deg (approx)
# let theta=40 degrees, phi= Cos(40)-minimum_margin = 0.506. angle=inv_cos(0.506)= 59 degrees --> margin_added= 19 deg (approx)
# let theta=70 degrees, phi= Cos(70)-minimum_margin = 0.082. angle=inv_cos(0.082)= 85 degrees --> margin_added= 15 deg (approx)
phi = tf.where(cosine > self.threshold, phi, cosine - self.minimum_margin)
one_hot = tf.cast(tf.one_hot(y, depth=self.n_classes),dtype=cosine.dtype)
output = (one_hot * phi) + ((1.0 - one_hot) * cosine)
output *= self.scale
return output
view raw ArcFace_2.py hosted with ❤ by GitHub

EfficientNet B3 (на основе изображения) обучен на этом достигнутом частном счете 0,69 с использованием порога Косинусного сходства как 0,6, и я добавил совпадения продуктов, предсказанные с использованием текстовых вложений с более высокими порогами косинусного сходства (IDF и ArcFace обучили BERT с CS порог 0,75 и 0,7), следя за тем, чтобы в матчи EfficientNet B3 добавлялись только точные прогнозы, и эта комбинация привела к частной оценке 0,72.

Будущая работа:

  1. Поскольку мы заметили, что заголовок находится на нескольких языках, мы можем перевести его с помощью таких ресурсов, как Google Translate, и векторизовать текст.
  2. Также мы можем использовать специализированный языковой или многоязычный обученный BERT, такой как индонезийский BERT и т. д.,
  3. Что касается изображения, обучение в сиамском стиле можно использовать для оптимизации с тройной или контрастной потерей. Кроме того, SBERT, который предварительно обучен сиамскому подходу, может быть дополнительно обучен на этих данных соревнований и использован.
  4. Можно попробовать другие метрики подобия, использующие fiass, и попытаться найти более эффективный способ объединения совпадений, найденных разными моделями, вместо того, чтобы просто объединять их.

Использованная литература:

  1. https://appliedaicourse.com/
  2. https://arxiv.org/pdf/1801.07698.pdf
  3. https://github.com/lyakaap/Landmark2019-1st-and-3rd-Place-Solution/blob/master/src/modeling/metric_learning.py
  4. https://kaggle.com/ragnar123/unsupervised-baseline-arcface

Репозиторий Github: https://github.com/Chaitanya-Boyalla/Shopee-Product-Matching

LinkedIn: www.linkedin.com/in/chaitanya-boyalla-23051998

электронная почта: chaitanya.boyalla@gmail.com