この記事では、ニューラルネットワークBPアルゴリズムの原理とPythonでの実装について説明します。

この記事では、ニューラルネットワークBPアルゴリズムの原理とPythonでの実装について説明します。

私は最近、BP アルゴリズムを体系的に研究し、この研究ノートを書きました。私の能力が限られているため、明らかな間違いがある場合は、ご指摘ください。

勾配降下法と連鎖律とは何か

以下に示すような関数 J(w) があるとします。

勾配降下図

ここで、w がどの値に等しくなると J(w) が最小値に達するかを知りたいと思います。図から、最小値は初期位置の左側にあることがわかります。つまり、J(w) を最小化するには、w の値を減らす必要があります。初期位置での接線の傾きはa > 0(つまり、この位置に対応する導関数は0より大きい)であり、w = w – aはwの値を減らすことができます。J(w)が最小値に達するまで、導関数を繰り返してwを更新します。関数J(w)に複数の変数が含まれている場合、異なる変数の値を更新するために、異なる変数の偏微分を個別に計算する必要があります。

いわゆる連鎖律は、合成関数の導関数を求めることです。

チェーンルール

わかりやすくするために例を挙げてみましょう。

連鎖導出の例

ニューラルネットワークの構造

ニューラル ネットワークは、左端の入力層、隠し層 (実際のアプリケーションでは複数の層があります)、右端の出力層の 3 つの部分で構成されます。層は線で接続されており、各接続線には対応する重み値 w があります。入力層を除いて、一般的に、各ニューロンには対応するバイアス b もあります。

入力層のニューロンを除いて、各ニューロンは加重和によって得られる入力値zと、シグモイド関数(活性化関数とも呼ばれる)を介してzが非線形変換された後の出力値aを持ちます。それらの計算式は次のとおりです。

ニューロン出力値aの計算式

式中の変数 l と j は l 層目の j 番目のニューロンを表し、ij は i 番目のニューロンから j 番目のニューロンへの接続を表し、w は重みを表し、b はバイアスを表します。以下の記号の意味はここで説明したものと大体同じなので、再度説明はしません。以下のGIFは、各ニューロンの入力値と出力値がどのように計算されるかをより明確にすることができます(ここでのGIFはバイアスを追加していませんが、使用中に追加されることに注意してください)

計算されたニューロン出力値を示すアニメーション

活性化関数を使用する理由は、線形モデル(線形不可分な状況を処理できない)では表現力が不十分であるため、通常はここでシグモイド関数を追加して非線形要素を追加し、ニューロンの出力値を取得する必要があります。

シグモイド関数の範囲は (0,1) であることがわかります。マルチ分類タスクの場合、出力層の各ニューロンはその分類の確率を表すことができます。もちろん、他にも活性化関数は存在し、それぞれに独自の用途、利点、欠点があります。

BPアルゴリズム実行のプロセス(順方向パスと逆方向更新)

BP アルゴリズムは、ニューラル ネットワーク層の数、各層のニューロン数、および学習率 η (後述) を手動で設定した後、まず各接続線の重みとバイアスをランダムに初期化します。次に、トレーニング セット内の各入力 x と出力 y に対して、BP アルゴリズムはまず順方向伝送を実行して予測値を取得し、次に真値と予測値の誤差に基づいて逆方向フィードバックを実行して、ニューラル ネットワーク内の各接続線の重みと各層の優先度を更新します。停止条件に達しない場合は上記のプロセスが繰り返されます。

停止条件は次の 3 つになります。

● 重量更新が一定の閾値を下回った場合

● 予測誤差率が一定の閾値を下回っている

● 事前に設定した反復回数に達する

たとえば、手書きの数字認識では、手書きの数字 1 の画像には 28*28 = 784 ピクセルが格納され、各ピクセルにはグレースケール値 (範囲は [0,255]) が格納されます。つまり、入力層には 784 個のニューロンがあり、出力層には 0 から 9 までの数字を表す 10 個のニューロンがあります。各ニューロンは 0 から 1 までの値を取り、画像がこの数字である確率を表します。

画像(つまりインスタンス)が入力されるたびに、ニューラル ネットワークは順方向転送を実行し、出力層のニューロンの値を層ごとに計算し、どの出力ニューロンが最大の値を持っているかに基づいて、入力画像によって表される手書きの数字を予測します。

そして、出力ニューロンの値に基づいて予測値と真の値との誤差を計算し、逆フィードバックを使用してニューラルネットワーク内の各接続ラインの重みと各ニューロンの優先度を更新します。

フィードフォワード

入力層=>隠れ層=>出力層と、層ごとに全てのニューロンの出力値を計算する処理。

バックプロパゲーション

出力層の値と真の値の間には誤差があるため、平均二乗誤差を使用して予測値と真の値の間の誤差を測定することができます。

平均二乗誤差

逆フィードバックの目標は、E関数の値をできるだけ小さくすることです。各ニューロンの出力値は、ポイントの接続線に対応する重み値とレイヤーに対応する優先度によって決まります。したがって、エラー関数を最小化するには、wとbの値を調整してエラー関数を最小化する必要があります。

重みとバイアスの式を更新する

目的関数 E の w と b の偏微分を取ることで、w と b の更新された値を得ることができます。ここで、導出の例として w の偏微分を取り上げます。

ここで、η は学習率であり、通常は 0.1 ~ 0.3 の範囲にあり、各勾配が取るステップとして理解できます。 w_hj の値は、まず j 番目の出力層ニューロンの入力値 a に影響し、次に出力値 y に影響することに注意してください。連鎖律によれば、

連鎖律を使用して重みの偏微分を展開する

ニューロン出力値aの定義によれば、

関数zに対するwの偏微分を求める

シグモイド導関数の式は次のようになります。これを見ると、コンピューターで実装するのも非常に便利であることがわかります。

シグモイド関数の微分

それで

重みwの更新量は次のようになります。

同様に、b の更新量は次のとおりです。

しかし、この 2 つの式では、出力層と前の層の間の接続線の重みと出力層のバイアスしか更新できません。その理由は、δ 値は真の値 y に依存しますが、出力層の真の値しかわかっておらず、各隠れ層の真の値はわからないため、各隠れ層の δ 値を計算することができません。したがって、l+1 層の δ 値を使用して l 層の δ 値を計算したいと考えています。これは、一連の数学的変換を通じて実行できます。これが逆フィードバックという名前の由来です。式は次のとおりです。

この式から、前の層の δ 値を計算するには、次の層の重みとニューロン出力層の値を知るだけでよいことがわかります。上記の式を継続的に使用することで、隠れ層の重みとバイアスをすべて更新できます。

導出する前に、次の図を確認してください。

まず、層 l の i 番目のニューロンは層 l+1 のすべてのニューロンに接続されているので、δ を次の式に展開できます。

つまり、Eはl+1層のすべてのニューロンの入力値のz関数とみなすことができ、上式のnはl+1層のニューロンの数を表します。簡略化すると、上式が得られます。

ここでの導出プロセスでは重要な部分のみを説明します。また、機械学習におけるニューラルネットワークの部分や、周志華著の「ニューラルネットワークとディープラーニング」も参考にしました。

Pythonソースコード分析

ソースコードは、Michael Nielsen のディープラーニング オンライン チュートリアルから取得しました。

Python で実装したニューラル ネットワークのコード行数は多くありません。Network クラスのみが含まれています。まずは、このクラスの構築方法を見てみましょう。

  1. def __init__( self 、 sizes ):
  2. 「」
  3. :param sizes: リスト型。ニューラルネットワークの各層のニューロンの数を格納します。
  4. 例えば、sizes = [2, 3, 2]は入力層に2つのニューロンがあることを意味します。
  5. 隠れ層には3つのニューロンがあり、出力層には2つのニューロンがある。
  6. 「」  
  7. # ニューラルネットワークの層は何層ありますか 
  8. self .num_layers = len(サイズ)
  9. 自己.sizes = サイズ
  10. # 入力層を削除し、各層のyニューロンのバイアス値(0 - 1)をランダムに生成します 
  11. self.biases = [np.random.randn(y, 1 ) ysizes[ 1 :]場合]
  12. # 各接続ラインの重み値をランダムに生成します(0 - 1)  
  13. 自己重み = [np.random.randn(y, x)
  14. x, y がzip(sizes[:- 1 ], sizes[ 1 :])]場合

FreedForward コード

  1. defフィードフォワード( self , a):
  2. 「」
  3. フォワードパスは各ニューロンの値を計算する
  4. :param a: 入力値
  5. :return: 計算後の各ニューロンの値
  6. 「」  
  7. b、wzip( self .biases、 self .weights) の場合:
  8. # 加重合計とバイアス 
  9. a = シグモイド(np.dot(w, a)+b)
  10. 返す

ソースコードでは、勾配降下法と同様の原理を持つ確率的勾配降下法 (SGD) を使用しています。違いは、確率的勾配降下法アルゴリズムでは、データセット内のサンプルの一部のみを使用して、各反復で w と b の値を更新することです。勾配降下法よりも高速ですが、必ずしも局所的最小値に収束するわけではなく、局所的最小値付近で推移する場合があります。

  1. def SGD( self , トレーニングデータ, エポック, ミニバッチサイズ, eta,
  2. test_data =なし):
  3. 「」
  4. 確率的勾配降下法
  5. :param training_data: 入力トレーニングセット
  6. :param epochs: 反復回数
  7. :param mini_batch_size: 小さなサンプルの数
  8. :param eta: 学習率
  9. :param test_data: テストデータセット
  10. 「」  
  11. test_dataの場合: n_test = len(test_data)
  12. n = len(トレーニングデータ)
  13. xrange(エポック)内のjの場合:
  14. # トレーニングセットをシャッフルしてソート順を変更します 
  15. ランダムシャッフル(トレーニングデータ)
  16. # 小さなサンプルの数に応じてトレーニングセットを分割する 
  17. ミニバッチ = [
  18. トレーニングデータ[k:k+ミニバッチサイズ]
  19. kxrange( 0 , n, mini_batch_size ) の場合]
  20. mini_batches内のmini_batchの場合:
  21. # 各小サンプルに基づいて w と b を更新します。コードは次の段落にあります。  
  22. 自己.update_mini_batch(mini_batch, eta)
  23. # 各テストラウンドの後にニューラルネットワークの精度を出力する 
  24. test_dataの場合:
  25. 印刷  "エポック {0}: {1} / {2}" .format(
  26. j、自己評価(test_data)、n_test)
  27. それ以外
  28. 印刷  「エポック {0} が完了しました」 .format(j)

バックプロパゲーション法で得られた偏微分に応じてwとbの値を更新します。

  1. def update_mini_batch( self , mini_batch, eta):
  2. 「」
  3. wとbの値を更新する
  4. :param mini_batch: サンプルの一部
  5. :param eta: 学習率
  6. 「」  
  7. # バイアスと重みの行と列の数に応じて、すべての要素の値が0に設定された空の行列を作成します 
  8. nabla_b = [np.zeros(b.shape) b場合 自己偏見]
  9. nabla_w = [np.zeros(w.shape) w場合 自己重み]
  10. mini_batchx、yについて:
  11. # サンプル内の各入力xに対する出力yに基づいてwとbの偏微分を計算する 
  12. delta_nabla_b、delta_nabla_w = self.backprop (x, y)
  13. # 偏微分 delta_nabla_b と delta_nabla_w を累積して保存します 
  14. nabla_b = [nb+dnb (nbの場合、dnbzip(nabla_b、delta_nabla_b)]
  15. nabla_w = [nw+dnw (nwの場合、dnwは zip)(nabla_w、delta_nabla_w)]
  16. # 累積偏微分に従ってwとbを更新します。ここでは小さなサンプルを使用しているため、  
  17. # したがって、ηは小さなサンプルの長さで割る必要があります 
  18. 自己.weights = [w-(eta/len(mini_batch))*nw
  19. w 、nwzip( self .weights、 nabla_w)]
  20. 自己バイアス = [b-(eta/len(mini_batch))*nb
  21. bの場合、nbzip( self .biases, nabla_b)]

次のコードはソースコードのコア部分であり、順方向伝送と逆方向フィードバックを含む BP アルゴリズムの実装です。順方向伝送には、ネットワーク内の単一のメソッド (上記のフィードフォワード メソッド) があり、トレーニングされたニューラル ネットワークの精度を検証するために使用されます。このメソッドについては、以下で説明します。

  1. def backprop( self , x, y):
  2. 「」
  3. :パラメータx:
  4. :パラメータy:
  5. :戻る:
  6. 「」  
  7. nabla_b = [np.zeros(b.shape) b場合 自己偏見]
  8. nabla_w = [np.zeros(w.shape) w場合 自己重み]
  9. # 前方送信 
  10. 活性化 = x
  11. # 各層のニューロンの値を格納する行列。次のループは各層のニューロンの値を追加します 
  12. アクティベーション = [x]
  13. # シグモイド計算の前に各ニューロンの値を保存します 
  14. zs = []
  15. b、wzip( self .biases、 self .weights) の場合:
  16. z = np.dot(w, 活性化)+b
  17. zs.append(z)
  18. 活性化 = シグモイド(z)
  19. アクティベーション.append(アクティベーション)
  20. # δの値を求める 
  21. デルタ =自己.cost_derivative(アクティベーション[- 1 ], y) * \
  22. シグモイドプライム(zs[- 1 ])
  23. nabla_b[- 1 ] = デルタ
  24. # 前のレイヤーの出力値を掛ける 
  25. nabla_w[- 1 ] = np.dot(デルタ、アクティベーション[- 2 ].transpose())
  26. xrange( 2 , self.num_layers )内のl場合:
  27. # 最後から **l** 番目のレイヤーから更新を開始します。**-l** は、最後から l 番目のレイヤーから計算を開始することを示す Python の特別な構文です。  
  28. # ここでは**l+1**層のδ値を使用して**l**のδ値を計算します 
  29. z = zs[-l]
  30. sp = シグモイドプライム(z)
  31. デルタ = np.dot( self .weights[-l+ 1 ].transpose(), デルタ) * sp
  32. nabla_b[-l] = デルタ
  33. nabla_w[-l] = np.dot(デルタ、アクティベーション[-l- 1 ].transpose())
  34. 戻り値(nabla_b, nabla_w)

次のステップは、評価を実装し、フィードフォワード メソッドを呼び出して、トレーニングされたニューラル ネットワークの出力層ニューロン値 (つまり、予測値) を計算し、正しい値と予測値を比較して精度を取得することです。

  1. defevaluate ( self , test_data):自己を評価する:
  2. # 予測結果を取得する 
  3. test_results = [(np.argmax( self .feedforward(x)), y)
  4. (x, y)が test_dataある場合]
  5. # 正しく識別された数を返す 
  6. test_results内の(x, y)に対して、 int( x == y ) の合計を返します

最後に、このソース コードを使用して、手書き数字認識用のニューラル ネットワークをトレーニングし、評価結果を出力します。コードは次のとおりです。

  1. mnist_loaderをインポートする
  2. インポートネットワーク
  3.  
  4. トレーニングデータ、検証データ、テストデータ = mnist_loader.load_data_wrapper()
  5. ネット = ネットワーク.ネットワーク([ 784 , 30 , 10 ])
  6. net.SGD (トレーニングデータ、 30、10、3.0 、テストデータ =テストデータ)
  7. # 出力結果 
  8. # エポック 0: 9038 / 10000  
  9. # エポック 1: 9178 / 10000  
  10. # エポック 2: 9231 / 10000  
  11. # ...  
  12. # エポック 27: 9483 / 10000  
  13. # エポック 28: 9485 / 10000  
  14. # エポック 29: 9477 / 10000  

30 回の反復処理後、手書き認識ニューラル ネットワークの精度は約 95% であることがわかります。もちろん、反復処理の数、学習率、サンプリング数を設定すると、精度に影響します。パラメータをどのように調整するかも技術的な作業です。この穴は後で埋められます。

要約する

ニューラルネットワークの利点:

ネットワークは本質的に入力から出力へのマッピング関数を実装し、数学理論によって複雑な非線形マッピングを実装する能力があることが証明されています。これにより、複雑な内部メカニズムの問題を解決するのに特に適しています。

ネットワークは、正解を持つインスタンスのセットを学習することで、「合理的な」解決ルールを自動的に抽出できます。つまり、自己学習能力を備えています。

インターネットには、一定の宣伝および一般化の機能があります。

ニューラルネットワークの欠点:

初期の重みに対して非常に敏感であり、局所的最小値に容易に収束します。

過剰装着や過剰トレーニングになりやすい。

隠れ層とニューロンの数をどのように選択するかについての科学的なガイダンスプロセスは存在せず、時にはただ推測しているように感じることもあります。

応用分野:

一般的なものとしては、画像分類、自動運転、自然言語処理などが挙げられます。

やるべきこと

しかし実際には、ニューラル ネットワークのトレーニングにはまだ多くの落とし穴が存在します (次の 4 つなど)。

  • ニューラルネットワークの各層の層数やニューロン数、学習率などのハイパーパラメータの値を選択する方法。
  • 初期化の重みに敏感なので、これを回避して修正するにはどうすればよいでしょうか?
  • ディープ ニューラル ネットワークのシグモイド活性化関数が直面する勾配消失問題をどのように解決するか?
  • 過剰適合を回避するための L1 および L2 正規化とは何ですか?

参照する

[1] 周志華機械学習

[2] スタンフォード大学機械学習オンラインコース

[3] 並列分散処理(1986年、David E. Rumelhart、James L. McClelland著)、第8章エラー伝播による内部表現の学習

[4] バックプロパゲーションアルゴリズムの仕組み

[5] バックプロパゲーションアルゴリズム

[6] Chain Rule、台湾の中国科学技術大学のデジタルコース、YouTubeビデオ、アクセスするにはVPNを使用する必要があります。ちなみに、数学関連のビデオは非常にわかりやすいのでお勧めです。

この記事はLeifeng.comから転載したものです。転載が必要な場合は、Leifeng.com公式サイトにアクセスして許可を申請してください。この記事の著者はZeng Zihuaです

<<:  人工知能オンライン機能システムのデータアクセス技術

>>:  純粋な乾物 | ディープラーニング研究の概要

ブログ    

推薦する

20 種類の機械学習ツール、プログラマーが AI を始めるのに最適な言語はどれですか? (優れた)

よく訓練された兵士であっても、手ぶらで任務を遂行することはできない。 データ サイエンティストには、...

スペルミスを心配する必要はありません。Microsoft Edge ブラウザに新しいウェブ「スマート検索」AI 機能が追加されます。

8月23日、Microsoft Edgeブラウザは、ユーザーがウェブ上で関連コンテンツを簡単に検索...

AIは数学データベースの問題の82%を証明でき、Transformerをベースにした新しいSOTAが達成されました。

科学者たちは最近、AI に数学の授業をさせることに夢中になっていると言わざるを得ません。現在、Fac...

URLベースのクライアント監視と分析における機械学習の最適化と実践

従来のクライアント監視および分析シナリオでは、特定の URL に基づく統計分析方法が使用されます。た...

家庭用ロボットを作り、独自の研究開発の道を歩む

ロボットを作ることは私の子供の頃からの夢でした。 2011年に私はハルビン工業大学に入学し、そこが私...

ビジュアルMambaモデルのSwinの瞬間:中国科学院、HuaweiなどがVMambaを発表

大型模型の分野におけるトランスフォーマーの地位は揺るぎない。しかし、モデルのサイズが拡大し、処理する...

自律的で制御可能なAIフレームワークは信頼性が高いが、すべてのAIコンピューティングセンターが同等というわけではない

現在、人工知能の発展レベルは、都市の競争力と将来の発展の可能性を測る新たな指標となっている。その結果...

...

2018年に「ブロックチェーン+人工知能」について知っておくべきこと

現在、ビジネス界、テクノロジー界、金融界を問わず、最もホットな言葉は「ブロックチェーン」に他なりませ...

...

このアルゴリズムはアーキテクチャを自動的に最適化し、エンジニアがニューラルネットワークを設計するのに役立ちます。

最近、カナダのバンクーバーで NeurIPS 2019 が開催されました。テンセントAIラボからは合...

真実に近いですか? LK-99型超伝導はCu_2S構造相転移によって引き起こされる可能性が高く、中国科学院物理研究所の論文もここにあります。

昨日、北京大学量子材料センター(ICQM)の郭開珍、賈爽らがarXivに提出した論文には、同チームが...

...

LLaVA-1.6は非常に強力で、Gemini Proを上回り、推論機能とOCR機能が向上しています。

昨年 4 月、ウィスコンシン大学マディソン校、マイクロソフト リサーチ、コロンビア大学の研究者が共同...

Google がディープラーニング ライブラリ TensorFlow Fold をリリース、動的計算グラフをサポート

ほとんどの機械学習プロセスでは、トレーニングと推論に使用するデータを前処理する必要があります。前処理...