連載第4回の目的

この回から2回にわたり、画像認識のサンプルを通じて、Googleの提供するMobileNetの使い方と、トレーニング済みのモデルを生かす転移学習を理解します。この回では、静止画像を認識するサンプルを通じて、MobileNetの基本的な使い方を理解します(図1)。

  • 図1:完成サンプルイメージ

    図1:完成サンプルイメージ

完成サンプル
https://github.com/wateryinhare62/mynavi_tensorflowjs/
[NOTE]転移学習とファインチューニング
転移学習とは追加学習ともいい、既存の学習モデルをベースとして、独自のデータをさらに学習させることにより、カスタマイズされた新たなモデルを作る手法です。通常のモデル作成に比べて、少ないデータかつ短時間で特定の目的に合ったモデルを作ることができます。
MobileNetをそのまま利用することはあまり現実的ではなく、転移学習を用いて目的/用途に応じたモデルに強化するのが一般的な使い方とされています。転移学習の例は、次回で紹介します。
なお、既存の学習モデルを再利用する手法としては、ファインチューニングもあります。転移学習が、追加の学習によってモデルをカスタム化するのに対し、ファインチューニングは「重み」というパラメータを文字通り微調整して再学習することで、モデルをカスタム化します。転移学習が後付け(上乗せ)でのカスタマイズになるのに対し、ファインチューニングはモデルそのものを作り変えるカスタマイズといえます。

今回のテーマは画像認識です。画像認識は、顔認証や自動車の運転支援など多方面で利用されており、機械学習の用途として分かりやすいもののひとつです。本記事では、静止画像が何の画像であるかを予測するサンプルを通じて、MobileNetによる画像認識の基本を理解します。

[NOTE]サンプルについて
本記事のサンプルは、Google Codelabのチュートリアル「TensorFlow.js 転移学習による画像分類器」(https://codelabs.developers.google.com/codelabs/tensorflowjs-teachablemachine-codelab?hl=ja#0)におけるサンプルをベースに、一部改変して作成、掲載しています。

MobileNetとは

前回前々回では、TensorFlow.jsのAPIを直接使ってモデルの構築、学習、汎化などを実践してきました。対象としていたデータは線形関係にある2次元データという極めてシンプルなもので、これを用いて機械学習の基本的な流れを理解するのが目的でした。
これに対して、画像認識や音声認識といったより実用的とされる用途では、一般的にモデルは複雑になり、学習のためのデータも膨大になり、計算量も大きなものとなります。誰もが適切なデータを大量に用意したり、学習のための時間や計算機リソースを確保できるかというと、それは一般的に困難です。
そこで、Googleが開発し、2017年にリリースしたのが「MobileNet」です。MobileNetは、モバイルデバイスなど非力なリソースの下でも効率的に動作するように設計された「畳み込みニューラルネットワーク」(CNN; Convolutional Neural Network)のアーキテクチャです。Depthwise Separable Convolutionといった計算量を削減するアルゴリズムを採用しており、スマートフォンなどでも十分な性能を発揮できる軽量さと、軽快な動作が特徴です。MobileNetのMobileとは文字通りモバイルユースを指し、Netはニューラルネットワークを意味します。
MobileNetは、初期バージョン(V1)から機能強化・改善を繰り返しており、最新版は2024年にリリースされたV4です。

畳み込みニューラルネットワークとは

MobileNetの実装する畳み込みニューラルネットワークとは、深層学習モデルの一つです。第1回において深層学習(ディープラーニング)について紹介しましたが、ディープラーニングで用いられる「ニューラルネットワーク」は、画像認識、音声認識、自然言語処理などの分野で応用できると説明しました。
畳み込みニューラルネットワークは、隠れ層に畳み込み層とプーリング層を組み合わせることで、画像内の特徴を効率的に学習し、高い精度で認識や分類を行うことができるように設計されたニューラルネットワークです(図2)。これにより、特に画像認識において高い能力を発揮し、画像分類、物体検出、画像生成などの幅広い用途で利用されています。

  • 図2:畳み込みニューラルネットワーク(CNN)

    図2:畳み込みニューラルネットワーク(CNN)

畳み込み層とは、画像データから特徴マップを生成することで、エッジや輪郭などの局所的な特徴を捉える役割を果たします。プーリング層とは、畳み込み層で抽出された特徴マップのサイズを縮小し、計算量を削減するとともに、位置のずれの影響を抑制する役割を果たします。

シンプルな画像認識――MobileNetの基本的な使い方を理解

MobileNetの基本的な使い方を理解するために、シンプルな画像認識の例を紹介します。MobileNetを使う準備と、あらかじめ用意した画像を認識するだけの、極めてシンプルなサンプルです。

[NOTE]CSSファイル
本記事のサンプルでは見た目を整えるために適当なスタイルをstyle.cssで設定しています。TensorFlow.jsやMobileNetとの関連は薄いので掲載は省略しています。具体的な内容は配布サンプルを参照してください。

HTMLファイルを用意する

サンプルの基点となるHTMLファイル(index.html)を用意します(リスト1)。ポイントは、2つのJavaScriptファイル(TensorFlow.jsとMobileNetライブラリ)をそれぞれCDNよりインポートしていることです。

リスト1 :index.html

…略…
<!-- (1)TensorFlow.js、MobileNetの読み込み -->
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/mobilenet"></script>
…略…
<!-- (2)判定する画像の選択 -->
<p><select id="photos" disabled>
  <option value="default">どれか画像を選んでください</option>
  <option value="image01">画像1</option>
  <option value="image02">画像2</option>
  <option value="image03">画像3</option>
  <option value="image04">画像4</option>
  <option value="image05">画像5</option>
  <option value="image06">画像6</option>
</select></p>
<!-- (3)判定する画像 -->
<img id="img" crossorigin width="227" height="227" alt="ここに画像が表示されます。" />
<!-- (4)判定結果の表示 -->
<div id="result" style="display: none;">
  <p>判定結果</p>
  <ol>
    <li><span id="result-class-1"></span>(確率:<span id="result-probability-1"></span>)</li>
    <li><span id="result-class-2"></span>(確率:<span id="result-probability-2"></span>)</li>
    <li><span id="result-class-3"></span>(確率:<span id="result-probability-3"></span>)</li>
  </ol>
</div>
<!-- (1)サンプル用スクリプトの読み込み -->
<script src="script.js"></script>
…略…

(1)の読み込みによって、以下のグローバル変数が利用可能になります。

  • tf:TensorFlow.jsライブラリを使うための変数
  • mobilenet:MobileNetライブラリを使うための変数

(2)に、判定したい画像のリストを作ります。option要素のvalue属性には、画像ファイルの名前(拡張子を除く)を設定します。ここではimage01~image06としましたが、同名のファイルか、あるいは画像ファイルに合わせてvalue属性を変更してください。

[NOTE]画像ファイルについて
配布サンプルには画像ファイルを含めていませんので、動作を確認するには各自で適当な画像ファイルを用意してください。この際、画像を正方形に整えておくと、画像認識の精度が向上します。

(3)は、(2)で選択した画像が表示されるプレースホルダです。ここに表示されている画像を判定します。
(4)に、判定結果を表示します。判定結果は3個得られるので、その個数分の「クラス」と「確率」を表示するspan要素を含めています。

JavaScriptファイルを用意する

続けて、JavaScriptファイル(script.js)を用意します(リスト2)。

リスト2 :script.js

// (1)モデルを収納する変数とHTML要素を参照する変数の用意
let net;
const selecterElement = document.getElementById('photos');
const imageElement = document.getElementById('img');
const resultElement = document.getElementById('result');

// (2)初期化関数。モデルを読み込む
async function init() {
  console.log('mobilenetを読み込み中です...');
  net = await mobilenet.load();
  console.log('mobilenetの読み込みが終了しました');
  selecterElement.disabled = false;
}

// (3)判定関数。画像から判定結果を取得してHTMLに反映する
async function classifyImage() {
  resultElement.style.display = 'none';
  const result = await net.classify(imageElement);
  for (let i = 0; i < result.length; i++) {
    document.getElementById(`result-class-${i + 1}`).innerText = result[i].className;
    document.getElementById(`result-probability-${i + 1}`).innerText = result[i].probability.toFixed(4);
  }
  resultElement.style.display = 'block';
}

// (4)画像ファイル選択で画像を表示するイベントハンドラ
selecterElement.addEventListener('change', () => {
  const value = selecterElement.value;
  if (value !== 'default') {
    imageElement.src = `${value}.jpg`;
  }
});

// (5)画像読み込み終了で判定を開始するイベントハンドラ
imageElement.addEventListener('load', () => {
  classifyImage();
});

// (6)初期化の実行(最後に行う)
init();

MobileNetに関連する処理は、(2)のloadメソッドと、(3)のclassifyメソッドです。それぞれ、以下の役割を持ちます。

  • loadメソッド:MobileNetの学習済みモデルを読み込む
  • classifyメソッド:引数の要素にある画像を判定する(第2引数で候補数を指定できる。既定値は3)

MobileNetを使うと、この2つのメソッドを使うだけで、最低限の画像判定ができるわけです。特にclassifyメソッドは、戻り値は候補の配列であり、それぞれのclassNameプロパティでクラスを、probabilityプロパティで確率を、それぞれ取得できます。

動作確認する

index.htmlファイルをブラウザで読み込んで画像を選択し、例えば図3のように表示されればOKです。

  • 図3:サンプル「MobileNetによる静止画像認識」の実行結果

    図3:サンプル「MobileNetによる静止画像認識」の実行結果

ここでは、画像の右に3つの判定結果が確率順に表示されています。猫(縞虎)の画像に対して「tiger cat」「tabby, tabby cat」などと表示され、それぞれ確率が0.8242、0.1584であることが分かります(確率は、実行のたびに微妙に変化します)。このとき「tiger cat」をクラスといい、画像が「tiger cat」クラスに確率0.8242で分類されたということになります。

まとめ

今回は、MobileNetを利用した静止画像の認識を紹介しました。極めてシンプルな手順で画像認識を実施できることをお伝えできたのではないかと思います。
次回は、MobileNetを利用した画像認識の続編として、カメラからの画像をリアルタイムで認識するサンプル、転移学習により独自の画像認識に対応させるサンプルを紹介します。

WINGSプロジェクト 山内直(著) 山田 祥寛(監修)
有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。現在も執筆メンバーを募集中。興味のある方は、どしどし応募頂きたい。著書、記事多数。
RSS
X:@WingsPro_info(公式)@WingsPro_info/wings(メンバーリスト)
Facebook

<著者について>
WINGSプロジェクト所属のテクニカルライター。出版社を経てフリーランスとして独立。ライター、エディター、デベロッパー、講師業に従事。屋号は「たまデジ。」。