ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
Metal Performance Shaders GraphでカスタムMLモデルを構築する
MetalのCompute能力をマルチディメンションTensorsに拡張する、Metal Performance Shaders (MPS) Graphをご紹介します。MPS Graphは高度にチューニングされた並列処理データライブラリの上に構築され、機械学習に欠かせないものであり、多大なGPUパワーを活用します。MPS Graphにより洗練された、ダイナミックなニューラルネットワーク学習のアーキテクチャを表現する方法、またアーキテクチャ上でGPUを加速させるための最適化の仕方をお伝えします。 このセッションで網羅するコンセプトをより深く理解するには、WWDC19の"Metal for Machine Learning"をご確認ください。
リソース
関連ビデオ
WWDC21
Tech Talks
WWDC19
-
ダウンロード
こんにちは WWDCへようこそ “Metal Performance Shaders Graphで カスタムMLモデルを構築する” AppleのGPUソフトウェアエンジニアの ドゥルヴです 新しいMetal Performance Shaders Graphを 使ってカスタマイズされた― 機械学習オペレーションの 実装についてお話します さぁ 始めましょう MPSは Metalベースの高性能GPU アクセラレーションプリミティブのライブラリで 画像処理 線形代数 レイトレーシング 機械学習などのさまざまな分野に対応しています MPSチームはMetalカーネルを最適化し Appleのプラットフォームのハードウェアで 最高のパフォーマンスを発揮させます
今日はエキサイティングな 一連の新機能についてお話します MPS全体に対して行われた パフォーマンスの改善 機械学習で32ビット浮動小数点の 完全サポートを活用する方法
新しいMPSNDArrayプリミティブと 最後は新しい Metal Performance Shaders Graphの紹介です
MPSで画像処理に追加された 驚くべき改善点をいくつかご紹介いたします 距離変換フィルターをチューニングして改良し Final Cut Proの機能が15倍速くなりました MPSはEDLineアルゴリズムを使用した 新しいエッジ検出プリミティブも持っています それによりMeasureアプリケーションが改善され 10倍速くなりました より優れた高解像度での セグメント検出も可能です
CNNプリミティブの サポートも拡大しました
畳み込みと完全に接続された プリミティブを FP32で完全にサポート できるようになりました そのため開発者は ハイパーパラメータを再計算したり 同じ精度を得るためにコードを リファクタリングしたりする必要はありません これを有効にするにはデータソースプロバイダに kernelWeightsDataTypeメソッドを実装して float32に設定します
畳み込みデータソースプロバイダの 実装方法については以前の講演をご参照ください
MPSNDArrayという 新しいMPSプリミティブがあります MPSNDArrayとそれに対応する操作は 最大16次元までサポートしています これは機械学習をはじめとする さまざまな科学領域に十二分に対応しています またメモリに収めることができる限り この新しいプリミティブは 次元の制限は実質的にありません
MPSNDArrayを作成するには まずMPSNDArrayデスクリプタを使用して 要素の形状とデータの型を指定します 次にMPSNDArrayを それを割り当てたいMetalデバイスと一緒に イニシャライザに渡します
MPSNDArrayは 既存のMetalテキスチャベースの MPSImageBatch型との間の コンバータを提供します
またMetalバッファを使用し データを インポートやエクスポートすることもできます
さて ここから本題に入りましょう 新しい Metal Performance Shaders Graph フレームワークです
MPS Graphはスタック内の MPSフレームワークの上にあります Metalの計算機能を多次元に 拡張するために使用しています
新しいMPS Graph Frameworkは macOS iOS iPadOS tvOSで MPS Frameworkと同様にサポートされます
新しいフレームワークはXcodeの Metal Performance Shaders Frameworkの すぐ隣にある“Build Phases”タブから プロジェクトに含められます
取り上げるべきことは たくさんあります 新しいMPS Graphの紹介 カスタム計算関数を書くための 利用可能なさまざまなAPI 最後は機械学習トレーニンググラフの 書き方と実行についてです
まずMPS Graphの基本を 見ていきましょう
MPS Graphは 演算とテンソルのDAGを表しています
演算は計算の単位を表す グラフのノードです ここでは3つの基本的な 数学演算の例を示しています 乗算 加算 減算です
テンソルは演算と共にグラフ内のデータフローを 定義するグラフの辺です この例では テンソルが基本的な数学演算の 流れの中を流れていることが分かります
このように記号的に表現することで 多くのデータプリミティブを抽象化でき GPU上で最高のパフォーマンスを得るための 統一されたインターフェースを提供できます
MPSGraphオブジェクトは グラフ上でメソッドを使って作成された― すべてのテンソルと 操作の所有権を保持します
MPSGraphTensorは データの記号的抽象化を表します テンソルは形状やデータ型および テンソルを作成する操作への参照から 構成されています
ここではグラフ上のconstantメソッドを 呼び出すだけで 定数テンソルを作成する 方法を見てみましょう
グラフ内の操作は3種類のエッジを介して 互いに接続しています
演算のデータ入力として 動作するテンソルを表す入力テンソル
操作自身により生成される出力テンソル
そして最後に制御依存と呼ばれる 特殊な種類のエッジです
これらは演算自体が 演算の集合に依存しない場合でも グラフが現在の操作の前に 実行するであろう操作のセットです
定数演算と同じように 演算もグラフ上で直感的な簡単なメソッドを 呼び出すことで作成できます ここではグラフ上に2つのテンソルを 追加する方法を見てみましょう
MPSGraphはグラフ上のテンソルを 操作するためのさまざまな操作を提供します 例えば1次元のテンソルを 2次元のテンソルに再形成することができます
テンソルを切り取り 一部分を取り出すことができます
一部を切り取る前のテンソルに連結して さらに大きなテンソルを作ることができます
どんな次元のテンソルにも転置できます
そして最後に長さゼロの スライスを作ることもできます MPSGraphではサイズがゼロのテンソルが サポートされています これにより可変長のシーケンスに対する ニューラルネットワークの再帰演算のような 動的な使用例が可能になります
MPSGraph上ではさまざまな操作を サポートしています 畳み込みや還元の複数のバリエーションから 計算グラフに必要な 基本的な数学演算まで網羅しています
それでは一番最初のMPSGraphで カスタム計算関数を作成して実行するために これらの演算を いくつか組み合わせてみましょう
近年 機械学習の研究では自然言語処理を扱う 新しい方法が発見されています そのような革新の一つがBERTで使用されている 新しい種類の活性化関数でした
この活性化は一般にGeLUとして知られている ガウス誤差線形単位と呼ばれるものです
今回の例ではMPSGraphを使用して GPU上にカスタムGeLU関数を実装してみます
これは簡単な3ステップのプロセスです グラフへの入力を定義し 実行する操作のセットを書き 最後に提供されたデータ上で グラフを実行します
グラフへの入力を 定義することから始めましょう
我々のGeLU活性化関数は 単一の入力で構成されています
入力テンソルはグラフ内の プレースホルダ演算を使って作成します これはその名の通り 実行時にプレースホルダとして機能します これらは呼び出し側が提供する 入力データによって置き換えられます
ここでは3つの列と2つの行を持つ float32型のプレースホルダを作成するための API コールの例を示します
実行時にしか分からないグラフに入る 入力のサイズが異なる場合があり得ます 例えば機械学習の分野では ユーザから可変長のシーケンスや 異なるバッチサイズの入力画像が 頻繁に渡されます
このようなシナリオのために MPSGraphは プレースホルダ内で動的サイズを サポートしています 次元のサイズを-1と指定するだけです そしてグラフは 実行時に対応する 入力から形状を評価します
入力された入力の次元数が 不明な場合でも 単にnilをプレースホルダシェイプに 渡してください MPSGraphは型推論を完全にサポートしており 実行時にグラフ全体に図形を伝播します
グラフへの入力を定義したのでステップ2に進み グラフ内にカスタム計算関数を書き出します
通常 ニューラルネットワークの さまざまなポイントで GeLU活性化を使用することを 想定しています そこでモジュール化のために テンソルを入力とするヘルパー関数を グラフ上に定義します 与えられた入力テンソルに 活性化を適用するため 必要な操作を追加してみましょう
まずGeLUニューロンで 使用する定数を定義します
スカラーを渡して グラフ上のconstantメソッドを呼び出し float32データ型に設定するだけです
次は単項演算 すなわち平方根です
MPSGraphは基本的な 単項演算を提供しています 半定数テンソルを入力にして グラフ上でsquareRootメソッドを 呼び出すだけです
定数と入力の準備ができたので いくつかの乗算を使って計算を始めます
これらの演算はブロードキャストを 暗黙にサポートしています そのため 結果のテンソルの形状は ニューロンへの入力と同じ形状であると 自動的に推論されます
2つの入力テンソルをグラフ上の 乗算メソッドに渡すとそのようになります
この小さな単項メソッドが 誤差関数として知られるGeLU ニューロンの 心臓部を形成しています
繰り返しますが 入力を単項演算に渡すだけで 左側の出力テンソルが返ってきます
最後に加算と乗算で 活性化を終了します
前と同じように二項演算を作成し 乗算の出力がGeLU関数から返されます
これでGeLUニューロンを表す演算のグラフを 簡単に作成することができました
3番目の最後のステップは このグラフの実行を確認することです
グラフの実行は非常に簡単です まずグラフのプレースホルダに対応する フィードのディクショナリを渡します
次にグラフを評価して 結果を返したい ターゲットテンソルのリストを指定します これらの結果は 左側のディクショナリに返されます
最後にユーザはオプションで グラフが実行を保証する ターゲットオペレーションのリストを渡せます
前に見たように実行時には MPMPSGraphTensorDataオブジェクトを渡すことで 開発者はプレースホルダを与えることができます これにより同じMPSGraphTensorData オブジェクトを使用した一連の出力が返されます
MPSGraphTensorDataはMetalエコシステムで 利用可能な多数のデータプリミティブを 抽象化するのに役立ちます Metalバッファを使用して それを初期化することができます
MPSImageBatchを使用して 4次元テンソルデータを作成することができます
MPSVectorsやMPSMatrixも同様に 抽象化しています そして最後に 新しいMPSNDArrayプリミティブを使って MPSGraphTensorDataを 初期化することもできます
では まとめてみましょう
まずMPSGraphを 作成することから始めます グラフへの入力を プレースホルダで定義します GeLUヘルパー関数を呼び出して グラフに必要な操作を書き出します
最後に入力データを フィードとして渡し GeLUテンソルをターゲットとして 要求してグラフを実行します GPU上の任意の多次元テンソル上で カスタム計算関数を実行するのに 必要なのはこれですべてです
MPSGraphの基本的な数学演算を使って カスタム計算関数を作成する方法を見てきました 通常は演算のたびに 出力がメモリに書きこまれます
次の演算はこの同じグローバルメモリから 読み出すことになります これはGPU上での不要なメモリトラフィックと パフォーマンスの問題を引き起こします
しかしMPSGraphコンパイラは 特別な最適化を適用して ユーザのために このような操作を 自動的に融合させます これをスティッチングと呼びます
MPSGraphコンパイラは 隣接するすべての演算を認識し Metalコンパイラに渡します
Metalコンパイラはこれらの操作を融合して 最適化された1つのMetalシェーダを作成します これによりメモリオーバーヘッドがなく パフォーマンスが向上します
MPSGraphコンパイラは もう一歩進んでいます 手作業によりチューニングされた MPSカーネルを中心とし 畳み込み 行列の乗算 還元など あらゆる演算に対応しています MPSGraphは領域を作成するために必要な 隣接するステッチ可能な操作を認識し
もう一度 操作の領域を Metalコンパイラに渡します 操作の領域を手作業でチューニングされた MPS カーネルに直接融合させるために 各ハードウェアに最適化された MPSカーネルの最適化を提供し Metal コンパイラによる演算の自動融合の メモリの節約を実現します
ステッチ最適化を使用することで GeLUは10倍から50倍近く高速化されます
さらにメモリを 大幅に節約することができます
これらすべての処理は1行のコードも必要とせず 常に自動的に実行されます
このようなカスタム計算機能の1つに 機械学習推論があります 推論とは入力にネットワークを適用して 出力を生成するプロセスです
ネットワークは畳み込みや ニューロン活性化層などの 操作の集合で構成されています これは ご紹介したようにMPSGraphの 操作で表現することができます
これらの層は訓練されたパラメータの 集合に依存します
推論中これらのパラメータは固定されており 値は訓練段階で決定されます 従って MPSGraphの中で これらのパラメータを表す定数を 推論のために使うことができます
このような多様な操作を MPSGraphでサポートすることにより グラフ上でも再帰ニューラルネットワークを サポートすることができるようになりました 私の同僚のクリスを紹介したいと思います テキスト生成推論ネットワークが動作する エキサイティングなデモを見せてくれます
ありがとう クリスです 私はGPUソフトウェアエンジニアで iPad Proにシェークスピアの劇を書かせています
これには Long Short Term Memory(LSTM)ベースの テキストジェネレータモデルを 使っています
ジェネレーターループは 1文字入力で動作します この場合 初期化文字列“Romeo”の 最後の文字である “O”を入力します この文字インデックスを 埋め込みレイヤーに送り込みます これはMPSGraphのギャザリング操作です
これにより単一ベクトルが生成され このランク1テンソルを訓練されたパラメータの 一定のセットを持っているLSTM層に送ります
LSTM層の結果は非埋め込み層に与えられ MPSGraphの行列乗算操作で実装でき
LSTM層の状態が 次の反復のために更新されます
その結果に逆温度が乗算されます
MPSGraphはこのスカラー値を 自動的にベクトル長にブロードキャストします その結果がSoftnax層に供給され 次の可能性のある文字の確率分布が得られます
Softmax層から予測された文字分布を サンプリングすることで 次の文字のインデックスを取得します これはインデックス対文字テーブルで 調べることが可能です
最後に 新しく生成された結果を入力して 次の繰り返しに移動し 文字を生成します
MPSGraphを動作させて 作成されたネットワークを見てみましょう iPad Pro上のアプリケーションで実行されている 新しいMPSGraphを使用して LSTMベースのテキストジェネレーター ネットワークを実装しました
MPSGraphによりユーザーは これらのモデルの実装が可能となります 新しいグラフインターフェースの柔軟性により モデルに微調整を加えて実験を実行し 最適化されたカーネルの利点を 容易に享受することができます ネットワークはシェイクスピアの文章を含む 大きなテキストファイルで訓練されており 上部の “Show Training DataSet”リンクを クリックすると 表示されます これはテキストの短い抜粋です
ネットワークを使い シェイクスピア風の テキストは生成されるのでしょうか デフォルトでは 初期テキストは “Romeo ”に設定されています 次に “Generate”を押します
モデルはシェイクスピアのような文章を 生成しています
別の単語の選択が可能なので “Juliet”と入力してみましょう
そして“Generate”を押します 生成されたテキストは“Juliet”で始まります
テキストの長さは 下のスライダーで調節可能です
これにより より長いテキストが生成されます
スライダーで温度変数を 変更することもできます この値の逆数が Softmaxレイヤーに入る 入力値を乗算するのに使われ 高温の値ではより滑らかで平坦な分布 低温の値ではよりシャープな分布を作成します サンプリングプロセスが高温になると ランダム性が高くなり 低温になるとランダム性が低くなります 温度スライダーを おおよそ2へ移動させ 驚くようなテキストを生成してみましょう
よりランダムになり 正しい英語なのかどうかも 分からなくなります 3に設定して もう一度“Generate”を押します
ランダムな文字が混じっているようです
伝統的なシェイクスピアに戻すため 温度スライダーを0.1に戻しましょう
モデルは訓練データセットに近いテキストを 生成しているようです
MPSGraphはこれらのモデルを グラフ上で実行するだけではありません スティッチング機能により チューニングされた カーネルの利点を享受し モデルに様々なカスタマイズを行えます これにより 多種多様なモデルのサポートと 迅速なプロトタイピングが可能になり モデルのサポートに必要な回避策や ハックの量を減らすことが可能です 僕からの説明は以上です
MPSGraphを使い カスタム計算関数を 書くことは 簡単であることが分かりました 次はニューラルネットワークを 最適に訓練するために利用可能な MPSGraphの機能を見ていきます
訓練プロセスでは 既知データ上で ネットワークを繰り返し実行します
試行ごとに パラメータのセットが更新され ネットワークが正しく動作する能力は向上します
ネットワークが十分に作動すると トレーニングプロセスは停止されます
これらのアイデアを実装する 新しいMPSGraphの使い方を紹介します
単純な桁分類ネットワークの実装が 必要となります
MPSGraphで計算を行う 主な手順は3つです ニューラルネットワークを 訓練するためのロードマップです 最初と最後の手順は同じです 手順2について詳しく説明します ニューラルネットワークのパラメーター訓練に 必要な操作を確認します
前と同じように 最初に入力セットを定義します
入力と対象ラベルの プレースホルダーを定義します -1を使用して ネットワークの 可変長バッチサイズを指定します
次に 前に紹介したトレーニング可能な パラメーターを指定します MPSGraphとこれらのパラメーターは グラフの一部です
簡単な例として 1層畳み込みニューラル ネットワークのトレーニングを紹介します
このネットワークには 畳み込みに対応する重みのセットと 畳み込みの結果に追加される バイアスがあります これらはトレーニングプロセスの一環として 更新されるパラメーターです
これらのパラメーターを指定するため MPSGraphでサポートされている 変数を利用します 変数は実行するグラフ全体で値を保持するので 反復ごとに これらを入力として グラフに渡す必要はありません
変数の作成には グラフで変数メソッドを呼び出し 初期値 形状 および要素の データ型を指定します
トレーニングするパラメーターが用意できたので 順方向パスを指定しましょう これはモデルの推論ネットワークでもあります
最初に 畳み込み層の作成方法を確認します
畳み込み層は ほとんどの計算が行われる ニューラルネットワークの主力です MPSGraphConvolution層は 多数のバリアントをサポートしています
畳み込み層の作成には まず最初に 畳み込み記述子を作成します
次に この記述子を グラフの畳み込みメソッドに渡します
畳み込みでは多数のパディングスタイルを サポートしています
開発者は高さと幅のパディングの設定が可能です または TensorFlowと同様に パディングを適用する― 便利なパディングモードSAMEと VALIDを使用できます
テンソルの次元には 意味論的意味が 付加されている場合があります この場合 MPSGraphTensorNamedDataLayoutが 役立ちます どの次元がバッチ チャネル 高さ 幅などの名前に 対応するのかを伝えます
MPSGraphはTensorFlowと PyTorchの画像データで― 一般的に使用されるNCHWとNHWC形式を サポートしています
重みはMPSで使用されるOIHW形式など 複数の形式で指定することが可能です TensorFlowなどのサードパーティの フレームワークで使用される HWIO形式でも指定できます
重み変数の値を畳み込みに渡す場合 readVariable演算を利用します グラフ実行中に この時点での 変数の値を表すテンソルを返します
トレーニングネットワークでは 重み変数を読み取り 返されたテンソルを畳み込みに渡します
畳み込み層は 渡された重みテンソルの形状を使用して カーネルサイズと出力機能チャネル数を 推測します
MPSGraphではreadVariable操作を 明示的に呼び出す必要はありません 変数テンソルが 任意の演算に直接渡される場合 グラフは便宜上 readVariable演算を追加します
畳み込み後のバイアスについては 暗黙的にブロードキャストをサポートする 加算ノードを呼び出します
非線形性については 一般的に使用される― 修正された線形単位関数を適用します
4次元のreLU出力を 2次元のテンソルに再形成します これは当社のラベルと同じ形状になります その次元は不明なバッチサイズと 分類するクラスの数を表しており― この場合は10桁となります
最後にsoftMax層を追加して 各クラスの確率を推定します 軸を-1に設定すると 最も速く動く軸を 指定する手がかりとなります
ニューラルネットワークの順方向パスを 定義しました 次に損失関数を定義します これを最小化して ニューラルネットワークをトレーニングします
一般的に使用されるSoftmax クロスエントロピー損失関数を使用します
ラベルと評価されたreshapeTensorを 渡すことで損失を定義します reductionSumを使用し バッチ全体の損失を 単一のスカラー損失値に累積します
最小化する損失値を定義したので トレーニング可能なパラメーターに関して 計算された損失の勾配を計算します
そのためには連鎖律を使用し 勾配を逆伝播する必要があります
連鎖律を開始する際には まず 損失の勾配を計算します ここでは1となります
次に 勾配演算とグラフで利用可能な 他の演算を使用します
そして 各層の偏微分係数を すべて乗算し 連鎖律を適用します この乗算はトレーニング可能なパラメーターに 関する損失の勾配が得られるまで行います
ただし MPSGraphにはテンソルの一覧に対して テンソルの勾配を与える方法があります これを自動微分と呼びます
グラフの逆方向パスを自動的に書き出し テンソルの辞書に対応する勾配を返します
勾配法を使用して 基本的な数学関数の 勾配関数を書き出すことが可能です 例として 単純な対数演算を使用します 勾配法は 逆数演算を 偏微分係数として正しく作成し 前述のように 常に1である開始勾配を掛けます
最終的には未使用の演算のセットとなります ここでもグラフコンパイラが役立ちます
グラフは結果が未使用のデッドコードを 排除するために切り詰められます また 1のような定数は すべて折り畳まれ 削除されます
ニューラルネットワークの場合 重みとバイアスに関する 損失テンソルの勾配を使用します
トレーニング可能なパラメーターに関して 損失の勾配が得られたら 変数の更新が可能です
テンソルの更新を計算するためには 確率的勾配降下法の オプティマイザを使用します これは勾配辞書を使用して 取得する学習率や元の重み値― そして重みの勾配を取り込みます
最後に 新しい更新テンソル値を 変数を割り当てるため グラフに変数演算子を使用します
この手順は先ほどと同じです 書き出したトレーニンググラフを 実行します
シンプルな反復の訓練です 1回の訓練を行うと 入力画像と対応する ラベルのサンプルを取得します これらをフィードとして グラフに渡します
次に損失テンソルを対象にして 返すように要求します グラフにある代入演算子も 対象とするため 反復する度に重さと 変数バイアスが更新されます
グラフは最初の呼び出しで それぞれの入力と出力の種類ごとに 1回更新されます そして実行可能ファイルは 自動的にキャッシュされます これは今後の反復が 最適なパフォーマンスを得るためです
MPSGraphは非同期メゾットも提供します 実行呼び出しは ノンブロッキングなので GPUの計算が完了する前に すぐに戻すことが出来ます オプションで実行時記述子を使用し CPUとGPU間で同期が可能です
同期方法の1つに記述子を利用します ユーザは完了ハンドラの登録が可能で GPUがグラフの実行を終了すると 呼び出されます
数年 CPUエンコーディングとGPU実行が 重なる利点を紹介してきました 私たちが行う反復トレーニングは 同じ原理を用います
値2のセマフォを作成します
実行記述子の完了ハンドラから セマフォに信号を送ります
ループ内でセマフォの処理が完了したら グラフを非同期に実行しすぐに戻します
MPSGraphを既存のMetalワークフローに 統合したい場合は MPSGraphは低い実行メソッドを提供し 既存のMTLコマンドキューに渡します
そしてMPSGraphはMPSスタイルの機能も提供し MPSコマンドバッファで グラフをエンコードします
ユーザは結果を示した ディクショナリを指定し 出力の割り当てを 細かく制御することが可能です
クリスに戻します 数字の分類器に関する ネットワークを実際にお見せします
ドゥルヴがトレーニング用の 新しいMPSGraphを見せたので iPhone 11に数字を分類する 実装方法を見てみます 新しいMPSGraphフレームワークを使用し 畳み込みニューラルネットワークを実装しました これをユーザが書いた数字へ 分類が出来ます
アプリケーションを開き 訓練されていないグラフを使います
“inference”タブでは ネットワークが番号にラベルを付けようと 無意味なことをしています “0”を書いても 予測することが出来ません
“training”タブに戻ると “play”を押して 訓練バッチ処理を開始します MPSGraphの自動微分機能を使用して 重みの勾配と対象の演算を取得し 重み変数を更新し トレーニングを簡単に実装します 各反復の損失は 画面上部にプロットされていて ネットワークが訓練されているため 損失が減少しています
小さなバッチサイズで 数百回の反復を訓練すれば テスト時の精度は 95%近くまでになります
inferenceタブに戻ります
新たに訓練されたグラフをテストします
すでに学習したのは 入力を高い精度で分類する方法です
新しいMPSGraphはカスタムした 機械学習モデルの構築が容易で 訓練と推論の両方に 活用出来るようになりました 例はMPSGraphを使用して 数字の分類器の実装までの方法ですが オンラインで サンプルコードを利用出来ます ドゥルヴに戻します
クリスがMPSGraphをiPhoneで 訓練する方法を見せてくれました MPSGraphはサポート機能を追加し より洗練された ニューラルネットワークを目指します
例を1つ見てみましょう 今回 生成するのは 手書きに見える数字です しかし 問題があります それは 数字を生成する時に 機械が手書きに見せる 判断基準が分からないことです
問題の解決は“競争”すること 長い間 人間は競争をして お互いを高め合うことで 自分自身では達成出来ない 卓越した技術を身に付けました この場合も同様です 2つのニューラルネットワークが 互いに競争し訓練します 1つは手書きの数字を生成し もう1つは 完成した数字を評価します
1つ目のネットワークはジェネレータです 作り手です 役割はランダムに選んだセットを シード値とすると 手書きに見える数字を生成します
ジェネレータのネットワークは 非常に単純です 値をランダムに選択し 3つの段階に分けて渡します 画像サイズを徐々に大きくし 手書きの数字を作り出します ここで新しいレイヤーを見てみます
まず 転置畳み込みを見ます
転置畳み込みは独特なレイヤーで 畳み込み演算子の勾配から 派生しています つまりストライド2の場合 出力サイズは入力サイズの2倍です 畳み込み転置を書き出すために 対応する畳み込みの記述子と 出力の形状を予測し渡します
もう1つの新しいレイヤーは バッチ正規化です
レイヤーの正規化は ニューラルネットワークの重要部分です 訓練された値と対応する勾配が 消失したり急上昇するのをを防ぎます
テンソルを正規化するためには テンソルの統計を使用します
MPSGraphのメゾットでは テンソルの選択した軸の 平均と分散を取得します 選択する軸によって バッチ正規化やインスタンスの正規化 または 他のバリアントが 必要かどうかを選択出来ます
バッチ正規化では バッチ 高さ 幅のディメンションを 選択します
次にレイヤーの正規化を呼び出すために 訓練可能なガンマ およびベータパラメータを使用します
2つ目のレイヤーは弁別器で 役割は探偵です 取り込んだ手書きの数字を 本物か偽物かを判断します
分類器のネットワークの 生成方法は説明しましたね 今回もよく似たネットワークです 異なるのは 予測するのは 10個の数字ではなく1つのクラスだけです つまり取り込む画像のリアルさです
弁別器にはドロップアウトという 新しいレイヤーがあります
このレイヤーは入力値を ランダムにドロップします つまり指定した割合で値をゼロにします 同時にこの割合の逆数を使い 残りの値を増加させ― 伝播機能のエネルギーを維持します
両方のネットワークを 順方向へ渡すことを確認したら 2つのネットワークの 訓練方法を確認します
初めに弁別器のネットワークです
本物または偽物の画像を 弁別器に渡すかを管理します 弁別器は取り込む画像の リアルさの度合いを予測します 本物の画像なら 確率として1を予測するし 偽物の画像なら 確立として0を予測します
生成された画像なら 1から弁別結果を差し引いて 代わりに入力画像の偽物を取得します
よく使われている 交差エントロピー誤差を用いて 弁別器が正または偽の予測から どれほど離れていたのかを数値化します
最後の手順は 弁別器に偏りを生じさせずに 本物と偽物の画像の区別を 学習する機会を与えます 反復ごとに同じ数の 本物と偽物の画像を渡し 合計の損失を加算します
算出された損失を利用し MPSGraphの自動微分機能を使います 注意弁別器の変数だけを一覧にした勾配を 求めていることに注意です 理由は弁別器を訓練したいのは 今回だけだからです
弁別器は探偵なのです 次に手書きの数字を生成するため 作り手を訓練する方法です
先ほど説明した通り― 弁別器を用いて生成した画像が どれほどリアルかを数値化します ジェネレータは生成画像が 本物であると予測するために 弁別器をだまそうと知恵を働かせます
そしてもう一度 交差エントロピー誤差を用いて 本物である確率を数値化します
このジェネレータを利用して 勾配を取得します
ジェネレータの変数の 勾配だけを取得することに注意です これは弁別器に偽物を 本物の画像として学習させないためです
MPSGraphは両方のネットワークを 自動で区別しジェネレータの 変数だけの勾配を返します
両方のネットワークの勾配を利用して オプティマイザを適用すると 以前と同じく変数の更新が出来ます
次に2つのネットワークの訓練の 実行方法を確認します
MPSGraphを使用すると 実行がとても楽になります まず両方の損失を対象として渡し ジェネレータと弁別器の 両方に要求することは 更新演算子を1回の実行で 呼び出すことです MPSGraphは更新と最適化を 両方のネットワークにわたって 一緒に実行します
1つのMPSGraphで 2つのネットワークを 書き出すことは簡単でした そして単一の実行呼び出しで 同時に実行しました クリスに数字を生成してもらいます
どうも ネットワークの機能が分かったので iPad Proで動作させてみます trainタブのplayを押して 訓練を開始します
画面上部はジェネレータの ネットワークの損失が表示され 画面下部は弁別器の ネットワークの損失が表示されます
画面中央はジェネレータの ネットワークで生成された画像です ネットワークを訓練する度に 生成される数値が数字に似てくるのです
数字の分類器で見たように MPSGraphの自動微分機能を用いて ジェネレータと弁別器のネットワークで 訓練可能なレイヤーを更新します 両方とも単一の MPSGraphを使い訓練させます
2つのネットワークが すでに競い合っていますが ジェネレータが信頼のある数字を 生成するまでには時間が必要です 訓練は一時停止が出来ます
inferenceタブへ行き 両方のネットワークを数百回 訓練させた後にテストをします
これは5と9ですね
次は分からないです
これは7で― 9ですね
確かに数字と分かりました すべてMPSGraphを使用し iPad Pro上で実行しています ドゥルヴに戻します
ありがとう クリス まとめます 新しいMPSGraphフレームワークを ご紹介しました MPSGraphを使用してカスタムの 計算関数を作成と実行方法を見ました MPSGraphのコンパイラがグラフ全体の 演算子を統合し最適化して パフォーマンスを 最大限にする方法を確認しました MPSGraphを使用すると ニューラルネットワークの訓練が簡単でした そしてMPSGraphは変数や自動微分など サポート機能もあります ありがとうございました サンプルコードとドキュメントも 是非ご確認ください
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。