3 분 소요


flask에 ML 모델 구현

sklearn의 모델 저장, 불러오기

In [1]:
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
import pickle
In [2]:
iris = load_iris()
X = iris.data
y = iris.target
dt_model = DecisionTreeClassifier(max_depth=3)
dt_model.fit(X, y)
Out [2]:
DecisionTreeClassifier(max_depth=3)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
In [3]:
iris.target_names
Out [3]:
array(['setosa', 'versicolor', 'virginica'], dtype='<U10')
In [4]:
test = [X[10], X[60], X[120]]
test
Out [4]:
[array([5.4, 3.7, 1.5, 0.2]),
 array([5. , 2. , 3.5, 1. ]),
 array([6.9, 3.2, 5.7, 2.3])]
In [5]:
dt_model.predict(test)
Out [5]:
array([0, 1, 2])
In [6]:
with open("pickled_model_iris.bin", "wb") as f:
    pickle.dump(dt_model, f)

Kernel Restart

In [1]:
import pickle
In [2]:
with open("pickled_model_iris.bin", "rb") as f:
    dt_model_loaded = pickle.load(f)
In [3]:
dt_model_loaded.predict([[6.9, 3.2, 5.7, 2.3]])
Out [3]:
array([2])

tensorflow의 모델 저장, 불러오기

In [4]:
import tensorflow as tf
In [5]:
fashion_mnist = tf.keras.datasets.fashion_mnist
(X_train, y_train), (X_test, y_test) = fashion_mnist.load_data()
X_train = X_train[:5000, :]
y_train = y_train[:5000]
X_test = X_test[:1000, :]
y_test = y_test[:1000]

X_train = X_train/255.0
X_test = X_test/255.0

model = tf.keras.Sequential([
    tf.keras.layers.Conv2D(32, (3, 3), input_shape=(28, 28, 1), padding='same'),
    tf.keras.layers.MaxPooling2D((2, 2)),
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['acc'])

model.fit(X_train, y_train, validation_split=0.2, epochs=10)
Out [5]:
Epoch 1/10
125/125 [==============================] - 4s 22ms/step - loss: 0.8404 - acc: 0.7145 - val_loss: 0.4930 - val_acc: 0.8210
Epoch 2/10
125/125 [==============================] - 2s 17ms/step - loss: 0.5320 - acc: 0.8173 - val_loss: 0.4192 - val_acc: 0.8590
Epoch 3/10
125/125 [==============================] - 2s 17ms/step - loss: 0.4681 - acc: 0.8385 - val_loss: 0.3925 - val_acc: 0.8650
Epoch 4/10
125/125 [==============================] - 2s 17ms/step - loss: 0.4193 - acc: 0.8590 - val_loss: 0.3503 - val_acc: 0.8780
Epoch 5/10
125/125 [==============================] - 2s 17ms/step - loss: 0.3918 - acc: 0.8680 - val_loss: 0.3398 - val_acc: 0.8840
Epoch 6/10
125/125 [==============================] - 2s 17ms/step - loss: 0.3695 - acc: 0.8750 - val_loss: 0.3502 - val_acc: 0.8760
Epoch 7/10
125/125 [==============================] - 2s 17ms/step - loss: 0.3407 - acc: 0.8845 - val_loss: 0.3329 - val_acc: 0.8810
Epoch 8/10
125/125 [==============================] - 2s 17ms/step - loss: 0.3207 - acc: 0.8955 - val_loss: 0.3354 - val_acc: 0.8800
Epoch 9/10
125/125 [==============================] - 2s 17ms/step - loss: 0.2960 - acc: 0.9030 - val_loss: 0.3151 - val_acc: 0.8850
Epoch 10/10
125/125 [==============================] - 2s 17ms/step - loss: 0.2807 - acc: 0.9065 - val_loss: 0.3187 - val_acc: 0.8770

<keras.callbacks.History at 0x22cb0b333a0>
In [6]:
model.evaluate(X_test, y_test)
Out [6]:
32/32 [==============================] - 0s 8ms/step - loss: 0.4271 - acc: 0.8590

[0.42713961005210876, 0.859000027179718]
In [7]:
model.save("my_fashion_model.h5")
In [8]:
model_loaded = tf.keras.models.load_model("my_fashion_model.h5")
In [9]:
model_loaded.evaluate(X_test, y_test)
Out [9]:
32/32 [==============================] - 1s 8ms/step - loss: 0.4271 - acc: 0.8590

[0.42713961005210876, 0.859000027179718]

모델을 업데이트! 여러서버가 필요하다.

flask 서버

In [10]:
#!pip install flask
In [11]:
from flask import Flask
In [None]:
app = Flask(__name__)

@app.route("/") # 데코레이터
def anyname():
    return "안녕하세요."

@app.route("/app1")
def app1():
    return "app1입니다"

@app.route("/app2")
def app2():
    return "app2입니다"

app.run(host="localhost", port=5000)

img

페이지 하나를 app 하나에 연결
유저상대 UI는 짜기 어렵다.

flask with ml_model

In [None]:
from flask import Flask
import pickle

with open("pickled_model_iris.bin", "rb") as f:
    dt_model_loaded = pickle.load(f)

app = Flask(__name__)

@app.route("/") # 데코레이터
def anyname():
    return "안녕하세요."

@app.route("/MLtest")
def app2():
    label_name = ['setosa', 'versicolor', 'virginica']
    idx = dt_model_loaded.predict([[6.9, 3.2, 5.7, 2.3]])
    return f"꽃은 {label_name[int(idx)]}입니다."

app.run(host="localhost", port=5000)

img

변수의 사용

In [None]:
from flask import Flask

my_count = 0

app = Flask(__name__)

@app.route("/")
def anyname():
    global my_count
    my_count+= 1
    
    return f"""
    <html>
    <head>
        <title>안녕하세요.</title>
    </head>
    <body>
        <p>{my_count} 번째 방문입니다.</p>
    </body>
    </html>
    """

app.run(host="localhost", port=5000)

img

controller와 view 분리

In [None]:
from flask import Flask

my_count = 0

# view
def build_input_page(my_count):
    page = f"""
    <html>
    <head>
        <title>안녕하세요.</title>
    </head>
    <body>
        <p>{my_count} 번째 방문입니다.</p>
    </body>
    </html>
    """
    return page

app = Flask(__name__)

# controller
@app.route("/input")
def app_input():
    global my_count
    my_count+= 1
    page = build_input_page(my_count)
    return page

app.run(host="localhost", port=5000)

img

=> MVC 패턴

머신러닝 모델 제공 웹페이지

In [None]:
from flask import Flask, request
import pickle

with open("pickled_model_iris.bin", "rb") as f:
    dt_model_loaded = pickle.load(f)

def build_home_page():
    page = f"""
    <html>
    <body>
    <h1>Iris 분류기</h1>
    <p>Iris 분류 시스템 입니다.</p>
    <a href="/input">새로 입고된 꽃의 치수 입력하기</a>
    </body>
    </html>
    """
    return page

def build_input_page():
    page = f"""
    <html>
    <body>
    꽃 측정원 님 안녕하세요<br>
    지금 입고된 꽃의 치수를 cm 단위로 입력해 주세요<br>
    저희 [나만돈벌어tm] 회사의 머신러닝 분류기가 꽃의 종류를 판단해 줍니다<br>
    그러면 그 결과에 맞추어 창고에 넣어 주세요<br>
    <form action="/result", method="get">
    <input type="text" placeholder="꽃받침 길이" name="sepal_length"></input>cm<br>
    <input type="text" placeholder="꽃받침 너비" name="sepal_width"></input>cm<br>
    <input type="text" placeholder="꽃잎 길이" name="petal_length"></input>cm<br>
    <input type="text" placeholder="꽃잎 너비" name="petal_width"></input>cm<br>
    <input type="submit"></input><br>
    </form>
    
    </body>
    </html>
    """
    return page

def build_result_page():
    sepal_length = request.args.get("sepal_length")
    sepal_width = request.args.get("sepal_width")
    petal_length = request.args.get("petal_length")
    petal_width = request.args.get("petal_width")
    values = [sepal_length, sepal_width, petal_length, petal_width]
    values = list(map(float, values))
    
    global dt_model_loaded
        
    res = dt_model_loaded.predict([values])
    label_name = ['setosa', 'versicolor', 'virginica']
    
    page = f"""
    수신결과: {sepal_length}, {sepal_width}, {petal_length}, {petal_width}<br>
    판단결과: 꽃은 {label_name[int(res)]}입니다. 창고에 넣어주세요.<br>    
    <a href="/input">다른 꽃의 치수 입력하기</a>
    """
    return page

app = Flask(__name__)

@app.route("/")
def home():
    page = build_home_page()
    return page

@app.route("/input")
def app_input():
    page = build_input_page()
    return page

@app.route("/result", methods=["POST", "GET"])
def app_result():
    page = build_result_page()
    return page

app.run(host="localhost", port=5000)

img

img

img

템플릿

In [None]:
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("flask_index.html", var1="이불밖은", var2="위험해요") # jinja 언어

app.run(host="localhost", port=5000)

flask_index.html

<html>
    <head>
        <link rel="stylesheet"
        href="{ {url_for('static', filename='test.css')}}">
    </head>
    <body>
        안녕하세요  
    </body>
</html>

test.css

body{background-color: burlywood;}

img

  • template: html 파일들을 모아둔다.
  • static: 그림, 음악, js, css 파일들을 모아둔다. => 귀찮으니 flask는 기능구현으로만 하자. (동시접속이 많다면 java로)
  • python 서버는 java와 다르게 security기능이 없다. 동시접속이 어렵다.

댓글남기기