TensorFlow.js: Firebase Hosting を使用して機械学習モデルの大規模なデプロイとホスティングを行う

TensorFlow.js で作成したカスタムの機械学習モデルをウェブサイトで使用するには、機械学習モデルをどこかでホストする必要があります。これを行う方法は多数ありますが、今回は Firebase Hosting を使用して簡単に実現する方法を紹介します。Firebase Hosting には、バージョニングやセキュアな接続を介したモデルの提供といった数多くの利点があり、さまざまな機能をすぐに利用できます。

作成するもの

この Codelab では、保存済みのカスタム TensorFlow.js モデルとその関連アセット(HTML、CSS、JavaScript など)をホストして実行する機能を備えた、完全なエンドツーエンド システムを作成します。ここでは、とてもシンプルで軽量なモデルを作成します。このモデルでは、指定された入力値に基づいて数値の予測値を出力します(具体的には、住宅の面積を指定してその住宅の価格を予測します)。大規模に使用できるように、そのモデルを Firebase Hosting でホストします。

学習内容

  • TensorFlow.js のカスタムモデルを適切な形式で保存する方法
  • ホスティングのための Firebase アカウントを設定する方法
  • Firebase Hosting にアセットをデプロイする方法
  • 新しいバージョンのモデルをデプロイする方法

注意: この Codelab では、カスタムのトレーニング済みモデルをデプロイしてホストする方法に焦点を当てています。完全なモデル アーキテクチャの作成に関するコースではないため、機械学習モデルの作成については簡単な例を使って手短に説明します。ここで述べられている原則は、最終的にどのようなモデルを作成するかにかかわらず、あらゆるケースに共通しています。

作成したものを共有する

このスタックを使用して素晴らしいシステムを作成できましたら、ぜひお知らせください。皆様の力作を多くの人たちが楽しみにしています。

ソーシャル メディアで #MadeWithTFJS ハッシュタグを使用すると、作成したプロジェクトが TensorFlow ブログShow & Tells などの今後のイベントで取り上げられる可能性があります。

Firebase Hosting は、ウェブアプリ、静的コンテンツ、動的コンテンツ、マイクロサービス向けの高速で安全なプロダクション グレードのホスティング サービスを提供します

1 つのコマンドでウェブアプリをすばやくデプロイし、グローバル CDN(コンテンツ配信ネットワーク)にコンテンツを配信できるため、世界中のほぼすべての場所で低レイテンシでコンテンツが提供されます。Firebase Hosting と Firebase Cloud Functions または Cloud Run を組み合わせることによって、マイクロサービスを構築してホストすることもできますが、それはこの Codelab の範囲外のトピックです。

Firebase Hosting の主な機能

  • 安全な接続を通じてコンテンツを配信 - モダンでセキュアなウェブを構築します。多くの場合、クライアント側のセンサーにアクセスするには、セキュアなコンテキストでサイトを配信する必要があります。Firebase Hosting には構成不要な SSL が組み込まれているため、ホストされるすべてのファイルのコンテンツは常に安全に配信されます。
  • 静的コンテンツ、動的コンテンツ、マイクロサービスをホストできます。認証をサポートしているため、必要に応じて、ログインしているユーザーのみがファイルの読み込みと表示を行えるようにすることができます。
  • コンテンツを高速に配信 - アップロードする各ファイルは世界中の CDN エッジにある SSD にキャッシュされます。ユーザーがどこにいても、コンテンツを高速に配信できます。
  • 1 つのコマンドで新しいバージョンをデプロイ - Firebase コマンドライン インターフェースを使用して、わずか数秒でアプリを稼働させることができます。
  • ワンクリックでロールバック - 迅速なデプロイは大いに有用ですが、間違いを元に戻せることはさらに優れた利点です。Firebase Hosting はワンクリックでロールバックできる完全なバージョニング機能とリリース管理機能を提供しています。

デプロイするのがシンプルなアプリ ランディング ページであっても、複雑なプログレッシブ ウェブアプリ(PWA)であっても、Hosting はウェブサイトとアプリのデプロイと管理に適したインフラストラクチャ、機能、ツールを提供します。

すべての Firebase プロジェクトにはデフォルトで無料のサブドメインが付属し、web.app ドメインと firebaseapp.com ドメインを利用できます。これら 2 つのサイトが、同じデプロイ済みのコンテンツと構成を配信します。必要に応じて、Firebase でホストするサイトに独自のドメイン名を接続することもできます。

実装の手順

ただし、上記の手順を行う前に、デプロイする機械学習モデルとウェブアプリを用意する必要があります。まずは、それらを作成しましょう。

この演習では、数値を予測する非常に単純な ML モデルを作成します。機械学習を使用して、平方フィート単位でサイズが指定されている架空の住宅の値を予測しますが、これはあくまでも例を示すためのものです。このデモでは、トレーニング データとして住宅の平方フィートを単に 1000 倍した予測値を用意しています。ただし、機械学習はこの予測値を独力で学習する必要があります。

実際の機械学習では現実世界のデータを使用しますが、その中にはより複雑な関係が存在する場合があります(たとえば、比較的小さい住宅の場合はサイズの倍率を 500 倍にして価格を見積もるが、一定のしきい値を超えたら徐々に 1000 倍に近づいていくなど)。また、値を予測するための最適な方法を学習するために、より高度なモデルが必要になることもあります。

今回作成するモデル(線形回帰)は、現実世界のデータを十分に用意すれば他の多くのことの予測に使用できます。また、このモデルはシンプルであり、今回の架空のユースケースに適しています。今回の焦点は、モデルを保存してデプロイする方法を学ぶことであり、特定のユースケース向けにモデルを設計して最適化することではありません。では始めましょう。

トレーニング用データとテスト用データ

すべての ML モデルは、トレーニング用のサンプルデータを用意することから始まります。そのデータを使用して、将来の値を予測する能力をモデルに教えていきます。通常は、データベース、ファイルのフォルダ、CSV などからデータを取得しますが、ここでは、以下に示すように 20 件のサンプルを JavaScript の配列として直接ハードコードします。お気に入りのコーディング環境(Glitch.com など)にこのコードを複製することをおすすめします。localhost でサーバーを実行できる場合は、ローカルの任意のテキスト エディタにこのコードを複製しても構いません。

model.js

// House square footage.
const data =    [800, 850, 900, 950, 980, 1000, 1050, 1075, 1100, 1150, 1200, 1250, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000];

// Estimated dollar cost of house for each piece of data above (1000x square footage).
const answers = [800000, 850000, 900000, 950000, 980000, 1000000, 1050000, 1075000, 1100000, 1150000, 1200000,  1250000 , 1300000, 1400000, 1500000, 1600000, 1700000, 1800000, 1900000, 2000000];

// Testing data separate from training data.
const dataTest =     [886, 1225, 500];
const answersTest =  [886000, 1225000, 500000];

個々のデータにはそれに対応する回答値が存在します。将来、このような値を予測できるようにします(これらは単純な 2D グラフ上の x と y の値と考えることができます)。

つまり、値 800 に対しては $800,000 という推測値を出力できるようにし、値 900 に対しては $900,000 を出力できるようにします。基本的には、数値を 1000 倍にします。しかし、ML モデルは 1000 * N という単純な関係をまだ把握していないので、提供されたサンプルから独力で学習する必要があります。

また、トレーニング データとは別のテストデータが用意されていることにも注目してください。このようにすることで、トレーニングしたモデルを評価し、未知のデータに対するモデルのパフォーマンスを確認できます。

次の HTML を使用して、このスクリプトを TensorFlow.js ライブラリとともに読み込みます。

train.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Training Model</title>
    <meta charset="utf-8">
  </head>
  <body>
    <!-- Import TensorFlow.js library -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>
    <!-- Import our JS code to train the model -->
    <script src="/model.js" defer></script>
  </body>
</html>

モデルのトレーニング

続いて、ファイルの末尾にある上記の JS コードの後に下記のコードを追加して、モデルをトレーニングします。

好奇心のあるユーザー向けにコメントが追加されていますが、前述のように、この Codelab では保存済みのモデルのホスティングに主眼を置いています。モデルの作成についてさらに詳しく知りたい方向けに、この Codelab の最後に別の Codelab へのリンクがあります。ここでは、コードをコピーしてプロジェクトに貼り付けます。

model.js

// Create Tensor representations of our vanilla JS arrays above
// so can be used to train our model.
const trainTensors = {
  data: tf.tensor2d(data, [data.length, 1]),
  answer: tf.tensor2d(answers, [answers.length, 1])
};

const testTensors = {
  data: tf.tensor2d(dataTest, [dataTest.length, 1]),
  answer: tf.tensor2d(answersTest, [answersTest.length, 1])
};

// Now actually create and define model architecture.
const model = tf.sequential();

// We will use one dense layer with 1 neuron and an input of
// a single value.
model.add(tf.layers.dense({inputShape: [1], units: 1}));

// Choose a learning rate that is suitable for the data we are using.
const LEARNING_RATE = 0.0001;

train();

async function train() {
  // Compile the model with the defined learning rate and specify
  // our loss function to use.
  model.compile({
    optimizer: tf.train.sgd(LEARNING_RATE),
    loss: 'meanAbsoluteError'
  });

  // Finally do the training itself over 500 iterations of the data.
  // As we have so little training data we use batch size of 1.
  // We also set for the data to be shuffled each time we try
  // and learn from it.
  let results = await model.fit(trainTensors.data, trainTensors.answer, {epochs: 500, batchSize: 1, shuffle: true});

  // Once trained we can evaluate the model.
  evaluate();
}

async function evaluate(stuff) {
  // Predict answer for a single piece of data.
  model.predict(tf.tensor2d([[768]])).print();
}

上記のコードを使用すると、入力値に基づいて出力値を予測するモデルをトレーニングできます。上記のコードを実行すると、入力値 768 に対して 768,073 という予測が得られ、ブラウザのデベロッパー コンソールに出力されます(デベロッパー コンソールは F12 キーを押すと開きます)。用意したサンプルは入力値の 1000 倍であったことを考慮すると、これは住宅価格をかなり正確に見積もった値です。注: 実際に表示される予測値が少し異なっていても、正常な動作です。

このパフォーマンスで問題なければ、このモデルをディスクに保存して Firebase Hosting にアップロードできます。

モデルの保存

上記の evaluate 関数の末尾(model.predict の後)に以下のコードを追加すると、トレーニング完了後のモデルをウェブブラウザから直接エクスポートしてディスクに保存できます。これにより、今後は毎回ページを読み込んで再トレーニングするのではなく、保存したファイルを使用してホストできるようになります。

model.js

await model.save('downloads://my-model');

ここで train.html にアクセスしてページを実行すると、モデルがトレーニングされ(数秒かかることがあります)、完了後にトレーニング済みモデルをダウンロードするかどうかを尋ねるプロンプトが表示されます。

Firebase にログインしてプロジェクトを作成する

Firebase を初めて使用する場合は、Google アカウントを使用して簡単に登録することができます。https://firebase.google.com/ にアクセスし、通常の Google アカウントでログインします。ホームページにリダイレクトされたら、ページ右上の [コンソールへ移動] をクリックします。

ea7ff3f08e4019b0.png

コンソールにリダイレクトされると、次のようなランディング ページが表示されます。

166d9408ad46599b.png

[プロジェクトを追加] をクリックして新しい Firebase プロジェクトを作成し、プロジェクトに一意の名前を付け、利用規約に同意して、[続行] をクリックします。

続いて、プロジェクトにアナリティクスを追加するかどうかを選択します。アナリティクスにアクセスしたい場合は、以下に示すようにこのオプションを有効にして [続行] をクリックします。

a34c2be47b26e6b5.png

問題がなければ、以下に示すように、プロジェクトの準備ができたことを示すページが表示されます。

1306dc803ad22338.png

おめでとうございます。プロジェクトが作成されました。[続行] をクリックすると、新しく作成したプロジェクトのコンソールに移動します。後で使用するため、このページは開いたままにします。まずはツールをインストールする必要があります。

CLI のインストールと接続

Firebase には Node NPM パッケージが用意されており、コマンドライン インターフェース(CLI)を通じてこのパッケージをインストールし、使用することができます。このパッケージを使用することにより、ローカルのファイルとフォルダを Firebase Hosting に簡単にデプロイできます。このチュートリアルでは Linux 環境を使用しますが、Windows または Mac をご利用の場合は、こちらの手順に沿ってデバイスに CLI ツールを設定してください。

Linux 環境で、NPM と Node.js がまだインストールされていない場合は、最初にこれらをインストールします(他の環境を使用している場合はこちらの手順をご覧ください)。これらをインストールするには、ターミナル ウィンドウで次の 3 つのコマンドを実行します。

コマンドライン ターミナル:

sudo apt update

コマンドライン ターミナル:

sudo apt install nodejs

コマンドライン ターミナル:

sudo apt install npm

これで Node.js と NPM がインストールされました。次に、ターミナル ウィンドウで以下のコマンドを実行して Firebase コマンドライン ツールをインストールします。

コマンドライン ターミナル:

sudo npm install -g firebase-tools

これで、システムに Firebase プロジェクトを接続する準備が整い、ファイルを push できるようになりました。

Firebase へのログイン

Google アカウントで Firebase にログインするには、次のコマンドを実行します。

コマンドライン ターミナル:

firebase login

以下に示すように、Google Firebase アカウントにアクセス権を付与するよう求められます。

4dc28589bef2ff5d.png

これを許可すると、コマンドライン ツールが Firebase アカウントに正常に接続されたことを示すメッセージが表示されます。

df397ec7a555e8de.png

ウィンドウを閉じ、先ほど作業を行っていたコマンドライン ターミナルに戻ります。このコマンドライン ターミナルでは、以下に示すように新しいコマンドを受け入れる準備ができています(このスクリーンショットでは機密情報を隠しています)。

67a3ff39d3c0f3e4.png

これで、作成したプロジェクトにローカルマシンからファイルを push する準備ができました。

Firebase Hosting にデプロイするためのプロジェクトの初期化

ローカル フォルダを Firebase プロジェクトに接続するには、ローカル プロジェクトのルート ディレクトリ(デプロイ時にファイルのアップロード元として使用するフォルダ)で次のコマンドを実行します。

コマンドライン ターミナル:

firebase init

このコマンドを実行したら、ターミナルに表示される以下の手順に沿って設定を完了します。

61e0f6d92ef3e1c4.png

ここでは、キーボードの下矢印キーを使って Hosting に移動し、Space キーを押して選択した後、Enter キーを押して確定します。

ここで、先ほど作成した既存のプロジェクトを選択できます。

4f2a1696d5cfd72f.png

以下に示すように、[Use an existing project] を選択した状態で Enter キーを押してから、下矢印キーを使って目的のプロジェクトを選択します。

4dfcf2dff745f2c.png

最後に、Enter キーを押してそのプロジェクトの使用を確定させます。ポップアップ表示される最終画面でデフォルトの設定をそのまま受け入れ、シングルページ アプリケーションとして構成するかどうかを尋ねられたら「No」と入力します。

7668a2175b624af2.png

このように選択することによって、複数の HTML ページをホストできるようになります。

これで初期化は完了です。上記のコマンドの実行元となったディレクトリに firebase.json ファイルと「public」フォルダが作成されています。

cd7724b92f3d507.png

デプロイするファイルをこの public フォルダに移動することで、デプロイの準備が整います。次にそれを行います。

保存したモデルの読み込み

最初に、先ほど保存した機械学習モデルを、Firebase によって作成された public フォルダにコピーします。以下に示すように、保存したファイルをこのフォルダにドラッグ&ドロップします。

cd6f565189e23705.png

Firebase によって index.html ファイルと 404.html ファイルも作成されていることに注目してください。お好みのテキスト エディタを使って index.html を編集し、以下のカスタムコードを追加します。

index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hello World - TensorFlow.js</title>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- Import the webpage's stylesheet -->
    <link rel="stylesheet" href="style.css">
  </head>
  <body>
    <h1>TensorFlow.js Hello World</h1>
    <p>Check the console (Press F12) to see predictions!</p>
    <!-- Import TensorFlow.js library -->
    <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs/dist/tf.min.js" type="text/javascript"></script>

    <!-- Import the page's JavaScript to do some stuff -->
    <script src="script.js" defer></script>
  </body>
</html>

先ほど index.html に追加した上記のコードではスタイルシートが指定されており、後でページにスタイルを追加できます。また、script.js も指定されています。この script.js ファイルに、TensorFlow.js の保存済みモデルを使用するためのコードを記述する必要があります。

これらのファイルを作成し、次のように入力してみましょう。

style.css

/** Leave blank for now **/

script.js

// Load our saved model from current directory (which will be
// hosted via Firebase Hosting)
async function predict() {
  // Relative URL provided for my-model.json.
  const model = await tf.loadLayersModel('my-model.json');
  // Once model is loaded, let's try using it to make a prediction!
  // Print to developer console for now.
  model.predict(tf.tensor2d([[1337]])).print();
}

predict();

ここまでの手順を正しく行った場合、public フォルダには以下の編集済みファイルが含まれています。

253498c703c04ee.png

次に、ファイルをデプロイして正常に動作することを確認しましょう。

実際に動かしてみる

先ほどローカルマシンの Firebase プロジェクト フォルダで開いていたターミナル ウィンドウに戻ります(前述の public フォルダと firebase init で作成されたファイルが置かれているフォルダです)。

次のコマンドを入力して、public フォルダのファイルをデプロイします。

コマンドライン ターミナル:

firebase deploy

このターミナル コマンドが完了するとリリースが完了し、デプロイしたコンテンツを使用するための URL が表示されます。

c5795cae85ed82a5.png

上記の例では、デプロイしたコンテンツを表示するための URL が次のように表示されています。

https://tensorflow-js-demo.web.app(実際の URL は作成したプロジェクトの名前になります)。

ウェブブラウザでこの URL を開き、正しく動作するか確認します。正しく動作している場合は、ページのデベロッパー コンソールに次のように出力されます(デベロッパー コンソールを開くには F12 キーを押します)。

182aee0acfa7c41e.png

デプロイされたドメインのページが読み込まれたことが確認できます。また、1337 平方フィートに対するモデルの予測が $1,336,999.25 という結果になったことも確認できます。結果は平方フィートの 1000 倍になると想定されていたため、実際にとても良い推測値となっています。モデルを呼び出す適切なユーザー インターフェースを作成すれば、何度でも予測を行うことできます。また、これらすべてを JavaScript 内で実行し、クエリをプライベートにしてセキュリティを確保することもできます。

モデルをデプロイしてホストしたので、このウェブサイトを世界中のユーザーと共有できます。ユーザーは各自のマシンでこのアプリケーションを使用できます。ユーザー インターフェースをもっと良くしたいと思うかもしれませんが、それはこのチュートリアルの対象外です。このように、機械学習で作成したモデルをホストするウェブアプリの可能性は無限大です。そのようなウェブアプリを、インストールなしで、ワンクリックで稼働させることができます。皆様も、ブラウザで機械学習モデルを利用する他の応用例について検討してみてください。

使用量のモニタリング

ウェブサイトのコードに Google アナリティクスを追加する機能に加え、Firebase ではプロジェクトのコンソールからバージョニング機能を利用でき、使用状況の統計情報も確認できます。デプロイが完了すると、次のような画面が表示されます。この画面の情報は必要に応じていつでも確認できます。

42b1cb8f7c10016.png

fbdd6504bec7c3d.png

この画面に表示されているように、無料枠ではデフォルトで、ホストするファイル用に 10 GB/月の帯域幅を利用できます。サイトの人気が高くなった場合は、毎月の使用量を増やすために、請求先アカウントの追加が必要になることがあります。大規模なプロジェクト向けの Firebase プランについては、こちらをご覧ください。ただし、プロトタイプ用として使用する多くのカジュアル ユーザーの場合、モデルが小さく使用量が少なければ、無料枠を超えることはほとんどありません。したがってこの無料枠は、有料プランを契約する前にテストを行い、ニーズを満たしているかをチェックするのに便利です。その後、ビジネスやアイデアが成長していく中で有料枠の利用をご検討ください。

おめでとうございます。これで、TensorFlow.js と Firebase を使用してカスタムビルドの機械学習モデルを作成し、デプロイするためのステップを学ぶことができました。このようにしてデプロイしたモデルは、世界中のユーザーと共有することができます。この強力でスケーラブルなアプローチを使用して実現できる他の事例を想像してみてください。Firebase は需要に応じて自動的にスケーリングするため、本番環境のユースケースにも容易に対応できます。ユーザー数が 10 人であっても 10,000 人であっても問題なく動作します。

ファイルを変更する場合は、先ほどと同じように firebase deploy を使用してアプリを再デプロイします。次回ページを読み込むときに新しいバージョンのファイルが取得されるようにするため、ブラウザのキャッシュをクリアしてください。デベロッパー ツールを開いている場合は、テスト中に [Network] タブの上部にある [Disable cache] チェックボックスをオンにすることによって、強制的に新しいファイルを読み込ませることができます。

b1e4c1bf304a4869.png

内容のまとめ

この Codelab では次のことを行いました。

  1. 住宅価格を予想する TensorFlow.js のカスタムモデルをゼロから定義してトレーニングしました。
  2. Firebase に登録して構成を行い、開発マシンに Firebase + Firebase CLI ツールをインストールしました。
  3. ステップ 1 でトレーニングしたモデルを読み込んで実行するウェブサイトをデプロイし、リリースしました。このウェブサイトは現実世界のウェブ アプリケーションでも利用でき、世界中のすべてのユーザーがアクセスできるような大規模なものにすることができます。

次のステップ

これで、実際に使える基礎的な知識を得ることができました。クリエイティブなアイデアを思いついたときは、この機械学習モデルのデプロイの原型を拡張して開発に役立ててください。

独自のデータを準備し、業種や分野に応じてトレーニングを行い、将来の予測に役立ててみてください。ここで取り上げた不動産はあくまでも一例です。この機能を独自の課題にぜひ応用してみてください。みなさんの成功をお祈りします。

素晴らしいシステムを作成できましたら、#MadeWithTFJS ハッシュタグを使用してお知らせください(このリンクをクリックすると、他のユーザーが作成したプロジェクトからインスピレーションが得られます)。作成したプロジェクトがソーシャル メディアで取り上げられたり、今後の TensorFlow イベントで紹介されたりする可能性があります。皆様の力作を多くの人たちが楽しみにしています。ご意見やご質問がある方は、この Codelab の作成者までお知らせください。

理解を深めるための TensorFlow.js のその他の Codelab

参考になるウェブサイト