На курсах Fast.ai мы научились создавать отличные модели. В этой статье я покажу вам, как загрузить вашу модель на сервер и создать для этого пользовательский интерфейс. Я использовал для этого код Дипаншу, который вы можете увидеть на его Github. Код модифицирован из кода Саймона Уиллисона, который вы можете увидеть здесь. Это было хорошо для этого урока, потому что не было ничего бесполезного. Когда вы создаете свою собственную версию этого кода, вы можете улучшить пользовательский интерфейс и код, как хотите, но в этой статье я делаю все просто, чтобы облегчить понимание. Я также хочу поблагодарить Дипаншу за помощь, когда у меня возникли проблемы с его кодом и серверами AWS.

Построение модели

Вы начинаете с построения модели. Я предполагаю, что если вы читаете это, вы уже знаете, как построить модель, которая может распознавать кошек, собак или, в нашем случае, объект на изображении аллигатора или крокодила. Самое главное - окончательно сохранить модель.

learn.save('model')

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

Вы можете использовать любой сервер, который вам нравится, но я использовал AWS, потому что была 12-месячная бесплатная пробная версия, и многие компании тоже ее используют.

  1. Перейдите на https://aws.amazon.com и создайте учетную запись.
  2. Добавьте свою кредитную карту.
  3. Создайте EC2. Я выбрал Ubuntu 18, потому что знаком с ней. Вы можете выбрать все, что хотите, но когда мы импортируем пакеты, код может отличаться от того, что я собираюсь показать.

Затем просто нажмите «Далее», пока не появится сообщение «Ваши экземпляры запускаются».

Я должен упомянуть об этом одну вещь. Сначала я выбрал t2.medium, потому что у меня были проблемы с установкой некоторых пакетов, когда у меня было всего 1 ГиБ ОЗУ. После установки всех пакетов я просто остановил экземпляр и изменил его на t2.micro. Если вы планируете использовать такой маленький экземпляр, как я, я рекомендую сделать это именно так.

4. Подключитесь к своему устройству.

Компьютеры Linux
Компьютеры Windows

Теперь у вас должен быть терминал вашей машины EC2 перед вами. Начнем с установки некоторых важных вещей. Выполните эти команды на своем серверном терминале.

sudo apt update
sudo apt upgrade
sudo apt install python3-pip
pip3 install fastai
pip3 install torch_nightly -f https://download.pytorch.org/whl/nightly/cpu/torch_nightly.html
pip3 install starlette
pip3 install uvicorn
pip3 install aiohttp
pip3 install python-multipart

Написание кода

Пора начинать писать код.

Сначала создайте name.py, где будет выполняться весь код. Это файл, который мы запускаем на сервере, поэтому он не может быть .Ipynb Я называю свой файл server.py, но это не имеет значения, каково ваше имя файла. Сделайте это на своем локальном компьютере, и мы передадим его позже на сервер.

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

from starlette.applications import Starlette
from starlette.responses import JSONResponse, HTMLResponse, RedirectResponse
from fastai import *
from fastai.vision import *
import torch
from pathlib import Path
from io import BytesIO
import sys
import uvicorn
import aiohttp
import asyncio

Звездочка.

app = Starlette()

Это базовые вещи Python. Сначала мы сообщаем, где находится наша модель. Затем мы определяем наши классы. DataBunch.loa... определите заполнитель данных, куда мы позже будем импортировать данные. В последних двух строках мы сначала создаем обучаемого, а затем загружаем старые веса, которые мы сохранили. Обратите внимание, что это происходит одновременно с загрузкой страницы.

path = Path("data")
classes = ["alligator", "crocodile"]
data = DataBunch.load_empty(path)
learn = cnn_learner(data, models.resnet50)
learn.load("model")

Это первая страница нашего сайта. Как видите, мы можем использовать базовый HTML, чтобы он выглядел немного красивее. У нас есть две формы. Другой обрабатывает загруженные изображения с пользовательского компьютера, а другой обрабатывает изображения с URL-адресов. Когда вы нажимаете кнопку «загрузить изображение», вы перейдете на / upload, а когда вы нажмете «получить и проанализировать изображение», вы перейдете на / classify-url. Это страницы, которые мы определяем ниже.

@app.route("/")
def form(request):
    return HTMLResponse("""
        <h3>This app will classify Alligator vs Crocodial<h3>
        <form action="/upload" method="post" enctype="multipart/form-data">
            Select image to upload:
            <input type="file" name="file">
            <input type="submit" value="Upload Image">
        </form>
        Or submit a URL:
        <form action="/classify-url" method="get">
            <input type="url" name="url">
            <input type="submit" value="Fetch and analyze image">
        </form>
    """)

Пользователь попадает сюда, когда нажимает кнопку «Загрузить изображение». Это берет изображение, загруженное пользователем, читает его и, наконец, передает его функции pred_image_from_bytes, которая определена ниже.

@app.route("/upload", methods=["POST"])
async def upload(request):
    data = await request.form()
    bytes = await (data["file"].read())
    return predict_image_from_bytes(bytes)

Это почти то же самое, но на этот раз мы берем изображение из Интернета, используя url.

@app.route("/classify-url", methods=["GET"])
async def classify_url(request):
    bytes = await get_bytes(request.query_params["url"])
    return predict_image_from_bytes(bytes)

Это то, что мы использовали в предыдущей части для получения изображения с URL-адреса.

async def get_bytes(url):
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as response:
            return await response.read()

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

def predict_image_from_bytes(bytes):
    img = open_image(BytesIO(bytes))
    _, class_, losses = learn.predict(img)
    return JSONResponse({
        "prediction": classes[class_.item()],
        "scores": sorted(
            zip(learn.data.classes, map(float, losses)),
            key=lambda p: p[1],
            reverse=True
        )
    })

И, наконец, мы просто запускаем этот сервер, проверив несколько вещей.

if __name__ == "__main__":
    if "serve" in sys.argv:
        uvicorn.run(app, host="0.0.0.0", port=80)

Перенесите свои данные в EC2

Теперь у вас должен быть код и модель Python на вашем локальном компьютере. Следующее, что вам нужно сделать, это загрузить их на свой сервер. Я использую Ubuntu, поэтому я использую следующую команду, чтобы загрузить что-то со своего локального компьютера в EC2. (Запустите это на своем локальном компьютере, а не на сервере!)

scp -i /path/public_key.pem /path/server.py ubuntu@ec2-18-257-46-41.us-east-2.compute.amazonaws.com:server.py

Но для пользователей Windows я рекомендую использовать FileZilla. Вы можете найти хорошие руководства по этому поводу в Интернете, и я не буду объяснять это больше, потому что это не руководство по FileZilla.

Теперь ваше дерево серверов должно выглядеть примерно так.

Обратите внимание, что fast.ai требует папки данных и моделей, хотя в данном случае они бесполезны.

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

sudo python3 server.py serve

(Замените server именем вашего файла, если оно другое)

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

Измените это, если ваш входящий не выглядит так, как на картинке выше. После этого вернитесь к инстансам.

Откройте браузер и введите свой IP-адрес (вы можете видеть его в экземплярах).

13.58.219.149

Сейчас все работает. Вы можете позвонить своей бабушке, чтобы открыть эту страницу, и она сможет использовать ее так же, как и вы. Но на этом статья еще не закончилась. Есть небольшая проблема. Если вы закроете терминал на локальном компьютере, он автоматически закроет и ваш код Python на сервере, и вы больше не сможете использовать это приложение.

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

nohup sudo python3 server.py serve >outfile.txt &

Чтобы остановить выполнение кода, сначала запустите ps -ef. Вы увидите список процессов (рисунок ниже), в котором вам нужно найти процесс, который вы хотите закрыть. Вероятно, он находится внизу, и его будет легко найти, потому что это единственный запущенный процесс Python.

После того, как вы нашли правильный процесс, вам нужно взять номер PID. В приведенном выше примере это 1751, и затем вы можете остановить его, запустив sudo kill 1751 Возможно, ваш номер другой, и поэтому важно сначала выполнить поиск с помощью ps -ef



~ Ланкинен