※このブログではサーバー運用、技術の検証等の費用のため広告をいれています。
記事が見づらいなどの問題がありましたらContactからお知らせください。

<前のページ
【Next.js+Tensorflow+TypeScript】機械学習Webアプリの作成|Part1

【Next.js+Tensorflow+TypeScript】機械学習Webアプリの作成|Part2

react web開発 フロント開発 機械学習 TypeScript next.js

投稿日:2021年7月3日

このエントリーをはてなブックマークに追加
この記事ではKerasに用意された訓練済のモデルEfficientNetをTensorflow.js用に出力し、それをNext.js + TypeScriptのアプリケーション上で読み込んで分類をする方法について詳しく解説しています。

はじめに

この記事について

この記事はPart1の続編で、Next.js + TypeScript + Tensorflow.jsで機械学習のWebアプリケーションを作成してみよう、のPart2です。

今回はKerasに用意された訓練済のモデルEfficientNetをTensorflow.js用に出力し、それをNext.js + TypeScriptのアプリケーション上で読み込んで分類をしてみましょう。

この記事の内容はNext.js、TypeScript、Tensorflow.jsになれることが目的であり、ベストプラクティスでは無いことに注意してください。

環境について

この記事では以下の環境を前提としています。

  • node v10.19.0
  • npm v6.14.4
  • Docker version 19.03.13
  • DockerCompose version 1.25.5
  • bashターミナル

参考


実践

Kerasの環境を構築

まずはtensorflow + Keras + JupyterNotebookの環境を用意します。今回はDockerDockerComposeを使ってみることにします。
イメージはtensorflowのものを使用します。このイメージはJupyterNotebookをデフォルトでサポートしているので非常に便利です。

ではDockerCompose用の定義ファイルを作成しましょう!

./docker-compose.yaml
version: "3"

services: 
    keras_app:
        image: tensorflow/tensorflow:2.4.2-jupyter
        volumes:
            - ./keras_app/notebooks:/tf/notebooks
        ports:
            - 8888:8888

ここではホスト(ローカルPC)の./keras_app/notebooksというディレクトリをコンテナの/tf/notebooksというディレクトリにマウントしています。
コンテナの/tf/notebooksディレクトリはtensorflow/tensorflowのDockerイメージがJupyterNotebookのデフォルトのルートとして指定しているディレクトリです。つまり、そこにマウントすることでJupyterNotebook上で生成したファイルをホストの./keras_app/notebooksにそのまま同期できるというわけです。

では起動させてみましょう。

ターミナル
$ sudo docker-compose up -d
▲出力のサンプル

出力されるurlにアクセスすると以下の様にJupyter Notebookのページにアクセスできます。

▲Jupyter Notebookの画面

では動作のテストをしてみます。

New > Python3

で新規ノートブックを開始できます。

ノートブックを開始できたら以下のコードをコピペして実行(Shift+ Enter)してみましょう。

ターミナル
import numpy as np
import tensorflow as tf
from tensorflow import keras

問題なく実行できていればKeras環境の構築は完了です!

訓練済NNモデルの出力

機械学習ライブラリKerasには訓練済のニューラルネットワークモデルが用意されています。今回はこの中からEfficientNetを使ってみます。

from tensorflow.keras.applications import EfficientNetB0

# モデルをインスタンス化
model = EfficientNetB0(weights = "imagenet")

これだけでモデルの構築は完了です!
構造を見てみましょう。

構造を見るにはモデルインスタンスのsummary()メソッドを呼び出します。

model.summary()
Model: "efficientnetb0"
__________________________________________________________________________________________________
Layer (type)                    Output Shape         Param #     Connected to                     
==================================================================================================
input_5 (InputLayer)            [(None, 224, 224, 3) 0                                            
__________________________________________________________________________________________________
rescaling_3 (Rescaling)         (None, 224, 224, 3)  0           input_5[0][0]                    
__________________________________________________________________________________________________
normalization_3 (Normalization) (None, 224, 224, 3)  7           rescaling_3[0][0]                

[...]

top_dropout (Dropout)           (None, 1280)         0           avg_pool[0][0]                   
__________________________________________________________________________________________________
predictions (Dense)             (None, 1000)         1281000     top_dropout[0][0]                
==================================================================================================
Total params: 5,330,571
Trainable params: 5,288,548
Non-trainable params: 42,023

これを見ると入力は(None, 224, 224, 3)、出力は(None, 1000)となっています。これは入力が224×224のRGB(3次元)画像、出力は1000次元のクラスタリングということを意味しています。
Noneは同時に読み込む入力が不定数であることを意味しています(同時に複数の枚数の画像を読み込める)。

pythonのKerasのモデルをそのままJavaScriptのTensorflowで読み込むことはできません。
modelをtensorflow.jsに読み込める形で生成しましょう。

tensorflow.js用のモデルの生成にはtensorflowjsというpythonパッケージが必要になります。
JupyterNotebookでは以下の様に!をつけることでNotebook上からシェルコマンドを実行できます。
今回はこれを使ってインストールしてみましょう。

!pip install tensorflowjs

ではこのパッケージを使ってモデルを生成してみましょう。

# pythonコードでjsモデルを出力
import tensorflowjs as tfjs

# tfjs_modelsディレクトリにモデルデータを出力
tfjs.converters.save_keras_model(model, "tfjs_models")

これでコンテナの/tf/notebooks/、そしてそこにマウントされているホストの./keras_app/notebookstfjs_modelsというディレクトリが作成され、そこにtensorflow.js用のモデルとパラメータ用データが生成されました。

ローカルPCのワーキングディレクトリを確認すると、以下のようなファイル群の生成が確認できると思います。

./keras_app/notebooks
└── tfjs_models
    ├── group1-shard10of25.bin
    ├── group1-shard11of25.bin
    ︙
    ├── group1-shard9of25.bin
    └── model.json

ではいよいよWebアプリケーションの作成に入ります!

Next.jsアプリケーションの作成

ここではNext.js+TypeScriptでアプリケーションを作成しましょう。

ターミナル
$ mkdir next_app
$ cd next_app
$ npm init
$ npx create-next-app --typescript app

モデルファイルの配信設定

次に、先程生成したtensorflow.js用に変換した訓練済EfficientNetモデルデータをブラウザ上で読み取らせる方法について考えましょう。方法はいくつかありますが、今回はサーバーから静的ファイルとして配信する方法でやってみましょう。


Next.jsで静的ファイルを配信するためにはpublicディレクトリに対象ファイルを配置します。

ターミナル
$ cp -r -f ./keras_app/notebooks/tfjs_models ./next_app/app/public

↑ここではコマンドで移動しましたが、普通に画面上からコピー&ペーストでOKです!

さあ、配信設定が問題なくできているか確認してみましょう。

ターミナル
$ npm run dev

この状態でブラウザからhttp://localhost:3000/tfjs_models/model.jsonにアクセスしてみてください。

以下のようにmodel.json内の内容が表示されましたか?

されていれば設定は完璧です!

▲ブラウザの表示例

次にブラウザ上でモデルを読み込みんでみます。
ブラウザ上でtensorflow.jsを実行するには@tensorflow/tfjsパッケージが必要になります。
まずはこれをインストールしましょう。

ターミナル
$ cd app
$ npm install --save @tensorflow/tfjs

では静的サーバーから訓練済EfficientNetのモデルを読み込んで見ましょう。

./next_app/pages/index.tsx
import * as tf from '@tensorflow/tfjs';
import { useState, useEffect, useRef} from "react";

export default function Home() {

  // Modelをstateで定義
  const [model, setModel] = useState<tf.LayersModel|null>(null);
  
  // TODO:デバッグ情報は公開時には消去
  // modelが読み込めたらコンソールに情報を出力
  useEffect(()=>{
    console.log(model);
  },[model]);

  // モデルは一度だけ読み込む
  useEffect(()=>{

    // モデルを静的サーバーから読み込む
    tf.loadLayersModel('/tfjs_models/model.json').then(model => {
      
      // stateにセット
      setModel(model);
    });
  },[]);

  return (
    <div>
      {model==null ? "読み込み中です…" : "準備完了しました…"}
    </div>
  )
}

このコンポーネントの中ではtensorflow.jsのモデルをmodelという名前でstateで定義しています。モデルの読み込みにはloadLayersModel()というメソッドを使います。このメソッドは非同期なので読み込みが終わったタイミングでthen()内のsetModel()が実行され、モデルがmodel変数にセットされます。

アプリケーションを実行してブラウザの開発者ツールなどで確認してみると下のようにモデルの内容が確認できると思います。

▲コンソールにモデルの概要が出力される

問題なくモデルの読み込みまで完了できました!

カメラを入力に推論を実行

では最後にカメラの入力を受け取り、先程読み込んだ訓練済モデルでの推論を自動的に行うコンポーネントを作成してみましょう。

./next_app/pages/index.tsx
import * as tf from '@tensorflow/tfjs';
import { useState, useEffect, useRef } from "react";

export default function Home() {

  // [ ref ] ビデオを参照するRef
  const videoRef = useRef<HTMLVideoElement>(null);

  // [ state ] 訓練済NNモデル
  const [model, setModel] = useState<tf.LayersModel|null>();

  // [ state ] 推論の結果
  const [predictionResult, setPredictionResult] = useState<number>(0);

  // モデルは初回一度だけ読み込む
  useEffect(()=>{
    // モデルを静的サーバーから読み込む
    tf.loadLayersModel('/tfjs_models/model.json').then(model => {
      
      // stateにセット
      setModel(model);
    });
  },[]);

  /**
   * ビデオの読み込み、モデルの読み込みが完了したら推論スタート
   */
  useEffect(()=>{
    if(videoRef.current == null || model == null){
      return;
    }
    
    // <video>の参照を取得
    let video = videoRef.current;

    // <video>にカメラのストリームを入力
    getVideo(video).then(video => {

      //<video>への入力が完了したら推論
      video.onloadeddata = () => {

        // 初回に1回だけ推論
        execEstimate(video, model);

        // 推論を1秒ごとにスケーリング
        setInterval(() => {
          execEstimate(video, model);
        },1000);
      }
    });
    
  },[model, videoRef]);

  /**
   * カメラの入力をvideoに流し込む
   * 今回のNNモデルの入力は224 * 224 * 3なのでそれに合わせる
   */
  const getVideo = (video: HTMLVideoElement):Promise<HTMLVideoElement> => {
    console.log("getVideo");
    return navigator.mediaDevices
      .getUserMedia({ video: { width: 224, height: 224 } })
      .then(stream => {
        video.srcObject = stream;
        video.play();
        return video;
      })
  };

  /**
   * 推論の実行
   * @returns 
   */
  const execEstimate = (video:HTMLVideoElement, model:tf.LayersModel): void => {
    // <video>に出力されている画像をTensorとして取得
    let input = tf.browser.fromPixels(video);

    // Batch=1(1枚の画像のみ)の入力を生成
    let inputReshaped = input.reshape([1,224,224,3]);

    // モデルで推論
    let prediction = model.predict(inputReshaped) as tf.Tensor<tf.Rank>;

    // 出力は0~1の値なので、0~100の値に変更
    let predictionHundredFold = prediction.dataSync<"float32">().map((value, index, array) => {
      return value * 100;
    });
    let predictionArgMax = tf.argMax(predictionHundredFold).dataSync<"int32">();
    setPredictionResult(predictionArgMax[0]);
  }

  return (
    <div>
      <video ref={videoRef}></video>
      {model==null ? "読み込み中です…" : `推測ラベル:${predictionResult}`}
    </div>
  )
}

ここでは新しくvideoRefという<video>へのrefと、訓練済NNモデルで推論した結果を値として保持するpredictionResultというstateを定義しました。
<video>への参照をrefとして定義することで、この変数越しに好きなタイミングで<video>の値を読み取ることができます。
predictionResultはmodelの出力をそのまま保持するのではなく、modelの出力配列のうち最も値の大きなクラスのインデックス(0~999)を保持します。

<video>はもともと動画を埋め込むためのタグで、それ自身にカメラの入力を受け取る機能が実装されているわけではありません。そこでgetVideo()でカメラの入力を受け取り、それをそのまま<video>に流す処理が実装してあります。

execEstimate()がモデルから推論を行う関数です。ここについて、詳しく解説すると長くなるので、今回は

『へ〜。こう書くとなんか推論できるんだ〜。』

程度に考えてください。

開発用サーバーを起動して実行するとカメラが起動して推論がスタートします。

試しにバナナを見せてみました。

▲バナナを見せてみる

動いた!!
バナナは818あたりに分類されていそうですね!

※もちろん、実際にこのモデルの訓練データにバナナが含まれているかどうかはわかりません。訓練済モデルは一般的にそのまま使うことはなく、途中の層のパラメータや転移学習をしてからの分類が一般的です。

※今回のアプリケーションをそのままサーバーにデプロイして動かすと、訓練済モデルのダウンロードに毎回100MBくらいダウンロードしてしまいます。当然そのようなWebアプリは適切な設計ではありません。

このエントリーをはてなブックマークに追加

<前のページ
【Next.js+Tensorflow+TypeScript】機械学習Webアプリの作成|Part1

関連記事

記事へのコメント
62:Wesleytophy
2023年11月16日20:06

любого предприятия независимо от его размеров включает в себя несколько сотен или даже тысяч приборов, которые выполняют различные технологические процессы https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/blok-formy-dlya-zamorozki-800h250h60-mm/ottajshhik-blok-form-obf-1

Цветные металлы (латунь, титан, алюминий, бронза, медь) составляют основу отдельных деталей, емкостей, трубопроводов, некоторых видов упаковки (например, консервных банок) https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/stellazh-dlya-razmorozki-aisi-304

Казино еще с прошлого века пользовалось бешеным успехом среди ценителей качественных развлечений и комфортного отдыха https://пищевоеоборудование.рф/moskva/katalog/oprokidyvateli-kontejnerov-i-telezhek/oprokidyvateli-bochek-ob-250
Когда реальные казино были запрещены законом и пришлось закрыть https://пищевоеоборудование.рф/katalog/oprokidyvateli-kontejnerov-i-telezhek/big-boksy
https://пищевоеоборудование.рф/katalog/bunkera-nakopitelnye-priemnye/
https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/stol-dlya-razdelki-aisi-304

Реакторы термические применяются для термической обработки продукции во всех отраслях пищевой промышленности https://пищевоеоборудование.рф/katalog/sanpropuskniki-doz-200/dezbarery-dlya-avtotransporta-doz-m-5000
Изготавливаются различного объема, комплектации по техническому заданию или чертежам заказчика заданной производительности https://пищевоеоборудование.рф/katalog/glazirovshhiki-pogruzhnoj/

Торговое холодильное оборудование отличается меньшей мощностью (хотя и здесь используются мощные ) и применяется для кратковременного хранения охлажденных или замороженных продуктов в магазинах и предприятиях общепита https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/rolgangi-rolikovye-aisi-304
Его отличительной особенностью является то, что это оборудование должно обеспечивать возможность демонстрации продуктов и удобство доступа к ним покупателей https://пищевоеоборудование.рф/katalog/oprokidyvateli-kontejnerov-i-telezhek/oprokidyvateli-cheburashka

ИСПЫТАНИЯ СЕЯЛКИ ДЛЯ ПОСЕВА СЕМЯН ГИДРАВЛИЧЕСКИМ СПОСОБОМ Виневский Е https://пищевоеоборудование.рф/katalog/centrifuga-reaktivnaya-ustanovka/
И https://пищевоеоборудование.рф/katalog/konvejera-z-obraznye/vibropitatel-s-bunkerom-v-200-l
*, д-р техн https://пищевоеоборудование.рф/soglashenie
наук, профессор Труфляк Е https://пищевоеоборудование.рф/katalog/oprokidyvateli-kontejnerov-i-telezhek/oprokidyvatel-cepnoj-orc-3000
В https://пищевоеоборудование.рф/soglashenie
**, д-р техн https://пищевоеоборудование.рф/katalog/oprokidyvateli-kontejnerov-i-telezhek/oprokidyvateli-cheburashek-och-250
наук Курченко Н https://пищевоеоборудование.рф/katalog/kamera-df/
Ю https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/rolgangi-rolikovye-aisi-304
** Скоробогаченко И https://пищевоеоборудование.рф/katalog/mashina-mojki/
С https://пищевоеоборудование.рф/katalog/izdeliya-iz-nerzh.-stali-aisi304/protivni-dlya-kopcheniya-sushki-aisi-304
** * ФГБНУ «Всероссийский научно

110:Danielmearo
2023年11月21日17:16

Септик в подарок https://красивые-дома-приморья.рф/vypolnennye-proekty/photo/lenovo-2173

Спецпредложение https://красивые-дома-приморья.рф/vypolnennye-proekty/photo/img_20230412_161955_123

Этажность: 1 этаж Срок строительства: от 4 мес https://красивые-дома-приморья.рф/vypolnennye-proekty/photo/img_20200312_112055

Проект ГБД-178 https://красивые-дома-приморья.рф/vypolnennye-proekty/photo/img-20230723-wa0063

Строим из оцилиндрованного бревна и профилированного бруса https://красивые-дома-приморья.рф/demontazh-zdaniya

Стоимость строительства от 4 513 000 руб https://красивые-дома-приморья.рф/poleznaya-informaciya/post/stroitelstvo-doma-zimoj
Площадь 97 https://красивые-дома-приморья.рф/vypolnennye-proekty/photo/img_20200312_112056
3 м?

132:KeenanUnula
2023年11月24日17:07

Обучалась в ППИЭ на курсе – Мастер маникюра и педикюра https://москва-курсы.рф/articles/kyrsu-nanoplastiki-volos/
https://москва-курсы.рф/главная/курсы-косметологов/
Здесь работают очень милые и отзывчивые люди https://москва-курсы.рф/финансово-хозяйственная-деятельност/
https://москва-курсы.рф/services/курс-вечерних-причесок/
Сотрудники и преподаватели профессионалы…
Курсы • Курсы маникюра •
Все необходимые инструменты и материалы включены в стоимость https://москва-курсы.рф/articles/kurcy-brobista-s-diplomom/

Все необходимые инструменты и материалы включены в стоимость http://москва-курсы.рф

Скидки на оборудование Скидка в магазинах профессиональной косметики https://москва-курсы.рф/articles/akkreditacia-medicinskih-rabotnikov/

hat_s Created with Sketch https://москва-курсы.рф/articles/individyalnue-kurcy-makiazha/

133:KeenanUnula
2023年11月24日23:19

Почему стоит учиться в Академии красоты Эколь https://москва-курсы.рф/%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F/kursi-makeup/

Школа Интеримидж https://москва-курсы.рф/финансово-хозяйственная-деятельност/

Курсы • Маникюр и педикюр обучение •
Имитация камня Стили тату и акварель Уникальный френч Эффект хрустальных камней https://москва-курсы.рф/services/%D0%BA%D1%83%D1%80%D1%81%D1%8B-%D0%BC%D0%B0%D0%BD%D0%B8%D0%BA%D1%8E%D1%80%D0%B0-%D0%BF%D0%B5%D0%B4%D0%B8%D0%BA%D1%8E%D1%80%D0%B0-%D0%BD%D0%B0%D1%80%D0%B0%D1%89%D0%B8%D0%B2%D0%B0%D0%BD%D0%B8%D1%8F/

маникюр классический, аппаратный, комбинированный, бразильский, горячий педикюр классический, аппаратный, комбинированный, бразильский, горячий спа уходы парафинотерапия техника массажа рук и ног наращивание ногтей по гелевой технологии на нижние формы и типсы наращивание ногтей полигель/акригель на нижние и верхние формы салонные дизайны (втирка, омбре, стемпинг, тонкие линии, геометрия, принты, фольга, все виды френч, блестки, стразы, глиттер, слайдеры) покрытие гель-лак под кутикулу, снятие вросший ноготь коррекция и снятие нарощенных ногтей ремонт ногтей https://москва-курсы.рф/%D0%B3%D0%BB%D0%B0%D0%B2%D0%BD%D0%B0%D1%8F/kursy-parikmahera/

6 академических часов https://москва-курсы.рф/платные-образовательные-услуги/

147:KeenanUnula
2023年11月25日22:36

250 академ https://москва-курсы.рф/articles/obychenie-permanentnomy-makiazhy-gyb-moskva/
ч https://москва-курсы.рф/articles/obychenie-na-estetista-bez-med-obrazovania/

Данные из анкеты отображаются на сайте https://москва-курсы.рф/services/маникюр-педикюр-наращивание/

“Рекомендую эти курсы всем, кто хочет освоить наращивание ногтей https://москва-курсы.рф/services/obychenie-na-barbera/
Здесь я смогла освоить различные техники и все закрепить на практике https://москва-курсы.рф/согласие-на-обработку-пд/
Планирую открыть собственный салон https://москва-курсы.рф/services/%D0%BA%D0%BE%D1%81%D0%BC%D0%B5%D1%82%D0%BE%D0%BB%D0%BE%D0%B3-%D0%B2%D0%B8%D0%B7%D0%B0%D0%B6%D0%B8%D1%81%D1%82/

На курсах обучения маникюру 6 часов отведено для практических занятий, в ходе которых обязательно обрабатываются все виды, а также проверяется усвоение полученных знаний:
Курсы • Курсы маникюра •
…маникюра, поскольку профессия достаточно востребованна https://москва-курсы.рф/services/маникюр-педикюр-наращивание/
Выбрала данные курсы и не пожалела грамотные педагоги https://москва-курсы.рф/services/kurs-koloristiki-s-nulia-moskva/
Екатерина спасибо за понятное…

150:KeenanUnula
2023年11月27日1:36

16 академических часов https://москва-курсы.рф/services/курсы-массажа/

Ближайший старт: 05 Декабря https://москва-курсы.рф/платные-образовательные-услуги/

Студент проходит обучение https://москва-курсы.рф/services/повышение-квалификации-косметологов/

Беспроцентная рассрочка https://москва-курсы.рф/articles/obuchenie-keratinovomu-vypriamleniu-volos/

15740 чел уже прошли этот курс https://москва-курсы.рф/отзывы/

Отзывы о нашей работе https://москва-курсы.рф/articles/obychenie-permanentnomy-makiazhy-gyb-moskva/

180:KeenanUnula
2023年11月29日21:47

Все необходимые инструменты и материалы включены в стоимость https://москва-курсы.рф/services/

Салонный мастер https://москва-курсы.рф/articles/devyshka-barber/

4 700 ?/в мес https://москва-курсы.рф/articles/lichnue-kachestva-parikmahera/

Подробности курса https://москва-курсы.рф/services/повышение-квалификации-косметологов/

Классический педикюр Аппаратный педикюр Дисковый педикюр Экспресс-педикюр и покрытие https://москва-курсы.рф/services/курсы-косметолога-vip-уровня/

У нас действует гибкое расписание, благодаря чему у студентов есть возможность совмещать занятия в Академии красоты с другой занятостью https://москва-курсы.рф/структура-и-органы-управления-образо/
Можно изучать теорию дистанционно, а в учебный центр приходить только для отработки практических навыков https://москва-курсы.рф/services/курсы-парикмахера-модельера-стилист/