Я давно думал о создании API, который другие разработчики могли бы использовать в облаке. Но я не хотел, чтобы это был традиционный Hello World API или простой SQL Flask API, поддерживающий классические запросы GET, PUT, POST, DELETE REST для имени пользователя и электронной почты. Поскольку AI и ML сейчас настолько распространены, я подумал о том, чтобы попробовать ML - и это легко :)

Классификация изображений с помощью PyTorch

Поскольку все в облаке и бесплатные версии, мне нужен был проект AI / ML с небольшими легковесными зависимостями для облака. Я разветвил проект под названием Img2vec, который использует PyTorch для генерации векторов признаков для набора данных изображений, а затем выполняет простое сопоставление (косинусное сходство в sklearn) тестового изображения с другими, используя предварительно обученные модели. . В файле readme достаточно фрагментов, чтобы демонстрация работала в вашей системе.

Обучение набора данных изображения

Для простоты я пропускаю часть обучения по набору данных - в Интернете есть много документации. Для нашего API я создаю векторы изображений и сохраняю их как файлы csv. Поскольку вычисления будут происходить в облаке, если мы сгенерируем векторы во время выполнения, API всегда будет тайм-аут. Но API сгенерирует вектор для данных изображения, которые вы будете пинговать, и прочитает другие векторы из файлов csv.

Настройка приложения Flask

Для простого сопоставления изображений мне понадобился запрос POST или PUT. Есть много фреймворков, поддерживающих функции REST, я использовал flask на Python 3.6. Как гласит официальный сайт

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

Итак, идея такая:

  1. Сервер получает изображение в виде байтового потока.
  2. Эти байты кодируются обратно в изображение с помощью Pillow в Python.
  3. Для этого изображения создается вектор признаков.
  4. Этот вектор сопоставляется с изображениями обучающих данных.
  5. Самые близкие подходящие изображения возвращаются обратно (с URL-адресом загрузки и значением процентного соответствия)

Вот суть API:

# endpoint to detect image
@app.route("/image_clustering", methods=["PUT"])
def image_clustering():

    # Image converted in Base64 encoded byte stream
    bytes = request.get_data()
    results = search(bytes)  # returns a list of image matches
    return jsonify(results)

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

Примечание: исходный код можно получить здесь.

Настройка сервера Heroku

Настроить сервер довольно просто, но я столкнулся с несколькими проблемами:

  • Размер слага. Heroku предоставляет максимальный размер слага 500 МБ - общий объем данных, которые приложение может хранить (код, исполняемые файлы и мультимедийные файлы, такие как изображения, PDF-файлы) после сжатия. Это проблема, поскольку библиотеки Python, такие как SciPy и PyTorch, довольно большие по размеру - PyTorch с CUDA 8 занимает около 600 МБ. Но есть обходные пути.
  • Версия PyTorch. PyTorch предоставляет вариант сборки только для ЦП, небольшую библиотеку размером 45 МБ, обеспечивающую все функции, необходимые для развертывания.
  • Ручная установка SciPy: Не знаю почему, но онлайн-установка SciPy на Heroku оказывается некорректной (подробнее здесь). Вместо этого я загрузил SciPy whl (или исходный код) в виде файла и вручную установил его на сервер.
  • JPEG против PNG: В демонстрационном коде я использовал файлы расширения JPEG (с данными в кодировке base64, начинающимися с / 9j / 9…). Поэтому, если вы отправите эхо-запрос на сервер с изображениями в других форматах, например PNG (данные в кодировке base64 начинаются с iVi…), вы получите сообщение об ошибке.

Демо-время

Вы можете пройти демо разными способами

  1. Вы можете установить приложение (получить здесь) на свое устройство Android. Нажмите на изображение, это займет некоторое время, и будут отображены наиболее подходящие изображения.
  2. Вы можете использовать этот скрипт на питоне. Просто введите относительный путь к изображению на рабочем столе, и он отобразит результаты.
  3. Вы можете сделать PUT-запрос онлайн (я рекомендую Hurl.it для начинающих) к этому URL-адресу с данными изображения в кодировке base64 в качестве тела.

Для показанного образца изображения кошки результаты следующие:

[
  [
    0.8155140106062471, 
    "https://www.googleapis.com/download/storage/v1/b/python-clustering-api.appspot.com/o/images%2FFace%2F124.jpg?generation=1522585329188523&alt=media"
  ], 
  [
    0.8145577585207011, 
    "https://www.googleapis.com/download/storage/v1/b/python-clustering-api.appspot.com/o/images%2FFace%2F242.jpg?generation=1522585299229997&alt=media"
  ], 
  [
    0.7914929138145477, 
    "https://www.googleapis.com/download/storage/v1/b/python-clustering-api.appspot.com/o/images%2FFace%2F212.jpg?generation=1522584727478100&alt=media"
  ], 
  [
    0.7806927914191767, 
    "https://www.googleapis.com/download/storage/v1/b/python-clustering-api.appspot.com/o/images%2FFace%2F099.jpg?generation=1522585251917855&alt=media"
  ], 
  [
    0.6948463995381056, 
    "https://www.googleapis.com/download/storage/v1/b/python-clustering-api.appspot.com/o/images%2FFace%2F119.jpg?generation=1522584693369035&alt=media"
  ]
]

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

Следите за мной и будьте в курсе моих новых сообщений: Medium, Github, Facebook, Twitter или LinkedIn.