虎の穴ラボ技術ブログ

虎の穴ラボ株式会社所属のエンジニアが書く技術ブログです

MENU

「初めてのTensorFlow.js」を読んで、簡単な転移学習やってみた

読んだきっかけ

こんにちは、虎の穴ラボの後藤です。今回は「初めてのTensorFlow.js ―JavaScriptで学ぶ機械学習」のご紹介です。

私がこの本を手に取ったのは、JavaScript 環境で機械学習を行う方法に興味を持ったからです。
機械学習といえば Python が主流ですが、TensorFlow.js を使えば JavaScript でも実現できることを知り、それならば自分でも出来るかもしれない!と思い取り組んでみました。

書籍情報

項目 詳細
タイトル 初めてのTensorFlow.js ―JavaScriptで学ぶ機械学習
著者 著者 Gant Laborde 著、あんどうやすし 訳
ページ数 368 ページ
発売日 2022/06/29
ISBN 978-4-87311-993-9
発行元 オライリー・ジャパン

www.oreilly.co.jp

全体的な感想

「初めてのTensorFlow.js ―JavaScriptで学ぶ機械学習」は機械学習初心者にとって非常に親しみやすい一冊でした!

自分の力で機械学習を活用できるようになる
書籍のゴールとして、自分の力で TensorFlow.js を用いて機械学習に取り組めることが設定されています。
そのため各章で復習問題と挑戦問題が用意されており、知識を確認しながら段階的に理解を進めることができます。

難解な数学を用いず、知識が全くなくても理解できる説明に努めている
書籍のなかで複雑な数式といったものは使われず、簡潔な説明やサンプルを通して学ぶことができます。
専門的な数学知識がなくても、理解しながら機械学習に入門することができました!

画像やスクリーンショットが多く、イメージを掴みやすい
視覚的な情報が豊富に掲載されているため、手順や結果を具体的にイメージしやすかったです。
実際にコードを書く際にも、どんな操作をしているかイメージしながら取り組め、スムーズに理解を深めることができました。

TensorFlow.js で重要な事柄をピックアップして解説している
幅広いトピックがカバーされていますが、それぞれの内容がしっかりと絞り込まれており、重要なポイントが分かりやすく解説されています。

全体として、この本は JavaScript 環境での機械学習に興味を持つ方にとって、とてもオススメできるものでした!

簡単な機械学習やってみた

書籍で得た知識を活用し「2種のメイドちゃんを識別するモデル」を転移学習で作ってみます。

データセット

とらラボが公開している素材集を利用します。

toranoana-lab.co.jp

特徴モデルの選択

今回は mobilenet_v3 を選択し、画像の特徴だけを抽出できる分割済みのモデルを利用します。

www.kaggle.com

また、モデルが期待する入力画像の要件は 2 つありました。

  • 入力画像は 224 x 224 のサイズであること
  • 各ピクセルの色値は 0 から 1 であること

画像の特徴検出

早速、特徴モデルを用いて画像の特徴を検出してみます。
特徴モデルのドキュメントに記載されていたサンプルコードを参考に下記の処理を実施しました。

  • 画像をテンソルに変換する
  • 入力画像テンソルを 224 x 224 にリサイズ、値を正規化
  • 特徴検出
// 一部省略しています

// 画像テンソルをリサイズかつ正規化
function preprocess(imageTensor: tf.Tensor3D): tf.Tensor4D {
  const widthToHeight = imageTensor.shape[1] / imageTensor.shape[0];
  let squareCrop;
  if (widthToHeight > 1) {
    const heightToWidth = imageTensor.shape[0] / imageTensor.shape[1];
    const cropTop = (1 - heightToWidth) / 2;
    const cropBottom = 1 - cropTop;
    squareCrop = [[cropTop, 0, cropBottom, 1]];
  } else {
    const cropLeft = (1 - widthToHeight) / 2;
    const cropRight = 1 - cropLeft;
    squareCrop = [[0, cropLeft, 1, cropRight]];
  }
  const crop = tf.image.cropAndResize(
    tf.expandDims(imageTensor) as tf.Tensor4D,
    squareCrop,
    [0],
    [224, 224],
  );
  return crop.div(255);
}

const loadImage = async (src: string) => {
  const img = new Image();
  img.src = src;
  await new Promise((resolve) => {
    img.onload = resolve;
  });
  const imageTensor = tf.browser.fromPixels(img);
  return preprocess(imageTensor);
};

// モデルの読み込み
const model = await tf.loadGraphModel("models/mobilenet-v3-feature-vector/model.json");

// 特徴検出
const features: tf.Tensor[] = [];
for (const src of images) {
  // オリジナル画像
  const imageTensor = await loadImage(src);
  const feature = model.predict(imageTensor) as tf.Tensor;
  features.push(feature);

  // 左右反転した画像
  const flippedImageTensor = tf.image.flipLeftRight(imageTensor);
  const flippedFeature = model.predict(flippedImageTensor) as tf.Tensor;
  features.push(flippedFeature);
}
const featureTensor = tf.concat(features, 0) as tf.Tensor2D;

特徴モデルを用いて画像を特徴量のテンソルに変換することができました!

転移学習

それではモデルを作成してみます
ユニット数やエポック数は最適なものがまだ分からず、試行錯誤しながら調整しました🫠

const transferModel = tf.sequential();
transferModel.add(
  tf.layers.dense({
    inputShape: [featureTensor.shape[1]],
    units: 128,
    activation: "relu",
  }),
);
transferModel.add(tf.layers.dense({ units: 2, activation: "softmax" }));

transferModel.compile({
  optimizer: "adam",
  loss: "sparseCategoricalCrossentropy",
  metrics: ["accuracy"],
});

await transferModel.fit(featureTensor, labels, {
  validationSplit: 0.2,
  epochs: 10,
  callbacks: { onEpochEnd: console.log },
});

作成したモデルで推論

学習に使用していないデータで推論してみると...

識別できていますね!

ふりかえり

過去に入門で挫折したことのある機械学習でしたが、「初めてのTensorFlow.js」は非常にわかりやすく、理解を深めながら学習を進めることが出来ました。
自分でモデルを見つけ、調整し、課題を解決するまでの力をつけることができるので、これから機械学習に入門したい方にオススメです!

Fantia開発採用情報

虎の穴ラボでは現在、一緒にFantiaを開発していく仲間を積極募集中です!
多くのユーザーに使っていただけるtoCサービスの開発をやってみたい方は、ぜひ弊社の採用情報をご覧ください。
toranoana-lab.co.jp