playdata/daily

10주차 : Day 2,3 (9/10,11)

soojin1 2024. 9. 23. 23:10

 

전체적인 프로세스는 length를 입력하면 LinearRegression에 의해 weight를 리턴하고, length와 weight를 입력하면 Knn에 의해 물고기 종류를 출력하게 된다. 

 

먼저 어제 만든 LinearRegression 모델을 pkl 파일로 저장하고, pkl 모델을 사용하여 무게를 예측하는 lr.py 을 작성했다.

import pickle

def lr(length:float):
    ### 모델 불러오기
    with open("/home/sujin/code/fr/src/note/linear_model.pkl", "rb") as f:
        lr_model = pickle.load(f)

    prediction = lr_model.predict([[length **2, length]])

    return float(prediction[0])

 

결과를 FastApi에서 확인할 수 있도록 main.py을 작성했다.

from typing import Union
from fastapi import FastAPI
from lr import lr

app = FastAPI()

@app.get("/")
def read_root():
    return {"Hello", "world"}
    
@app.get("/how_weight")
def lr_api(length:float):
    """
    물고기 무게 예측

    Args:
        length (float): 물고기 길이(cm)

    Returns:
        weight (float): 물고기 무게(kg)
    """

    weight = lr(l)
    return {"weight": weight}

 

 

Knn도 마찬가지로 pkl 파일을 저장하여 같은 방식으로 수행했다.

import pickle

def knn(length: float, weight:float):
    """
    물고기의 종류 판별기

    Args:
        length (float): 물고기 길이(cm)
        weight (float): 물고기 무게(g)

    Returns:
        dict: 물고기 종류를 담은 딕셔너리
    """

    ### 모델 불러오기
    with open("/Users/sujinya/code/fr/src/note/knn_model.pkl", "rb") as f:
        knn_model = pickle.load(f)

    prediction = knn_model.predict([[length, weight]])

    if prediction[0] == 1:
        fish_class = "도미"
    else:
        fish_class = "빙어"

    return fish_class
$ cat main.py

@app.get("/fish")
def knn_api(length: float, weight:float):
    """
    물고기의 종류 판별기

    Args:
        length (float): 물고기 길이(cm)
        weight (float): 물고기 무게(g)

    Returns:
        dict: 물고기 종류를 담은 딕셔너리
    """

    fish = knn(length,weight)

    return {
                "prediction": fish,
                "length": length,
                "weight": weight
            }

 

마지막으로 cli 프로그램을 만들어야한다.

cli에서 length에 해당하는 값을 입력하면 weight와 종류를 리턴해주어야 한다.

from api.knn import knn_api
from api.lr import lr_api

def predict():
    length = float(input("물고기의 크기를 입력하세요: "))

    ## weight 예측 선형회귀 API 호출
    weight = lr_api(length)

    ## 물고기 분류 API 호출
    fish_class = knn_api(length, weight)

    print(f"🐟 length:{length} 물고기는 weight:{weight} 으로 예측 되며 종류는 {fish_class} 입니다")
$ cat pyproject.toml

[project.scripts]
fish = 'fr.cli:predict'

 

근데 도커를 이해를 잘 못하겠어서 도커 사용을 아예 하지 않고 여기까지 수행했다.


  • Docker
$ cat Dockerfile

FROM python:3.11

WORKDIR /code

COPY src/api/main.py /code/

RUN pip install --no-cache-dir --upgrade git+https://github.com/sooj1n/fr.git

# 모델 서빙을 위해 API 구동을 위한 FastAPI RUN
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8080"]

 

도커파일을 기본적으로 이렇게 작성했었는데 이것..이제서야 이해했다.

로컬의 소스 코드의 특정 파일들을 도커 이미지 내로 복사하고, 필요한 패키지를 설치한 후, FastAPI 서버를 구동한다.

* COPY로 디렉토리 전체를 복사할 수도 있다.

 

$ docker exec -it fish_kind bash
root@3f47b9ec103a:/code# ls
__pycache__  main.py

이렇게 보니까 COPY 부분이 이해가 됐다. 도커 run 후에 exec하여 ls를 입력했더니 main.py를 확인할 수 있었다.

 

CMD 명령어를 사용하여 FastAPI 애플리케이션을 uvicorn 서버로 구동하고 있다. , 0.0.0.0 주소를 사용하여 컨테이너 외부에서 접근할 수 있도록 하고 있다.


$ cat LB/Dockerfile

FROM nginx:1.25.1

COPY default.conf /etc/nginx/conf.d/
$ cat LB/default.conf

# 긴 도메인 이름이나 여러 도메인을 사용할 때 성능과 관련된 문제를 해결하는 옵션
server_names_hash_bucket_size 128;

server {
	# 80번 포트에서 HTTP 요청을 수신.
    listen 80;
    # 3.39.251.54 IP 주소로 들어오는 요청을 처리
    server_name 3.39.251.54;

    # sudo docker run -d -p 8001:8080 --name how_serv <IMAGE>
    # /how_weight/ 경로로 들어오는 요청을 172.17.0.1 서버의 8001 포트로 전달
    location /how_weight/ {
        proxy_pass http://172.17.0.1:8001/;
    }

    # sudo docker run -d -p 8002:8080 --name kind_serv <IMAGE>
    # /kind_fish/ 경로로 들어오는 요청을 172.17.0.1 서버의 8002 포트로 전달
    location /kind_fish/ {
        proxy_pass http://172.17.0.1:8002/;
    }
}
# 또 다른 서버 블록으로, 80번 포트에서 HTTP 요청을 수신.
server {
    listen 80;
    server_name ec2-43-203-225-43.ap-northeast-2.compute.amazonaws.com;
# 루트 경로(/)로 들어오는 요청을 172.17.0.1 서버의 8001 포트로 전달.
    location / {
        proxy_pass http://172.17.0.1:8001/;
    }
}

'playdata > daily' 카테고리의 다른 글

12주차 : Day 3 (9/25)  (1) 2024.09.30
12주차 : Day 2 (9/24)  (0) 2024.09.30
12주차 : Day 1 (9/23)  (2) 2024.09.24
10주차 : Day 4,5 (9/12,13)  (3) 2024.09.23
10주차 - Day 1(9/9)  (0) 2024.09.23