TensorFlow.jsでローカルファイルやURLから画像認識モデルを安全にロードする:Pythonからの移行者向け
TensorFlow.js(TF.js)を用いてWebブラウザやNode.js環境で画像認識AIを動作させるためには、まず学習済みのモデルをメモリ上にロードする必要があります。PythonのTensorFlowやKerasでは、tf.saved_model.load
や tf.keras.models.load_model
といった関数を使って簡単にモデルをロードできますが、TF.jsではJavaScriptの特性(特に非同期処理)を考慮したロード方法を理解することが重要です。
この記事では、Pythonでの機械学習開発経験を持つ読者の方々に向けて、TF.jsで画像認識モデルをローカルファイルやWeb上のURLから安全かつ効率的にロードするための具体的なコード例と技術解説を提供します。
TF.jsにおけるモデルロードの基本
TF.jsでサポートされているモデル形式は主に以下の2種類です。
- Graph Model: TensorFlow SavedModel形式から変換されたモデル。計算グラフ(演算の定義と順序)と重み(変数)を含みます。
tf.loadGraphModel()
関数でロードします。 - Layers Model: Kerasモデル形式から変換されたモデル。モデルのアーキテクチャ(レイヤー構成)と重みを含みます。
tf.loadLayersModel()
関数でロードします。
Pythonで tensorflowjs_converter
ツールを使ってモデルを変換した場合、通常は model.json
ファイルと、重みが格納された複数のバイナリファイル(.bin
拡張子)が出力されます。これらのファイルを、TF.jsのロード関数に指定することでモデルをロードします。
ロード処理は非同期で行われます。これはJavaScriptの特徴であり、モデルのダウンロードやファイル読み込みといったI/O処理中にプログラム全体の実行がブロックされないようにするためです。Pythonでのモデルロードが同期的に行われることが多いのとは異なる点です。
Web上のURLからのモデルロード
最も一般的なTF.jsでのモデルロード方法は、Webサーバー上に配置されたモデルファイルをURL経由で取得する方法です。特にブラウザ環境で利用する場合に適しています。
import * as tf from '@tensorflow/tfjs';
// モデルファイル(model.json)のURLを指定
const MODEL_URL = 'https://example.com/path/to/your/model/model.json'; // 実際のURLに置き換えてください
async function loadModelFromUrl() {
try {
console.log('モデルをロード中です...');
// tf.loadLayersModel または tf.loadGraphModel を使用
// 変換元のPythonモデルがKerasモデルなら loadLayersModel、SavedModelなら loadGraphModel を使うのが一般的です。
// model.jsonファイルの中身を確認すると、"format": "layers-model" または "format": "graph-model" という記述で形式を判別できます。
const model = await tf.loadLayersModel(MODEL_URL);
console.log('モデルのロードに成功しました。');
// ロードしたモデルを使って推論などの処理を実行
// const dummyInput = tf.zeros([1, 224, 224, 3]); // 例: 画像入力のダミーテンソル
// const prediction = model.predict(dummyInput);
// prediction.print();
return model;
} catch (error) {
console.error('モデルのロードに失敗しました:', error);
// エラーに応じた処理(ユーザーへの通知など)
throw error; // エラーを再スローして呼び出し元に通知
}
}
// 非同期関数を実行
loadModelFromUrl();
tf.loadLayersModel
およびtf.loadGraphModel
は、model.json
ファイルのURLを引数に取ります。TF.jsライブラリが自動的にmodel.json
を解析し、関連する.bin
ファイルも同じディレクトリからダウンロードします。- ロード処理は
Promise
を返します。async/await
構文を使用することで、非同期処理を同期的なコードのように記述でき、可読性が向上します。Pythonのasyncioやawaitableオブジェクトに慣れている方には馴染みやすいでしょう。 try...catch
ブロックでロード時のエラー(ネットワークエラー、ファイルが見つからない、形式不正など)を捕捉し、適切に処理することが重要です。
認証や追加ヘッダーが必要な場合
場合によっては、モデルファイルが認証保護された場所に置かれていることがあります。その際は、ロードオプションに headers
を指定できます。
const MODEL_URL_AUTH = 'https://example.com/path/to/private_model/model.json';
async function loadAuthenticatedModel() {
try {
const model = await tf.loadLayersModel(MODEL_URL_AUTH, {
headers: {
'Authorization': 'Bearer YOUR_AUTH_TOKEN' // 例: Bearerトークンによる認証
}
});
console.log('認証モデルのロードに成功しました。');
return model;
} catch (error) {
console.error('認証モデルのロードに失敗しました:', error);
throw error;
}
}
// loadAuthenticatedModel();
ローカルファイルからのモデルロード
ローカルファイルシステムからモデルをロードする方法は、実行環境によって異なります。
Node.js環境でのファイルシステムからのロード
Node.js環境では、ファイルシステムへのアクセスが可能です。file://
プロトコルを使用してファイルパスを指定します。
import * as tf from '@tensorflow/tfjs-node'; // Node.js環境では -node パッケージを使用
import * as path from 'path';
// モデルファイル(model.json)のローカルパスを指定
const MODEL_PATH = 'file://' + path.resolve('/path/to/your/local/model/model.json'); // 実際のパスに置き換えてください
async function loadModelFromFileSystem() {
try {
console.log(`モデルをロード中です: ${MODEL_PATH}`);
// Node.js環境では tfjs-node パッケージがファイルシステムアクセスをサポート
const model = await tf.loadLayersModel(MODEL_PATH);
console.log('モデルのロードに成功しました。');
// ロードしたモデルを使って推論などの処理を実行
return model;
} catch (error) {
console.error('モデルのロードに失敗しました:', error);
throw error;
}
}
// Node.js環境で実行
if (tf.getBackend() === 'tensorflow') { // tfjs-node が有効な場合
loadModelFromFileSystem();
} else {
console.warn('Node.js環境ではありません(またはtfjs-nodeが有効ではありません)。ファイルシステムからのロードはできません。');
}
- Node.jsでファイルシステムからロードするには、
@tensorflow/tfjs-node
あるいは@tensorflow/tfjs-node-gpu
パッケージを使用する必要があります。標準の@tensorflow/tfjs
パッケージはブラウザでの使用を想定しており、ファイルシステムAPIへの直接アクセスをサポートしていません。 - パス指定には
file://
というプレフィックスが必要です。path.resolve
などを用いて絶対パスを取得するのが確実です。
ブラウザ環境でのローカルファイル(ユーザー選択)からのロード
ブラウザはセキュリティ上の制約から、ユーザーが明示的に選択したファイル以外にJavaScriptから直接アクセスすることはできません。したがって、ユーザーにファイルを選択してもらい、その内容を読み込んでTF.jsに渡す必要があります。これは、Webアプリケーションでユーザーがローカルのモデルファイルや重みファイルをアップロードして利用する場合に役立ちます。
HTML:
<input type="file" id="model-file-input" webkitdirectory directory />
<input type="file" id="weights-file-input" multiple />
<button id="load-button" disabled>モデルをロード</button>
<p id="status"></p>
JavaScript:
import * as tf from '@tensorflow/tfjs';
const modelFileInput = document.getElementById('model-file-input');
const weightsFileInput = document.getElementById('weights-file-input');
const loadButton = document.getElementById('load-button');
const statusElement = document.getElementById('status');
let modelJsonFile = null;
const weightsFiles = [];
// model.json ファイルが選択された時の処理
modelFileInput.addEventListener('change', (event) => {
modelJsonFile = event.target.files[0];
console.log('model.json が選択されました:', modelJsonFile.name);
checkFilesSelected();
});
// .bin 重みファイルが選択された時の処理
weightsFileInput.addEventListener('change', (event) => {
weightsFiles.length = 0; // 配列をクリア
for (let i = 0; i < event.target.files.length; i++) {
weightsFiles.push(event.target.files[i]);
}
console.log(`${weightsFiles.length}個の重みファイルが選択されました。`);
checkFilesSelected();
});
// ロードボタンの有効化/無効化をチェック
function checkFilesSelected() {
if (modelJsonFile && weightsFiles.length > 0) {
loadButton.disabled = false;
statusElement.textContent = 'モデルファイルをロード可能です。';
} else {
loadButton.disabled = true;
statusElement.textContent = 'model.jsonと重みファイル(.bin)を選択してください。';
}
}
// ロードボタンがクリックされた時の処理
loadButton.addEventListener('click', async () => {
if (!modelJsonFile || weightsFiles.length === 0) {
statusElement.textContent = 'モデルファイルが不足しています。';
return;
}
statusElement.textContent = 'モデルをロード中です...';
loadButton.disabled = true; // ロード中はボタンを無効化
try {
// ブラウザでローカルファイルからロードする場合、tf.io.browserFiles を使用
// これは File オブジェクトのマップ({model.jsonのFileオブジェクト, 重み.binのFileオブジェクト...})を期待します。
const files = [modelJsonFile, ...weightsFiles];
const model = await tf.loadLayersModel(tf.io.browserFiles(files));
statusElement.textContent = 'モデルのロードに成功しました。';
console.log('モデルのロードに成功しました。');
// ロードしたモデルを使って推論などの処理を実行
// const dummyInput = tf.zeros([1, 224, 224, 3]); // 例: 画像入力のダミーテンソル
// const prediction = model.predict(dummyInput);
// prediction.print();
} catch (error) {
statusElement.textContent = `モデルのロードに失敗しました: ${error.message}`;
console.error('モデルのロードに失敗しました:', error);
} finally {
loadButton.disabled = false; // ロード終了後、ボタンを再度有効化
}
});
// 初期状態をチェック
checkFilesSelected();
- ブラウザ環境でローカルファイルからロードするには、
tf.io.browserFiles
メソッドを使用します。このメソッドは、ユーザーが<input type="file">
要素で選択したFile
オブジェクトの配列を引数として受け取ります。 model.json
ファイルとすべての.bin
重みファイルをユーザーに選択してもらう必要があります。HTMLの<input type="file" multiple>
や、ディレクトリ全体を選択できるwebkitdirectory directory
属性(非標準ながら広くサポート)を組み合わせることで、複数のファイルを簡単に選択できるようにできます。tf.io.browserFiles
は内部でファイルリーダー(FileReader API)を使用してファイルの内容を読み込み、それをTF.jsが解釈できる形式に変換します。この処理も非同期で行われます。
Pythonからの移行者へのヒント:非同期処理とファイル構造
Pythonでのモデルロードは通常、ファイルパスを指定するだけで完了します。一方、TF.jsでは非同期処理が中心となるため、await
キーワードを適切に使うことが重要です。初めてJavaScriptの非同期処理に触れる場合は、Promiseやasync/awaitの概念を別途学習することをお勧めします。Pythonのasyncioと同様の考え方で理解できる部分が多いです。
また、tensorflowjs_converter
で変換されたモデルは、model.json
ファイルと複数の .bin
ファイルに分割されます。model.json
にはモデルの構造や重みファイルへの参照が含まれており、ロード関数にはこの model.json
のパス(またはURL)を指定します。.bin
ファイルは model.json
からの相対パスで指定されているため、ロード時には通常 model.json
と同じディレクトリに置かれている必要があります。ローカルファイルからのロード(Node.js)やURLからのロードでは、TF.jsが自動的に .bin
ファイルを見つけ出してくれますが、ブラウザで tf.io.browserFiles
を使う場合は、model.json
と全ての .bin
ファイルをユーザーに選択してもらう必要があります。
まとめ
この記事では、TensorFlow.jsを使って画像認識モデルをローカルファイルやWeb上のURLからロードする具体的な方法を解説しました。
- TF.jsでのモデルロードは基本的に非同期で行われるため、
async/await
を用いたコーディングスタイルが推奨されます。 - Web上のURLからは
tf.loadLayersModel
やtf.loadGraphModel
にURLを直接指定します。認証が必要な場合はオプションを指定します。 - Node.js環境では
tfjs-node
パッケージを使用し、file://
プロトコルでファイルパスを指定します。 - ブラウザ環境でユーザーが選択したローカルファイルからは
tf.io.browserFiles
を使用します。 - Pythonでの経験を活かしつつ、JavaScript固有の非同期処理とTF.jsのファイル読み込みAPIを理解することが、スムーズなモデル利用の鍵となります。
モデルをロードできた後は、入力画像(テンソル)を準備し、モデルの predict
メソッドを使って推論を実行するステップに進むことができます。ロード処理と同様に、推論処理も通常は非同期で行われます。この記事で紹介したロード方法を基盤として、様々な環境でのTF.jsによる画像認識開発にぜひ挑戦してください。