この記事は、の一部として公開されました データサイエンスブログソン
概要
また、私の意見では、Transfer Learningは、TensorFlowJSを使用してクライアント側で使用する最も有望な手法です。 ここで、サーバーで同じ手法を使用することに対する大きな利点は、クライアント情報の機密性を維持し、センサー(カメラ、ジオロケーションなど)にアクセスする機能を利用できることです。
トランスファーラーニングはどのように機能しますか?
トランスファーラーニングの仕組みは簡単です。 モデルは、最初に大量のトレーニングデータでトレーニングされます。 トレーニングプロセス中に、ニューラルネットワークは、解決されている特定の問題の多数の有用な特性(機能)を抽出します。これは、新しい問題の基礎として使用でき、少数のトレーニングデータでトレーニングされます。より具体的ですが、同様の問題です(図1)。 したがって、リソースが限られているデバイスでは、比較的短時間で過剰適合が発生する可能性があります。
図1-転移学習のブロック図
モデルをTensorFlowにロードするには、特別なJSON形式を使用します。これには、次のXNUMXつのタイプがあります。 グラフモデル or レイヤーモデル (図2)。
図2–TensorFlowJSと互換性のあるモデルシリアル化形式の分類
転移学習の場合、 グラフモデル 形式は適用されません。このモデルは、新しいデータサンプルで再トレーニングしたり、ニーズに合わせてトポロジを変更したりすることなく、ロードされた形式でのみ使用できます。 したがって、以下では、モデルについてのみ説明します。 レイヤーモデル 形式でダウンロードすることができます。
事前にトレーニングされたモデルをロードするには レイヤーモデル TensrFlowJSは、CUIにtf.loadLayersModelメソッドを提供します。このメソッドは、長いトレーニングプロセスからモデルのトポロジとその重みをロードします。 モデルのトポロジはJSON形式で設定され、JSON形式には 重みマニフェスト トレーニングされたニューラルネットワークの接続のすべての重みを含むバイナリ形式のパスを示すフィールド(数百万のトレーニングされたパラメーターを持つ複雑なニューラルネットワークの場合、モデルの重みはいくつかのシャードファイルで表すことができます)。
特別なコンバーターを使用すると、Kerasフレームワーク(現在はTensorFlowのサブモジュールとして含まれています)を使用してPythonでトレーニングされたモデルなど、モデルをTF.js互換形式に変換できます。
モデルをロードした後、タスクの要件に応じてモデルを変更および再トレーニングできます。 新しいデータサンプルに基づいてモデルのトレーニングにかかる時間を短縮するよう努めているため、元のモデルのできるだけ多くのレイヤーを「フリーズ」する必要があることは明らかです。 層の凍結は、層内のすべてのニューロンの転送です。 訓練可能 カテゴリに 訓練不能 カテゴリー。 ネットワークトレーニング中、オプティマイザはトレーニングされたネットワークパラメータのみを変更するため、トレーニングの時間を大幅に短縮できます。
その場合、公正な質問は、フリーズするレイヤーの数とレイヤーです。 これを直感的に理解するために、Nクラス間の画像分類を扱う典型的なニューラルネットワークのブロック図を見てみましょう。
図3–Nクラス間の画像分類のためのニューラルネットワークトポロジ
ニューラルネットワークは、複数の直列接続された層の畳み込み( 畳み込み層 )そして、完全に接続されたニューラルネットワーク( 密な層、完全に接続された層 ).
畳み込み層の目的は画像の特徴を抽出することですが、最初の畳み込み層(ネットワーク入力に対して)は、画像から最も単純なパターン(エッジ、輪郭、円弧)を抽出することを思い出してください。 次の畳み込み層は、前の層のさまざまなパターンを組み合わせて、より複雑なテクスチャを形成します。円、正方形は、人の顔の一部、車のホイールなどに折りたたむことができます。ここでのすべては、解決されている問題。
機械の認識方法を知っているモデルを使用し、画像内の人間の顔の存在を認識する必要がある場合でも、タスクは完全に異なっているように見えますが、入力に近い畳み込み層は両方のネットワークのニューラルネットワークは、同一の特徴を抽出します。
図4 –ニューラルネットワークのさまざまなレベルで畳み込み層によって割り当てられた機能
!!!! したがって、上記を考慮すると、ニューラルネットワークの入力から層の凍結を開始する必要があり、凍結層の数は、プリロードされたモデルが解決する問題と解決される問題の類似性に正比例します。.
フリーズするレイヤーの数を選択するためのもうXNUMXつの同様に重要なパラメーターは、モデルを再トレーニングするために使用できるデータセットのサイズです。
たとえば、 限られた数のトレーニングデータ モデルを再トレーニングするために使用します。 新しいタスクも同様です プリロードされたネットワークが解決したタスクに対して、この場合、すべての畳み込み層をフリーズすることは理にかなっています。 一方、 大量のトレーニング データ、およびプリロードされたネットワーク のように見えません 私たちが解決している問題ですが、ここではレイヤーをフリーズすることはできません。
後者の場合、質問をすることができます。したがって、単一のレイヤーを修正しない場合は、事前にトレーニングされたモデルにその重みをロードするのが理にかなっています。 ただし、モデルを最初からトレーニングする場合、フレームワークはニューラルネットワークの重みを任意に初期化します。これにより、モデルのトレーニングプロセスは、前述のように低レベルの事前設定された重みを使用した場合よりも長くなります。異なるタスクのレイヤーは、ほぼ同じ設定になります。
!!!! 要約すると、上記のとおり、トレーニングモデルのトレーニングサンプルが多いほど、フリーズする必要のあるレイヤーが少なくなります。
上記の図5で説明したアルゴリズムの視覚化を見ることができます。
図5 –>すでにトレーニングされたものに基づいて新しいニューラルネットワークをセットアップするスキーム
Tensorflow.jsを使用した転移学習の実装
プレイするためのコンポーネントのXNUMXつを開発するタスクがあります 最初はグー、じゃんけん。 このコンポーネントは、ユーザーにカメラを表示するように求めるインターフェースです。 じゃんけん、紙。 学習プロセスの後、コンポーネントはユーザーが何を表示しているかを独自に決定する必要があります。
まず、全体像と、これから行うことを見て、各ステップを分析しましょう。
図6 –>トレーニングされたMobileNetモデルに基づいて新しいモデルを作成するための構造図
トレーニング済みのMobileNetモデルをロードして分析する
MobileNetは、ImageNetサンプル(1000万を超える画像のコレクション、手動でXNUMXのクラスに分割)でトレーニングされたモデルです。
カスタムReactフックを使用してモデルをロードしましょう:
export デフォルト ()=> { 定数 [モデル、setModel] = useState(); useEffect(()=> {(非同期 function INIT(){ 定数 モデル= 待つ tf.loadLayersModel(MODEL_URL); setModel(()=>モデル); model.summary(); })(); }、[]); return モデル; }
呼び出して、ロードされたネットワークのトポロジを見てみましょう。 model.summary() 、図7。
図7–ロードされたモデルのトポロジー
モデルは88層で構成され、その入力層は次元[null、224、224、3]のテンソルで表され、224つのカラーチャネルを持つ224×1000ピクセルの次元の画像を受け入れます。 出力層は、次元[null、XNUMX]のテンソルです。
出力テンソル[null、1000]はいわゆる ワンホットベクター、たとえば[0、0、1、0、0]のように、1つを除いてすべての値がゼロに等しい–これは、ニューラルネットワークが確率2でカウントし、画像にインデックスを持つクラスがあることを意味します0.07(通常どおり、インデックス作成はゼロから始まります)。 モデルを使用する場合、このベクトルは各クラスの確率分布を表します。たとえば、次の値を取得できます:[0.1、0.03、0.75、0.05、1]。 すべての値の合計は0.75に等しくなり、モデルはこれがインデックス3のクラスのオブジェクトであると最大確率XNUMXで考慮することに注意してください。
このタスクではクラスが3つしかないため、ロードされた元のモデルは1000のクラスに分類できるため、モデルのトポロジを変更する必要があります。 私たちがやりたいことの図を描きましょう。
モデルレイヤーは、以下を担当するグループに任意に分割できます。
–画像の特徴を抽出する
–1000クラス間の画像の分類
新しいモデルでは、画像の特徴抽出を担当するすべてのレイヤーを使用すると同時に、1000クラス間の画像の分類を担当するすべてのレイヤーを削除し、代わりに独自の分類器を提供します。 3つのクラス。
図8は、ロードされたレイヤーの目的別の内訳の図を示しています(図8)。
図8–既存のモデルに基づいて新しいモデルを作成する
ちなみに、ここでは、レイヤーをフリーズする価値があるかどうかというテーマでタスクを分析できます。 まず、ネットワークをトレーニングするためにユーザーに大規模なトレーニングサンプルを作成するように強制することは絶対にありません。各クラスの30〜50枚の画像で十分です。 また、私たちが解決している問題、つまりジェスチャーによる3つのクラスの画像の分類は、以前は大量のトレーニング画像でトレーニングされていた1000のクラス間の画像の分類の問題に非常に近いものです。 したがって、図5に従って、ニーズに合わせて抽出したMobileNetV2モデルの一部のすべてのレイヤーをフリーズできます。
// フリーズ を 層 of モバイルネット
for (constレイヤー of pretrainedModel.layers){layer.trainable = false; }
画像署名の抽出を担当するロードされたモデルの最後のレイヤーを見つけます
これを行うには、API tf.LayersModel.getLayerを使用します。これにより、インデックスまたは一意の名前で目的のレイヤーを見つけることができます。 インデックスよりも一意の名前でレイヤーを検索することをお勧めします。 注意してください(図7)。ロードされたモデルの各レイヤーには一意の名前があります。 入力_1; conv_pw_13_bn; conv_pw_13_relu 、など。合意したように、モデル内の最後の畳み込み層が見つかります。これはconv_pw_13_reluという名前の層です。 したがって、コードは次のようになります。
定数 切り捨てられたレイヤー= pretrainedModel.getLayer( 'conv_pw_13_relu'); 定数 切り捨てられたレイヤー出力=切り捨てられたレイヤー.output as シンボリックテンソル;
XNUMXつのクラスを分類するための新しい分類子を作成します
モデルはいくつかのレイヤーで構成されます(図8)。
- 最初の層 – MobileNetV2畳み込み層から取得した多次元テンソルをXNUMX次元配列に変換して、分類のためにモデルの完全に接続された密な層と互換性を持たせる必要があります。
– 100番目の層は、RELU活性化関数を備えたXNUMX個のニューロン(パラメーターは実験に基づいて選択できます。これはいわゆるハイパーパラメーターです)を含む、完全に接続された非表示の層です。 RELUは、モデルに非線形性を追加する最も一般的な活性化関数です。
– 3番目の層は、正確にXNUMXつのニューロンを含む完全に接続された出力層であり、各ニューロンは、じゃんけん、紙のXNUMXつのクラスのいずれかに属する画像の確率を決定します。 レイヤーはSOFTMAXアクティベーション機能を備えています。 SOFTMAXは、複数の分類問題を解決するために最後の層に常に使用される関数です。 ベクトルを変換します のz 寸法 K 同じ次元のベクトルに σ、ここで、各値は区間[0、1]の実数で表され、それらの合計はXNUMXに等しくなります。 そして、上記のように、ベクトルの各値 σ 私は オブジェクトがクラスに属する確率として扱われます i.
図9–3つのクラス間の分類を担当するモデルの新しいレイヤー
コードは次のようになります。
function ビルドニューヘッド(inputShape:Shape、numClasses:number){// 2層の完全に接続されたモデルを作成します return tf.sequential({layers:[tf.layers.flatten({name: 'flatten'、inputShape:inputShape.slice(1)、})、tf.layers.dense({name: 'hidden_dense_1'、units:100、アクティベーション: 'relu'})、tf.layers.dense({名前: 'softmax_classification'、ユニット:numClasses、アクティベーション: 'softmax'})]}); }
新しい分類器を事前トレーニング済みモデルのレイヤーに関連付ける
ステップ2で、新しい開発モデルに保持したいモデルグラフの最後のレイヤーを見つけました。 このレイヤーをステップ3で作成した分類子にリンクしましょう(図6を参照)。 このため、モデル/レイヤークラスのインスタンスには、レイヤー間の接続を行う特別なアプリケーションメソッドがあります。 次のようになります。
定数 transferHead = buildNewHead(truncatedLayerOutput.shape、numClasses); 定数 newOutput = transferHead.apply(truncatedLayerOutput) as シンボリックテンソル;
新しいモデルを作成してコンパイルする
既存のモデルに基づいて新しいモデルを作成するには、XNUMXつの必須フィールドを持つオブジェクトを取得するtf.modelを使用します。 入力 & outputs。 両方のパラメーターは配列を想定しています。配列の各要素は シンボリックテンソル (通常のテンソルとの違いは、実際には、次元とタイプに関する情報を持っているテンソルの記述ですが、データ、いわゆるプレースホルダーはありません)。
モデルの各レイヤーには、シンボリックテンソルで表される入力と出力のXNUMXつの属性があります。
ここでは、入力パラメーターを受け取る通常のJS関数にレイヤーを関連付けると便利な場合があります。一部の計算ロジックは内部で実行され、常に出力パラメーターを返します。 ここでの違いは、入力パラメーターと出力パラメーターがシンボリックテンソルになることです。
したがって、定義する必要があります 入力 & outputs 新しいモデルのために。 新しいモデルの入力は、ロードされたモデルの入力と一致し、を介して利用できます。 pretrainedModel.inputs.
そして、シンボリックテンソルの出力は、新しい分類器の最後の層の後の出力であり、 新しい出力 前のステップでapplyメソッドを適用した後の変数。
//新しいモデルを作成します
定数 model = tf.model({入力:pretrainedModel.inputs、出力:newOutput});
目的のオプティマイザーと損失関数を指定して、モデルをコンパイルしてみましょう。 最適なオプティマイザはtf.train.adamであり、分類損失関数は通常、カテゴリのクロスエントロピーです。
。コンパイル({ オプティマイザ:tfC.train.adam(0.0001)、損失: 'categoricalCrossentropy'});
事前トレーニング済みのMobileNetに基づいて新しいモデルを作成するための完全なコード
ユーザーがXNUMX種類の画像の選択を設定できるようにするUX要素を追加し、学習プロセスを開始するボタンを提供するだけです。
function App(){//簡潔にするためにスキップ 定数 tr = 非同期 ()=> { if (モデル&& controllerDataset.current.xs!== null && controllerDataset.current.ys!== null){ 定数 {現在:{xs、ys}} = controllerDataset; model.fit(xs、ys、{batchSize:24、エポック:20、シャッフル:true、コールバック:{onBatchEnd: 非同期 (バッチ、ログ)=> {setLoss(()=>(logs?.loss as 番号).toFixed(5)); }、onTrainEnd:()=> {changeTrainingState(()=> TRAINING_STATES.TRAINED); }}}); }}; return ((div要素> {/ *簡潔にするためにスキップ* /}(Comma Separated Values) ボタンをクリックして、各々のジョブ実行の詳細(開始/停止時間、変数値など)のCSVファイルをダウンロードします。 disable = {trainingState === TRAINING_STATES.TRAINING} onClick = {()=> {if(trainingState!== TRAINING_STATES.TRAINING){changeTrainingState(()=> TRAINING_STATES.TRAINING); 訓練(); }}}>電車</(Comma Separated Values) ボタンをクリックして、各々のジョブ実行の詳細(開始/停止時間、変数値など)のCSVファイルをダウンロードします。> </div要素>); }
トレーニングプロセスが完了したら、このモデルを使用して画像を分類するプロセスを開始する必要があります。
const Forecast = async()=> { if (webcamIterator && model){const image = 待つ websiteIterator.capture(); constprocessedImage = tf.tidy(()=> image.expandDims()。toFloat()。div(127).sub(1)); const label = tf.argMax(model.predict(processedImage) as テンソル、1).dataSync(); setActiveLabel(()=> label [0]); image.dispose(); processedImage.dispose(); requestAnimationFrame(()=> Forecast()); }}; useEffect(()=> { if (trainingState === TRAINING_STATES.TRAINED){requestAnimationFrame(()=> Forecast()); }}、[trainingState]);
まとめ
トランスファーラーニングの仕組みは簡単です。 モデルは、最初に大量のトレーニングデータでトレーニングされます。 トレーニングプロセス中に、ニューラルネットワークは、解決されている特定の問題の多数の有用な特性(機能)を抽出します。これは、新しい問題の基礎として使用でき、少数のトレーニングデータでトレーニングされます。より具体的ですが、同様の問題です。 したがって、リソースが限られているデバイスでは、比較的短時間で過剰適合が発生する可能性があります。
画像ソース:
図1
図2
図3
Figure 4 https://image.slidesharecdn.com/150721cdbn-150720184716-lva1-app6892/95/convolutional-deep-belief-networks-for-scalable-unsupervised-learning-of-hierarchical-representations-41-638.jpg?cb=1437418192
Figure 5 https://image.slidesharecdn.com/150721cdbn-150720184716-lva1-app6892/95/convolutional-deep-belief-networks-for-scalable-unsupervised-learning-of-hierarchical-representations-41-638.jpg?cb=1437418192
Figure 6 https://image.slidesharecdn.com/150721cdbn-150720184716-lva1-app6892/95/convolutional-deep-belief-networks-for-scalable-unsupervised-learning-of-hierarchical-representations-41-638.jpg?cb=1437418192
図7
図8
図9
この記事に示されているメディアは、Analytics Vidhyaが所有しておらず、作成者の裁量で使用されています。
PlatoAi。 Web3の再考。 増幅されたデータインテリジェンス。
アクセスするには、ここをクリックしてください。
出典:https://www.analyticsvidhya.com/blog/2021/09/understand-transfer-learning-using-tensorflow-js/