TensorFlow.js 및 Flask 를 이용한 MobileNet 배포

JavaScriptBeginner
지금 연습하기

소개

이 프로젝트는 TensorFlow.js 를 사용하여 Flask 웹 애플리케이션 내에서 사전 훈련된 MobileNetV2 모델을 배포하는 과정을 안내합니다. MobileNetV2 는 주로 이미지 분류에 사용되는 경량 딥 뉴럴 네트워크입니다. TensorFlow.js 는 머신 러닝 모델을 브라우저에서 직접 실행할 수 있도록 하여 대화형 웹 애플리케이션을 가능하게 합니다. Python 웹 프레임워크인 Flask 는 애플리케이션을 호스팅하는 백엔드 역할을 합니다. 이 프로젝트가 끝나면 MobileNetV2 모델을 사용하여 이미지를 즉시 분류하는 웹 애플리케이션을 실행하게 됩니다.

👀 미리보기

🎯 작업

이 프로젝트에서는 다음을 배우게 됩니다.

  • Keras 에서 TensorFlow.js 호환 형식으로 사전 훈련된 MobileNetV2 모델을 내보내는 방법.
  • 웹 콘텐츠와 모델을 제공하기 위한 간단한 Flask 애플리케이션을 만드는 방법.
  • 분류를 위해 이미지를 업로드하고 표시하는 HTML 페이지를 디자인하는 방법.
  • 브라우저에서 내보낸 모델을 로드하기 위해 TensorFlow.js 를 사용하는 방법.
  • MobileNetV2 의 입력 요구 사항에 맞게 브라우저에서 이미지를 전처리하는 방법.
  • 브라우저에서 모델을 실행하여 이미지를 분류하고 결과를 표시하는 방법.

🏆 성과

이 프로젝트를 완료하면 다음을 수행할 수 있습니다.

  • 사전 훈련된 Keras 모델을 TensorFlow.js 와 함께 사용할 수 있는 형식으로 변환하여 ML 모델을 브라우저에서 실행할 수 있도록 합니다.
  • Flask 애플리케이션을 설정하고 HTML 콘텐츠 및 정적 파일을 제공합니다.
  • 클라이언트 측에서 머신 러닝 작업을 수행하기 위해 TensorFlow.js 를 웹 애플리케이션에 통합합니다.
  • 딥 러닝 모델의 입력 요구 사항과 호환되도록 JavaScript 에서 이미지를 전처리합니다.
  • 브라우저에서 딥 러닝 모델을 사용하여 예측을 수행하고 웹 페이지에 결과를 동적으로 표시합니다.

프로젝트 환경 및 파일 준비

코딩을 시작하기 전에 프로젝트 환경을 올바르게 설정하는 것이 중요합니다. 여기에는 필요한 패키지 설치와 이미 준비된 프로젝트 파일 구조를 이해하는 것이 포함됩니다.

먼저, 초기 프로젝트 파일 구조에 익숙해지십시오. 다음 파일과 폴더가 작업 디렉토리에 이미 제공되어 있습니다.

tree

출력:

.
├── app.py
├── model_convert.py
├── static
│ ├── imagenet_classes.js
│ ├── tfjs.css
│ └── tfjs.js
└── templates
└── tfjs.html

2 directories, 6 files

프로젝트 구조는 여러 핵심 구성 요소로 구성되며, 각 구성 요소는 TensorFlow.js 및 Flask 를 사용하여 MobileNetV2 모델로 이미지 분류를 위한 웹 애플리케이션을 배포하는 데 중요한 역할을 합니다. 다음은 프로젝트 내 각 디렉토리 및 파일에 대한 개요입니다.

  • app.py: Flask 애플리케이션의 주요 Python 파일입니다. Flask 앱을 초기화하고, 웹 페이지에 대한 라우팅을 설정하며, TensorFlow.js 모델 및 웹 콘텐츠를 제공하는 데 필요한 모든 백엔드 로직을 포함합니다.
  • model_convert.py: 이 Python 스크립트는 사전 훈련된 MobileNetV2 모델을 로드하고 TensorFlow.js 와 호환되는 형식으로 변환하는 역할을 합니다. 이 변환은 모델이 웹 브라우저에서 실행될 수 있도록 하는 데 중요합니다.
  • static/: 이 디렉토리는 웹 애플리케이션에 필요한 정적 파일을 저장합니다. 여기에는 다음이 포함됩니다.
    • imagenet_classes.js: ImageNet 클래스를 포함하는 JavaScript 파일입니다. 이 파일은 모델의 숫자 예측을 사람이 읽을 수 있는 클래스 이름에 매핑하는 데 사용됩니다.
    • tfjs.css: 새로운 추가 사항인 이 Cascading Style Sheets (CSS) 파일은 웹 애플리케이션의 사용자 인터페이스 스타일을 지정하는 데 사용됩니다. 레이아웃, 색상 및 글꼴과 같은 애플리케이션의 시각적 측면을 정의하여 더욱 매력적이고 사용자 친화적인 인터페이스를 보장합니다.
    • tfjs.js: 또 다른 새로운 파일인 이 JavaScript 파일은 TensorFlow.js 모델을 로드하고, 이미지를 처리하며, 브라우저 내에서 예측을 실행하는 로직을 포함할 가능성이 높습니다. 이 스크립트는 TensorFlow.js 모델과 관련된 클라이언트 측 작업을 처리하여 애플리케이션의 상호 작용성에 핵심적입니다.
  • templates/: 이 디렉토리는 웹 애플리케이션의 구조와 레이아웃을 정의하는 HTML 파일을 포함합니다. 이 경우 다음이 포함됩니다.
    • tfjs.html: 애플리케이션의 기본 HTML 템플릿인 tfjs.html은 이미지, 예측 결과 및 파일 업로드 버튼과 같은 사용자 상호 작용 요소를 표시하는 데 필요한 마크업을 포함합니다. TensorFlow.js 모델을 통합하여 모델 관련 기능에 tfjs.js 스크립트를 활용하고 스타일 지정을 위해 tfjs.css를 활용합니다.

이 구조는 관심사를 분리하여 프로젝트를 모듈화하고 관리하기 쉽게 설계되었습니다. statictemplates 디렉토리는 Flask 애플리케이션에서 표준이며, 각각 정적 자산과 HTML 템플릿을 구성하는 데 도움이 됩니다. 모델 변환 스크립트 (model_convert.py) 를 주요 애플리케이션 로직 (app.py) 에서 분리하면 코드의 모듈성과 유지 관리성이 향상됩니다.

다음으로, 필요한 패키지를 설치합니다.

## Install the required Python packages
pip install tensorflow==2.14.0 tensorflowjs==4.17.0 flask==3.0.2 flask-cors==4.0.0

패키지에는 머신 러닝 모델을 위한 TensorFlow, 웹 환경에서 사용할 모델을 변환하기 위한 TensorFlow.js, 웹 서버를 생성하기 위한 Flask, 웹 애플리케이션에서 흔히 사용되는 교차 출처 요청을 처리하기 위한 Flask-CORS 가 포함됩니다.

사전 훈련된 MobileNetV2 모델을 TensorFlow.js 형식으로 내보내기

브라우저에서 MobileNetV2 모델을 사용하려면 먼저 Keras 에서 TensorFlow.js 가 이해할 수 있는 형식으로 내보내야 합니다.

## Complete the model_convert.py

## Exporting MobileNetV2 model
import tensorflowjs as tfjs
from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2

## Load the pre-trained MobileNetV2 model
model = MobileNetV2(weights='imagenet')

## Convert and save the model in TensorFlow.js format
tfjs.converters.save_keras_model(model, 'static/model/')

이 단계에서는 TensorFlow 및 TensorFlow.js 라이브러리를 활용하여 사전 훈련된 MobileNetV2 모델을 로드하고 TensorFlow.js 와 호환되는 형식으로 변환합니다.

MobileNetV2 는 효율성과 비교적 작은 크기로 인해 선택되었으며, 웹 배포에 적합합니다. 이 변환은 Python 기반 TensorFlow 에서 사용되는 원래 모델 형식이 웹 환경에서 직접 사용할 수 없기 때문에 필요합니다. tfjs.converters.save_keras_model 함수는 Keras 모델을 가져와 TensorFlow.js 가 웹 애플리케이션에서 나중에 쉽게 로드할 수 있도록 구조화된 디렉토리에 저장합니다.

그런 다음 다음을 실행할 수 있습니다.

python model_convert.py

변환된 모델은 static/model/ 폴더에 저장됩니다.

ls static/model

## group1-shard1of4.bin  group1-shard2of4.bin  group1-shard3of4.bin  group1-shard4of4.bin  model.json

이 프로세스에는 모델의 가중치와 아키텍처를 일련의 shard 파일과 model.json 파일에 각각 저장하는 것이 포함됩니다.

Flask 애플리케이션 생성

이제 웹 페이지와 TensorFlow.js 모델을 제공하기 위해 간단한 Flask 애플리케이션을 설정합니다.

## Complete the app.py

## Setting up the Flask application
from flask import Flask, render_template
from flask_cors import CORS

app = Flask(__name__)
cors = CORS(app)  ## Enable Cross-Origin Resource Sharing

@app.route("/")
def hello():
    ## Serve the HTML page
    return render_template('tfjs.html')

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

이 단계에서는 기본적인 Flask 웹 서버를 설정합니다. Flask 는 Python 으로 작성된 마이크로 웹 프레임워크로, 단순성과 사용 편의성으로 유명합니다.

먼저 Flask 와 CORS (Cross-Origin Resource Sharing) 를 해당 라이브러리에서 가져오는 것으로 시작합니다. CORS 는 서로 다른 도메인에서 리소스를 요청하는 웹 애플리케이션에 필수적이며, 웹 앱이 Flask 서버에 안전하게 요청을 보낼 수 있도록 보장합니다.

클라이언트 측 TensorFlow.js 코드를 포함할 HTML 페이지 (tfjs.html) 를 제공하는 간단한 경로 ("/") 를 정의합니다. Flask 애플리케이션은 로컬 머신 (host='0.0.0.0') 에서 실행되도록 구성되고 포트 8080 에서 수신 대기합니다. debug=True 설정은 개발 중에 자세한 오류 메시지를 제공하고 코드 변경 사항이 감지되면 서버를 자동으로 다시 로드하므로 유용합니다.

이제 Flask 웹 애플리케이션을 실행할 수 있습니다.

python app.py
## * Serving Flask app 'app'
## * Debug mode: on
## WARNING: This is a development server. Do not use it in a production ## deployment. Use a production WSGI server instead.
## * Running on all addresses (0.0.0.0)
## * Running on http://127.0.0.1:8080
## * Running on http://172.18.0.7:8080
## Press CTRL+C to quit

HTML 구조 준비

이제 templates/tfjs.html에서 애플리케이션의 HTML 구조를 만들어야 합니다. 여기에는 이미지 업로드, 미리 보기 및 예측 결과 표시를 위한 레이아웃이 포함됩니다.

<!-- HTML structure for the Image Prediction application -->
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Image Prediction</title>
    <link
      href="https://cdn.jsdelivr.net/npm/tailwindcss@2.0.2/dist/tailwind.min.css"
      rel="stylesheet"
    />
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
    <link rel="stylesheet" href="static/tfjs.css" />
  </head>
  <body class="flex flex-col items-center justify-center min-h-screen">
    <div class="card bg-white p-6 rounded-lg max-w-sm">
      <h1 class="text-xl font-semibold mb-4 text-center">Image Prediction</h1>
      <div class="flex flex-col items-center">
        <label
          for="imageUpload"
          class="button-custom cursor-pointer mb-4 flex items-center justify-center"
        >
          <span>Upload Image</span>
          <input
            type="file"
            id="imageUpload"
            class="file-input"
            accept="image/*"
          />
        </label>
        <div
          id="imagePreviewContainer"
          class="mb-4 w-56 h-56 border border-dashed border-gray-300 flex items-center justify-center"
        >
          <img
            id="imagePreview"
            class="max-w-full max-h-full"
            style="display: none"
          />
        </div>
        <h5 id="output" class="text-md text-gray-700">
          Upload an image to start prediction
        </h5>
        <script type="module" src="static/tfjs.js"></script>
      </div>
    </div>
  </body>
</html>

이 단계에서는 HTML 을 사용하여 웹 애플리케이션의 기본 구조를 만듭니다. 문서 유형을 HTML 로 정의하고 언어 속성을 영어로 설정합니다.

head 섹션에는 반응형 디자인을 위한 문자 집합 및 뷰포트 설정과 같은 메타데이터가 포함되어 있습니다. 또한 Tailwind CSS 라이브러리에 연결하여 애플리케이션 스타일 지정을 위한 유틸리티 클래스를 활용합니다. body 섹션에는 애플리케이션 콘텐츠의 컨테이너 역할을 하는 card 클래스가 있는 div 요소가 포함되어 있습니다.

이 컨테이너 내부에는 애플리케이션 제목을 위한 h1 태그, 이미지 업로드 버튼을 위한 label 요소 (Tailwind CSS 및 사용자 정의 클래스를 사용하여 버튼처럼 스타일 지정됨) 및 이미지 미리 보기를 위한 컨테이너 역할을 하는 div 요소가 있습니다. file 유형의 input 요소는 숨겨져 있으며 레이블을 클릭하면 트리거되어 사용자가 이미지를 업로드할 수 있습니다. idimagePreviewContainerdiv 요소는 업로드된 이미지를 표시하고, h5 태그는 사용자에게 메시지를 표시하는 데 사용됩니다.

스타일 추가

이 단계에서는 static/tfjs.css에서 레이아웃 및 미적 감각을 위해 Tailwind CSS 를 사용하여 기본 CSS 스타일을 추가하고, 애플리케이션에 대한 몇 가지 사용자 정의 스타일을 추가합니다.

body {
  background-color: #f0f2f5;
}
.card {
  box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}
.button-custom {
  background-color: #4f46e5; /* Indigo 600 */
  color: white;
  padding: 0.5rem 1.5rem;
  border-radius: 0.375rem; /* rounded-md */
  transition: background-color 0.2s;
}
.button-custom:hover {
  background-color: #4338ca; /* Indigo 700 */
}
.file-input {
  opacity: 0;
  position: absolute;
  z-index: -1;
}

이 단계에서는 웹 애플리케이션의 모양을 향상시키기 위해 사용자 정의 CSS 스타일을 추가합니다.

본문의 배경색을 중립적인 배경을 위해 밝은 회색으로 설정합니다. card 클래스는 컨테이너에 카드와 같은 효과를 만들기 위해 그림자를 추가합니다. button-custom 클래스는 업로드 버튼에 인디고 배경색, 흰색 텍스트, 패딩 및 둥근 모서리를 스타일링합니다.

또한 사용자가 마우스를 올렸을 때 버튼의 배경색을 약간 변경하여 사용자에게 시각적 피드백을 제공하는 호버 효과도 포함합니다. file-input 클래스는 실제 파일 입력 요소를 숨기는 데 사용되어 사용자 정의 스타일의 레이블을 파일 업로드를 위한 주요 대화형 요소로 만듭니다.

TensorFlow 모델 로드

남은 단계에서는 templates/tfjs.js 파일을 완성합니다.

이제 TensorFlow.js 를 프로젝트에 추가한 다음, TensorFlow 모델을 로드하는 JavaScript 코드를 작성합니다. 예측을 수행하기 전에 모델 로드를 기다리기 위해 async 함수를 사용합니다.

import { IMAGENET_CLASSES } from "./imagenet_classes.js";

const outputDiv = document.getElementById("output");
let model;

async function loadModel() {
  try {
    outputDiv.textContent = "Loading TF Model...";
    model = await tf.loadLayersModel(
      "https://****.labex.io/static/model/model.json"
    ); // Update URL
    outputDiv.textContent = "TF Model Loaded.";
  } catch (error) {
    outputDiv.textContent = `Error loading model: ${error}`;
  }
}

loadModel();

참고: tf.loadLayersModel의 URL 을 현재 환경의 URL 로 바꿔야 합니다. Web 8080 탭으로 전환하여 찾을 수 있습니다.

TensorFlow model loading diagram

이 단계에서는 HTML 문서에 스크립트 태그를 포함하여 TensorFlow.js 를 프로젝트에 추가하는 작업이 포함됩니다.

그런 다음, 사전 훈련된 TensorFlow 모델을 비동기적으로 로드하는 JavaScript 코드를 작성합니다. tf.loadLayersModel 함수를 사용하여 모델의 JSON 파일에 대한 URL 을 제공합니다. 이 함수는 로드된 모델로 확인되는 promise 를 반환합니다. outputDiv의 텍스트 내용을 업데이트하여 사용자에게 모델 로드 상태를 알립니다. 모델이 성공적으로 로드되면 "TF Model Loaded."를 표시합니다.

그렇지 않으면 오류를 포착하고 사용자에게 오류 메시지를 표시합니다. 이 단계는 애플리케이션이 예측을 수행할 수 있도록 하는 데 중요합니다. 모델이 로드되어 이미지 처리를 시작하기 전에 준비되어야 하기 때문입니다.

이미지 업로드 및 미리보기 처리

이 단계에서는 사용자가 이미지를 업로드하고 예측 전에 미리 보기를 볼 수 있는 기능을 생성하는 작업이 포함됩니다. 업로드된 파일을 읽고 표시하기 위해 FileReader 를 사용합니다.

// Continue in static/tfjs.js
const imageUpload = document.getElementById("imageUpload");
const imagePreview = document.getElementById("imagePreview");

imageUpload.addEventListener("change", async (e) => {
  const file = e.target.files[0];
  if (file) {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.src = e.target.result;
      img.onload = async () => {
        imagePreview.src = img.src;
        imagePreview.style.display = "block";
        const processedImage = await preprocessImage(img);
        makePrediction(processedImage);
      };
    };
    reader.readAsDataURL(file);
  }
});

이 단계에서는 이미지 업로드 입력에 대한 이벤트 리스너를 설정하는 작업이 포함됩니다.

사용자가 파일을 선택하면 FileReader를 사용하여 파일을 Data URL 로 읽습니다. 그런 다음 Image 객체를 생성하고 해당 src 속성을 FileReader의 결과로 설정하여 이미지를 브라우저에 효과적으로 로드합니다. 이미지가 로드되면 imagePreviewsrc 속성을 이미지의 src로 설정하고 imagePreview 요소를 표시하여 imagePreview 컨테이너 내에 표시합니다.

그런 다음 이미지는 모델에 의해 전처리 및 예측됩니다. 이러한 함수는 이후 단계에서 완성할 것입니다.

예측을 위한 이미지 전처리

예측을 수행하기 전에 업로드된 이미지를 모델의 입력 요구 사항에 맞게 전처리해야 합니다.

// Continue in static/tfjs.js
async function preprocessImage(imageElement) {
  try {
    let img = tf.browser.fromPixels(imageElement).toFloat();
    img = tf.image.resizeBilinear(img, [224, 224]);
    const offset = tf.scalar(127.5);
    const normalized = img.sub(offset).div(offset);
    const batched = normalized.reshape([1, 224, 224, 3]);
    return batched;
  } catch (error) {
    outputDiv.textContent = `Error in model prediction: ${error}`;
  }
}

예측을 수행하기 전에 TensorFlow 모델에서 예상하는 입력 형식에 맞게 업로드된 이미지를 전처리해야 합니다. 이 전처리에는 이미지 크기를 필요한 치수 (이 경우 224x224 픽셀) 로 조정하고 픽셀 값을 정규화하는 작업이 포함됩니다.

TensorFlow.js 연산인 tf.browser.fromPixels를 사용하여 이미지를 텐서로 변환하고, tf.image.resizeBilinear를 사용하여 크기를 조정하며, 산술 연산을 사용하여 픽셀 값을 정규화합니다. 그런 다음 전처리된 이미지는 하나의 배치로 재구성되어 (모델의 예상 입력 모양에 맞게) 예측 준비가 완료됩니다.

예측 실행

이미지가 전처리되면 예측을 수행할 준비가 됩니다. makePrediction 함수는 처리된 이미지를 입력으로 받아 모델을 통해 전달하고, 출력을 해석하여 가장 가능성이 높은 클래스 레이블을 결정합니다.

// Continue in static/tfjs.js
async function makePrediction(processedImage) {
  try {
    const prediction = model.predict(processedImage);
    const highestPredictionIndex = await tf.argMax(prediction, 1).data();
    const label = IMAGENET_CLASSES[highestPredictionIndex];
    outputDiv.textContent = `Prediction: ${label}`;
  } catch (error) {
    outputDiv.textContent = `Error making prediction: ${error}`;
  }
}

이 단계에서는 model.predict(processedImage) 함수를 사용하여 전처리된 이미지를 TensorFlow 모델에 입력합니다. tf.argMax(prediction, 1).data() 함수는 예측 배열에서 가장 높은 값의 인덱스를 찾아 이미지에 대한 가장 가능성이 높은 클래스 레이블에 해당합니다. 그런 다음 이 레이블이 사용자에게 표시됩니다.

"Web 8080" 탭으로 전환하고 웹 페이지를 다시 로드하여 다음 효과를 확인하십시오.

요약

이 프로젝트에서는 TensorFlow.js 를 사용하여 Flask 웹 애플리케이션에서 사전 훈련된 MobileNetV2 모델을 사용하는 방법을 배웠습니다. 먼저 필요한 종속성을 설치했습니다. 그런 다음 MobileNetV2 모델을 TensorFlow.js 호환 형식으로 내보내고 웹 페이지를 제공하기 위해 Flask 애플리케이션을 설정했습니다. 마지막으로, 브라우저에서 MobileNetV2 모델로 이미지를 분류하기 위해 TensorFlow.js 를 사용하는 HTML 페이지를 만들었습니다. 이러한 단계를 따르면 실시간 이미지 분류를 위해 딥 러닝을 사용하는 웹 애플리케이션을 만들었습니다.

이 프로젝트는 기존 웹 기술과 고급 머신 러닝 모델을 결합하여 대화형 및 지능형 웹 애플리케이션을 만드는 강력함을 보여줍니다. 다른 이미지를 업로드하는 기능, 사용자 인터페이스 개선 또는 더 복잡한 모델을 다른 작업에 통합하는 기능과 같은 더 많은 기능을 추가하여 이 프로젝트를 확장할 수 있습니다.

✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습✨ 솔루션 확인 및 연습