WebAssembly 백엔드에서 사용할 수 있는 Tensorflow.js 🔥

Tensorflow.js은 브라우저 또는 Node.js에서 기계 학습을 수행할 수 있게 해주는 라이브러리입니다. GPU 또는 CPU를 사용하여 교육 및 계산을 수행하지만 최근 팀은 훌륭한 작업을 수행하고 예측을 더 빠르게 수행할 수 있도록 WebAssembly 백엔드를 생태계로 가져왔습니다. 이제 더 이상 고민하지 않고 이 위대함에 대해 자세히 살펴보겠습니다.

대본



주어진 이미지에서 객체 감지를 수행한다고 가정해 봅시다. 이를 위해 여러 모델을 사용할 수 있지만 지금은 MobileNet 에 집중하겠습니다.

소포를 사용하여 앱을 설정합니다.

WASM 백엔드 없이 설정



패키지



아래 설정이 포함된 package.json 파일이 필요합니다.

{
  "name": "wasm-parcel",
  "version": "1.0.0",
  "description": "Sample parcel app that uses the WASM backend",
  "scripts": {
    "watch": "parcel index.html --open",
    "build": "parcel build index.html"
  },
  "dependencies": {
    "@tensorflow/tfjs": "^1.4.0"
  },
  "browserslist": [
    "defaults"
  ],
  "devDependencies": {
    "@babel/core": "7.7.5",
    "@babel/plugin-transform-runtime": "^7.7.6",
    "@babel/preset-env": "^7.7.6",
    "parcel-bundler": "^1.12.4",
    "parcel-plugin-static-files-copy": "^2.2.1"
  },
  "keywords": []
}


HTML



Tensorflow.js에서 평소처럼 앱을 설정해 보겠습니다. 상태를 표시하기 위해 div를 추가하고 이미지 태그를 포함하는 또 다른 div를 추가해야 합니다.

<div class="tfjs-example-container">
  <section class="title-area">
    <h1>TensorFlow.js running on WebAssembly backend</h1>
  </section>

  <section>
    <p class="section-head">Status</p>
    <div id="status"></div>
  </section>

  <section>
    <p class="section-head">Image used</p>

    <img id="img" src="./img/piano.jpg" width="224px" />
  </section>
</div>


본문 닫기 태그 앞에 JavaScript 파일을 추가해 보겠습니다.

<script src="index.js"></script>


HTML은 전체적으로 다음과 같아야 합니다.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello!</title>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <div class="tfjs-example-container">
      <section class="title-area">
        <h1>TensorFlow.js running on WebAssembly backend</h1>
      </section>

      <section>
        <p class="section-head">Status</p>
        <div id="status"></div>
      </section>

      <section>
        <p class="section-head">Image used</p>

        <img id="img" src="./img/piano.jpg" width="224px" />
      </section>

      <script src="index.js"></script>
    </div>
  </body>
</html>


CSS



앱을 실행할 때 못생긴 앱이 되지 않도록 기본 스타일을 추가해 보겠습니다. 우리는 여기서 멋진 일을 하고 있으며 멋지게 보일 가치가 있습니다 😉:

/* CSS files add styling rules to your content */

body {
  font-family: helvetica, arial, sans-serif;
  margin: 2em;
}

p {
  max-width: 960px;
  line-height: 1.6em;
}

p.section-head {
  font-variant: small-caps;
  text-transform: uppercase;
  letter-spacing: 0.17em;
  line-height: 1.2em;
  font-weight: 500;
  margin-top: 2em;
  margin-bottom: 1em;
  border-left: 2px solid #ef6c00;
  padding-left: 24px;
  margin-left: -24px;
  color: #818181;
}



자바스크립트



코드에서 두 가지 주요 작업을 수행하고, 모델을 로드하고, 예측에 사용해야 합니다. 먼저 모델을 로드해 보겠습니다.

import * as tf from "@tensorflow/tfjs";

let model = await tf.loadGraphModel(
  "https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/2",
  { fromTFHub: true }
);


그리고 이미지 태그에 대한 참조를 얻고 Tensorflow.js의 browser.fromPixel 메서드를 사용하여 이미지를 로드하고 정규화합니다. 마지막으로 모델의 예측 방법에 입력합니다.

const imgElement = document.getElementById("img");

let img = tf.browser
    .fromPixels(imgElement)
    .resizeBilinear([224, 224])
    .expandDims(0)
    .toFloat();

const prediction = model.predict(img);


두 접근 방식 간의 타이밍을 비교하고 싶기 때문에 메서드에 몇 가지 타이머를 추가하고 작업에 걸리는 시간을 측정해 보겠습니다. 전체적으로 JavaScript 파일은 다음과 같아야 합니다.

import * as tf from "@tensorflow/tfjs";

function status(text) {
  document.getElementById("status").textContent = text;
}

async function main() {

  let model = await tf.loadGraphModel(
    "https://tfhub.dev/google/imagenet/mobilenet_v2_100_224/classification/2",
    { fromTFHub: true }
  );

  const startTime1 = performance.now();  

  const imgElement = document.getElementById("img");
  status("Model loaded!");

  let img = tf.browser
    .fromPixels(imgElement)
    .resizeBilinear([224, 224])
    .expandDims(0)
    .toFloat();

  let startTime2 = performance.now();

  const logits = model.predict(img);

  const totalTime1 = performance.now() - startTime1;
  const totalTime2 = performance.now() - startTime2;
  status(`Done in ${Math.floor(totalTime1)} ms ` +
      `(not including preprocessing: ${Math.floor(totalTime2)} ms)`);

  const values = await logits.data();
  console.log(values);  
}

document.addEventListener("DOMContentLoaded", main);


.babelrc



babel 플러그인을 제대로 설정하지 않으면 아래와 같은 오류가 발생합니다.

❌ Uncaught ReferenceError: regeneratorRuntime is not defined at HTMLDocument.main (index.js:8)



최상위 수준에서 async 함수를 사용하고 있기 때문입니다. 오류를 해결하려면 아래 구성을 .babelrc 파일에 추가하십시오.

{
  "presets": ["@babel/preset-env"],
  "plugins": ["@babel/plugin-transform-runtime"]
}


앱 실행



이제 yarn 다음에 yarn watch를 실행할 수 있으며 내부에 앱이 있는 브라우저 창이 열립니다. 다음과 같은 페이지가 표시됩니다.



그림에 무엇이 있는지 예측하는 데 걸리는 시간을 기록하십시오. 이제 WebAssebly 백엔드를 추가하고 앱을 실행하여 성능을 확인합니다.

WASM 백엔드 사용



WebAssembly 백엔드를 추가하려면 @tensorflow/tfjs-backend-wasm 패키지를 설치해야 합니다.

{
  ...,
  "dependencies": {
    "@tensorflow/tfjs": "^1.4.0",
    "@tensorflow/tfjs-backend-wasm": "1.4.0-alpha3"
  },
  ...
}


다음 단계는 Parcel에 WASM 파일을 로드하는 방법을 알리는 것입니다. WASM 백엔드가 초기화되면 기본 JS 파일에 상대적인 fetch라는 파일에 대해 readFile/tfjs-backend-wasm.wasm가 있습니다. 이것이 번들러를 사용하는 경우 이 섹션을 사용해야 하는 이유입니다.

{
  ...,
  "staticFiles": {
    "staticPath": "./node_modules/@tensorflow/tfjs-backend-wasm/dist",
    "excludeGlob": [
      "**/!(*.wasm)"
    ]
  },
  ...
}


마지막으로 해야 할 일은 Tensorflow.js에게 이 백엔드를 사용하도록 지시하는 것입니다.

import "@tensorflow/tfjs-backend-wasm";

async function main() {  
  await tf.setBackend("wasm");
  //...
}


그리고 이것이 WebAssembly 백엔드를 활성화하기 위해 필요한 전부입니다. 이제 앱을 실행하고 차이점을 살펴보겠습니다.

yarn && yarn watch


앱이 컴파일되고 브라우저 창이 열리는 것을 볼 수 있습니다.



그리고 쾅 🤯, 차이점을 보세요. 거의 2초가 줄어들었고, 그것은 단지 단일 작업을 수행하는 것입니다. 더 많은 작업을 수행하고 이 접근 방식을 통해 얻을 수 있는 이점을 상상해 보십시오.

요약



the full demo on my GitHub repo 을(를) 찾을 수 있습니다.

이 기능은 웹 개발자가 브라우저 내에서 ML 및 AI에 들어갈 수 있도록 Tensorflow.js를 도입한 이후 발생한 최고의 기능 중 하나라고 생각합니다. 따라서 이 기능을 사용하여 엄청난 성능 향상의 이점을 누리십시오.

그러나 문제가 있습니다 👇🏼:

캐치가 무엇입니까



문제는 모든 기능이 WASM 백엔드에서 구현되는 것은 아니라는 것입니다. 이는 팀에서 구현하지 않는 한 많은 데모를 실행할 수 없음을 의미합니다. follow the progress on their GitHub repo 게임에서 우위를 점할 수 있습니다.

좋은 웹페이지 즐겨찾기