ETC

🎓 졸업과제 - Flask Server, Mock Tensorflow Model

HaningYa 2020. 8. 7. 15:40
728x90

목표

  1. 질문을 입력받을 수 있는 웹페이지에서 질문을 입력한다.
  2. 해당 질문을 일단 서버로 보내 모델에서 prediction 했다고 가정하고 응답을 웹에 표시한다.

*파이썬 프로젝트에 Flask 를 추가 했었고 templates 패키지에 필요한 HTML 코드를 작성 해놓은 상태이다.

HTML 코드

더보기
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Table</title>

    <script type="text/javascript">
	window.onload = function() {
	    //제출하기 clickListener
		document.getElementById("submit").onclick = function() { // on click
		    loadFileAsText()
		}
	}
	//HTML File -> show table
	function loadFileAsText(){
        var fileToLoad = document.getElementById("fileToLoad").files[0];
        var fileReader = new FileReader();
        fileReader.onload = function(fileLoadedEvent){
            //불러온 텍스트 파일
            var textFromFileLoaded = fileLoadedEvent.target.result;
            //html 형식
            var html = new DOMParser().parseFromString(textFromFileLoaded, "text/html");
            //table 추출
            var table = html.querySelector("table");
            //원문 html 문자열
            var htmlString = html.documentElement.outerHTML
            //테이블 표시
            document.getElementById("disp").appendChild(table);
            //원문 표시
            document.getElementById("html").innerHTML = htmlString

<!--            post_to_url('/handle_data',html,POST)-->

        };
        fileReader.readAsText(fileToLoad, "UTF-8");
    }


    </script>

</head>
<body>
<hr>
<h1>Table</h1>
<!--<form action="/handle_data" method="POST">-->
    <input type="file" id="file" accept="html/*" name="table"/>
    <button id="submit">제출하기</button>
<!--</form>-->

<br>
<br>
<hr>
<div id="disp">표 출력</div>
<h2>Question</h2>
  <form action="/post" method="post">
        <p>질문입력해주세요 : <input type="text" name="test"></p>
        <input type="submit" value="질문하기">
    </form>
<br>
<br>
<hr>
<h2>Answer</h2>
<div id="html">원문 출력</div>

</body>
</html>

 

Flask 코드

더보기
from flask import Flask , render_template, request

app = Flask(__name__)


@app.route('/')
def index():

    return render_template('tableView.html')

@app.route('/handle_data',methods = ['POST'])
def handle_data():
    projectpath = request.form['table']
    print(projectpath)
    return projectpath

@app.route('/post', methods=['POST'])
def post():
    value = request.form['test']
    print(value)
    return value


if __name__ == '__main__':
    app.run(debug = True)

Flask 실행시 로컬호스트로 가면 아래 페이지가 뜬다.

여기서 질문입력을 받으면 서버에 출력을 먼저 해보겠다.

단순 웹페이지

입력한 질문을 받을 수 있다.

이까지는 해놨었다.

 

그런데 나는 웹 페이지 전체를 다시 로드하지 않고 모델에서 prediction 후에 결과값만 기존 페이지에 update 해주고 싶다.

이상태로는 return value 라서 텍스트만 띡 하고 표시된다.

음 웹 하나도 모르겠는데

 

Jinja — Jinja Documentation (2.11.x)

 

jinja.palletsprojects.com

일단 python 코드에 있는 데이터를 html 로 표시해 줄땐 

@app.route('/')
def index():
    title = "이것은 타이틀이다."
    return render_template('tableView.html', title=title)
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>

이런식으로 하면 title 웹페이지에 표시된다.

이걸 기본으로 mock 웹페이지를 만들어 보겠다.



텐서플로우 예제 모델을 하나 들고와 붙이자

[참고한 글]

 

[GCP] Flask로 TF 2.0 MNIST 모델 서빙하기

우선 TensorFlow 2.0을 설치하자. 머신에 직접 설치하거나 도커를 다운받아 사용, 혹은 구글 colab을 활용( https://www.tensorflow.org/install)하면 되는데, TensorFlow에서 권장하는대로 머신에…

medium.com

MNIST 모델 만드는 코드

더보기
## 출처: https://medium.com/@kiseon_twt/flask%EB%A1%9C-tf-2-0-mnist-%EB%AA%A8%EB%8D%B8-%EC%84%9C%EB%B9%99%ED%95%98%EA%B8%B0-6c9fb7cf3322

import tensorflow as tf
import numpy as np

# 학습 데이터 load
((train_data, train_label), (eval_data, eval_label)) = tf.keras.datasets.mnist.load_data()
# data를 정규화하여 28x28로 reshape
train_data = train_data / np.float32(255)
train_data = train_data.reshape(60000, 28, 28, 1)
train_data.shape
eval_data = eval_data / np.float32(255)
eval_data = eval_data.reshape(10000, 28, 28, 1)
eval_data.shape
from tensorflow.keras import models

# CNN으로 모델 생성
model = models.Sequential()
model.add(tf.keras.layers.Conv2D(32, (5, 5), padding='same', activation='relu', input_shape=(28, 28, 1)))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu'))
model.add(tf.keras.layers.MaxPooling2D((2, 2)))
model.add(tf.keras.layers.Conv2D(64, (5, 5), activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(64, activation='relu'))
model.add(tf.keras.layers.Dense(10, activation='softmax'))
model.summary()
# graph를 생성하고 training
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(train_data, train_label, epochs=5)
test_loss, test_acc = model.evaluate(eval_data, eval_label, verbose=2)
test_acc
# save the model. TF 2.0에서는 experimental 대신 save_model만 하면됨
model_dir = "/tmp/tfkeras_mnist"
tf.keras.experimental.export_saved_model(model, model_dir)

 

prediction 함수 부분

더보기
# 출처: https://medium.com/@kiseon_twt/flask%EB%A1%9C-tf-2-0-mnist-%EB%AA%A8%EB%8D%B8-%EC%84%9C%EB%B9%99%ED%95%98%EA%B8%B0-6c9fb7cf3322
def prediction(question):
    # 데이터를 읽어들이고
    ((train_data, train_label), (eval_data, eval_label)) = tf.keras.datasets.mnist.load_data()
    eval_data = eval_data / np.float32(255)
    eval_data = eval_data.reshape(10000, 28, 28, 1)
    # 저장해 두었던 모델을 읽어들인 후
    model_dir = "/tmp/tfkeras_mnist"
    new_model = tf.keras.experimental.load_from_saved_model(model_dir)
    new_model.summary()
    # 그래프를 생성하고
    new_model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

    answer = '예시 정답 텍스트'
    random_idx = np.random.choice(eval_data.shape[0])
    test_data = eval_data[random_idx].reshape(1, 28, 28, 1)
    res = new_model.predict(test_data)
    answer = "predict: {}, original: {}".format(np.argmax(res), eval_label[random_idx])
    return answer

 

아무 질문이나 넣어서 제출하기 POST 누르면

MNIST Prediction 이 수행되고 결과값이 웹페이지에 리턴된다.

나중에 테이블 QA모델이 만들어 지면 모델만 바꿔치면 될 것 같다.

 

앞으로 할일

  • 질의할 테이블 선택후 보여주는 화면 구성
  • QA 에 대한 어텐션 테이블에 시각화
  • BERT, TAPAS 코드분석
728x90