ディープラーニングチュートリアル:パーセプトロンからディープネットワークまで
公開: 2022-03-11近年、人工知能の分野で復活が見られます。 それは、グーグル、マイクロソフト、フェイスブックのような主要なプレーヤーが独自の研究チームを作り、いくつかの印象的な買収を行うことで、学術界を超えて広がっています。
これの一部は、ソーシャルネットワークユーザーによって生成された豊富な生データ、その多くを分析する必要があること、高度なデータサイエンスソリューションの台頭、およびGPGPUを介して利用できる安価な計算能力に起因する可能性があります。
しかし、これらの現象を超えて、この復活は、AI、特に「ディープラーニング」として知られる機械学習の新しいトレンドによって少なからず推進されてきました。 このチュートリアルでは、ディープラーニングの背後にある主要な概念とアルゴリズムを紹介します。まず、構成の最も単純な単位から始めて、Javaでの機械学習の概念を構築します。
(完全な開示について:私はJavaディープラーニングライブラリの作成者でもあり、ここで入手できます。この記事の例は、上記のライブラリを使用して実装されています。気に入った場合は、GitHubでスターを付けることでサポートできます。 、ありがたいです。使用方法については、ホームページをご覧ください。)
機械学習に関する32番目のチュートリアル
慣れていない場合は、この機械学習の概要を確認してください。
一般的な手順は次のとおりです。
- いくつかのラベル付きの例を示すアルゴリズムがあります。たとえば、ラベル1(「犬」)の犬の画像10枚と、ラベル0(「犬ではない」)のその他の画像10枚です。主に貼り付けていることに注意してください。この投稿の監視対象のバイナリ分類に。
- アルゴリズムは犬の画像を識別するために「学習」し、新しい画像が供給されると、正しいラベル(犬の画像の場合は1、それ以外の場合は0)を生成することを期待します。
この設定は非常に一般的です。データは症状であり、ラベルは病気である可能性があります。 または、データは手書き文字の画像であり、ラベルはそれらが表す実際の文字である可能性があります。
パーセプトロン:初期の深層学習アルゴリズム
最も初期の教師ありトレーニングアルゴリズムの1つは、基本的なニューラルネットワークの構成要素であるパーセプトロンのアルゴリズムです。
平面に「0」と「1」のラベルが付いたn個の点があるとします。 新しいポイントが与えられ、そのラベルを推測したいと思います(これは、上記の「犬」と「犬ではない」のシナリオに似ています)。 どうすればいいですか?
1つのアプローチは、最も近いネイバーを調べて、そのポイントのラベルを返すことです。 ただし、もう少しインテリジェントな方法は、ラベル付けされたデータを最もよく分離する行を選択し、それを分類子として使用することです。
この場合、入力データの各部分はベクトルx =( x_1、x_2 )として表され、関数は「線より下の場合は「0」、上の場合は「1」」のようになります。
これを数学的に表すために、重みのベクトルwと垂直オフセット(またはバイアス) bによってセパレーターを定義します。 次に、この関数は、入力と重みを加重和伝達関数と組み合わせます。
次に、この伝達関数の結果が活性化関数に送られ、ラベリングが生成されます。 上記の例では、活性化関数はしきい値のカットオフでした(たとえば、ある値より大きい場合は1)。
パーセプトロンのトレーニング
パーセプトロンのトレーニングは、複数のトレーニングサンプルをフィードし、それぞれの出力を計算することで構成されます。 各サンプルの後、重みwは、目的の(ターゲット)出力と実際の出力の差として定義される出力エラーを最小化するように調整されます。 平均二乗誤差のような他の誤差関数がありますが、トレーニングの基本原理は同じままです。
単一パーセプトロンの欠点
深層学習への単一パーセプトロンアプローチには、1つの大きな欠点があります。それは、線形分離可能な関数しか学習できないことです。 この欠点はどれほど大きなものですか? 比較的単純な関数であるXORを使用して、線形セパレーターで分類できないことに注意してください(以下の失敗した試行に注意してください)。
この問題に対処するには、フィードフォワードニューラルネットワークとも呼ばれる多層パーセプトロンを使用する必要があります。実際には、これらのパーセプトロンの束を組み合わせて、学習のためのより強力なメカニズムを作成します。
ディープラーニングのためのフィードフォワードニューラルネットワーク
ニューラルネットワークは、実際にはパーセプトロンの単なる構成であり、さまざまな方法で接続され、さまざまな活性化関数で動作します。
手始めに、次のプロパティを持つフィードフォワードニューラルネットワークを見ていきます。
- 入力、出力、および1つ以上の非表示レイヤー。 上の図は、3ユニットの入力層、4ユニットの隠れ層、および2ユニットの出力層を備えたネットワークを示しています(ユニットとニューロンという用語は交換可能です)。
- 各ユニットは、上記のような単一のパーセプトロンです。
- 入力レイヤーのユニットは、非表示レイヤーのユニットの入力として機能し、非表示レイヤーのユニットは、出力レイヤーへの入力です。
- 2つのニューロン間の各接続には、重みwがあります(パーセプトロンの重みと同様)。
- レイヤーtの各ユニットは、通常、前のレイヤーt-1のすべてのユニットに接続されています(ただし、重みを0に設定することで切断できます)。
- 入力データを処理するには、入力ベクトルを入力レイヤーに「クランプ」し、ベクトルの値を各入力ユニットの「出力」として設定します。 この特定のケースでは、ネットワークは3次元の入力ベクトルを処理できます(3つの入力ユニットがあるため)。 たとえば、入力ベクトルが[7、1、2]の場合、一番上の入力ユニットの出力を7に設定し、中央のユニットを1に設定します。 次に、これらの値は、各隠れユニットの加重和伝達関数を使用して隠れユニットに前方に伝播され(したがって、前方伝播という用語)、次にそれらの出力が計算されます(活性化関数)。
- 出力レイヤーは、非表示レイヤーと同じ方法で出力を計算します。 出力層の結果は、ネットワークの出力です。
直線性を超えて
各パーセプトロンが線形活性化関数の使用のみを許可されている場合はどうなりますか? 次に、ネットワークの最終出力は、入力の線形関数のままであり、ネットワーク全体で収集された1トンの異なる重みで調整されます。 言い換えれば、一次関数の束の線形構成は、依然として単なる線形関数です。 線形活性化関数に制限されている場合、フィードフォワードニューラルネットワークは、層がいくつあっても、パーセプトロンほど強力ではありません。
このため、ほとんどのニューラルネットワークは、ロジスティック、タン、バイナリ、整流器などの非線形活性化関数を使用します。 それらがないと、ネットワークは入力の線形結合である関数のみを学習できます。
パーセプトロンのトレーニング
多層パーセプトロンの教師ありトレーニングのための最も一般的な深層学習アルゴリズムは、バックプロパゲーションとして知られています。 基本的な手順:
- トレーニングサンプルが提示され、ネットワークを介して転送されます。
出力誤差が計算されます。通常、平均二乗誤差は次のとおりです。
ここで、 tは目標値、 yは実際のネットワーク出力です。 他の誤差計算も許容されますが、MSEは良い選択です。
ネットワークエラーは、確率的勾配降下法と呼ばれる方法を使用して最小化されます。
最急降下法は普遍的ですが、ニューラルネットワークの場合、これは入力パラメーターの関数としてのトレーニングエラーのグラフになります。 各重みの最適値は、エラーがグローバル最小値を達成する値です。 トレーニングフェーズでは、ウェイトが小さなステップで(各トレーニングサンプルまたはいくつかのサンプルのミニバッチの後に)更新され、常にグローバル最小値に到達しようとしますが、これは簡単な作業ではありません。多くの場合、右側のように極小値になります。 たとえば、重みの値が0.6の場合、0.4に変更する必要があります。
この図は、エラーが単一のパラメーターに依存する最も単純なケースを表しています。 ただし、ネットワークエラーはすべてのネットワークの重みに依存し、エラー関数ははるかに複雑です。
ありがたいことに、バックプロパゲーションは、出力エラーに関して2つのニューロン間の各重みを更新する方法を提供します。 導出自体は非常に複雑ですが、特定のノードの重みの更新は次の(単純な)形式になります。
ここで、 Eは出力誤差、 w_iはニューロンへの入力iの重みです。
基本的に、目標は重みiに対して勾配の方向に移動することです。 もちろん、重要な用語は誤差の導関数であり、必ずしも計算するのは簡単ではありません。大規模なネットワークの真ん中にあるランダムな隠れノードのランダムな重みに対して、この導関数をどのように見つけますか?
答え:バックプロパゲーションによる。 エラーは、最初に式が非常に単純な出力ユニットで計算され(ターゲット値と予測値の差に基づいて)、次に巧妙な方法でネットワークを介して伝播され、トレーニング中に重みを効率的に更新できます。 (うまくいけば)最小値に達します。
隠しレイヤー
隠れ層は特に興味深いものです。 普遍近似定理により、有限数のニューロンを持つ単一の隠れ層ネットワークをトレーニングして、任意のランダム関数を近似することができます。 言い換えれば、単一の隠れ層は、あらゆる機能を学習するのに十分強力です。 とは言うものの、私たちは多くの場合、複数の隠れたレイヤー(つまり、より深いネット)を使用して実際によりよく学習します。
隠れ層は、人間の脳(非常に単純化されたアナロジー)が現実世界の内部表現を持っているのと同じように、ネットワークがトレーニングデータの内部抽象表現を格納する場所です。 チュートリアルでは、隠しレイヤーをいじるさまざまな方法を見ていきます。
ネットワークの例
ここでは、 testMLPSigmoidBPメソッドを介してJavaに実装されたIRISデータセットを分類する単純な(4-2-3層)フィードフォワードニューラルネットワークを見ることができます。 データセットには、がく片の長さ、花びらの長さなどの機能を備えた3つのクラスのアヤメ植物が含まれています。ネットワークには、クラスごとに50のサンプルが提供されます。 機能は入力ユニットにクランプされますが、各出力ユニットはデータセットの単一のクラスに対応します。「1/0/0」は植物がSetosaクラスであることを示し、「0/1/0」はVersicolourを示し、「 0/0/1」はVirginicaを示します)。 分類エラーは2/150です(つまり、150のうち2つのサンプルを誤って分類します)。
大規模ネットワークの問題
ニューラルネットワークは複数の隠れ層を持つことができます。その場合、上位層は前の層の上に新しい抽象化を「構築」します。 また、前述したように、大規模なネットワークを使用すると、実際に学習することができます。
ただし、非表示レイヤーの数を増やすと、2つの既知の問題が発生します。
- 勾配消失:隠れ層を追加するにつれて、下位層に情報を渡す際の逆伝播の有用性はますます低下します。 事実上、情報が返されると、勾配は消え始め、ネットワークの重みに比べて小さくなります。
- 過剰適合:おそらく機械学習の中心的な問題です。 簡単に言えば、過剰適合は、おそらく複雑すぎる仮説で、トレーニングデータをあまりにも密接に適合させる現象を説明します。 このような場合、学習者はトレーニングデータを非常にうまく適合させることになりますが、実際の例でははるかにパフォーマンスが低下します。
これらの問題に対処するためのいくつかの深層学習アルゴリズムを見てみましょう。
オートエンコーダ
ほとんどの機械学習入門クラスは、フィードフォワードニューラルネットワークで停止する傾向があります。 しかし、可能なネットのスペースははるかに豊富なので、続けましょう。
オートエンコーダは通常、データセットの圧縮された分散表現(エンコーディング)を学習することを目的としたフィードフォワードニューラルネットワークです。
概念的には、ネットワークは入力を「再作成」するようにトレーニングされています。つまり、入力とターゲットデータは同じです。 言い換えると、入力したものと同じものを出力しようとしていますが、何らかの方法で圧縮されています。 これは紛らわしいアプローチなので、例を見てみましょう。
入力の圧縮:グレースケール画像
トレーニングデータが28x28のグレースケール画像で構成され、各ピクセルの値が1つの入力層ニューロンにクランプされているとします(つまり、入力層には784ニューロンが含まれます)。 その場合、出力層は入力層と同じ数のユニット(784)を持ち、各出力ユニットのターゲット値は画像の1ピクセルのグレースケール値になります。
このアーキテクチャの背後にある直感は、ネットワークがトレーニングデータとそのラベルの間の「マッピング」を学習せず、代わりにデータ自体の内部構造と機能を学習することです。 (このため、隠れ層は特徴検出器とも呼ばれます。)通常、隠れユニットの数は入力/出力層よりも少なく、ネットワークは最も重要な特徴のみを学習し、次元削減を実現します。
事実上、中央にあるいくつかの小さなノードが実際に概念レベルでデータを学習し、入力のコア機能を何らかの方法でキャプチャするコンパクトな表現を生成する必要があります。
インフルエンザの病気
オートエンコーダをさらに実証するために、もう1つのアプリケーションを見てみましょう。
この場合、インフルエンザの症状で構成される単純なデータセットを使用します(アイデアについてはこのブログ投稿のクレジット)。 興味がある場合は、この例のコードはtestAEBackpropagationメソッドにあります。
データセットの内訳は次のとおりです。
- 6つのバイナリ入力機能があります。
- 最初の3つは病気の症状です。 たとえば、 1 0 0 0 0 0はこの患者が高温であることを示し、 0 1 0 0 0 0は咳を示し、 1 1 0 000は咳と高温を示します。
- 最後の3つの機能は、「対抗」症状です。 患者がこれらのいずれかを持っている場合、彼または彼女が病気である可能性は低くなります。 たとえば、 0 0 0 1 0 0は、この患者がインフルエンザワクチンを接種していることを示します。 2つの機能セットを組み合わせることができます。0101 0 0は、咳をしているワクチン患者を示します。
最初の3つの特徴のうち少なくとも2つを持っている場合は患者が病気であり、次の3つのうち少なくとも2つを持っている場合は健康であると見なします(健康な患者に有利な関係を断ち切る)。
- 111000、101000、110000、011000、011100 =病気
- 000111、001110、000101、000011、000110 =健康
6つの入力ユニットと6つの出力ユニットを使用して(バックプロパゲーションを使用して)オートエンコーダーをトレーニングしますが、非表示のユニットは2つだけです。
数百回の反復の後、「病気の」サンプルのそれぞれが機械学習ネットワークに提示されると、2つの隠れたユニットの1つ(「病気の」サンプルごとに同じユニット)が常により高いアクティベーション値を示すことがわかります。他の。 逆に、「正常な」サンプルが提示されると、他の非表示のユニットのアクティブ化が高くなります。
機械学習に戻る
基本的に、2つの隠れたユニットは、インフルエンザの症状データセットのコンパクトな表現を学習しました。 これが学習とどのように関連しているかを確認するために、過剰適合の問題に戻ります。 データのコンパクトな表現を学習するようにネットをトレーニングすることにより、トレーニングデータに適合しすぎる非常に複雑な仮説ではなく、より単純な表現を優先します。
ある意味で、これらのより単純な表現を支持することによって、私たちはより真実の意味でデータを学習しようとしています。
制限付きボルツマンマシン
次の論理的なステップは、制限付きボルツマンマシン(RBM)を調べることです。これは、入力のセット全体の確率分布を学習できる生成確率ニューラルネットワークです。
RBMは、隠れた、目に見える、バイアス層で構成されています。 フィードフォワードネットワークとは異なり、可視層と非表示層の間の接続は無向であり(値は可視から非表示の方向と非表示から可視の方向の両方に伝播できます)、完全に接続されます(特定の層の各ユニットはに接続されます)次の各ユニット—任意のレイヤーの任意のユニットが他のレイヤーに接続できるようにすると、(制限付きのボルツマンではなく)ボルツマンマシンができます。
標準のRBMには、バイナリの非表示ユニットと表示ユニットがあります。つまり、ベルヌーイ分布ではユニットのアクティブ化は0または1ですが、他の非線形性を持つバリアントがあります。
研究者はRBMについてしばらく前から知っていましたが、対照的な発散教師なしトレーニングアルゴリズムの最近の導入により、関心が新たになりました。
対照的な発散
シングルステップの対照的発散アルゴリズム(CD-1)は、次のように機能します。

- 正相:
- 入力サンプルvは入力層にクランプされます。
- vは、フィードフォワードネットワークと同様の方法で隠れ層に伝播されます。 隠れ層のアクティブ化の結果はhです。
- ネガティブフェーズ:
- hを可視レイヤーに伝播して結果v'にします(可視レイヤーと非表示レイヤーの間の接続は無向であるため、両方向に移動できます)。
- 新しいv'を非表示レイヤーに伝播し、アクティベーション結果h'を使用します。
体重の更新:
ここで、aは学習率、 v 、 v' 、 h 、 h' 、およびwはベクトルです。
アルゴリズムの背後にある直感は、正のフェーズ( vが与えられた場合はh )がネットワークの実世界データの内部表現を反映しているということです。 一方、負のフェーズは、この内部表現( v'がh )に基づいてデータを再作成する試みを表します。 主な目標は、生成されたデータを現実の世界にできるだけ近づけることであり、これは重みの更新式に反映されます。
つまり、ネットは入力データをどのように表現できるかをある程度認識しているため、この認識に基づいてデータを再現しようとします。 その再現が現実に十分に近づいていない場合は、調整を行って再試行します。
インフルエンザに戻る
対照的な発散を示すために、以前と同じ症状データセットを使用します。 テストネットワークは、6つの可視ユニットと2つの非表示ユニットを備えたRBMです。 症状vが可視層に固定された対照的な発散を使用してネットワークをトレーニングします。 テスト中、症状は再び目に見える層に現れます。 次に、データは隠れ層に伝播されます。 非表示のユニットは、病気/正常な状態を表します。これは、オートエンコーダーと非常によく似たアーキテクチャです(データを表示レイヤーから非表示レイヤーに伝播します)。
数百回の反復の後、オートエンコーダーの場合と同じ結果を観察できます。「病気の」サンプルのいずれかが提示されると、非表示のユニットの1つがより高いアクティブ化値を持ち、もう1つは「正常な」サンプルに対して常によりアクティブになります。
この例は、 testContrastiveDivergenceメソッドで実際に動作していることがわかります。
ディープネットワーク
これで、オートエンコーダーとRBMの隠れ層が効果的な機能検出器として機能することを実証しました。 ただし、これらの機能を直接使用できることはまれです。 実際、上記のデータセットはルールよりも例外です。 代わりに、これらの検出された機能を間接的に使用する方法を見つける必要があります。
幸いなことに、これらの構造を積み重ねて深いネットワークを形成できることが発見されました。 これらのネットワークは、古典的なバックプロパゲーションに関連する勾配消失問題と過剰適合問題を克服するために、一度に1層ずつ貪欲にトレーニングできます。
結果として得られる構造は非常に強力であることが多く、印象的な結果を生み出します。 たとえば、Googleの有名な「猫」の論文では、特殊な種類のディープオートエンコーダを使用して、ラベルのないデータに基づいて人間と猫の顔の検出を「学習」しています。
よく見てみましょう。
スタック型オートエンコーダ
名前が示すように、このネットワークは複数のスタック型オートエンコーダで構成されています。
オートエンコーダtの隠れ層は、オートエンコーダt+1への入力層として機能します。 最初のオートエンコーダの入力層は、ネットワーク全体の入力層です。 貪欲なレイヤーごとのトレーニング手順は、次のように機能します。
- 利用可能なすべてのトレーニングデータを使用してバックプロパゲーション法を使用して、最初のオートエンコーダー( t = 1 、または上の図の赤い接続、ただし追加の出力レイヤーを使用)を個別にトレーニングします。
- 2番目のオートエンコーダーt=2 (緑色の接続)をトレーニングします。 t=2の入力層はt=1の隠れ層であるため、t = 1の出力層には関心がなくなり、ネットワークから削除します。 トレーニングは、入力サンプルをt = 1の入力層にクランプすることから始まります。これは、 t=2の出力層に前方に伝播されます。 次に、 t = 2の重み(入力-非表示および非表示-出力)がバックプロパゲーションを使用して更新されます。 t = 2は、 t = 1と同様に、すべてのトレーニングサンプルを使用します。
- すべてのレイヤーに対して前の手順を繰り返します(つまり、前のオートエンコーダーの出力レイヤーを削除し、さらに別のオートエンコーダーと交換して、バックプロパゲーションでトレーニングします)。
- 手順1〜3は事前トレーニングと呼ばれ、重みを適切に初期化したままにします。 ただし、入力データと出力ラベルの間にマッピングはありません。 たとえば、ネットワークが手書き数字の画像を認識するようにトレーニングされている場合でも、最後の特徴検出器(つまり、最後のオートエンコーダの隠れ層)からの単位を画像の数字タイプにマッピングすることはできません。 その場合、最も一般的な解決策は、1つ以上の完全に接続されたレイヤーを最後のレイヤーに追加することです(青い接続)。 これで、ネットワーク全体を多層パーセプトロンと見なすことができ、バックプロパゲーションを使用してトレーニングされます(このステップは微調整とも呼ばれます)。
スタック型オートエンコーダーは、ネットワークの重みを初期化するための効果的な事前トレーニング方法を提供することであり、トレーニング(または微調整)の準備ができている複雑な多層パーセプトロンを提供します。
ディープビリーフネットワーク
オートエンコーダーと同様に、ボルツマンマシンをスタックして、ディープビリーフネットワーク(DBN)と呼ばれるクラスを作成することもできます。
この場合、RBM tの隠れ層は、RBM t+1の可視層として機能します。 最初のRBMの入力層は、ネットワーク全体の入力層であり、貪欲な層ごとの事前トレーニングは次のように機能します。
- すべてのトレーニングサンプルで対照的な発散を使用して、最初のRBM t=1をトレーニングします。
- 2番目のRBMt =2をトレーニングします。 t=2の可視層はt=1の隠れ層であるため、トレーニングは入力サンプルをt = 1の可視層にクランプすることから始まり、t=1の隠れ層に伝播されます。 次に、このデータは、 t=2の対照的な発散トレーニングを開始するのに役立ちます。
- すべてのレイヤーに対して前の手順を繰り返します。
- スタック型オートエンコーダと同様に、事前トレーニング後、1つまたは複数の完全に接続されたレイヤーを最終的なRBM非表示レイヤーに接続することでネットワークを拡張できます。 これにより多層パーセプトロンが形成され、バックプロパゲーションを使用して微調整できます。
この手順は、スタック型オートエンコーダの手順と似ていますが、オートエンコーダがRBMに置き換えられ、バックプロパゲーションが対照的な発散アルゴリズムに置き換えられています。
(注:スタック型オートエンコーダーまたはディープビリーフネットワークの構築とトレーニングの詳細については、こちらのサンプルコードを確認してください。)
畳み込みネットワーク
最後の深層学習アーキテクチャとして、畳み込みネットワークを見てみましょう。畳み込みネットワークは、画像認識に非常に適した、特に興味深く、特別なクラスのフィードフォワードネットワークです。
畳み込みネットワークの実際の構造を見る前に、まず画像フィルター、または関連する重みを持つ正方形の領域を定義します。 フィルタは入力画像全体に適用され、多くの場合、複数のフィルタが適用されます。 たとえば、特定の入力画像に4つの6x6フィルターを適用できます。 次に、座標が1,1の出力ピクセルは、左上隅が1,1の入力ピクセルの6x6の正方形と、フィルターの重み(これも6x6の正方形)の加重和です。 出力ピクセル2,1は、左上隅2,1などの入力正方形の結果です。
これをカバーすると、これらのネットワークは次のプロパティによって定義されます。
- 畳み込み層は、入力にいくつかのフィルターを適用します。 たとえば、画像の最初の畳み込み層には4つの6x6フィルターを含めることができます。 画像全体に適用された1つのフィルターの結果は、特徴マップ(FM)と呼ばれ、特徴マップの数はフィルターの数と同じです。 前の層も畳み込みである場合、フィルターは異なる重みを持つすべてのFMに適用されるため、各入力FMは各出力FMに接続されます。 画像全体で共有される重みの背後にある直感は、位置に関係なく特徴が検出される一方で、フィルターの多様性により、各特徴が異なる特徴のセットを検出できることです。
- サブサンプリングレイヤーは、入力のサイズを縮小します。 たとえば、入力が32x32の画像で構成され、レイヤーに2x2のサブサンプリング領域がある場合、出力値は16x16の画像になります。つまり、入力画像の4ピクセル(各2x2の正方形)が1つの出力に結合されます。ピクセル。 サブサンプリングする方法は複数ありますが、最も一般的なのは、最大プーリング、平均プーリング、および確率的プーリングです。
- 最後のサブサンプリング(または畳み込み)層は通常、1つ以上の完全に接続された層に接続され、最後の層はターゲットデータを表します。
- トレーニングは、サブサンプリングレイヤーを考慮に入れ、そのフィルターが適用されるすべての値に基づいて畳み込みフィルターの重みを更新する修正されたバックプロパゲーションを使用して実行されます。
ここで、特にtestLeNet *メソッド(約2%の低いエラー率を達成するため、 testLeNetTiny2をお勧めします)でMNISTデータセット(手書き文字のグレースケール画像)で(バックプロパゲーションを使用して)トレーニングされた畳み込みネットワークのいくつかの例を見ることができます。比較的短期間で)。 同様のネットワークの優れたJavaScript視覚化もここにあります。
実装
最も一般的なニューラルネットワークのバリエーションについて説明したので、これらの深層学習構造の実装中に発生する課題について少し書きたいと思いました。
大まかに言えば、ディープラーニングライブラリを作成する際の私の目標は、次の基準を満たすニューラルネットワークベースのフレームワークを構築することでした(そして今もそうです)。
- 多様なモデルを表すことができる一般的なアーキテクチャ(たとえば、上記で見たニューラルネットワーク上のすべてのバリアント)。
- 多様なトレーニングアルゴリズム(バックプロパゲーション、対照的な発散など)を使用する機能。
- まともなパフォーマンス。
これらの要件を満たすために、私はソフトウェアの設計に段階的(またはモジュール式)アプローチを採用しました。
構造
基本から始めましょう:
- NeuralNetworkImplは、すべてのニューラルネットワークモデルの基本クラスです。
- 各ネットワークには、一連のレイヤーが含まれています。
- 各レイヤーには接続のリストがあり、ネットワークが有向非巡回グラフになるように、接続は2つのレイヤー間のリンクです。
この構造は、従来のフィードフォワードネットワークだけでなく、RBMやImageNetなどのより複雑なアーキテクチャにも使用できるほど機敏です。
また、レイヤーを複数のネットワークの一部にすることもできます。 たとえば、Deep Belief Networkのレイヤーは、対応するRBMのレイヤーでもあります。
さらに、このアーキテクチャにより、DBNは、事前トレーニングフェーズではスタックされたRBMのリストとして表示され、微調整フェーズではフィードフォワードネットワークとして表示されます。これは直感的にもプログラム的にも便利です。
データの伝播
次のモジュールは、ネットワークを介したデータの伝播を処理します。これは2段階のプロセスです。
- レイヤーの順序を決定します。 たとえば、多層パーセプトロンから結果を取得するには、データを入力層に「クランプ」し(したがって、これが最初に計算される層になります)、出力層まで伝播されます。 バックプロパゲーション中に重みを更新するには、出力レイヤーから始めて、出力エラーを幅優先ですべてのレイヤーに伝播する必要があります。 これは、さまざまなグラフ走査方法を使用して、ネットワークのグラフ構造を利用するLayerOrderStrategyのさまざまな実装を使用して実現されます。 いくつかの例には、幅優先戦略と特定のレイヤーのターゲティングが含まれます。 順序は実際にはレイヤー間の接続によって決定されるため、ストラテジーは接続の順序付きリストを返します。
- アクティベーション値を計算します。 各レイヤーには、接続のリスト(前のステップから)と入力値(他のレイヤーから)を取得し、結果のアクティブ化を計算するConnectionCalculatorが関連付けられています。 たとえば、単純なシグモイドフィードフォワードネットワークでは、隠れ層のConnectionCalculatorは、入力層とバイアス層(それぞれ、入力データと1の配列)の値と、ユニット間の重み(完全に接続されている場合)を取得します。レイヤーでは、重みは実際にはMatrixとしてFullyConnected接続に格納され、重み付き合計を計算し、その結果をシグモイド関数にフィードします。 接続計算機は、さまざまな転送(たとえば、加重和、畳み込み)およびアクティブ化(たとえば、多層パーセプトロンのロジスティックおよびタン、RBMのバイナリ)関数を実装します。 それらのほとんどは、Aparapiを使用してGPUで実行でき、ミニバッチトレーニングで使用できます。
Aparapiを使用したGPU計算
先に述べたように、近年ニューラルネットワークが復活した理由の1つは、そのトレーニング方法が並列処理に非常に役立ち、GPGPUを使用してトレーニングを大幅にスピードアップできることです。 この場合、GPUサポートを追加するためにAparapiライブラリを使用することを選択しました。
Aparapiは、接続計算機にいくつかの重要な制限を課しています。
- プリミティブデータ型の1次元配列(および変数)のみが許可されます。
- GPU実行可能コードから呼び出すことができるのは、 AparapiKernelクラス自体のメンバーメソッドのみです。
そのため、ほとんどのデータ(重み、入力、および出力配列)は、内部で1次元のfloat配列を使用するMatrixインスタンスに格納されます。 すべてのAparapi接続計算機は、 AparapiWeightedSum (完全に接続されたレイヤーと加重和入力関数の場合)、 AparapiSubsampling2D (サブサンプリングレイヤーの場合)、またはAparapiConv2D (畳み込みレイヤーの場合)のいずれかを使用します。 これらの制限のいくつかは、異種システムアーキテクチャを導入することで克服できます。 Aparapiでは、CPUとGPUの両方で同じコードを実行することもできます。
トレーニング
トレーニングモジュールは、さまざまなトレーニングアルゴリズムを実装します。 これは、前の2つのモジュールに依存しています。 For example, BackPropagationTrainer (all the trainers are using the Trainer base class) uses feedforward layer calculator for the feedforward phase and a special breadth-first layer calculator for propagating the error and updating the weights.
My latest work is on Java 8 support and some other improvements, will soon be merged into master.
結論
The aim of this Java deep learning tutorial was to give you a brief introduction to the field of deep learning algorithms, beginning with the most basic unit of composition (the perceptron) and progressing through various effective and popular architectures, like that of the restricted Boltzmann machine.
The ideas behind neural networks have been around for a long time; but today, you can't step foot in the machine learning community without hearing about deep networks or some other take on deep learning. Hype shouldn't be mistaken for justification, but with the advances of GPGPU computing and the impressive progress made by researchers like Geoffrey Hinton, Yoshua Bengio, Yann LeCun and Andrew Ng, the field certainly shows a lot of promise. There's no better time to get familiar and get involved like the present.
Appendix: Resources
If you're interested in learning more, I found the following resources quite helpful during my work:
- DeepLearning.net: a portal for all things deep learning. It has some nice tutorials, software library and a great reading list.
- An active Google+ community.
- Two very good courses: Machine Learning and Neural Networks for Machine Learning, both offered on Coursera.
- The Stanford neural networks tutorial.