Система рекомендаций - одна из самых важных и сложных систем разработки программного обеспечения во многих аспектах и одна из причин успеха таких гигантов, как netflix, youtube и т. Д.
Создание полномасштабной системы рекомендаций в виде готового к развертыванию продукта для работающей компании требует глубоких знаний в области глубокого обучения, логического программирования, баз данных и предметной области, помимо этого, вы должны иметь необходимые знания в области разработки и разработки программного обеспечения для развертывания и обслуживания. [«Да Я все это знаю, ага »]
Привет всем, меня зовут Адитья Радж, я учусь на втором курсе IIIT в Аллахабаде, а также работаю удаленно инженером по машинному обучению на yellowbacks.com.
Я работаю уже 5 месяцев и чувствую себя безмерно удачливым, работая в растущем стартапе, я узнал множество вещей и получил возможность спроектировать, создать и развернуть несколько интересных систем на основе ИИ.
Что ж, здесь я буду говорить о моем любимом проекте, который буквально сделал меня полноценным инженером-программистом. Что ж, я попытаюсь объяснить с нуля, но базовые инженерные и математические знания не заставят вас чувствовать себя дерьмом.
Здесь желательно иметь достойное знание компьютерного зрения. Если у вас его нет, ниже приведена ссылка на другой блог.
Также я буду держать вещи немного базовыми по сравнению с исходным проектом, чтобы каждый мог ссылаться на это в своем будущем проекте.
Система рекомендаций: - Система рекомендаций - это программная система на основе искусственного интеллекта, которая рекомендует продукты пользователю на основе характеристик продукта или характеристик пользователей или того и другого.
В системе рекомендаций на основе элементов мы находим характеристики элементов, а затем делаем рекомендации на основе сходства между функциями (фильтрация содержимого).
На основе пользователей мы находим особенности пользователей, а затем рекомендуем аналогичные продукты аналогичным пользователям (совместная фильтрация)
Гибридная система рекомендаций использует их обе. Я работаю над разработкой гибридной системы рекомендаций.
Сегодня я расскажу о части, основанной на контенте, я все еще работаю над ее преобразованием в гибридную. Система рекомендаций, которую я сделал, предназначена для модного стартапа, поэтому это продукт на основе визуализации (материал Computer Vision). показывает ваш продукт в форме «ВАМ ТАКЖЕ МОЖЕТ ПОНРАВИТЬСЯ» на Amazon.
Базовая демонстрация моей рабочей системы: -
А теперь сравните это с данными крупной технологической компании:
Хорошо, спасибо, я знаю, что у меня все хорошо …… ..
Не плачьте о дизайне, это всего лишь API, который еще предстоит встроить в красивое программное обеспечение.
А теперь давайте узнаем.
Итак, я объясню всю систему в следующих частях:
- Внешний вид и дизайн высокого уровня
- R&E (Исследования и эксперименты)
- Глубокое обучение и инженерия данных
- Backend кодирование и создание API
- Развертывание
Высококачественный внешний вид и дизайн
Итак, эту часть мне написать сложнее всего, давайте попробуем: -
Упростив это в 007000000128 раз, предположим, что каждое изображение модного веб-сайта хранится на сервере базы данных. Предположим, каждое изображение преобразовано в 2048-мерный математический вектор (или массив с 2048 элементами для кодеров). Теперь предположим, что пользователь просматривает джинсы для его девушки, и моя система искусственного интеллекта должна рекомендовать ему похожие джинсы, как это будет?
Это просто: вычислить расстояние между вектором текущей джинсовой ткани и вектором всех изображений и вывести изображения с наименьшим расстоянием.
Итак, мне нужно разработать и написать алгоритм для поиска вложений (вектора) для каждого изображения и сохранить его в базе данных, а также другой базовый код, чтобы найти расстояние между векторами и рекомендовать изображения с меньшим расстоянием.
Что ж, это не так просто, поиск встраивания для каждого изображения требует глубокого обучения, знаний и опыта в области машинного обучения и, самое главное, терпения.
Часть исследований и экспериментов
Эта часть включала больше изучения и понимания существующих систем и моделей на github, colab, medium и других платформах с открытым исходным кодом.
Теперь объяснение всех моих исследований и экспериментов наверняка утомит вас, так что сразу спешите с выводами.
Что я узнал из исследований и экспериментов: -
- Я должен использовать подход трансфертного обучения с классификацией имиджа моды в качестве основы.
- DeepFashion Dataset - лучший доступный вариант.
- Архитектура трансферного обучения должна быть изменена на обнаружение объектов или архитектуру ограничивающего прямоугольника параллельно с классификацией, чтобы игнорировать фон, а также рекомендовать каждую подчасть моды отдельно.
- Вложения должны быть одномерными и ранжированными, чтобы сделать базу данных менее дорогой и ускорить расчет расстояний.
- Задержка системы должна быть низкой, а евклидово расстояние - простой, легкий и эффективный метод.
- Обнаружение и кадрирование объектов также должны выполняться очень эффективно, и поскольку в моем случае требовались рекомендации по верхнему и нижнему белью, я использовал для кадрирования детектор 2 от Facebook AI («Я довольно продвинутый»).
- С помощью 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
Не забывайте ставить лайки и делиться моим контентом, спасибо ...