10_1 Kerasモデルを訓練し、TensorFlow.jsモデルに変換して、サーバーに配置する

ネコと犬を区別するKerasモデルをインターネット上で探すと、「ardamavi/Dog-Cat-Classifier」というページが見つかったので、これを使わせてもらうことにします。ページ右端にある[Clone or download]ボタンを使って、ZIPファイルをダウンロードします。

ZIPファイルを展開すると、Dog-Cat-Classifier-masterという名前のフォルダが現れます。この中には、モデルを訓練するPythonコードが書かれたファイルtrain.pyや、モデルの訓練に必要なデータがセットになって含まれています。

train.pyをテキストエディタで開き、34行めのsave_model(model)の下に、次の1行を挿入します。

model.save('cat_dog_model.h5')

[Anaconda Prompt (tfjs)]を起動し、Dog-Cat-Classifier-masterフォルダに移動します。そして、次のコマンドを使って、Python環境での訓練を開始します。

python train.py

すると、[Anaconda Prompt (tfjs)]で次のような訓練経過が表示され、長い時間をかけてモデルが訓練されます。

Epoch 1/25
1259/1259 [==============================] - 37s 30ms/step - loss: 1.4986 - acc: 0.5134 - val_loss: 0.6899 - val_acc: 0.4893
Epoch 2/25
1259/1259 [==============================] - 37s 29ms/step - loss: 0.6954 - acc: 0.5450 - val_loss: 0.7377 - val_acc: 0.5536
Epoch 3/25
1259/1259 [==============================] - 37s 29ms/step - loss: 0.6645 - acc: 0.5961 - val_loss: 0.7586 - val_acc: 0.5821
Epoch 4/25
1259/1259 [==============================] - 37s 29ms/step - loss: 0.6294 - acc: 0.6500 - val_loss: 0.7160 - val_acc: 0.6500

訓練が終わると、Dog-Cat-Classifier-masterフォルダにcat_dog_model.h5という名前のファイルが作成されます。

このH5ファイルを、tensorflowjs converterでTensorFlow.jsモデルに変換します。

tensorflowjs_converter --input_format=keras cat_dog_model.h5 model

TensorFlow.jsモデルへの変換に成功すると、Dog-Cat-Classifier-masterフォルダにmodelフォルダが作成されます。中にはmodel.jsonとgroup1-shard1of1ファイルが含まれているので、modelフォルダを、適切なWebサーバーにコピーします。

モデルは次のようなコードで、TensorFlow.jsアプリに読み込むことができます。

const model = await tf.loadModel('https://localhost/dev/9_dog_cat/model/model.json');

下図は、Dog-Cat-Classifier-masterフォルダで提供されているサンプル画像をテストしたところです。

以下は、上図で使用しているJavaScriptコードの抜粋です。

const inputFile = document.getElementById('input-file');
// ページには表示されない<img>要素
const preview = document.querySelector('img');
// [ファイルを選択]ボタンで画像を選択したら
inputFile.addEventListener('change', (e) => {
    // 取得したファイル
    const imageFile = e.target.files[0];
    // ファイルの読み取りに成功したら、readPromise.then()を実行する
    new Promise((resolve, reject) => {
        const reader = new FileReader();
        // ファイルの読み取りに成功したら解決する
        reader.onload = (e) => {
                resolve(e.target.result);
            }
            // ファイルを画像として読み取る
        reader.readAsDataURL(imageFile);
        // 成功したら、<img>要素に画像を割り当てる
    }).then((img) => {
        // 画像が読み込まれたら
        preview.onload = async() => {
            // 読み込む画像の幅と高さ用変数
            const imageWidth = preview.naturalWidth;
            const imageHeight = preview.naturalHeight;
            // <canvas>を作成して、それに画像のイメージデータを割り当てる
            const canvas = document.createElement('canvas');
            canvas.width = imageWidth;
            canvas.height = imageHeight;
            const context = canvas.getContext('2d');

            // キャンバスに画像を描画する
            context.drawImage(preview, 0, 0);
            // イメージデータを取得
            const imageData = context.getImageData(0, 0, imageWidth, imageHeight);
            // キャンバスをページに表示 = 写真が見えるようになる。
            document.getElementById('image-container').appendChild(canvas);

            // モデルを読み込む
            const model = await tf.loadModel('https://localhost/dev/9_dog_cat/model/model.json');
            // imageDataを、カラーを保持したまま、tf.Tensorに変換する。
            // tf.fromPixels()はtf.Tensor3Dを返す。
            const image3d = tf.fromPixels(imageData, 3);
            console.log(image3d.shape); // [128, 128, 3]
            // 64 x 64のサイズに変更する
            const image6464 = tf.image.resizeBilinear(image3d, [64, 64]);
            console.log(image6464.shape); // [64, 64, 3]
            const imageExpanded = tf.expandDims(image6464);
            console.log(imageExpanded.shape); // [1, 64, 64, 3]
            const output = model.predict(imageExpanded);
            const predictions = Array.from(output.argMax(1).dataSync());
            // 0がネコ、1が犬
            console.log(predictions);

        }
        preview.src = img;
    });
}, false);

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

CAPTCHA