728x90

AINIZE

- 오픈 소스 프로젝트를 간편하게 배포하는 툴

ref : ai-network.gitbook.io/ainize-tutorials/

 

DevOps(Development Operation)

- IT 제품 개발 사이클을 의미

1. 프로토타이핑

2. 테스트

3. 패키징

4. 배포

5. 실행

6. 반복

=> MLOps(Machine Learning Operation)을 구현하자.

 

MLOps 준비

1. ML 프로젝트를 웹(flask)으로 연동 준비

2. 도커화

3. Ainize로 프로젝트 배포

 

포크할 ML proj

github.com/minsulee2/mnist-mlp-app

- 위 저장소의 숫자 인식 ml proj를 클론 받아 웹 연동 후 ainize로 배포할 예정

 

 

 

파일 구조

 

 

 

Flask 서버 코드 작성(server.py)

from flask import Flask, render_template, request, Response
from PIL import Image
from image_preprocessor import preprocess
from mnist_mlp import load_keras_model, predict_number

model = load_keras_model()
app = Flask(__name__, template_folder="./templates/",
        static_url_path="/images", static_folder="images")

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/healthz", methods=["GET"])
def healthCheck():
    return "", 200

@app.route("/image", methods=["POST"])
def get_result():
    if request.method == "POST":
        width, height = 28, 28
        try:
            source = Image.open(request.files["source"])
            adjusted_img = preprocess(source, width, height)
            res = predict_number(model, adjusted_img, width, height)
        except Exception as e:
            print("error : %s"%e)
            return Response("fail", status=400)
    return str(res)

if __name__=="__main__":
    app.run(host="0.0.0.0", port="80", debug=True)

 

index.html

- 작업 폴더에 템플릿 폴더를 만들어 그안에 배치

- (workspace)/template/index.html

<HTML>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
		<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css"
			 integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh"
			 crossorigin="anonymous">

		<title>Handwritten Number Reader</title>
		<style>
			.img{
				height: 250px;
			}

			figure{
				display: inline-block;
				text-align:center;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<div class="jumbotron mt-3">
				<h1>digit reader</h1>
				<a>github repo</a>
				<a href="https://github.com/JeongChanDo/mnist-mlp-app">mnist</a>
				<br>
				<hr class="solid">
				<div id="sampleBox">
					<figure>
						<img class="img" src="./images/2.png">
					</figure>
				</div>
				<br>
				<div id="input img">
					<label for="source">source num img : </label>
					<input type="file" id="source" style="margin-right: 10px; margin-bottom: 10px;">
					<button id="submit" type="submit" class="btn btn-primary btn-lg" style="margin-left: auto;"> run</button>
				</div>
				<div id="resultbox" style="margin-left: auto; margiin-right: auto;">
					<p id="errorbox"></p>
					<p id="result"></p>
				</div>
				<script>
				  document.getElementById("submit").onclick = () => {
				       var formData = new FormData();
				       var source = document.getElementById('source').files[0];

				       formData.append('source', source);

				       fetch(
					   '/image',
					   {
					       method: 'POST',
					       body: formData
					   }
				       )
				       .then(response => {
					   if (response.status == 200) {
					       return response.text();
					   }
					   else {
					       throw Error("Loading image error");
					   }
				       }).then(text => {
					   document.getElementById('result').innerText = text;
				       }).catch(e =>{
					   document.getElementById("errorbox").innerHTML = e;
				       });
				   };
				</script>
			</div>
		</div>
	</body>
</HTML>

 

Dockerfile 수정

FROM tensorflow/tensorflow:latest-gpu

RUN apt-get update
RUN apt-get install -y libgl1-mesa-dev
RUN pip install keras numpy pillow flask

COPY . .

EXPOSE 80
ENTRYPOINT ["python"]
CMD ["server.py"]

 

mnist_mlp.py 수정

from __future__ import print_function

import keras
import numpy as np
from keras.datasets import mnist
from keras.models import Sequential, load_model
from keras.layers import Dense, Dropout
from keras.optimizers import RMSprop
from keras.preprocessing import image

def load_keras_model():
    model = load_model("models")
    return model

def predict_number(model, img, width, height):
    test_img = image.img_to_array(img)
    test_img = test_img.astype("float32")
    test_img = test_img.reshape(width, height)
    test_img /= 255
    test_img = test_img.reshape(1, width * height)
    res = model.predict(test_img, batch_size=1)
    return np.argmax(res)

 

 

도커 이미지 빌드 및 실행

- localhost/healthz로 서버가 잘 살아있는지 확인 가능

docker build -t mnist-mlp-app .
docker run -p 80:80 mnist-mlp-app

 

동작 확인

http://localhost/

에 들어가서 아래의 이미지 업로드

num4.png
0.01MB

 

 

 

 

ainize를 이용한 배포

- ainize.ai/dashboard

 

 

 

 

300x250

+ Recent posts