Система рекомендаций - одна из самых важных и сложных систем разработки программного обеспечения во многих аспектах и ​​одна из причин успеха таких гигантов, как netflix, youtube и т. Д.

Создание полномасштабной системы рекомендаций в виде готового к развертыванию продукта для работающей компании требует глубоких знаний в области глубокого обучения, логического программирования, баз данных и предметной области, помимо этого, вы должны иметь необходимые знания в области разработки и разработки программного обеспечения для развертывания и обслуживания. [«Да Я все это знаю, ага »]

Привет всем, меня зовут Адитья Радж, я учусь на втором курсе IIIT в Аллахабаде, а также работаю удаленно инженером по машинному обучению на yellowbacks.com.

Я работаю уже 5 месяцев и чувствую себя безмерно удачливым, работая в растущем стартапе, я узнал множество вещей и получил возможность спроектировать, создать и развернуть несколько интересных систем на основе ИИ.

Что ж, здесь я буду говорить о моем любимом проекте, который буквально сделал меня полноценным инженером-программистом. Что ж, я попытаюсь объяснить с нуля, но базовые инженерные и математические знания не заставят вас чувствовать себя дерьмом.

Здесь желательно иметь достойное знание компьютерного зрения. Если у вас его нет, ниже приведена ссылка на другой блог.

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

Система рекомендаций: - Система рекомендаций - это программная система на основе искусственного интеллекта, которая рекомендует продукты пользователю на основе характеристик продукта или характеристик пользователей или того и другого.

В системе рекомендаций на основе элементов мы находим характеристики элементов, а затем делаем рекомендации на основе сходства между функциями (фильтрация содержимого).

На основе пользователей мы находим особенности пользователей, а затем рекомендуем аналогичные продукты аналогичным пользователям (совместная фильтрация)

Гибридная система рекомендаций использует их обе. Я работаю над разработкой гибридной системы рекомендаций.

Сегодня я расскажу о части, основанной на контенте, я все еще работаю над ее преобразованием в гибридную. Система рекомендаций, которую я сделал, предназначена для модного стартапа, поэтому это продукт на основе визуализации (материал Computer Vision). показывает ваш продукт в форме «ВАМ ТАКЖЕ МОЖЕТ ПОНРАВИТЬСЯ» на Amazon.

Базовая демонстрация моей рабочей системы: -

А теперь сравните это с данными крупной технологической компании:

Хорошо, спасибо, я знаю, что у меня все хорошо …… ..

Не плачьте о дизайне, это всего лишь API, который еще предстоит встроить в красивое программное обеспечение.

А теперь давайте узнаем.

Итак, я объясню всю систему в следующих частях:

  1. Внешний вид и дизайн высокого уровня
  2. R&E (Исследования и эксперименты)
  3. Глубокое обучение и инженерия данных
  4. Backend кодирование и создание API
  5. Развертывание

Высококачественный внешний вид и дизайн

Итак, эту часть мне написать сложнее всего, давайте попробуем: -

Упростив это в 007000000128 раз, предположим, что каждое изображение модного веб-сайта хранится на сервере базы данных. Предположим, каждое изображение преобразовано в 2048-мерный математический вектор (или массив с 2048 элементами для кодеров). Теперь предположим, что пользователь просматривает джинсы для его девушки, и моя система искусственного интеллекта должна рекомендовать ему похожие джинсы, как это будет?

Это просто: вычислить расстояние между вектором текущей джинсовой ткани и вектором всех изображений и вывести изображения с наименьшим расстоянием.

Итак, мне нужно разработать и написать алгоритм для поиска вложений (вектора) для каждого изображения и сохранить его в базе данных, а также другой базовый код, чтобы найти расстояние между векторами и рекомендовать изображения с меньшим расстоянием.

Что ж, это не так просто, поиск встраивания для каждого изображения требует глубокого обучения, знаний и опыта в области машинного обучения и, самое главное, терпения.

Часть исследований и экспериментов

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

Теперь объяснение всех моих исследований и экспериментов наверняка утомит вас, так что сразу спешите с выводами.

Что я узнал из исследований и экспериментов: -

  1. Я должен использовать подход трансфертного обучения с классификацией имиджа моды в качестве основы.
  2. DeepFashion Dataset - лучший доступный вариант.
  3. Архитектура трансферного обучения должна быть изменена на обнаружение объектов или архитектуру ограничивающего прямоугольника параллельно с классификацией, чтобы игнорировать фон, а также рекомендовать каждую подчасть моды отдельно.
  4. Вложения должны быть одномерными и ранжированными, чтобы сделать базу данных менее дорогой и ускорить расчет расстояний.
  5. Задержка системы должна быть низкой, а евклидово расстояние - простой, легкий и эффективный метод.
  6. Обнаружение и кадрирование объектов также должны выполняться очень эффективно, и поскольку в моем случае требовались рекомендации по верхнему и нижнему белью, я использовал для кадрирования детектор 2 от Facebook AI («Я довольно продвинутый»).
  7. С помощью detectron 2 для обнаружения множества объектов использовалась технология deepfashion 2.

Глубокое обучение и инженерия данных

Эта часть относится к самому сложному аспекту проекта, то есть к получению эмбеддингов (математических векторов).

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

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

шаг 1: - Предварительная обработка deepfashion2: -

from PIL import Image
import numpy as np
import json

dataset = {
    "info": {},
    "licenses": [],
    "images": [],
    "annotations": [],
    "categories": []
}

lst_name = ['short_sleeved_shirt', 'long_sleeved_shirt', 'short_sleeved_outwear', 'long_sleeved_outwear',
            'vest', 'sling', 'shorts', 'trousers', 'skirt', 'short_sleeved_dress',
            'long_sleeved_dress', 'vest_dress', 'sling_dress']

for idx, e  in enumerate(lst_name):
    dataset['categories'].append({
        'id': idx + 1,
        'name': e,
        'supercategory': "clothes",
        'keypoints': ['%i' % (i) for i in range(1, 295)],
        'skeleton': []
    })

num_images = 32153 #191961 
sub_index = 0  # the index of ground truth instance
for num in range(1, num_images + 1):
    json_name = '/content/validation/annos/' + str(num).zfill(6) + '.json'
    image_name = '/content/validation/image/' + str(num).zfill(6) + '.jpg'

    if (num >= 0):
        imag = Image.open(image_name)
        width, height = imag.size
        with open(json_name, 'r') as f:
            temp = json.loads(f.read())
            pair_id = temp['pair_id']

            dataset['images'].append({
                'coco_url': '',
                'date_captured': '',
                'file_name': str(num).zfill(6) + '.jpg',
                'flickr_url': '',
                'id': num,
                'license': 0,
                'width': width,
                'height': height
            })
            for i in temp:
                if i == 'source' or i == 'pair_id':
                    continue
                else:
                    points = np.zeros(294 * 3)
                    sub_index = sub_index + 1
                    box = temp[i]['bounding_box']
                    w = box[2] - box[0]
                    h = box[3] - box[1]
                    x_1 = box[0]
                    y_1 = box[1]
                    bbox = [x_1, y_1, w, h]
                    cat = temp[i]['category_id']
                    style = temp[i]['style']
                    seg = temp[i]['segmentation']
                    landmarks = temp[i]['landmarks']

                    points_x = landmarks[0::3]
                    points_y = landmarks[1::3]
                    points_v = landmarks[2::3]
                    points_x = np.array(points_x)
                    points_y = np.array(points_y)
                    points_v = np.array(points_v)
                    case = [0, 25, 58, 89, 128, 143, 158, 168, 182, 190, 219, 256, 275, 294]
                    idx_i, idx_j = case[cat - 1], case[cat]

                    for n in range(idx_i, idx_j):
                        points[3 * n] = points_x[n - idx_i]
                        points[3 * n + 1] = points_y[n - idx_i]
                        points[3 * n + 2] = points_v[n - idx_i]

                    num_points = len(np.where(points_v > 0)[0])

                    dataset['annotations'].append({
                        'area': w * h,
                        'bbox': bbox,
                        'category_id': cat,
                        'id': sub_index,
                        'pair_id': pair_id,
                        'image_id': num,
                        'iscrowd': 0,
                        'style': style,
                        'num_keypoints': num_points,
                        'keypoints': points.tolist(),
                        'segmentation': seg,
                    })

json_name = '/content/deepfashion2_train.json'
with open(json_name, 'w') as f:
    json.dump(dataset, f)

шаг 2: - обучение detectron2 на DeepFashion2: -

cfg = get_cfg()

cfg.merge_from_file(model_zoo.get_config_file("COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml"))
cfg.DATASETS.TRAIN = ("deepfashion_train",)
cfg.DATASETS.TEST = ()
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url("COCO-Detection/faster_rcnn_R_101_FPN_3x.yaml")  # Let training initialize from model zoo

cfg.SOLVER.IMS_PER_BATCH = 4
cfg.SOLVER.BASE_LR = 0.001
cfg.SOLVER.WARMUP_ITERS = 1000
cfg.SOLVER.MAX_ITER = 1500
cfg.SOLVER.STEPS = (1000,1500)
cfg.SOLVER.GAMMA = 0.05
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 64
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 13

cfg.TEST.EVAL_PERIOD = 500
os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)
trainer = DefaultTrainer(cfg) 
trainer.resume_or_load(resume=False)
trainer.train()

шаг 3: - сохранение готовой модели и конфига в zip-архиве

import shutil
shutil.make_archive('fashion_model', 'zip', '/content/output')
%cp "/content/fashion_model.zip" "/content/drive/My Drive/"

Теперь давайте разработаем функцию кадрирования, которая будет обрезать любое изображение на верхнюю и нижнюю одежду с помощью обученной детекторной модели.

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

Это настоящий проект для углубленного изучения. Используйте модель кераса resnet 50 и настройте последние несколько слоев на Deepfashion. Теперь, чтобы получить лучший результат, мы также добавим 2 слоя для ограничивающего прямоугольника и, наконец, сделаем определение классификации на deepfashion.

model_resnet = ResNet50 (weights = ’imagenet’, include_top = False, pooling = ’avg’)

для слоя в model_resnet.layers [: - 12]:

layer.trainable = Ложь

x = model_resnet.output

x = Dense (512, Activation = ’elu’, kernel_regularizer = l2 (0.001)) (x) # ЭТО ELU, НЕ RELU

y = плотный (46, активация = ’softmax’, name = ’img’) (x)

x_bbox = model_resnet.output

x_bbox = Dense (512, активация = ’relu’, kernel_regularizer = l2 (0,001)) (x_bbox)

x_bbox = Dense (128, активация = ’relu’, kernel_regularizer = l2 (0,001)) (x_bbox)

bbox = Dense (4, kernel_initializer = ’normal’, name = ’bbox’) (x_bbox)

final_model = Модель (входы = model_resnet.input,

output = [y, bbox])

архитектура до: -

__________________________________________________________________________________________________ conv5_block3_3_bn (BatchNormali (None, None, None, 2 8192 conv5_block3_3_conv [0] [0] __________________________________________________________________________________________________ conv5_block3_add (Добавить) (None, None, None, 2 0 conv5________________5_block] [conv5________________5_block] [03________________5_block] [03________________5_block] [03_________________block] [03_________________block] [03 (Активация) (Нет, Нет, Нет, 2 0 conv5_block3_add [0] [0] __________________________________________________________________________________________________ avg_pool (GlobalAveragePooling2 (Нет, 2048) 0 conv5_block3_out [0] [0] __________________________________________________________________________________________________ density_1 (Densepool) (Нет, avg_ 512) 10490 ] [0] __________________________________________________________________________________________________ плотный (Плотный) (Нет, 512) 104908 8 avg_pool [0] [0] __________________________________________________________________________________________________ плотный_2 (плотный) (нет, 128) 65664 плотный_1 [0] [0] __________________________________________________________________________________________________ img (плотный) (нет, 46) 23598 плотный [0] [0] __________________________________________________________________________________________________ bbox (плотный) ( Нет, 4) 516 density_2 [0] [0] ======================================== ================================================== ========== Всего параметров: 25,775,666 Обучаемые параметры: 6,653,618 Необучаемые параметры: 19,122,048

Эта архитектура была обучена для 120 эпох на графическом процессоре на наборе данных deepfashion.

архитектура после: -

conv5_block3_3_bn (BatchNormali (None, None, None, 2 8192 conv5_block3_3_conv [0] [0] __________________________________________________________________________________________________ conv5_block3_add (Add) (None, None, None, 2 0 conv5_block2_out [0] _________________block] [0_conv5_block2_out] Активация) (Нет, Нет, Нет, 2 0 conv5_block3_add [0] [0] __________________________________________________________________________________________________ avg_pool (GlobalAveragePooling2 (Нет, 2048) 0 conv5_block3_out [0] [0]

Выходные данные вектора длины 2048 из этой модифицированной модели после обучения будут использоваться как вложения для изображений.

Часть глубокого обучения была сделана здесь, и теперь мы перейдем к части бэкэнд-кодирования.

Backend кодирование и разработка API

Давайте сначала получим функцию обрезки изображений, используя усердную работу детектора, которую мы проделали в части обнаружения объектов: -

def crop_images(image):
  config_file_path = "config.yaml"
  model_path = "model_final.pth"
  
  lst_name = ['short_sleeved_shirt', 'long_sleeved_shirt', 'short_sleeved_outwear', 'long_sleeved_outwear',
              'vest', 'sling', 'shorts', 'bottom_wear', 'skirt', 'short_sleeved_dress',
              'long_sleeved_dress', 'vest_dress', 'sling_dress']
  
  bottom = ['shorts', 'bottom_wear', 'skirt']
  top = ['short_sleeved_shirt', 'long_sleeved_shirt', 'short_sleeved_outwear', 'long_sleeved_outwear','vest','short_sleeved_dress',
              'long_sleeved_dress', 'vest_dress']


  cfg = get_cfg()
  cfg.merge_from_file(config_file_path)
  cfg.MODEL.WEIGHTS =  model_path
  cfg.DATASETS.TEST = ("deepfashion_val", )
  cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.55   # set the testing threshold for this model
  predictor = DefaultPredictor(cfg)

  im = cv2.imread(image)
  outputs = predictor(im)
 

  boxes = {}
  for coordinates in outputs["instances"].to("cpu").pred_boxes:
    coordinates_array = []
    for k in coordinates:
      coordinates_array.append(int(k))
  
    boxes[uuid.uuid4().hex[:].upper()] = coordinates_array

  image_batch = []
  image_details = []
  for k,v in boxes.items():
    crop_img = im[v[1]:v[3], v[0]:v[2], :]
    image_batch.append(crop_img)

  for i in range(0,len(boxes)):
      image_details.append(lst_name[outputs['instances'][i].pred_classes.item()])

  botret = []
  topret = []
  for i in np.arange(0,len(image_batch)):
    if image_details[i] in bottom:
      botret.append(image_batch[i])
    if image_details[i] in top:
      topret.append(image_batch[i])

  print("Cropping Successful")
  return topret,botret

После получения кадрированного изображения время его встраивания.

Давайте посмотрим код для создания базы данных встраивания с помощью изображений обрезки и этой модели.

for items in os.listdir('images'):
    if items in rotten:
        continue
    else:
        top,bottom = crop.crop_images('images/'+items)
        
        for img in top[:1]:
            img = img.reshape(1,img.shape[0],img.shape[1],img.shape[2])
            topwear_database[items] = embed(img).numpy()[0]

        for img in bottom[:1]:
            img = img.reshape(1,img.shape[0],img.shape[1],img.shape[2])
            bottomwear_database[items] = embed(img).numpy()[0]

        im = cv2.imread('images/'+items)
        img = im.reshape(1,im.shape[0],im.shape[1],im.shape[2])
        main_database[items] = embed(img).numpy()[0]

после этого долгого процесса база данных была подготовлена.

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

Функция для получения k похожих рекомендаций: -

def similar_k(image_id,k):

  toprecommended = []
  bottomrecommended = []
  output1 = topwear_database[image_id]
  output2 = bottomwear_database[image_id]
  
  dis_dict = {}
  for key in topwear_database:
    dis_dict[key] = euclidean_distance(topwear_database[key],output1)

  sorted_dis_dict = dict(sorted(dis_dict.items(), key=lambda item: item[1]))
  i = 0

  for key in sorted_dis_dict:
    if i == k:
      break
    if key == image_id:
      continue;
    else:
        toprecommended.append(key)

    i = i+1

  dis_dict = {}
  for key in bottomwear_database:
    dis_dict[key] = euclidean_distance(bottomwear_database[key],output2)

  sorted_dis_dict = dict(sorted(dis_dict.items(), key=lambda item: item[1]))
  i = 0

  for key in sorted_dis_dict:
    if i == k:
      break
    if key == image_id:
      continue;
    else:
        bottomrecommended.append(key)

    i = i+1
  

  return toprecommended,bottomrecommended

Все следующие функции кода используются в API, разработанном с помощью fastAPI. Код работы fastapi очень прост и не нуждается в обсуждении.

Развертывание:

Мне пришлось развернуть api на докере, чтобы его могли использовать другие разработчики для интеграции.

Docker - это своего рода виртуальный контейнер, который можно переносить внутри серверов и систем.

Сначала я установил все свои требования в файл requirements.txt, а затем создаю файл докера.

API можно использовать и интегрировать напрямую, но для создания и встраивания базы данных нам определенно понадобится Docker.

FROM ubuntu:20.04


RUN apt update && apt install -y htop python3
RUN apt install -y python3-pip

RUN pip install torch==1.5.0+cpu torchvision==0.6.0+cpu -f https://download.pytorch.org/whl/torch_stable.html
RUN pip install detectron2==0.1.3+cpu -f https://dl.fbaipublicfiles.com/detectron2/wheels/cpu/index.html

COPY requirements.txt ./requirements.txt

RUN pip install -r requirements.txt
COPY . .

RUN python3 database.py && python3 test.py

Отправка контекста сборки демону Docker 613,5 МБ
Шаг 1/9: ИЗ ubuntu: 20.04
- - ›7e0aa2d69a15
Шаг 2/9: ЗАПУСК apt update && apt install -y htop python3
- - ›Использование кеша
- -› 75031337f4ce
Шаг 3/9: ЗАПУСК apt install -y python3-pip
- - ›Использование кеша
- -› af01d295f9e7 < br /> Шаг 4/9: ЗАПУСК pip install torch == 1.5.0 + cpu torchvision == 0.6.0 + cpu -f https://download.pytorch.org/whl/torch_stable.html
- - ›Использование кеша
- -› cb2ab85a33c0
Шаг 5/9: RUN pip install detectron2 == 0.1.3 + cpu -f https://dl.fbaipublicfiles.com/detectron2/wheels/ cpu / index.html
- -› Использование кеша
- - ›1059cff99453
Шаг 6/9: КОПИРОВАНИЕ requirements.txt ./requirements.txt
- -› Использование кеша
- - ›1ef1b3763905
Шаг 7/9: RUN pip install -r requirements.txt
- -› Использование кеша
- - ›54aafe521f90
Шаг 8/9 : КОПИЯ. .
- - ›4f991a474a99
Шаг 9/9: ЗАПУСК python3 database.py && python3 test.py
- -› Запуск в 391ab8cfe128

МЫ ГОТОВЫ

Любые сомнения, замечания, предложения, благодарности будут оценены

Мой WhatsApp №: - 8292098293

Идентификатор электронной почты: - [email protected]

Ссылка на блог по основам обнаружения объектов и компьютерного зрения: - https://aditya007.medium.com/research-summary-object-detection-upto-fast-rcnn-43d5944f4f6f

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