[인공지능 모델 서빙] fast api resnet

개발노트·2025년 1월 31일

resnet

준비는 끝났다! 제일 간단한 예제로 resnet 을 서버에 올려보자

https://pytorch.org/hub/pytorch_vision_resnet/
[추론 코드]

import torch

from threading import Lock
from torchvision import transforms


class Singleton:
    _instance = None
    _lock = Lock()

    def __new__(cls, *args, **kwargs):
        with cls._lock:
            if not cls._instance:
                cls._instance = super().__new__(cls)
        return cls._instance

class ResNet(Singleton):
    """Singleton class for ResNet model."""
    def __init__(self) -> None:
        self.device = "mps"
        self.model = torch.hub.load('pytorch/vision:v0.10.0', 'resnet18', pretrained=True).to(self.device)
        self.model.eval()
        self.preprocess = 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]),
        ])
        with open("imagenet_classes.txt", "r") as f:
            self.categories = [s.strip() for s in f.readlines()]

if __name__ == "__main__":
    resnet1 = ResNet()
    resnet2 = ResNet()

    print(f"resnet1 ID: {id(resnet1)}")
    print(f"resnet2 ID: {id(resnet2)}")

    if id(resnet1) == id(resnet2):
        print("싱글턴 패턴이 제대로 적용되었습니다.")
    else:
        print("싱글턴 패턴이 적용되지 않았습니다.")

우선 추론 코드에 싱글턴 패턴이 제대로 적용 되었는지 확인해보았다

성공👏


서버 실행

설치해둔 가상환경에 fastapi와 uvicorn 을 설치

$ pip install "fastapi[all]" uvicorn
app = FastAPI()

class ResNet(Singleton):
    def __init__(self) -> None:
        self.device = "mps" if torch.backends.mps.is_available() else "cpu"
        self.model = torch.hub.load('pytorch/vision:v0.10.0',
                                    'resnet18',
                                    pretrained=True).to(
                                    self.device)
        self.model.eval()

        self.preprocess = 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]),
        ])

        with open("imagenet_classes.txt", "r") as f:
            self.categories = [s.strip() for s in f.readlines()]

위 싱글턴을 그대로 사용하여 하나의 모델 객체만 생성 될 수 있게 만들어준다.

    def predict(self, image_bytes: bytes) -> dict:
        input_image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
        input_tensor = self.preprocess(input_image).unsqueeze(0).to(
            self.device)

        with torch.no_grad():
            output = self.model(input_tensor)

        predict_tensor = torch.nn.functional.softmax(output[0], dim=0)
        top5_prob, top5_catid = torch.topk(predict_tensor, 5)

        top5_dict = {}
        for i in range(top5_prob.size(0)):
            top5_dict[self.categories[top5_catid[i]]] = top5_prob[i].item()

        return top5_dict
resnet_model = ResNet()

추론은 추론만 하면 될 수 있게 분리.

@app.post("/predict")
async def predict(file: UploadFile = File(...)):
    try:
        image_bytes = await file.read()
        predictions = resnet_model.predict(image_bytes)
        return JSONResponse(content=predictions)
    except Exception as e:
        return JSONResponse(content={"error": str(e)}, status_code=500)

엔드포인트를 만들어주고, 사진은 byte 정보를 post로 받을 수 있게 만들었다

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=8000)
$ python app.py

그러고 나서 파일을 실행하면 추론 서버가 켜진다 👍

이제 해당 사진을 요청으로 보내보면,

import requests

def send_image(image_path: str, url: str = "http://127.0.0.1:8000/predict") -> None:
    with open(image_path, "rb") as image_file:
        files = {"file": image_file}
        try:
            response = requests.post(url, files=files)
            for cls, score in response.json().items():
                print(cls, score)
            
        except requests.exceptions.RequestException as e:
            print(f"An error occurred: {e}")

if __name__ == "__main__":
    image_path = "dog.jpg"
    send_image(image_path)

사모예드로 분류해냈다
🐶


fast api와 singleton패턴 resnet 을 사용하여 간단하게 비동기 서버에 인공지능 모델을 올리는 과정을 해보았다. 이제 서버 환경에 맞춰서 약간 수정하고, 위 예제에 다른 모델들만 바꿔서 쓰면 될 것 이다

0개의 댓글