paint-brush
Как обучить модель обнаружения объектов с использованием пользовательского набора данных с помощью MinIO и YOLOк@minio
9,178 чтения
9,178 чтения

Как обучить модель обнаружения объектов с использованием пользовательского набора данных с помощью MinIO и YOLO

к MinIO13m2023/11/22
Read on Terminal Reader

Слишком долго; Читать

В этом посте мы создадим собственный набор данных изображений, а затем обучим модель You-Only-Look-Once (YOLO) для повсеместной задачи обнаружения объектов. Затем мы реализуем систему с использованием уведомлений MinIO Bucket Notifications, которая сможет автоматически выполнять логические выводы для нового изображения.
featured image - Как обучить модель обнаружения объектов с использованием пользовательского набора данных с помощью MinIO и YOLO
MinIO HackerNoon profile picture
0-item
1-item

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


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


В этом сообщении блога мы шаг за шагом рассмотрим, как решить эти проблемы с помощью лучших в своем классе инструментов, таких как CVAT и MinIO Bucket Notifications. К концу этого поста вы сможете обучить модель обнаружения объектов на собственном наборе данных и использовать ее для прогнозирования всякий раз, когда появляется новое изображение.

Предпосылка

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


Слева направо: (1) Су-30, (2) Ту-95.


Шаги, описанные в этом посте, можно распространить практически на любой домен. Вместо определения типов самолетов мы могли бы классифицировать землепользование или выполнять регрессию для прогнозирования урожайности сельскохозяйственных культур. Помимо традиционных изображений, мы также могли бы обучать и выполнять выводы на других типах многомерных данных, таких как облака точек LiDAR или 3D сейсмические изображения; становится просто вопросом, как выглядят данные обучения (и, возможно, другая модель глубокого обучения вместо YOLO). Если у вас есть дополнительные вопросы о том, как это будет выглядеть в конкретном случае использования, не стесняйтесь задавать вопросы в репозитории GitHub!


Шаг 1. Получение обучающих выборок и управление ими

Для этого проекта, во многом из-за отсутствия у меня спутника для получения изображений по требованию, я посетил аэродромы в Google Earth и сделал несколько снимков экрана областей, где были видны некоторые из этих самолетов. Сборка этого набора изображений заняла довольно много времени, поэтому я сохранил их все в корзине на моем сервере MinIO под названием «обнаружение объектов». В производственных условиях преимущества хранения собранных образцов на MinIO становятся еще более очевидными. Активно-активная репликация, высочайшие уровни шифрования и сверхбыстрые GET/PUT (и это лишь некоторые из них) означают, что ваши тщательно собранные образцы будут иметь высокую доступность, безопасность и надежность.

Шаг 2. Создание набора данных

Создание набора данных


Чтобы обучить модель обнаружения объектов для вашего варианта использования, необходим помеченный (или «аннотированный») набор данных. Отличным инструментом для этого является CVAT от OpenCV. Интересной особенностью является то, что CVAT предоставляет утилиту для подключения вашей корзины MinIO в качестве «облачного хранилища» для передачи изображений вашей корзины непосредственно в инструмент аннотирования набора данных. Для этого убедитесь, что хост вашего сервера MinIO доступен для сервера CVAT, особенно если вы используете сервер MinIO локально или локально на своем ноутбуке. Также, как примечание, существует два способа использования CVAT: (1) использование предоставленного веб-приложения по адресу app.cvat.ai или (2) запуск его локально. В любом случае, открыв CVAT, нажмите «Облачные хранилища» в строке меню. Отсюда вы можете заполнить форму, чтобы прикрепить корзину MinIO (совместимую с S3):


Создайте облачное хранилище


Давайте теперь создадим нашу новую задачу по маркировке в разделе «Задачи»:


Задача маркировки


Вам будет предложена форма для заполнения:


Создать новую задачу


При создании задачи важно правильно определить метки классов (я определил две метки Rectangle с названиями «SU30» и «TU95», соответствующие двум самолетам, которые я хотел обнаружить):


Определение меток классов


Теперь осталось прикрепить ранее добавленную корзину MinIO в качестве источника данных. В разделе «Выбрать файлы» нажмите «Облачное хранилище» и введите имя, которое вы указали для этого источника ранее. Выше я использовал имя «minio-cv-bucket».


Подключение MinIO Bucket в качестве источника данных


Процесс загрузки займет несколько минут. После завершения вы сможете увидеть свою работу по аннотациям в разделе «Вакансии».


Загрузка завершена


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


Начало аннотирования


Закончив аннотирование, экспортируйте набор данных в формате YOLO.


Экспорт данных

Шаг 3. Организация данных обучения

Экспортированный набор данных будет в виде zip-файла. После разархивирования текстовые файлы аннотаций в формате YOLO окажутся в закрытой папке. Не стесняйтесь взглянуть на них. В формате YOLO аннотации каждого изображения находятся в текстовом файле, где каждая строка содержит два угла ограничивающей рамки и класс. Номер класса соответствует порядку, в котором вы определили метки при создании задачи. Итак, в данном примере 0 будет соответствовать Су-30, а 1 — Ту-95.


На этом этапе создайте новый рабочий каталог (или введите тот, который вы уже создали). В этом каталоге создайте подкаталог с именем «набор данных». В «наборе данных» создайте каталоги, чтобы ваш рабочий каталог выглядел следующим образом:


 my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train |----val |----test |----annotations |----train |----val |----test



Теперь вам нужно будет заполнить подкаталоги train, val и test как для изображений, так и для соответствующих им аннотаций (текстовых файлов). Вам решать, как вы хотите получить и разделить образцы. Хорошей практикой является разделение общего количества обучающих выборок на 80 % обучения, 10 % проверки и 10 % тестирования. Обязательно перетасуйте изображения перед их разделением.


Лично я использовал mc cp клиента MinIO в командной строке, чтобы быстро получить все изображения из моей корзины «обнаружения объектов». Альтернативно, если у вас уже есть все образцы изображений в одном месте на локальном компьютере, вы можете работать с ними напрямую. Собрав все образцы в одном месте, я использовал скрипт Python для перетасовки, разделения и перемещения изображений и аннотаций в каталоги train, val и test. Вот скрипт, предоставленный для удобства . Если у вас есть какие-либо вопросы о том, как его использовать, не стесняйтесь задавать их в репозитории !


В конечном итоге убедитесь, что для каждого изображения, которое вы поместили в images/train, images/val или images/test, соответствующий файл аннотации .txt также находится в соответствующем подкаталоге внутри каталога annotations/. Например:


 my_cv_project (WORKING DIRECTORY) |---- dataset |----images |----train - 5.png - 3.png - 2.png |----val - 4.png |----test - 1.png |----annotations |----train - 5.txt - 3.txt - 2.txt |----val - 4.txt |----test - 1.txt


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

Шаг 4: Модель обнаружения объектов

Текущим золотым стандартом (с точки зрения производительности и простоты использования) распознавания объектов является класс моделей YOLO («Вы смотрите только один раз»). На момент написания YOLOv8 является последней версией и поддерживается Ultralytics как открытый исходный код. YOLOv8 предоставляет простой API, который мы можем использовать для обучения модели на наших недавно созданных аннотациях (и, в конечном итоге, также для выполнения вывода).


Давайте скачаем YOLOv8:


 $ pip install ultralytics


Теперь мы можем использовать инструмент YOLOv8 CLI или Python SDK для обучения, проверки и прогнозирования. Дополнительную информацию можно найти в документации YOLOv8.

Шаг 5: Обучение

В своем рабочем каталоге определите файл YAML, в котором указано расположение набора данных и сведения о классах. Обратите внимание, что пути такие же, как те, которые я создал ранее в рабочем каталоге. Я назвал свой файл « objdetect.yaml ». Также обратите внимание, что две метки класса самолета должны быть определены в том же порядке, что и в CVAT.


 train: ./dataset/images/train/ val: ./dataset/images/val/ test: ./dataset/images/test/ # number of classes nc: 2 # class names names: ["SU-30","TU-95"]


Начните обучение модели YOLOv8 на нашем наборе данных с помощью следующей команды (используя инструмент YOLO CLI). Обратитесь к документации YOLO, чтобы узнать больше обо всех различных параметрах, которые вы можете настроить для обучения. Здесь я начинаю обучение на 100 эпох и устанавливаю размер изображения 640 пикселей (все наши обучающие изображения будут соответствующим образом масштабироваться во время обучения):


 $ yolo task=detect \ mode=train \ model=yolov8s.pt \ data=objdetect.yaml \ epochs=100 \ imgsz=640


Обучение займет некоторое время, особенно если вы работаете на ноутбуке (как я), так что сейчас самое время сделать перерыв (или почитать дальше 😀)!


В конце цикла обучения ваша обученная модель вместе с другими интересными графиками и диаграммами будет сохранена в автоматически созданном каталоге под названием «runs». Вывод терминала (как показано ниже) будет указывать конкретное местоположение результатов последнего запуска. Каждый раз, когда вы обучаете модель, аналогичный каталог будет создан в «runs/detect/».


 Results saved to runs/detect/train


Примечание: run/detect/train/weights/ будет содержать файлы PT с точными тренированными весами. Запомните это место на будущее.

Шаг 5B: Проверка и тестирование модели

Вы можете запустить проверку с помощью следующей команды:


 $ yolo task=detect \ mode=val \ model=path/to/best.pt \ data=objdetect.yaml


Результаты будут автоматически сохранены в папке в вашем рабочем каталоге с путем в форме «runs/detect/val».


Чтобы выполнить вывод на тестовом наборе, вы можете использовать следующую команду:


 $ yolo task=detect \ mode=predict \ model=path/to/best.pt \ conf=0.5 \ source=dataset/images/test


Результаты будут храниться в папке «runs/detect/predict». Вот некоторые результаты прогнозирования на тестовом наборе:


Результаты прогнозирования


Шаг 6. Вывод нового изображения с использованием уведомлений сегмента MinIO

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


Использование уведомлений сегмента MinIO


MinIO Bucket Notifications — идеальный инструмент для этого. Мы можем создать систему, которая сможет автоматически выполнять выводы об обнаружении объекта при добавлении нового изображения в нашу корзину с помощью веб-перехватчика.


На высоком уровне у нас есть 3 шага. Во-первых, нам нужно определить конечную точку, которая может служить веб-перехватчиком для обнаружения объектов на новом изображении с помощью нашей обученной модели. Во-вторых, нам нужно настроить некоторые переменные среды для развертывания нашего сервера MinIO, которые предписывают ему обращаться к конечной точке веб-перехватчика при возникновении какого-либо события. В-третьих, нам нужно настроить, на какие типы событий корзины (например, PUT) мы хотим воздействовать. Давайте пройдемся по нему шаг за шагом.


Вот код простого сервера на основе Flask ( Detection_server.py ), который выполняет логический вывод для нового изображения, добавленного в корзину MinIO:


 """ This is a simple Flask inference server implementation that serves as a webhook for the event of a new image being added to a MinIO bucket. Object detection using YOLO will be performed on that image and the resulting predictions will be returned. """ from flask import Flask, request, abort, make_response from ultralytics import YOLO import tempfile from minio import Minio # Make sure the following are populated with your MinIO details # (Best practice is to use environment variables!) MINIO_ENDPOINT = '' MINIO_ACCESS_KEY = '' MINIO_SECRET_KEY = '' model = YOLO('/PATH/TO/best.pt') # load a custom model (path to trained weights) client = Minio( MINIO_ENDPOINT, access_key=MINIO_ACCESS_KEY, secret_key=MINIO_SECRET_KEY, ) app = Flask(__name__) @app.route('/', methods=['POST']) async def inference_bucket_webhook(): """ This endpoint will be called when a new object is placed in your inference bucket """ if request.method == 'POST': # Get the request event from the 'POST' call event = request.json bucket = event['Records'][0]['s3']['bucket']['name'] obj_name = event['Records'][0]['s3']['object']['key'] with tempfile.TemporaryDirectory() as temp_dir: temp_file_name = temp_dir+'/'+obj_name client.fget_object(bucket, obj_name, temp_file_name) # See https://docs.ultralytics.com/modes/predict/ for more information about YOLO inference options results = model.predict(source=temp_file_name, conf=0.5, stream=False) # A list of bounding boxes (if any) is returned. # Each bounding box is in the format [x1, y1, x2, y2, probability, class]. result = {"results": results[0].boxes.data.tolist()} print(result) resp = make_response(result, 200) return resp else: abort(400) if __name__ == '__main__': app.run()


Запустим сервер вывода:


 $ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit


Запишите имя хоста и порт, на котором работает приложение Flask.


Далее приступим к настройке вебхуков на стороне MinIO. Сначала установите следующие переменные среды. Замените <YOURFUNCTIONNAME> именем функции по вашему выбору. Для простоты я использовал «вывод». Кроме того, убедитесь, что для переменной среды конечной точки задан правильный хост и порт для вашего сервера вывода. В данном случае http://localhost:5000 — это место, где работает наше приложение Flask.


 $ export MINIO_NOTIFY_WEBHOOK_ENABLE_<YOURFUNCTIONNAME>=on $ export MINIO_NOTIFY_WEBHOOK_ENDPOINT_<YOURFUNCTIONNAME>=http://localhost:5000


Теперь перезапустите сервер MinIO, используя команду mc admin service restart ALIAS , или, если вы запускаете сервер впервые, вы также можете просто использовать команду minio server . Для получения дополнительной информации о перезапуске сервера MinIO ознакомьтесь с документацией MinIO. Примечание. ALIAS следует заменить псевдонимом вашего развертывания сервера MinIO. Для получения дополнительной информации о том, как установить псевдоним или просмотреть существующие псевдонимы, ознакомьтесь с документацией .


Наконец, давайте добавим сегмент и событие, о котором мы хотим получать уведомления. В нашем случае мы хотим получать уведомления о событиях ` put` (создание новых объектов) в нашей корзине. Для этой цели я создал совершенно новое пустое ведро под названием «обнаружение-вывод», поэтому я заменю его на «ВЕДРО».


 $ mc event add ALIAS/BUCKET arn:minio:sqs::<YOURFUNCTIONNAME>:webhook --event put


Вы можете проверить, что вы настроили правильный тип событий для уведомлений корзины, проверив, выводится ли « s3:ObjectCreated:* » при запуске этой команды:


 $ mc event ls local/detect-inference arn:minio:sqs::<YOURFUNCTIONNAME>:webhook


Более подробное объяснение публикации событий корзины в веб-перехватчике можно найти в документации . Теперь мы готовы попробовать обнаружение объектов на совершенно новом изображении!

Испытание нашей системы вывода

Вот новое изображение (под названием «1.png»), по которому я хочу сделать вывод:


Опробование системы вывода


Я помещаю новое изображение в корзину «обнаружения-вывода»:


Перенос изображения в новую корзину


Почти мгновенно я вижу на своем сервере Flask следующие результаты:


 $ python detection_server.py * Serving Flask app 'detection_server' * Debug mode: off * Running on http://127.0.0.1:5000 Press CTRL+C to quit image 1/1 /var/folders/xf/q7x0z8sn5nvckccp1g0m1vpm0000gn/T/tmpo6jx3w8u/1.png: 448x736 2 SU-30s, 101.0ms Speed: 4.1ms preprocess, 101.0ms inference, 5.8ms postprocess per image at shape (1, 3, 448, 736) {'results': [[1927.78369140625, 627.7123413085938, 1995.090576171875, 715.3443603515625, 0.8142037987709045, 0.0], [1735.740234375, 477.2108154296875, 1809.181640625, 555.767578125, 0.7766116261482239, 0.0]]} 127.0.0.1 - - [14/Sep/2023 15:39:21] "POST / HTTP/1.1" 200 -


Обратите внимание, что каждая обнаруженная ограничивающая рамка в списке результатов имеет формат YOLO [x1, y1, x2, y2, вероятность, класс]. Вот ограничивающие рамки и прогнозируемые классы, наложенные на исходное изображение:


Два других самолета не Су-30. Мой первоначальный набор данных включал около 100 изображений, поэтому я был удивлен, что модель уже смогла уловить нюансы между похожими самолетами. Я думаю, урок здесь таков: никогда не стоит недооценивать градиентный спуск!


Примечание. Для производственных сред и/или больших моделей машинного обучения рекомендуется использовать устоявшуюся платформу обслуживания моделей, такую как PyTorch Serve или Triton Server, чтобы сделать вывод более устойчивым и надежным. Если вам это интересно, прочтите предыдущий пост об оптимизации обслуживания моделей ИИ с помощью MinIO и PyTorch Serve .

Заключительные мысли

Мы сделали это! Мы рассказали, как MinIO и CVAT объединились, чтобы обеспечить безопасность и доступность собранных образцов изображений, а также как создать собственный набор данных для обнаружения объектов. Затем мы обучили нашу собственную модель YOLO для нашей специальной задачи. Наконец, с помощью чуть более 50 строк кода мы собрали сервер вывода с использованием уведомлений MinIO Bucket Notifications, который мог запускать новое изображение мимо нашей специально обученной модели обнаружения объектов.


MinIO и YOLO развернуты на периферии.


Более того, для большинства критически важных приложений компьютерного зрения лучше всего делать выводы на периферии. В противном случае указанные приложения уязвимы из-за задержки, связанной с загрузкой новых данных в общедоступное облако и ожиданием ответа от сервера вывода в облаке, не говоря уже о рисках неисправного сетевого подключения. По этой причине конвейер компьютерного зрения, ориентированный на MinIO как уровень данных, имеет гораздо больше смысла. Представьте себе дрон, летящий над аэродромом, способный захватывать, хранить и использовать нашу обученную модель на новых изображениях с полностью встроенным аппаратным и программным обеспечением. При локальном развертывании сервера MinIO система вывода на основе Bucket Notification, которую мы создали в конце статьи, отлично работает для этого сценария и для множества других подобных сценариев.


Если у вас есть какие-либо вопросы, присоединяйтесь к нашему каналу Slack или напишите нам по адресу [email protected] . Мы здесь чтобы помочь вам.


Также опубликовано здесь .