フロントエンドエンジニアは、これらの18のトリッ​​クをマスターすることで、ブラウザでディープラーニングを習得できます

フロントエンドエンジニアは、これらの18のトリッ​​クをマスターすることで、ブラウザでディープラーニングを習得できます

TensorFlow.js がリリースされた後、以前にトレーニングしたターゲット/顔検出モデルと顔認識モデルを TensorFlow.js にインポートしました。モデルの一部はブラウザで非常にうまく動作することがわかりました。 TensorFlow.js のおかげで、フロントエンド開発者が流行りだした気がします。

ブラウザはディープラーニング モデルを実行できますが、これらのモデルはブラウザで実行するように設計されていないため、多くの制限と課題が生じます。ターゲット検出を例に挙げると、リアルタイム検出は言うまでもなく、一定のフレームレートを維持することさえ難しい場合があります。数百メガバイトにもなるモデルがユーザーのブラウザや帯域幅(携帯電話)に与える負担についても言うまでもありません。

ただし、特定の原則に従う限り、畳み込みニューラル ネットワーク CNN と TensorFlow.js を使用してブラウザーで適切なディープラーニング モデルをトレーニングすることは夢ではありません。下の図からわかるように、私がトレーニングしたモデルのサイズはすべて 2 MB 未満に抑えられており、最小のモデルでも 3 KB しかありませんでした。

頭の中で疑問に思うことがあるかもしれません。あなたはバカですか? ブラウザを使ってモデルをトレーニングしたいのですか? はい、自分のコンピューター、サーバー、クラスター、またはクラウドを使用してディープラーニング モデルをトレーニングするのは間違いなく正しい方法ですが、誰もが NVIDIA GTX 1080 Ti または Titan X を使用するお金を持っているわけではありません (特にグラフィック カードの価格が全体的に上昇した後では)。このとき、ブラウザでディープラーニング モデルをトレーニングする利点が反映されます。WebGL と TensorFLow.js を使用すると、コンピューター上の AMD GPU を使用してディープラーニング モデルを簡単にトレーニングできます。

ターゲット認識問題では、安全のために、YOLO、SSD、残差ネットワークResNet、MobileNetなどの既製のアーキテクチャを使用することが推奨されることが多いですが、個人的には、それらを完全にコピーすると、ブラウザでのトレーニング効果が確実に悪くなると思います。ブラウザ上でトレーニングするには、モデルが小さく、高速で、できるだけ簡単にトレーニングできることが求められます。次に、モデルアーキテクチャ、トレーニング、デバッグの観点から、これら 3 つのポイントを実現する方法を見ていきます。

モデルアーキテクチャ

1. モデルのサイズを制御する

モデルのスケールを制御することが重要です。モデル アーキテクチャが大きすぎて複雑すぎると、トレーニングと実行が遅くなり、ブラウザーからのモデルの読み込みも遅くなります。モデルのサイズを制御することは言うのは簡単ですが、難しいのは精度とモデルのサイズのバランスを取ることです。精度が要件を満たさない場合、モデルがどれだけ小さくても役に立たなくなります。

2. 深さ方向に分離可能な畳み込み演算を使用する

標準的な畳み込み演算とは異なり、深さ方向に分離可能な畳み込みでは、最初に各チャネルで畳み込み演算を実行し、次に 1X1 クロスチャネル畳み込みを実行します。これを行う利点は、パラメータの数を大幅に削減できるため、モデルの実行速度が大幅に向上し、リソースの消費とトレーニング速度も向上することです。深さ方向に分離可能な畳み込み演算のプロセスを次の図に示します。

MobileNet と Xception はどちらも深さ方向に分離可能な畳み込みを使用しており、MobileNet と PoseNet の TensorFlow.js バージョンでも深さ方向に分離可能な畳み込みを確認できます。深さ方向に分離可能な畳み込みがモデルの精度に与える影響についてはまだ議論の余地がありますが、私の個人的な経験からすると、ブラウザでモデルをトレーニングする場合、これを使用するのは間違いなく正しい選択です。

最初のレイヤーでは、特徴抽出後のチャネル間の関係を維持するために、標準の conv2d 操作を使用することをお勧めします。 *** レイヤーには一般にパラメータが少ないため、パフォーマンスへの影響はほとんどありません。

他の畳み込み層はすべて、深さ方向に分離可能な畳み込みを使用できます。たとえば、ここでは 2 つのフィルターを使用します。

ここで、tf.separableConv2dで使用される畳み込みカーネル構造はそれぞれ[3,3,32,1]と[1,1,32,64]です。

3. スキップ接続と密なブロックを使用する

ネットワーク層の数が増えると、勾配消失問題が発生する可能性も高まります。勾配消失により損失関数の減少が遅くなりすぎて、トレーニング時間が非常に長くなったり、失敗したりする可能性があります。 ResNet および DenseNet で使用されるスキップ接続により、この問題を回避できます。簡単に言うと、スキップ接続とは、次の図に示すように、活性化関数をスキップし、いくつかの層の出力をネットワークの深部にある隠し層に直接入力として渡すことです。

これにより、活性化関数とチェーン導出によって引き起こされる勾配消失の問題を回避でき、必要に応じてネットワーク層の数を増やすこともできます。

明らかに、スキップ接続の暗黙の要件は、接続された 2 つのレイヤーの出力と入力の形式が一致する必要があることです。残差ネットワークを使用する場合は、両方のレイヤーのフィルター数とパディングが同じであり、ストライドが 1 であることを確認する必要があります (ただし、形式が対応していることを確認する方法は他にもあります)。

最初は、残差ネットワークの考え方を真似して、1層おきにスキップ接続を追加しました(下図参照)。しかし、スキップ接続を追加するよりも密なブロックの方がうまく機能し、モデルの収束がはるかに速くなることがわかりました。

具体的なコードを見てみましょう。ここでの密なブロックには、深さ方向に分離可能な 4 つの畳み込み層があります。最初の層では、入力サイズを変更するためにストライドを 2 に設定しました。

4. 活性化関数としてReLUを選択する

ブラウザでディープ ネットワークをトレーニングする場合、活性化関数を確認せずに ReLU を選択するだけで済みます。主な理由は、勾配が消えるためです。しかし、ReLUのさまざまなバリエーションを試すこともできます。

MobileNetで使用されるReLU-6 (y = min(max(x, 0), 6)):

トレーニングプロセス

5. 最適化ツールとしてAdamを選択する

これは単なる私の個人的な経験です。以前は、SGD は局所最小値で行き詰まったり、勾配爆発が発生したりすることがよくありました。まず学習率を 0.001 に設定し、他のすべてのパラメータをデフォルトのままにしておくことをお勧めします。

6. 学習率を動的に調整する

一般的に言えば、損失関数が減少しなくなったらトレーニングを停止する必要があります。それ以上のトレーニングは過剰適合につながるためです。ただし、損失関数が上下に振動していることがわかった場合は、学習率を下げることで損失関数を小さくできる可能性があります。

以下の例では、学習率が最初は 0.01 に設定され、エポック 32 (黄色の線) から振動していることがわかります。ここで、学習率を 0.001 (青線) に変更すると、損失関数は約 0.3 減少します。

7. 重み初期化の原理

個人的には、バイアスを 0 に設定し、重みには従来の正規分布を使用するのが好きです。私は通常、Glorot 正規分布初期化メソッドを使用します。

8.データセットの順序をシャッフルする

それは決まり文句です。 TensorFlow.js では、tf.utils.shuffle を使用してこれを実現できます。

9. モデルを保存する

js は FileSaver.js を使用してモデルを保存 (またはダウンロード) できます。たとえば、次のコードはモデルのすべての重みを保存できます。

保存する形式を決めることはできますが、FileSaver.js は保存するだけなので、ここでは JSON.strinfify を使用して Blob を文字列に変換する必要があります。

デバッグ

[[246862]]

10. 前処理と後処理の正確性を確認する

ナンセンスではありますが、「ゴミデータ、ゴミ結果」というのは確かに真実です。ラベルは正しく、各レイヤーの入力と出力は一貫している必要があります。特に、画像に対して何らかの前処理や後処理を行った場合は、こうした小さな問題を見つけるのが難しい場合もあるため、より注意する必要があります。したがって、多少の労力はかかりますが、ナイフを研ぐことで木を切る作業が遅れることはありません。

11. カスタム損失関数

TensorFlow.js には、誰でも使用できる既製の損失関数が多数用意されており、一般的にはそれで十分なので、独自の損失関数を作成することはお勧めしません。実際に自分で書いてみたい場合は、必ず事前にテストしてください。

12. データのサブセットにオーバーフィッティングを試みる

モデルを定義した後、まず 12 枚または 20 枚の画像を選択して、損失関数が収束するかどうかを確認することをお勧めします。 ***結果を視覚化することで、モデルが成功する可能性があるかどうかを明確に確認できます。

[[246863]]

これを行うことで、モデルと前処理における低レベルのエラーを早い段階で発見することもできます。これは実際には項目 11 で説明したテスト損失関数です。

パフォーマンス

13. メモリリーク

TensorFlow.js がガベージ コレクションを自動的に支援しないことをご存知かどうかはわかりません。テンソルによって占有されているメモリは、tensor.dispose() を呼び出して手動で解放する必要があります。リサイクルを忘れると、遅かれ早かれメモリリークが発生します。

メモリリークがあるかどうかは簡単に判断できます。テンソルの数を確認するために、各反復で tf.memory() を出力してみましょう。増加し続けなければ、漏れはありません。

14. テンソルではなくキャンバスのサイズを変更する

TF.fromPixels を呼び出す前にキャンバスをテンソルに変換するには、キャンバスのサイズを変更します。そうしないと、すぐに GPU メモリが不足します。

トレーニング画像がすべて同じサイズであれば問題はありませんが、明示的にサイズを変更する必要がある場合は、以下のコードを参照してください。 (以下の記述は tfjs-core の現在の状態でのみ有効であることに注意してください。現在、tfjs-core バージョン 0.12.14 を使用しています)

15. バッチサイズを慎重に選択する

各バッチ内のサンプル数、つまりバッチ サイズは、使用する GPU とネットワーク構造によって異なることは明らかです。そのため、さまざまなバッチ サイズを試して、どれが最も高速かを確認するのが最適です。私は通常 1 から始めますが、バッチ サイズを大きくしてもトレーニングの効率が向上しないことがあります。

16. IndexedDBを有効活用する

私たちがトレーニングに使用するデータセットはすべて画像なので、かなり大きくなることがあります。毎回ダウンロードするのは間違いなく非効率です。IndexedDB を使用して保存するのが最善の方法です。 IndexedDB は実際にはブラウザに埋め込まれたローカル データベースであり、任意のデータをキーと値のペアの形式で保存できます。データの読み取りと保存は、わずか数行のコードで実行できます。

17. 損失関数の値を非同期的に返す

損失関数の値をリアルタイムで監視するには、次のコードを使用して自分で計算し、非同期で返すことができます。

各トレーニング期間後に損失関数の値をファイルに保存する場合、そのようなコードにはいくつかの問題が発生することに注意してください。損失関数の値は非同期的に返されるようになったため、保存する前に最後の Promise が返されるまで待つ必要があります。しかし、私は通常、問題が終了してから保存するまで 10 秒待ちます。

18. 重量の定量化

小型で高速という目標を達成するには、モデルのトレーニングが完了した後に重みを量子化してモデルを圧縮する必要があります。重み量子化はモデルのサイズを縮小するだけでなく、モデルの速度を向上させるのにも役立ち、欠点がなくほとんどすべての利点があります。このステップにより、モデルが小さく高速になり、ブラウザでディープラーニング モデルをトレーニングするのに非常に適しています。

これで、ブラウザでディープラーニング モデルをトレーニングするための 18 のヒント (実際には 17 のヒント) は終了です。この記事を読んで何かを得ていただければ幸いです。

<<:  Megvii Technology: 人工知能が携帯電話の「視覚」革命をリード

>>:  AIは人間の感情を理解できるのか?

ブログ    

推薦する

2020年にはAI技術はさらに環境に優しくなる

人工知能(AI)技術の環境への影響は最近、幅広い注目を集めていますが、これは今後10年間でAIの中心...

ニューラルスタイル転送アルゴリズムで絵を描くことを学習する人間は、芸術分野で人工知能に負けるのでしょうか?

人工知能はますます多用途になり、すでに私たちの仕事のすべてを人工知能が引き継ぐことができるようです。...

人間は AI シミュレーションの中で生きられるのか?

人々が自らに問うべき実存的な問いは、自分たちがシミュレートされた宇宙に住んでいるかどうかだ。 [[3...

...

100,000 台以上の Vision Transformer を一度にトレーニングするにはどうすればよいでしょうか?

[[413052]]この記事はLeiphone.comから転載したものです。転載する場合は、Lei...

Apple M3全シリーズのランニングスコアを公開! 16コアのMaxが24コアのM2 Ultraを上回り、IntelとAMDの主力CPUと並ぶ

Appleの記者会見を受けて、M3シリーズチップは新しいMac製品とともについに実用化されることにな...

Python が Java や C/C++ に勝って機械学習に最適な言語である理由!

Python は、1989 年にオランダ人の Guido van Rossum によって発明され、...

自動運転車を最も必要としているのは誰でしょうか?

ほぼすべての道路状況に適応できる自動運転車の開発は、間違いなく非常に困難な課題です。無人運転車を実現...

AI ロボットは製造業にどのような変化をもたらすのでしょうか?

AIロボットとは?人工知能 (AI) ロボットは、現実世界の環境で動作する人工知能エンティティです...

...

巨大企業間の今後の AI 戦争: マイクロソフトは左に進んで 2B、グーグルは右に進んで 2C

AI時代の到来非常にドラマチックなのは、Microsoft Build 開発者会議と Google...

シスコが新たな調査レポートを発表:企業はAIの準備に大きなギャップを抱えている

ニュースハイライト:中国企業の98%は、過去6か月間にAI技術導入の緊急性が高まったと回答した。戦略...

DIFFアルゴリズムがわからない場合は、私に連絡してください(画像付き)

序文インタビュアー: 「仮想 DOM と Diff アルゴリズムをご存知ですか? 説明してください。...

ゼロから学ぶPythonによるディープラーニング!

人工知能は現在、飛躍的に成長しています。たとえば、自動運転車は時速数百万マイルで走行し、IBM Wa...

NVIDIA が Tensor RT-LLM を発表、RTX 搭載 PC プラットフォームで大規模言語モデルを 4 倍高速化

10月18日、NVIDIAはハードウェア分野における生成型人工知能の王者となった。同社のGPUは、M...