[DL 프로젝트: 패션 스타일 분류 앱 'FASI'] 3. 플라스크(Flask)에 텐서플로우(TensorFlow) 모델 서빙

모델 불러오기

  • 저번 시간까지 딥러닝 모델을 만들고 h5 파일로 저장했다.
  • 먼저 저장한 모델을 사용할 수 있도록 flask app에 불러와야한다.
  • 머신러닝 모델링을 불러올 땐 pickle을 이용했는데, keras 모델의 경우 h5를 이용한다.

라이브러리 불러오기

1
2
3
4
5
from flask import Flask, render_template, request
from keras.preprocessing.image import img_to_array
from keras.models import load_model
from PIL import Image
import io

app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# export model
model = load_model('data/h5/model.h5')

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        
        return render_template('index.html')

    if request.method == 'POST':
        img = request.files["file"].read()
        img = Image.open(io.BytesIO(img))
        img = img.resize((256, 256))
        img = img_to_array(img)
        img = img.reshape((1, img.shape[0], img.shape[1], img.shape[2]))
        pred = model_for_man.predict(img)
        label = pred.argmax()

        return render_template("index.html", label=label)
  • 일단 app.py는 간단히 위와 같이 구성했다.
  • 사용자가 이미지 파일을 submit하면 PIL형태로 읽어와 모델에 알맞게 사이즈를 변경하고 예측을 진행한다.
  • 마지막엔 라벨 형태로 제공되는데, 알맞게 변경해줄 것이다.

index.html

1
2
3
4
5
6
7
8
9
10
11
12

    <form method="post" action="/" enctype="multipart/form-data">
        <dl>
            <p>
                <input type="file" name="file" autocomplete="off" required>
            </p>
        </dl>
        <p>
            <input type="submit" value="Submit">
        </p>
    </form>

  • index.html은 위와 같이 설정해준다.

테스트

  • 일단 못생긴 이 파일 업로드 form에,

image

  • 파일을 선택하여,

image

  • submit하면 결과가 나온다!

image

  • 일단 기본적인 기능을 하는 틀은 완성했다.
  • 이제 어여쁜 템플릿을 골라 추가하여 적당히 꾸미고, 라벨을 수정하여 사용자에게 보여줄 어떤 스타일인지와 간략한 설명도 추가해야한다.(할일이 태산…)
  • 그럼 완성시키고 오겠다.
  • 완성시키고 왔다.
  • 메인 페이지에서,

image

  • 사진을 올리고 성별을 선택하고 Predict를 누르면, (내 사진으로 테스트해본다.)

image

  • 이렇게 분석을 해준다!

image

  • (근데 이게 포멀 클래식이 맞나… 후… 넘어가자…)
  • 아무래도 predict 시간이 좀 걸리는데, 로딩 페이지도 조만간 구현해야겠다.
  • 일단 구경하러 가봅시다. FASI 바로가기
  • flask 앱을 완성하고 heroku에 배포까지 하였다.
  • 일단 수많은 오류에 부딪혔는데, 생각나는 것 위주로 써내려가겠다.

트러블슈팅

convert RGB

  • 사진마다 scale이 다른 문제가 있었다.
  • 모델은 RGB를 사용해서 마지막 shape이 3인데 다른 경우 오류가 났다.
  • PIL을 이용하여 모든 이미지가 RGB로 변경되게끔 설계했다.
1
pred_img = Image.open(io.BytesIO(pred_img)).convert("RGB")

heroku memory

  • 배포에서 문제가 있었다.
  • heroku의 메모리 용량은 500mb인데, 내 앱의 총 용량이 800mb인 것…
  • 딥러닝 모델 자체가 각각 100mb라서 그거부터가 반을 차지해버린다는게 굉장히 골치였다.
  • 아쉽지만 일단 heroku 배포가 목적이니 하나로 통일해야만 했다.
  • 또, tensorflow의 용량을 줄이는 방법이 있었다.
  • tensorflow의 용량이 394mb나 되는데, 어차피 heroku에서는 cpu mode로만 돌아간다고 한다.
  • 그래서 requirements의 tf를 tensorflow-cpu==2.7.0로 설치하게끔 했다.

기타

행동 데이터 수집

  • 저번 데이터 엔지니어링 프로젝트에서 하지 못했던 이용자의 데이터를 축적하는 테스크를 진행하고 싶었다.
  • 예측에 쓰이는 이미지를 AWS S3에 적재해보고자 한다.
  • flask에서 post 요청으로 받은 이미지를 boto3를 활용하여 저장시킨다.
1
2
3
4
5
6
7
8
9
import boto3

AWS_ACCESS_KEY = "your key"
AWS_SECRET_KEY = "your key"
BUCKET_NAME = "your bucket name"

s3 = boto3.client('s3',
        aws_access_key_id = AWS_ACCESS_KEY,
        aws_secret_access_key = AWS_SECRET_KEY)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
.
.
img = request.files["file"]
upload_img(img)
.
.

def upload_img(image):
    image.seek(0) # s3 저장에 필요
    s3.put_object(
        Bucket = BUCKET_NAME, # 버킷 이름
        Body = image, # 업로드 파일
        Key = 'image/{}'.format(image.filename), # 저장 위치 및 이름 지정
        ContentType = image.content_type) # 이미지 타입
  • s3로 보낼 수 있는 함수를 생성했다.

image

  • 이미지를 예측에 사용할 때 마다 s3에 저장되는 것을 볼 수 있다.
0%