1. 概要
このラボでは、畳み込みレイヤを組み立てて、花を認識できるニューラル ネットワーク モデルを作成する方法について学習します。今回は、自分でモデルをゼロから構築し、TPU のパワーを使用して数秒でトレーニングし、その設計を反復処理します。
このコースには、畳み込みニューラル ネットワークに関して必要な理論的な説明が含まれており、ディープ ラーニングについて学習する出発点として適しています。
このラボは「TPU での Keras」シリーズのパート 3 です。これらの操作は、次の順序で行うことも、個別に行うこともできます。
- TPU スピードのデータ パイプライン: tf.data.Dataset と TFRecords
- 転移学習を使用した最初の Keras モデル
- [このラボ] Keras と TPU を使用した畳み込みニューラル ネットワーク
- Keras と TPU での最新の convnets、squeezenet、Xception
学習内容
- Keras Sequential モデルを使用して畳み込み画像分類器を作成する。
- TPU で Keras モデルをトレーニングする
- 適切な畳み込みレイヤを選択してモデルをファインチューニングする。
フィードバック
この Codelab で何か問題がありましたらお知らせください。フィードバックは GitHub Issues [フィードバック リンク] から送信できます。
2. Google Colaboratory クイック スタート
このラボでは Google Colaboratory を使用します。セットアップは必要ありません。Colaboratory は、教育目的のオンライン ノートブック プラットフォームです。CPU、GPU、TPU を無料でトレーニングできます。
このサンプル ノートブックを開いていくつかのセルを実行し、Colaboratory についてよく理解してください。
TPU バックエンドを選択する
Colab メニューで、[ランタイム] > [ランタイムのタイプを変更] の順に選択し、TPU を選択します。この Codelab では、ハードウェア アクセラレーションによるトレーニングをサポートする強力な TPU(Tensor Processing Unit)を使用します。ランタイムへの接続は、初回実行時に自動的に行われます。右上の [接続] ボタンを使用することもできます。
ノートブックの実行
セルを 1 つずつ実行するには、セルをクリックして Shift+Enter キーを押します。[ランタイム] > [すべて実行] でノートブック全体を実行することもできます。
目次
すべてのノートブックには目次があります。左側にある黒い矢印をクリックすると開きます。
非表示のセル
一部のセルはタイトルのみが表示されます。これは Colab 固有のノートブック機能です。ダブルクリックすると内部のコードを確認できますが、通常はあまり興味深いものではありません。通常は、サポート機能または可視化機能です。内部の関数を定義するには、これらのセルを実行する必要があります。
認証
承認済みアカウントで認証すると、Colab は非公開の Google Cloud Storage バケットにアクセスできます。上記のコード スニペットによって認証プロセスがトリガーされます。
3. [INFO] Tensor Processing Unit(TPU)とは
概要
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 を使用して、インタラクティブな速度(トレーニング実行あたり数分)で花の分類システムを構築して最適化します。
TPU を選ぶ理由
最新の GPU は、プログラム可能な「コア」を中心に構成されています。コアは、3D レンダリング、ディープ ラーニング、物理シミュレーションなどのさまざまなタスクを処理できる非常に柔軟なアーキテクチャです。一方、TPU は従来のベクトル プロセッサと専用の行列乗算ユニットを組み合わせ、ニューラル ネットワークなど、大規模な行列乗算が主体となるあらゆるタスクに優れています。
イラスト: 行列乗算としての高密度ニューラル ネットワーク レイヤ。ニューラル ネットワークによって一度に処理された 8 つの画像のバッチを示しています。1 行 x 列の乗算を実行して、画像のすべてのピクセル値の加重合計が実際に行われていることを確認してください。畳み込み層も行列の乗算として表すことができますが、やや複雑です( 説明はセクション 1)。
ハードウェア
MXU と VPU
TPU v2 コアは、行列乗算を実行する行列乗算ユニット(MXU)と、活性化やソフトマックスなどの他のタスクのためのベクトル処理ユニット(VPU)で構成されます。VPU は、float32 と int32 の計算を処理します。一方、MXU は、混合精度の 16 ~ 32 ビット浮動小数点形式で動作します。
混合精度の浮動小数点と bfloat16
MXU は、bfloat16 入力と float32 出力を使用して行列乗算を計算します。中間累積は float32 精度で実行されます。
通常、ニューラル ネットワークのトレーニングは、浮動小数点精度の低下によって生じるノイズに耐性があります。ノイズがオプティマイザーの収束に役立つ場合もあります。従来、計算を高速化するために 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=16, 000 個のコアが必要になりますが、通常は不可能です。最大の GPU は約 4,000 コアです。一方、TPU は MXU の計算ユニットに最小限のハードウェアを使用します。bfloat16 x bfloat16 => float32
乗算累算器のみです。これらのサイズは非常に小さいため、TPU は 128x128 MXU に 16,000 個を実装し、この行列乗算を一度に処理できます。
イラスト: MXU シストリック アレイ。コンピューティング要素は乗算アキュムレータです。1 つの行列の値が配列に読み込まれます(赤いドット)。もう一方の行列の値は、配列(グレーのドット)を通過します。縦線により値が上に移動します。水平線は部分和を伝播します。配列の中をデータが流れるときに、行列乗算の結果が右側から出力されることを確認するのは、ユーザーの演習として行います。
さらに、ドット積が MXU で計算されている間、中間和は隣接するコンピューティング単位間で単純に転送されます。メモリやレジスタ ファイルへの格納や取得も不要です。最終的に、TPU シストリック アレイ アーキテクチャは、行列の乗算の計算において、密度と電力の大幅な利点があるだけでなく、GPU よりも無視できないほどの速度で優れています。
Cloud TPU
Google Cloud Platform で「Cloud TPU v2」を 1 つリクエストすると、PCI 接続 TPU ボードを備えた仮想マシン(VM)が手に入ります。TPU ボードには、デュアルコア TPU チップが 4 つあります。各 TPU コアは、VPU(ベクトル プロセッシング ユニット)と 128x128 MXU(MatriX 乗算ユニット)を備えています。この「Cloud TPU」は通常、リクエストした VM にネットワーク経由で接続されます。全体像は次のようになります。
図: ネットワークに接続された「Cloud TPU」アクセラレータを備えた VM。「Cloud TPU」自体は、4 つのデュアルコア TPU チップを搭載した PCI 接続 TPU ボードを備えた VM で構成されています。
TPU Pod
Google のデータセンターでは、TPU がハイ パフォーマンス コンピューティング(HPC)相互接続に接続されているため、1 つの非常に大規模なアクセラレータのように見えます。Google ではこれを Pod と呼び、最大 512 個の TPU v2 コアまたは 2,048 個の TPU v3 コアを含めることができます。
イラスト: TPU v3 Pod。HPC Interconnect で接続された TPU ボードとラック。
トレーニング中には、all-reduce アルゴリズムを使用して TPU コア間で勾配が交換されます(all-reduce についてはこちらの説明をご覧ください)。トレーニング対象のモデルは、大規模なバッチサイズでトレーニングすることでハードウェアを利用できます。
図: Google TPU の 2 次元トーラス状メッシュ HPC ネットワークで all-reduce アルゴリズムを使用してトレーニング中に勾配を同期する。
ソフトウェア
大規模なバッチサイズのトレーニング
TPU に最適なバッチサイズは TPU コアあたり 128 個のデータ項目ですが、ハードウェアは TPU コアあたり 8 個のデータ項目からすでに優れた使用率を示します。1 つの Cloud TPU には 8 個のコアがあることに注意してください。
この Codelab では、Keras API を使用します。Keras では、指定するバッチは TPU 全体のグローバル バッチサイズです。バッチは自動的に 8 に分割され、TPU の 8 コアで実行されます。
パフォーマンスに関するその他のヒントについては、TPU パフォーマンス ガイドをご覧ください。非常に大きなバッチサイズの場合、一部のモデルでは特別な注意が必要です。詳細については、LARSOptimizer をご覧ください。
仕組み: XLA
TensorFlow プログラムは計算グラフを定義します。TPU は Python コードを直接実行するのではなく、TensorFlow プログラムで定義された計算グラフを実行します。内部では、XLA(アクセラレータ線形代数コンパイラ)と呼ばれるコンパイラが、計算ノードの Tensorflow グラフを TPU マシンコードに変換します。このコンパイラは、コードとメモリ レイアウトに対して多くの高度な最適化も行います。処理が TPU に送信されると、コンパイルが自動的に行われます。XLA をビルドチェーンに明示的に含める必要はありません。
図: TPU で実行するには、Tensorflow プログラムで定義された計算グラフがまず XLA(高速線形代数コンパイラ)表現に変換され、その後 XLA によって TPU マシンコードにコンパイルされます。
Keras での TPU の使用
TPU は、Tensorflow 2.1 以降の Keras API を通じてサポートされています。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(tp_uname, zone, project)
を指定してTPUClusterResolver
を呼び出します。TPUStrategy
は、分散と「all-reduce」勾配同期アルゴリズムを実装する部分です。- 戦略はスコープを通じて適用されます。モデルは strategy scope() 内で定義する必要があります。
tpu_model.fit
関数は、TPU トレーニングの入力として tf.data.Dataset オブジェクトを想定しています。
TPU の一般的な移植タスク
- TensorFlow モデルにデータを読み込む方法は数多くありますが、TPU では
tf.data.Dataset
API を使用する必要があります。 - TPU は非常に高速であり、実行時にデータの取り込みがボトルネックになることがよくあります。TPU パフォーマンス ガイドには、データのボトルネックを検出するためのツールや、パフォーマンスに関するその他のヒントが記載されています。
- int8 または int16 の数値は int32 として扱われます。TPU には、32 ビット未満で動作する整数ハードウェアはありません。
- 一部の Tensorflow オペレーションはサポートされていません。こちらのリストをご覧ください。幸いなことに、この制限はトレーニング コード、つまりモデルのフォワード パスとバックワード パスにのみ適用されます。Tensorflow のオペレーションはすべて CPU で実行されるため、データ入力パイプラインでも使用できます。
tf.py_func
は TPU でサポートされていません。
4. [情報] ニューラル ネットワーク分類器 101
概要
次の段落の太字の用語をすべてご存じの場合は、次の演習に進んでください。ディープ ラーニングを初めて学ぶ場合は、ぜひこのままお読みください。
レイヤのシーケンスとして構築されたモデルの場合、Keras には Sequential API があります。たとえば、3 つの Dense レイヤを使用する画像分類器は、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, ... )
密なニューラル ネットワーク
これは、画像を分類するための最もシンプルなニューラル ネットワークです。層状に並んだ「ニューロン」で構成されています。最初のレイヤは入力データを処理し、出力を他のレイヤにフィードします。「密」と呼ばれるのは、各ニューロンが前の層のすべてのニューロンに接続されているためです。
このようなネットワークに画像を入力するには、すべてのピクセルの RGB 値を長いベクトルにフラット化して入力として使用します。これは画像認識に最適な手法ではありませんが、後で改善します。
ニューロン、活性化、RELU
「ニューロン」は、すべての入力の加重合計を計算し、「バイアス」と呼ばれる値を追加して、その結果を「活性化関数」にフィードします。重みとバイアスは、最初は未知です。これらのパラメータはランダムに初期化され、大量の既知のデータでニューラル ネットワークをトレーニングすることで「学習」されます。
最も一般的な活性化関数は、正規化線形ユニット(ReLU)と呼ばれます。上のグラフに示すように、非常にシンプルな関数です。
ソフトマックスの有効化
花を 5 つのカテゴリ(バラ、チューリップ、タンポポ、ヒマワリ、ヒマワリ)に分類しているため、上記のネットワークは 5 個のニューロン層で終わります。中間レイヤのニューロンは、従来の RELU 活性化関数を使用して活性化されます。最後のレイヤでは、この花がバラやチューリップである確率を表す 0~1 の数値を計算します。そのために、「softmax」という活性化関数を使用します。
ベクトルにソフトマックスを適用するには、各要素の指数を受け取り、通常は L1 ノルム(絶対値の合計)を使用してベクトルを正規化します。これにより、値の和が 1 になり、確率として解釈できるようになります。
交差エントロピー損失
ニューラル ネットワークが入力画像から予測を生成したので、その精度を測定する必要があります。つまり、ネットワークが示す結果と正解(多くの場合「ラベル」と呼ばれる)との距離を測定する必要があります。データセット内のすべての画像に正しいラベルが付いていることを覚えておいてください。
任意の距離を使用できますが、分類問題では、いわゆる「交差エントロピー距離」が最も効果的です。これをエラーまたは「損失」関数と呼びます。
勾配降下法
ニューラル ネットワークの「トレーニング」とは、トレーニング画像とラベルを使用して重みとバイアスを調整し、交差エントロピー損失関数を最小化することを意味します。仕組みは次のとおりです。
クロスエントロピーは、トレーニング画像の重み、バイアス、ピクセル、既知のクラスの関数です。
すべての重みとすべてのバイアスに対して交差エントロピーの偏導関数を計算すると、与えられた画像、ラベル、重みとバイアスの現在値に対して計算される「勾配」が得られます。数百万もの重みとバイアスがある可能性があるため、勾配の計算は大変な作業のように思えます。幸い、Tensorflow がその作業を行います。勾配の数学的特性は、「上」を指すことです。交差エントロピーが低い方向に移動したいので、反対の方向に移動します。重みとバイアスは勾配の一部で更新されます。その後、トレーニング ループ内で、次のトレーニング画像とラベルのバッチを使用して、同じことを何度も繰り返します。クロスエントロピーが最小になる場所に収束することを期待しますが、この最小値が一意であることを保証するものではありません。
ミニバッチ処理とモメンタム
1 つのサンプル画像についてグラデーションを計算し、重みとバイアスをすぐに更新することもできますが、たとえば 128 枚の画像でバッチにすることで、異なるサンプル画像による制約をより適切に表現するグラデーションが得られるため、より速く解に収束する可能性が高くなります。ミニバッチのサイズは調整可能なパラメータです。
この手法(「確率的勾配降下法」と呼ばれることもあります)には、より実用的な別の利点もあります。バッチを使用すると、より大きな行列を扱うことになり、通常、GPU と TPU で最適化しやすくなります。
ただし、収束はやや混沌とすることがあり、勾配ベクトルがすべてゼロになると停止することさえあります。これは最小値が見つかったことを意味しますか?必ずしも違反警告を受けるとは限りません。勾配コンポーネントは、最小値または最大値で 0 にできます。数百万個の要素を持つ勾配ベクトルがすべてゼロの場合、すべてのゼロが最小値に対応し、最大値に対応するゼロがないことはかなり低い確率です。さまざまな次元の空間では、サドルポイントは非常に一般的なものなので、それだけでは不十分です。
イラスト: サドルポイント。勾配は 0 ですが、すべての方向で最小値ではありません。(画像の帰属: Wikimedia: Nicoguaro - 自著、CC BY 3.0)
解決策は、最適化アルゴリズムに勢いをつけ、止まることなく踏切を乗り越えることです。
用語集
バッチまたはミニバッチ: トレーニングは常に、トレーニング データとラベルのバッチで実行されます。これにより、アルゴリズムの収束が促進されます。通常、「バッチ」次元はデータ テンソルの最初の次元です。たとえば、シェイプが [100, 192, 192, 3] のテンサーには、ピクセルあたり 3 つの値(RGB)を持つ 192 x 192 ピクセルの画像が 100 個含まれています。
交差エントロピー損失: 分類器でよく使用される特別な損失関数。
密結合レイヤ: 各ニューロンが前のレイヤのすべてのニューロンに接続されているニューロンのレイヤ。
特徴量: ニューラル ネットワークの入力は「特徴量」と呼ばれることもあります。ニューラル ネットワークにフィードして適切な予測を取得するデータセットの部分(または部分の組み合わせ)を特定する手法は「特徴量エンジニアリング」と呼ばれます。
labels: 教師あり分類問題の「クラス」または正解の別名
学習率: トレーニング ループの反復処理で重みとバイアスが更新される勾配の割合。
ロジット: 活性化関数を適用する前のニューロンの層の出力は「ロジット」と呼ばれます。この用語は、かつて最も一般的な活性化関数であった「ロジスティック関数」(別名「シグモイド関数」)に由来しています。「ロジスティック関数前のニューロン出力」を「ロジット」に短縮しました。
loss: ニューラル ネットワークの出力と正解を比較する誤差関数
ニューロン: 入力の加重合計を計算し、バイアスを追加して、結果を活性化関数に渡します。
ワンホット エンコーディング: クラス 5 のうち、クラス 3 が 5 つの要素のベクトルとしてエンコードされます。3 番目の要素である 1 を除き、すべてゼロになります。
relu: 正規化線形ユニット。ニューロンでよく使用される活性化関数。
シグモイド: かつては人気があり、特殊なケースでは今でも有用な活性化関数です。
ソフトマックス: ベクトルに作用し、最大の要素と他のすべての要素の差を増やし、ベクトルの合計が 1 になるように正規化して、確率のベクトルとして解釈できるようにする特別な活性化関数。分類システムの最後のステップとして使用されます。
テンソル: 「テンソル」は行列に似ていますが、任意の次元数を持ちます。1 次元のテンソルはベクトルです。2 次元のテンソルは行列です。3、4、5 以上のディメンションを持つテンソルも作成できます。
5. [最新情報] 畳み込みニューラル ネットワーク
概要
次の段落で太字になっている用語をすべて理解している場合は、次の演習に進みましょう。畳み込みニューラル ネットワークをこれから始める場合は、本記事をお読みください。
図: 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'])
畳み込みニューラル ネットワーク 101
畳み込みネットワークのレイヤでは、1 つの「ニューロン」が、画像の小さな領域にわたって、そのすぐ上のピクセルの重み付き合計を計算します。通常の密集層のニューロンと同様に、バイアスを追加して、その和を活性化関数に渡します。この処理は、同じ重みを使用して画像全体で繰り返されます。密な層では、各ニューロンに独自の重みがあったことを思い出してください。ここでは、重みの単一の「パッチ」が画像の両方向にスライドします(「畳み込み」)。出力には、画像内のピクセルと同じ数の値が含まれます(ただし、端にはパディングが必要です)。これは、4x4x3=48 の重みを持つフィルタを使用するフィルタリング オペレーションです。
ただし、48 個の重みでは不十分です。自由度をさらに広げるには、新しい重みのセットで同じ操作を繰り返します。これにより、新しい一連のフィルタ出力が生成されます。入力画像の R、G、B チャネルに類似して、これを出力の「チャネル」と呼びましょう。
2 組(または複数)の重みのセットは、新しい次元を追加することで 1 つのテンソルとして合計できます。これにより、畳み込みレイヤの重みテンソルの一般的な形状が得られます。入力チャンネルと出力チャンネルの数はパラメータであるため、畳み込みレイヤのスタックとチェーンを開始できます。
図: 畳み込みニューラル ネットワークは、データの「キューブ」を他の「キューブ」に変換します。
ストライド畳み込み、最大プーリング
2 または 3 のストライドで畳み込みを実行すると、結果として得られるデータキューブを水平方向に縮小することもできます。一般的な方法は次の 2 つです。
- ストライド畳み込み: 上記のスライディング フィルタで、ストライドが 1 より大きい
- 最大プーリング: MAX 演算を適用するスライディング ウィンドウ(通常は 2x2 パッチで、2 ピクセルごとに繰り返される)
例: 計算ウィンドウを 3 ピクセルずらすと、出力値が少なくなります。ストライド畳み込みまたは最大プーリング(2 ストライドでスライドする 2x2 ウィンドウの最大)は、データキューブを水平次元で縮小する方法です。
畳み込み分類器
最後に、最後のデータキューブをフラット化し、密集したソフトマックス活性化層に通すことで分類ヘッドを接続します。一般的な畳み込み分類器は次のようになります。
図: 畳み込みレイヤとソフトマックス レイヤを使用する画像分類器。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. お客様のカスタム コンバージョン
ハンズオン
畳み込みニューラル ネットワークをゼロから構築してトレーニングします。TPU を使用すると、反復処理を非常に高速に行うことができます。次のノートブックを開いてセルを実行(Shift+Enter キー)し、「WORK REQUIRED」というラベルが付いている場所をすべて手順に沿って操作してください。
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 フィルタは安価です。実際には何も「フィルタリング」ではなく、チャネルの線形結合を計算します。実際のフィルタと交互に使用します。(「1x1 畳み込み」の詳細については、次のセクションで説明します)。
- このような分類問題では、マックスプーリング レイヤ(またはストライドが 1 より大きい畳み込み)を使用して頻繁にダウンサンプリングします。花がどこにあるかは重要ではなく、バラかタンポポかだけが重要なので、x と y の情報が失われても問題はなく、より狭い範囲をフィルタリングする方が費用対効果に優れています。
- 通常、フィルタの数はネットワークの末端のクラス数に近くなります(理由については、後述の「グローバル平均プーリング」のヒントを参照)。数百のクラスに分類する場合は、連続するレイヤでフィルタ数を段階的に増やします。5 つのクラスを含む花のデータセットの場合、5 つのフィルタのみでフィルタリングしても不十分です。ほとんどのレイヤで同じフィルタ数(例: 32)を使用して、終端に向かって減らすことができます。
- 最終的な高密度レイヤは高価です。すべての畳み込みレイヤの合計よりも多くの重みを持つことができます。たとえば、24x24x10 個のデータポイントの最後のデータキューブから非常に妥当な出力が得られた場合でも、100 個のニューロンの密集層では、24x24x10x100 = 576,000 個の重みが使用されます。慎重に検討するか、グローバル平均プーリングを試してください(下記を参照)。
グローバル平均プーリング
畳み込みニューラル ネットワークの最後に高価な高密度レイヤを使用する代わりに、受信データ「キューブ」をクラスの数だけ分割し、それらの値を平均してソフトマックス活性化関数に渡すことができます。この方法で分類ヘッドを作成する場合、重みは 0 です。Keras の構文は tf.keras.layers.GlobalAveragePooling2D().
です。
ソリューション
こちらがソリューション ノートブックです。行き詰まった場合に使用できます。
Keras_Flowers_TPU (solution).ipynb
学習した内容
- 🤔? 畳み込みレイヤで遊んでいた
- 🤓 マックスプーリング、ストライド、グローバル平均プーリングなどを試しました。
- 😃? TPU で実際のモデルを迅速に反復処理
以下のチェックリストを頭の中で確認してください。
7. 完了
最新の畳み込みニューラル ネットワークを初めて構築し、80% 以上の精度までトレーニングし、TPU のおかげでわずか数分でアーキテクチャの反復処理を完了できました。最新の畳み込みアーキテクチャについて学習するには、次のラボに進んでください。
- TPU スピードのデータ パイプライン: tf.data.Dataset と TFRecords
- 転移学習を使用した最初の Keras モデル
- [このラボ] Keras と TPU を使用した畳み込みニューラル ネットワーク
- Keras と TPU での最新の convnets、squeezenet、Xception
TPU の実践
TPU と GPU は Cloud AI Platform で利用できます。
最後に、皆様のフィードバックをお待ちしています。このラボで問題が見つかった場合や、改善が必要だと思われる場合は、お知らせください。フィードバックは、GitHub の問題 [フィードバック リンク] からお送りいただけます。
|