playdata/daily

12주차 : Day 3 (9/25)

soojin1 2024. 9. 30. 09:10

 

□ notebook 위 코드를 worker에 이식하여 예측을 진행

- model.py 

import numpy as np
from PIL import Image
from keras.models import load_model
import os

def get_model():
    # 모델 로드
    f = __file__
    dir_name = os.path.dirname(f)
    model_path = os.path.join(dir_name,"mnist240924.keras")
    model = load_model(model_path)

    return model

# 사용자 이미지 불러오기 및 전처리
def preprocess_image(file_path):
    img = Image.open(file_path).convert('L')  # 흑백 이미지로 변환
    img = img.resize((28, 28))  # 크기 조정

    # 흑백 반전
    # img = 255 - np.array(img)  # 흑백 반전
    img = np.array(img)

    img = img.reshape(1, 28, 28, 1)  # 모델 입력 형태에 맞게 변형
    img = img / 255.0  # 정규화

    return img

# 예측
def predict_digit(file_path):
    model = get_model()
    img = preprocess_image(file_path)
    prediction = model.predict(img)
    digit = np.argmax(prediction)

    return digit

 

-worker.py

import jigeum.seoul
from mnist.db import select, dml
from mnist.model import get_model, preprocess_image, predict_digit
import os
import requests

def get_job_img_task():
    sql = """
    SELECT 
        num, file_name, file_path
    FROM image_processing
    WHERE prediction_result is NULL
    ORDER BY num -- 가장 오래된 요청
    LIMIT 1 -- 하나씩
    """

    r = select(sql, 1)
    if len(r) > 0:
        return r[0]
    else:
        return None

    return r[0]


def prediction(file_path,num):
    sql = """UPDATE image_processing
    SET prediction_result=%s,
        prediction_model='n23',
        prediction_time=%s
    WHERE num=%s
    """
    
    presult = predict_digit(file_path)
    print(f"*********************** {presult}   { jigeum.seoul.now()}      {num}")
    dml(sql, presult, jigeum.seoul.now(), num)
    return presult

def run():
  """image_processing 테이블을 읽어서 가장 오래된 요청 하나씩을 처리"""
  
  # STEP 1
  # image_processing 테이블의 prediction_result IS NULL 인 ROW 1 개 조회 - num 갖여오기

  job = get_job_img_task()
  if job is None:
      print(f"{jigeum.seoul.now()}, num")
      return 

  num = job['num']
  file_name = job['file_name']
  file_path = job['file_path']

  # STEP 2
  # RANDOM 으로 0 ~ 9 중 하나 값을 prediction_result 컬럼에 업데이트
  # 동시에 prediction_model, prediction_time 도 업데이트
  presult = prediction(file_path,num)


  # STEP 3
  # LINE 으로 처리 결과 전송

  send_line_noti(file_name,presult)
  print(jigeum.seoul.now())

def send_line_noti(file_name='test', presult='-1'):
    api = "https://notify-api.line.me/api/notify"
    token = os.getenv('LINE_NOTI_TOKEN', 't5mTs8lD9zRUisWxZrbKHoHWKDUipPur73gYPs1c5IE')
    h = {'Authorization' : 'Bearer ' + token}
    msg = {
        "message" : f"{file_name} => {presult}"
    }
    r = requests.post(api, headers=h, data=msg)
    print(r)
    print(f"SEND LINE NOTI: + {presult}")

 

나는 Dockerfile에 모델을 COPY 해서 사용하는 방법을 생각했는데, 알고보니 pip install로 내 깃허브를 설치하기 때문에 그렇게 할 필요가 없었다.  (model.py : get_model() 참고)

__file__ 에 대해서 알게 되었다.

그리고 이 부분이 잘 작동되기 위해서는 model.py가 있는 위치에 모델이 존재해야한다.

 

 

로컬에서 테스트 완료했다.

 

그리고 도커 빌드해서 도커허브에 push 하고 AWS 서버에서 pull 받아와서 테스트를 했는데...

내가 모르는 새에 테이블에 lable 컬럼이 이 생겼다.ㅎ

 

숫자를 예측하는 프로그램이니까 예측한 값 말고 실제 값이 있어야한다고 했다.

파일 이름의 첫 번째 글자를 가져오도록 했다. 

 

[main.py 수정]

@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    # 파일 저장
    img = await file.read()
    file_name = file.filename
    file_ext = file.content_type.split('/')[-1]
    label = file_name[0]

    # 디렉토리가 없으면 오류, 코드에서 확인 및 만들기 추가
    upload_dir = os.getenv('UPLOAD_DIR','/home/sujin/code/mnist/img')
    if not os.path.exists(upload_dir):
        os.makedirs(upload_dir)
    import uuid
    file_full_path = os.path.join(upload_dir, 
            f'{uuid.uuid4()}.{file_ext}')

    with open(file_full_path, "wb") as f:
        f.write(img)

    sql = "INSERT INTO image_processing(file_name, label file_path, request_time, request_user) VALUES(%s, %s, %s, %s, %s)"
    import jigeum.seoul 
    from mnist.db import dml
    insert_row = dml(sql, file_name, label, file_full_path, jigeum.seoul.now(), 'n23')
    
    return {
            "filename": file.filename,
            "content_type": file.content_type,
            "file_full_path": file_full_path,
            "insert_row_cont": insert_row,
            "label" : label
           }

 

서버 DB에 이런식으로 들어가고 (원래는 NULL ~~로 들어감)

내가 돌린 건 알람도 잘 온당

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

12주차 : Day 5 (9/27)  (1) 2024.09.30
12주차 : Day 4 (9/26)  (0) 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