Keras と TPU を使用した畳み込みニューラル ネットワーク

1. 概要

このラボでは、花を認識できるニューラル ネットワーク モデルに畳み込みレイヤを組み立てる方法を学習します。今回は、モデルをゼロから構築し、TPU のパワーを使用して数秒でトレーニングして、設計を反復処理します。

このラボには、畳み込みニューラル ネットワークに関する必要な理論的説明が含まれており、ディープ ラーニングを学習するデベロッパーにとって良い出発点となります。

このラボは、「Keras on TPU」シリーズのパート 3 です。これらの手順は、次の順序で実行することも、個別に行うこともできます。

ca8cc21f6838eccc.png

学習内容

  • Keras Sequential モデルを使用して畳み込み画像分類子を構築する。
  • TPU で Keras モデルをトレーニングするには
  • 畳み込みレイヤを適切に選択してモデルをファインチューニングする。

フィードバック

この Codelab で何か問題が見つかった場合は、お知らせください。フィードバックは GitHub の問題 [フィードバック リンク] から送信できます。

2. Google Colaboratory クイック スタート

このラボでは Google Collaboratory を使用するため、ユーザー側での設定は不要です。Colaboratory は、教育目的のオンライン ノートブック プラットフォームです。CPU、GPU、TPU のトレーニングを無料で提供しています。

688858c21e3beff2.png

このサンプル ノートブックを開いて、いくつかのセルを実行すると、Colaboratory の使い方を理解できます。

c3df49e90e5a654f.png Welcome to Colab.ipynb

TPU バックエンドを選択する

8832c6208c99687d.png

Colab のメニューで、[ランタイム] > [ランタイムのタイプを変更] を選択し、[TPU] を選択します。このコードラボでは、ハードウェア アクセラレータによるトレーニングをサポートする強力な TPU(Tensor Processing Unit)を使用します。ランタイムへの接続は、初回実行時に自動的に行われます。右上にある [接続] ボタンを使用することもできます。

ノートブックの実行

76d05caa8b4db6da.png

セルを 1 つずつ実行するには、セルをクリックして Shift+Enter キーを押します。[ランタイム] > [すべて実行] を選択して、ノートブック全体を実行することもできます。

目次

429f106990037ec4.png

すべてのノートブックに目次があります。左側の黒い矢印を使用して開くことができます。

非表示のセル

edc3dba45d26f12a.png

一部のセルにはタイトルのみが表示されます。これは Colab 固有のノートブック機能です。ダブルクリックすると内部のコードを確認できますが、通常はあまり興味深いものではありません。通常はサポート関数またはビジュアリゼーション関数。内部の関数を定義するには、これらのセルを実行する必要があります。

認証

cdd4b41413100543.png

承認済みアカウントで認証すれば、Colab からプライベート Google Cloud Storage バケットにアクセスできます。上記のコード スニペットは、認証プロセスをトリガーします。

3. [INFO] Tensor Processing Unit(TPU)とは

概要

f88cf6facfc70166.png

Keras で TPU 上でモデルをトレーニングするコード(TPU が使用できない場合は GPU または CPU にフォールバックします)。

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

今日は、TPU を使用して、インタラクティブな速度(トレーニング実行あたり数分)で花の分類子を構築して最適化します。

688858c21e3beff2.png

TPU を使用する理由

最新の GPU は、プログラマブルな「コア」を中心に構成されています。これは、3D レンダリング、ディープ ラーニング、物理シミュレーションなど、さまざまなタスクを処理できる非常に柔軟なアーキテクチャです。一方、TPU は、従来のベクトル プロセッサと専用の行列乗算ユニットを組み合わせたもので、ニューラル ネットワークなど、大規模な行列乗算が支配的なタスクに優れています。

8eb3e718b8e2ed08.png

図: 密ニューラル ネットワーク レイヤを行列乗算として表した図。8 枚の画像のバッチがニューラル ネットワークで一度に処理されます。1 行 x 列の乗算を実行して、画像内のすべてのピクセル値の加重和が実際に計算されていることを確認してください。畳み込みレイヤも行列乗算として表現できますが、少し複雑になります( 説明はこちらのセクション 1 をご覧ください)。

ハードウェア

MXU と VPU

TPU v2 コアは、行列乗算を実行する Matrix Multiply Unit(MXU)と、活性化やソフトマックスなどの他のすべてのタスク用の Vector Processing Unit(VPU)で構成されています。VPU は float32 と int32 の計算を処理します。一方、MXU は混合精度 16 ~ 32 ビットの浮動小数点形式で動作します。

7d68944718f76b18.png

混合精度浮動小数点と bfloat16

MXU は、bfloat16 入力と float32 出力を使用して行列乗算を計算します。中間累積は float32 精度で実行されます。

19c5fc432840c714.png

通常、ニューラル ネットワークのトレーニングは、浮動小数点精度の低下によって生じるノイズの影響を受けません。ノイズがオプティマイザーの収束に役立つ場合もあります。16 ビット浮動小数点精度は、従来、計算の高速化に使用されてきましたが、float16 形式と float32 形式では範囲が大きく異なります。精度を float32 から float16 に下げると、通常はオーバーフローとアンダーフローが発生します。ソリューションは存在しますが、通常は float16 を機能させるために追加の作業が必要です。

そのため、Google は TPU に bfloat16 形式を導入しました。bfloat16 は、float32 とまったく同じ指数ビットと範囲を持つ切り捨てられた float32 です。また、TPU は bfloat16 入力と float32 出力を使用して混合精度で行列乗算を計算するため、通常は、精度を下げてパフォーマンスを向上させるためにコードを変更する必要はありません。

シストリック アレイ

MXU は、データ要素がハードウェア コンピューティング ユニットの配列を流れる「シストリック アレイ」アーキテクチャを使用して、ハードウェアで行列乗算を実装します。(医学では、収縮期とは心臓の収縮と血流を指しますが、ここではデータの流れを指します)。

行列乗算の基本要素は、一方の行列の行と他方の行列の列の内積です(このセクションの上部の図を参照)。行列乗算 Y=X*W の場合、結果の 1 つの要素は次のようになります。

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

GPU では、このドット積を GPU の「コア」にプログラムし、利用可能なすべての「コア」で並列実行して、結果の行列のすべての値を一度に計算しようとします。結果の行列が 128x128 の大きさの場合、128x128=16K 個の「コア」が必要になりますが、これは通常不可能です。最大の GPU には約 4,000 個のコアがあります。一方、TPU は MXU のコンピューティング ユニットに最小限のハードウェア(bfloat16 x bfloat16 => float32 乗算累算器のみ)を使用します。これらは非常に小さいため、TPU は 128x128 MXU に 16 K 個を実装し、この行列乗算を一度に処理できます。

f1b283fc45966717.gif

図: MXU シストリック アレイ。コンピューティング要素は乗算アキュムレータです。1 つの行列の値が配列に読み込まれます(赤い点)。もう一方の行列の値は配列を通過します(灰色の点)。縦線は値を上に伝播します。水平線は部分和を伝播します。配列をデータが流れるときに、右側から行列乗算の結果が得られることを確認するのは、ユーザーの演習として残されています。

また、MXU でドット積が計算されている間、中間合計は隣接するコンピューティング単位間を流れるだけです。メモリやレジスタ ファイルに保存して取得する必要はありません。その結果、TPU シストリック アレイ アーキテクチャは、行列乗算の計算において、GPU よりも密度と電力の面で大きな利点があり、速度の面でも無視できない利点があります。

Cloud TPU

Google Cloud Platform で「Cloud TPU v2」をリクエストすると、PCI 接続の TPU ボードを備えた仮想マシン(VM)が取得されます。TPU ボードには、4 つのデュアルコア TPU チップがあります。各 TPU コアには、VPU(ベクトル処理ユニット)と 128x128 MXU(マトリックス乗算ユニット)があります。この「Cloud TPU」は通常、ネットワークを介してリクエストした VM に接続されます。全体像は次のようになります。

dfce5522ed644ece.png

図: ネットワーク接続された「Cloud TPU」アクセラレータを備えた VM。「Cloud TPU」自体は、PCI 接続の TPU ボードと、そのボードに搭載された 4 つのデュアルコア TPU チップを備えた VM で構成されています。

TPU Pod

Google のデータセンターでは、TPU はハイ パフォーマンス コンピューティング(HPC)相互接続に接続されており、1 つの非常に大きなアクセラレータとして認識されることがあります。Google はこれらを Pod と呼び、最大 512 個の TPU v2 コアまたは 2,048 個の TPU v3 コアを包含できます。

2ec1e0d341e7fc34.jpeg

図: TPU v3 Pod。HPC 相互接続を介して接続された TPU ボードとラック。

トレーニング中、勾配は all-reduce アルゴリズム(all-reduce の詳細はこちら)を使用して TPU コア間で交換されます。トレーニング対象のモデルは、大きなバッチサイズでトレーニングすることでハードウェアを活用できます。

d97b9cc5d40fdb1d.gif

図: Google TPU の 2 次元トーラス メッシュ HPC ネットワークで all-reduce アルゴリズムを使用してトレーニング中に勾配を同期する。

ソフトウェア

大規模なバッチサイズのトレーニング

TPU の理想的なバッチサイズは TPU コアあたり 128 個のデータ項目ですが、ハードウェアは TPU コアあたり 8 個のデータ項目から高い使用率を示します。1 つの Cloud TPU には 8 個のコアがあります。

この Codelab では、Keras API を使用します。Keras で指定するバッチは、TPU 全体のグローバル バッチサイズです。バッチは自動的に 8 つに分割され、TPU の 8 個のコアで実行されます。

da534407825f01e3.png

パフォーマンスに関するその他のヒントについては、TPU パフォーマンス ガイドをご覧ください。バッチサイズが非常に大きい場合は、一部のモデルで特別な注意が必要になることがあります。詳しくは、LARSOptimizer をご覧ください。

仕組み: XLA

Tensorflow プログラムは計算グラフを定義します。TPU は Python コードを直接実行するのではなく、TensorFlow プログラムで定義された計算グラフを実行します。内部では、XLA(高速線形代数コンパイラ)と呼ばれるコンパイラが、計算ノードの Tensorflow グラフを TPU マシンコードに変換します。このコンパイラは、コードとメモリ レイアウトに対して多くの高度な最適化も実行します。コンパイルは、作業が TPU に送信されると自動的に行われます。ビルドチェーンに XLA を明示的に含める必要はありません。

edce61112cd57972.png

図: TPU で実行するには、TensorFlow プログラムで定義された計算グラフをまず XLA(アクセラレータ線形代数コンパイラ)表現に変換し、次に XLA によって TPU マシンコードにコンパイルします。

Keras で TPU を使用する

Tensorflow 2.1 以降、Keras API を介して TPU がサポートされています。Keras のサポートは、TPU と TPU Pod で機能します。TPU、GPU、CPU で動作する例を次に示します。

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

このコード スニペットでは:

  • TPUClusterResolver().connect() は、ネットワーク上の TPU を検出します。ほとんどの Google Cloud システム(AI Platform ジョブ、Colaboratory、Kubeflow、ctpu up ユーティリティで作成された Deep Learning VM)でパラメータなしで動作します。これらのシステムは、TPU_NAME 環境変数のおかげで TPU の場所を認識しています。TPU を手動で作成する場合は、使用する VM で TPU_NAME 環境変数を設定するか、明示的なパラメータを指定して TPUClusterResolver を呼び出します。TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy は、分布と「all-reduce」勾配同期アルゴリズムを実装する部分です。
  • この戦略はスコープを通じて適用されます。モデルは strategy scope() 内で定義する必要があります。
  • tpu_model.fit 関数は、TPU トレーニングの入力として tf.data.Dataset オブジェクトを想定しています。

一般的な TPU の移植タスク

  • Tensorflow モデルでデータを読み込む方法は多数ありますが、TPU では tf.data.Dataset API を使用する必要があります。
  • TPU は非常に高速であるため、TPU で実行すると、データの取り込みがボトルネックになることがよくあります。TPU パフォーマンス ガイドには、データ ボトルネックを検出するために使用できるツールや、その他のパフォーマンスに関するヒントが記載されています。
  • int8 または int16 の数値は int32 として扱われます。TPU には、32 ビット未満で動作する整数ハードウェアはありません。
  • 一部の TensorFlow オペレーションはサポートされていません。リストはこちらをご覧ください。この制限はトレーニング コード(モデルのフォワード パスとバックワード パス)にのみ適用されます。データ入力パイプラインでは、すべての TensorFlow オペレーションを CPU で実行できるため、引き続き使用できます。
  • TPU では tf.py_func はサポートされていません。

4. [INFO] ニューラル ネットワーク分類器 101

概要

次の段落の太字の用語をすべてご存知の場合は、次の演習に進んでください。ディープ ラーニングを始めたばかりの方は、ぜひこのまま読み進めてください。

レイヤのシーケンスとして構築されたモデルの場合、Keras は Sequential API を提供します。たとえば、3 つの密なレイヤを使用する画像分類器は、Keras で次のように記述できます。

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

密結合ニューラル ネットワーク

これは、画像を分類するための最も単純なニューラル ネットワークです。レイヤに配置された「ニューロン」で構成されています。最初のレイヤは入力データを処理し、その出力を他のレイヤに渡します。各ニューロンが前のレイヤのすべてのニューロンに接続されているため、「密」と呼ばれます。

c21bae6dade487bc.png

このようなネットワークに画像をフィードするには、すべてのピクセルの RGB 値を長いベクトルに平坦化して入力として使用します。画像認識に最適な手法ではありませんが、後で改善します。

ニューロン、アクティベーション、RELU

「ニューロン」は、すべての入力の加重和を計算し、「バイアス」と呼ばれる値を加算して、結果を「活性化関数」と呼ばれる関数に渡します。重みとバイアスは最初は不明です。これらはランダムに初期化され、既知のデータでニューラル ネットワークをトレーニングすることで「学習」されます。

644f4213a4ee70e5.png

最も一般的な活性化関数は、Rectified Linear Unit の略である RELU と呼ばれます。上のグラフでわかるように、非常にシンプルな関数です。

Softmax アクティベーション

上記のネットワークは、花を 5 つのカテゴリ(バラ、チューリップ、タンポポ、デイジー、ヒマワリ)に分類するため、5 つのニューロン レイヤで終わります。中間レイヤのニューロンは、従来の RELU アクティベーション関数を使用してアクティブ化されます。ただし、最後のレイヤでは、この花がバラである確率、チューリップである確率などを表す 0 ~ 1 の数値を計算します。これには、「ソフトマックス」と呼ばれる活性化関数を使用します。

ベクトルに softmax を適用するには、各要素の指数関数を取り、通常は L1 ノルム(絶対値の合計)を使用してベクトルを正規化します。これにより、値の合計が 1 になり、確率として解釈できます。

ef0d98c0952c262d.png d51252f75894479e.gif

交差エントロピー損失

ニューラル ネットワークが入力画像から予測を生成するようになったので、その予測の精度を測定する必要があります。つまり、ネットワークが示す内容と正解(ラベルと呼ばれることが多い)との間の距離を測定します。データセット内のすべての画像に正しいラベルが付いていることを思い出してください。

どの距離でも機能しますが、分類問題では「交差エントロピー距離」が最も効果的です。これをエラー関数または損失関数と呼びます。

7bdf8753d20617fb.png

勾配降下法

ニューラル ネットワークの「トレーニング」とは、実際には、トレーニング画像とラベルを使用して、交差エントロピー損失関数を最小限に抑えるように重みとバイアスを調整することを意味します。仕組みは次のとおりです。

クロスエントロピーは、重み、バイアス、トレーニング画像のピクセル、既知のクラスの関数です。

すべての重みとすべてのバイアスに対してクロスエントロピーの偏導関数を計算すると、特定の画像、ラベル、重みとバイアスの現在の値に対して計算された「勾配」が得られます。重みとバイアスは数百万個になる可能性があるため、勾配の計算は大変な作業になります。幸いなことに、Tensorflow がこの処理を代わりに行ってくれます。グラデーションの数学的特性は、「上」を指すことです。交差エントロピーが低い方向に進みたいので、反対方向に進みます。重みとバイアスは、勾配の分数で更新します。次に、トレーニング ループで、次のバッチのトレーニング画像とラベルを使用して同じ処理を繰り返し行います。この最小値が 1 つである保証はありませんが、この最小値に収束することを期待します。

gradient descent2.png

ミニバッチ処理とモメンタム

1 つのサンプル画像でグラデーションを計算し、重みとバイアスをすぐに更新することもできますが、たとえば 128 枚の画像のバッチでグラデーションを計算すると、さまざまなサンプル画像によって課せられる制約をより適切に表すグラデーションが得られるため、解に収束する可能性が高くなります。ミニバッチのサイズは調整可能なパラメータです。

この手法は「確率的勾配降下法」と呼ばれることもありますが、バッチ処理を行うことで、より大きな行列を扱うことになり、GPU や TPU での最適化が容易になるという実用的なメリットもあります。

ただし、収束はややカオスになる可能性があり、グラデーション ベクトルがすべてゼロの場合には停止することもあります。これは、最小値が見つかったことを意味しますか?必ずしも違反警告を受けるとは限りません。グラデーション コンポーネントは、最小値または最大値でゼロになることがあります。数百万個の要素を持つ勾配ベクトルで、すべての要素がゼロの場合、すべてのゼロが最小値に対応し、最大値に対応するゼロがない確率はかなり小さくなります。多次元空間では鞍点が非常に一般的であり、そこで停止したくありません。

52e824fe4716c4a0.png

イラスト: 鞍点。グラデーションは 0 ですが、すべての方向で最小値ではありません。(画像帰属 Wikimedia: By Nicoguaro - Own work, CC BY 3.0

解決策は、最適化アルゴリズムに運動量を追加して、鞍点を停止せずに通過できるようにすることです。

用語集

バッチまたはミニバッチ: トレーニングは常にトレーニング データとラベルのバッチで実行されます。これにより、アルゴリズムの収束が促進されます。「バッチ」ディメンションは通常、データテンソルの最初のディメンションです。たとえば、シェイプ [100, 192, 192, 3] のテンソルには、192x192 ピクセルの画像が 100 個含まれており、各ピクセルには 3 つの値(RGB)があります。

交差エントロピー損失: 分類子でよく使用される特殊な損失関数。

密結合層: 各ニューロンが前のレイヤのすべてのニューロンに接続されているニューロンのレイヤ。

特徴: ニューラル ネットワークの入力は「特徴」と呼ばれることもあります。優れた予測を得るために、データセットのどの部分(または部分の組み合わせ)をニューラル ネットワークにフィードするかを判断する技術は、「特徴量エンジニアリング」と呼ばれます。

ラベル: 教師あり分類問題における「クラス」または正解の別の名前

学習率: トレーニング ループの各イテレーションで重みとバイアスが更新される勾配の割合。

ロジット: 活性化関数が適用される前のニューロンのレイヤの出力は「ロジット」と呼ばれます。この用語は、かつて最も一般的な活性化関数であった「ロジスティック関数」(「シグモイド関数」とも呼ばれます)に由来します。「Neuron outputs before logistic function」が「logits」に短縮されました。

loss: ニューラル ネットワークの出力と正解を比較する誤差関数

ニューロン: 入力の加重和を計算し、バイアスを追加して、活性化関数を通じて結果をフィードします。

ワンホット エンコード: 5 つのクラスのうちのクラス 3 は、5 つの要素のベクトルとしてエンコードされます。3 番目の要素を除いてすべてゼロです。

relu: 正規化線形ユニット。ニューロンでよく使用される活性化関数。

sigmoid: 以前はよく使用されていた別の活性化関数で、特殊なケースでは今でも有用です。

softmax: ベクトルに作用し、最大成分と他のすべての成分の差を大きくする特別な活性化関数。また、確率のベクトルとして解釈できるように、ベクトルの合計が 1 になるように正規化します。分類子の最後のステップとして使用されます。

tensor: 「テンソル」は行列のようなものですが、任意の数の次元を持つことができます。1 次元テンソルはベクトルです。2 次元テンソルは行列です。3 次元、4 次元、5 次元以上のテンソルを使用することもできます。

5. [新情報] 畳み込みニューラル ネットワーク

概要

次の段落の太字の用語をすべてご存知の場合は、次の演習に進んでください。畳み込みニューラル ネットワークを初めて使用する場合は、このままお読みください。

convolutional.gif

図: 4x4x3=48 個の学習可能な重みで構成される 2 つの連続したフィルタで画像をフィルタリングする。

Keras での単純な畳み込みニューラル ネットワークは次のようになります。

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

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

畳み込みネットワークのレイヤでは、1 つの「ニューロン」が、画像の小さな領域のみで、すぐ上のピクセルの加重和を計算します。通常の密結合レイヤのニューロンと同様に、バイアスを追加して、活性化関数を介して合計を渡します。このオペレーションは、同じ重みを使用して画像全体で繰り返されます。密結合レイヤでは、各ニューロンに独自の重みがありました。ここでは、重みの単一の「パッチ」が画像上を双方向にスライドします(「畳み込み」)。出力には、画像内のピクセル数と同じ数の値が含まれます(ただし、エッジでパディングが必要になります)。これは、4×4×3=48 個の重みを持つフィルタを使用するフィルタリング オペレーションです。

ただし、48 個の重みでは不十分です。自由度を高めるために、新しい重みのセットで同じ操作を繰り返します。これにより、新しい一連のフィルタ出力が生成されます。入力画像の R、G、B チャネルとの類似性から、出力の「チャネル」と呼びます。

Screen Shot 2016-07-29 at 16.02.37.png

2 つ以上の重みのセットは、新しいディメンションを追加することで 1 つのテンソルとして合計できます。これにより、畳み込みレイヤの重みテンソルの一般的な形状が得られます。入力チャネルと出力チャネルの数はパラメータであるため、畳み込みレイヤのスタックとチェーンを開始できます。

d1b557707bcd1cb9.png

図: 畳み込みニューラル ネットワークがデータの「キューブ」を別のデータの「キューブ」に変換する。

ストライド畳み込み、最大プーリング

ストライド 2 または 3 で畳み込みを行うことで、結果のデータキューブを水平方向に縮小することもできます。これを行うには、次の 2 つの一般的な方法があります。

  • ストライド畳み込み: 上記のスライディング フィルタ。ただし、ストライドが 1 より大きい
  • 最大プーリング: MAX オペレーションを適用するスライディング ウィンドウ(通常は 2x2 パッチで、2 ピクセルごとに繰り返されます)

2b2d4263bb8470b.gif

図: コンピューティング ウィンドウを 3 ピクセル スライドさせると、出力値が少なくなります。ストライド畳み込みまたは最大プーリング(ストライド 2 でスライドする 2x2 ウィンドウの最大値)は、水平方向にデータキューブを縮小する方法です。

Convolutional classifier

最後に、最後のデータキューブをフラット化し、密な softmax 活性化レイヤを介してフィードすることで、分類ヘッドを接続します。一般的な畳み込み分類器は次のようになります。

4a61aaffb6cba3d1.png

図: 畳み込みレイヤと softmax レイヤを使用する画像分類器。3x3 フィルタと 1x1 フィルタを使用します。maxpool レイヤは、2x2 のデータポイントのグループの最大値を取得します。分類ヘッドは、ソフトマックス活性化関数を持つ密結合レイヤで実装されます。

Keras で

上記の畳み込みスタックは、Keras で次のように記述できます。

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. カスタム convnet

ハンズオン

畳み込みニューラル ネットワークをゼロから構築してトレーニングしてみましょう。TPU を使用すると、非常に高速に反復処理を行うことができます。次のノートブックを開き、セルを実行(Shift+Enter)して、「WORK REQUIRED」ラベルが表示されている手順に沿って操作してください。

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

目標は、転移学習モデルの 75% の精度を上回ることです。このモデルは、数百万枚の画像のデータセットで事前トレーニングされているという利点がありましたが、ここでは 3, 670 枚の画像しかありません。少なくとも同額にしていただけませんか?

その他の情報

レイヤの数とサイズはどのくらいですか?

レイヤサイズの選択は、科学というよりアートです。パラメータ(重みとバイアス)の数が少なすぎたり多すぎたりしないように、適切なバランスを見つける必要があります。重みが少なすぎると、ニューラル ネットワークで花の形の複雑さを表現できません。多すぎると、「過学習」になりやすく、トレーニング画像に特化して一般化できなくなる可能性があります。パラメータが多いと、モデルのトレーニングも遅くなります。Keras では、model.summary() 関数はモデルの構造とパラメータ数を表示します。

Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 192, 192, 16)      448       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 192, 192, 30)      4350      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 96, 96, 30)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 96, 96, 60)        16260     
_________________________________________________________________
 ... 
_________________________________________________________________
global_average_pooling2d (Gl (None, 130)               0         
_________________________________________________________________
dense (Dense)                (None, 90)                11790     
_________________________________________________________________
dense_1 (Dense)              (None, 5)                 455       
=================================================================
Total params: 300,033
Trainable params: 300,033
Non-trainable params: 0
_________________________________________________________________

ヒント:

  • 複数のレイヤがあることが、ディープ ニューラル ネットワークを効果的にする理由です。この単純な花の認識問題では、5 ~ 10 個のレイヤが適切です。
  • 小さなフィルタを使用します。通常、3x3 フィルタはどこでも有効です。
  • 1x1 フィルタも使用でき、安価です。実際には何もフィルタリングせず、チャネルの線形結合を計算します。実際のフィルタと交互に適用します。(「1x1 畳み込み」については、次のセクションで詳しく説明します)。
  • このような分類問題では、最大プーリング レイヤ(またはストライド > 1 の畳み込み)を使用して頻繁にダウンサンプリングします。花の位置は重要ではなく、バラかタンポポかだけが重要なので、x と y の情報を失っても問題なく、小さな領域をフィルタリングする方がコストを抑えられます。
  • 通常、フィルタの数はネットワークの最後にあるクラスの数とほぼ同じになります(理由は、以下の「グローバル平均プーリング」のトリックをご覧ください)。数百のクラスに分類する場合は、連続するレイヤでフィルタ数を段階的に増やします。5 つのクラスを含む花データセットの場合、5 つのフィルタのみでフィルタリングすることはできません。ほとんどのレイヤで同じフィルタ数(32 など)を使用し、最後に向かって減らしていくことができます。
  • 最後の Dense レイヤはコストが高くなります。すべての畳み込みレイヤの合計よりも多くの重みを持つことができます。たとえば、最後のデータキューブから 24x24x10 のデータポイントという非常に妥当な出力が得られたとしても、100 個のニューロンを持つ密結合レイヤには 24x24x10x100=576,000 個の重みが必要になります。慎重に検討するか、グローバル平均プーリングを試してください(下記を参照)。

グローバル平均プーリング

畳み込みニューラル ネットワークの最後に高価な密結合レイヤを使用する代わりに、入力データ「キューブ」をクラスの数だけ分割し、それらの値を平均して、ソフトマックス アクティベーション関数に渡すことができます。この分類ヘッドの構築方法では、重みは 0 になります。Keras では、構文は tf.keras.layers.GlobalAveragePooling2D(). です。

93240029f59df7c2.png

ソリューション

ソリューション ノートブックは次のとおりです。行き詰まった場合は、こちらをご利用ください。

c3df49e90e5a654f.png Keras_Flowers_TPU (solution).ipynb

学習した内容

  • 🤔 畳み込みレイヤを試した
  • 🤓 最大プーリング、ストライド、グローバル平均プーリングなどを試した。
  • 😀 TPU で実際のモデルを迅速に反復処理した

このチェックリストを頭の中で確認してください。

7. 完了

最初の最新の畳み込みニューラル ネットワークを構築し、TPU のおかげでわずか数分でアーキテクチャを反復処理して 80% 以上の精度でトレーニングしました。最新の畳み込みアーキテクチャについては、次のラボに進んでください。

TPU の実践

TPU と GPU は Cloud AI Platform で使用できます。

最後に、皆様のフィードバックをお待ちしています。このラボで不具合が見つかった場合や、改善すべき点があると思われる場合は、お知らせください。フィードバックは GitHub の問題 [フィードバック リンク] から送信できます。

HR.png

Martin Görner ID small.jpg
著者: Martin Görner
Twitter: @martin_gorner

tensorflow logo.jpg
www.tensorflow.org