Update model configuration without shutting down services
Production deployement of Deep Learning models is very difficult. So we are going to see how we can create a very light weight asynchronous service using FastAPI and pytorch models (resnet and alexnet). The aim of this blog is to resolve the common problem in production where retrained model is configured in running service without shutting down.
Pretrained models : Neural Network models trained on large benchmark datasets like ImageNet.
Create fastapi service by using pretrained model(resnet and alexnet) in pytorch which will predict an image of a dog with probabilities of predicted classes.
FastAPI intro
FastAPI is a modern, fast (high-performance), web framework for building APIs with Python 3.6+ based on standard Python type hints.
-
key features:
- Fast: Very high performance, on par with NodeJS and Go (thanks to Starlette and Pydantic). One of the fastest Python frameworks available.
- Fast to code: Increase the speed to develop features by about 200% to 300%. *
- Fewer bugs: Reduce about 40% of human (developer) induced errors. *
- Intuitive: Great editor support. Completion everywhere. Less time debugging.
- Easy: Designed to be easy to use and learn. Less time reading docs.
- Short: Minimize code duplication. Multiple features from each parameter declaration. Fewer bugs.
- Robust: Get production-ready code. With automatic interactive documentation.
- Standards-based: Based on (and fully compatible with) the open standards for APIs: OpenAPI (previously known as Swagger) and JSON Schema.
Reference FastAPI
Build Services
python dependecies need to install using pip: torch, torchvision, fastapi, uvicorn, Pillow
torch : Dynamic neural networks in Python
torchvision : consists of popular datasets, model architectures, and common image transformations for computer vision.
fastapi : fast web framework for building APIs
uvcorn : lightning-fast ASGI server
Pillow : Python Imaging Library
folder structure
├── app.py
├── dog.jpg
├── imagenet_classes.txt
└── predict.py
app.py : fastapi service
predict.py : predict the probabilities of type of image and type of model
dog.jpg : Image of a dog
imagenet_classes.txt : classes of pretrained model (resnet and alexnet)
code is available here
Code walkthrough
predict.py
import required packages
from torchvision import models, transforms
import torch
from PIL import Image
method -> predicted_results
input parameter: image_path , pretrained model
read image using PIL
img = Image.open(img)
transform the input image so that they have the right shape and values should be similar to the ones which were used while training the model using torchvision module
transform = transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225]
)])
pre-process the image
img_t = transform(img)
batch_t = torch.unsqueeze(img_t, 0)
Load ImageNet classes
with open('imagenet_classes.txt') as f:
classes = [line.strip() for line in f.readlines()]
get index of maximum output vector scores
out = pymodel(batch_t)
# Forth, print the top 5 classes predicted by the model
_, indices = torch.sort(out, descending=True)
percentage = torch.nn.functional.softmax(out, dim=1)[0] * 100
return model name and most probable classes
return {
"model_name" : pymodel.__class__.__name__,
"predicted_results" : [{classes[idx] : percentage[idx].item()} for idx in indices[0][:5]]
}
Reference here
app.py
import required packages and predict class dependencies
from fastapi import FastAPI
import uvicorn
from torchvision import models
from predict import predicted_results
initialize fastapi
app = FastAPI()
initialize resnet model for the app
pymodel = models.resnet101(pretrained=True)
call predict get method with img_path parameter and call predict method with the details
# query parameter http://127.0.0.1:8000/predict/?img_path=path/dog.jpg
@app.get("/predict/")
async def predict(img_path: str = ""):
return predicted_results(img_path, pymodel)
update alexnet model without shutting down the application
call global model variable update with new model
@app.post("/update_model")
async def read_item():
global pymodel
pymodel = models.alexnet(pretrained=True)
return {"message": "model updated sucessfully"}
start uvicorn application
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=8000)
Demo
steps:
- initialize service
- predict image and see the result of resnet model
- update the model to alexnet
- predict image and see the result of alexnet model