シンプルな人工ニューラル ネットワークをゼロから構築する: 1 つの隠れ層

シンプルな人工ニューラル ネットワークをゼロから構築する: 1 つの隠れ層

[51CTO.com クイック翻訳] 前回の記事「人工ニューラルネットワークをゼロから構築する(パート 1)」では、まず人工ニューラルネットワークとは何かを説明し、次に Python を使用して、入力層と出力層が 1 つずつだけのシンプルなニューラルネットワークをゼロから構築する方法を紹介しました。このニューラルネットワークはパーセプトロンと呼ばれます。ただし、画像分類や株式市場分析などの複雑なタスクを実行できる実際のニューラル ネットワークには、入力層と出力層に加えて複数の隠し層があります。

前回の記事では、パーセプトロンは線形決定境界を見つけることができると結論付けました。ダミーデータセットを使用して、パーセプトロンを使用して、ある人が糖尿病に罹患しているかどうかを予測します。ただし、パーセプトロンは非線形の決定境界を見つけることができません。

この記事では、入力層 1 つ、隠し層 1 つ、出力層 1 つを持つニューラル ネットワークを構築します。構築したニューラル ネットワークが非線形境界を見つけることができることを確認します。

データセットを生成する

まず、試してみるためのデータセットを作成しましょう。幸いなことに、scikit-learn には便利なデータセット ジェネレーターがいくつかあるため、このコードを自分で書く必要はありません。 make_moons 関数を使用します。

  1. sklearnからデータセットをインポートする 
  2. np.ランダムシード(0)  
  3. feature_set、ラベル = datasets.make_moons(300、ノイズ=0.20)  
  4. plt.figure(図サイズ=(10,7))  
  5. plt.scatter(feature_set[:,0], feature_set[:,1], c=ラベル, cmap=plt.cm.Spectral)

図1

生成したデータセットには、赤い点と青い点でマークされた 2 つのクラスがあります。青い点は男性患者、赤い点は女性患者、X 軸と Y 軸は医療指標と考えられます。

私たちの目標は、x 座標と y 座標に基づいて正しいクラス (男性または女性) を予測できる機械学習分類器をトレーニングすることです。データは線形に分離できないため、2 つのクラスを分離する直線を描くことはできないことに注意してください。つまり、特定のデータセットに適した非線形機能 (多項式など) を手動で設計しない限り、線形分類器 (隠し層のない ANN やロジスティック回帰など) はデータに適合できません。

1つの隠れ層を持つニューラルネットワーク

これが私たちのシンプルなネットワークです:

図2

入力は x1 と x2 の 2 つです。 3 つのユニット (ノード) h1、h2、h3 を持つ単一の隠し層があります。最後に、y1 と y2 の 2 つの出力があります。これらを結ぶ矢印は重みです。重み行列には w と u の 2 つがあります。 w 重みは入力層と隠れ層を接続し、u 重みは隠れ層と出力層を接続します。注目したい計算に集中しやすくするために、文字 w と u を使用します。また、出力 y1 と y2 をターゲット t1 と t2 と比較していることもわかります。

計算に入る前に、最後の文字を 1 つ紹介する必要があります。活性化前の線形結合をaとします。したがって、次のようになります。

すべての活性化関数と損失関数を網羅的に考慮することはできないため、最も一般的な 2 つの関数に焦点を当てます。シグモイド活性化と L2 ノルム損失。この新しい情報と新しい符号により、出力 y は活性化の線形結合に等しくなります。

したがって、出力層に関しては次のようになります。

アプローチが異なるため、出力層と隠し層のバックプロパゲーションを個別に検討します。

次の点にご注意ください。

シグモイド関数は次のとおりです。

導関数は次のようになります。

出力層のバックプロパゲーション

更新ルールを取得するには:

計算しなければならない

単一の重み uij を例に挙げます。損失の uij に対する偏微分は次の式に等しくなります。

ここで、i は前のレイヤー (変換の入力レイヤー) に対応し、j は次のレイヤー (変換の出力レイヤー) に対応します。偏導関数は連鎖律に従うだけで簡単に計算できます。

L2 ノルム損失導関数に注目します。

シグモイド導関数に注目します。

最後に、3 次偏微分は次の微分になります。

それで、

上記の式に偏微分を代入すると、次のようになります。

したがって、出力層の単一の重みの更新規則は次のように表されます。

隠れ層を通した逆伝播

出力層のバックプロパゲーションと同様に、wij は次の要素に依存します。

チェーンルールに注目してください。これまでの結果を使用して、シグモイド活性化と線形モデルを使用して変換すると、次のようになります。

そして

バックプロパゲーションの実際の問題は、

それは、「隠された」ターゲットが存在しないという事実によるものです。重み w11 の解は以下を参照してください。計算プロセスを見るときは、まず上に示した NN 図を見ることをお勧めします。

ここから計算すると

これが私たちが望んでいることです。最終的な表現は次のようになります。

この方程式の一般化された形式は次のようになります。

バックプロパゲーションの一般化

出力層と隠れ層のバックプロパゲーションの結果を使用して、L2 ノルム損失とシグモイド活性化がある場合のバックプロパゲーションを要約する式を作成できます。

隠れ層の場合

1つの隠れ層を持つニューラルネットワークを実装するコード

それでは、Python を使用して、ゼロから構築したニューラル ネットワークを実装してみましょう。上記で作成した非線形データを再度分類してみます。

まず、トレーニング データセットのサイズ、入力層と出力層の次元など、勾配降下法に役立つ変数とパラメーターをいくつか定義します。

  1. num_examples = len(X) # トレーニングセット サイズ 
  2. nn_input_dim = 2 # 入力層の次元
  3. nn_output_dim = 2 #出力層の次元

勾配降下パラメータも定義します。

  1. epsilon = 0.01 #勾配降下法学習率 
  2. reg_lambda = 0.01 # 正規化の強度

まず、上で定義した損失関数を実装しましょう。この関数を使用して、モデルのパフォーマンスを評価します。

  1. # ヘルパー関数 データセット総損失を評価する 
  2. def calculate_loss(モデル, X, y):  
  3. num_examples = len(X) # トレーニングセット サイズ   
  4. W1、b1、W2、b2 = モデル[ 'W1' ]、モデル[ 'b1' ]、モデル[ 'W2' ]、モデル[ 'b2' ]  
  5. #予測を計算するための順方向伝播 
  6. z1 = X.dot(W1) + b1  
  7. a1 = np.tanh(z1)  
  8. z2 = a1.dot(W2) + b2  
  9. exp_scores = np.exp(z2)  
  10. probs = exp_scores / np.sum (exp_scores、axis=1、keepdims= True )  
  11. # 損失の計算 
  12. corect_logprobs = -np.log(probs[range(num_examples), y])  
  13. データ損失 = np.sum (正しいログ確率)  
  14. # 損失規制項を追加する(オプション)  
  15. データ損失 += Config.reg_lambda / 2 * ( np.sum (np.square(W1)) + np.sum ( np.square(W2)))  
  16. 1. / num_examples * data_loss を返します

ネットワークの出力を計算するためのヘルパー関数も実装しました。順方向伝播を実行し、最も高い確率を持つクラスを返します。

  1. def predict(モデル, x):  
  2. W1、b1、W2、b2 = モデル[ 'W1' ]、モデル[ 'b1' ]、モデル[ 'W2' ]、モデル[ 'b2' ]  
  3. #前方伝播 
  4. z1 = x.dot(W1) + b1  
  5. a1 = np.tanh(z1)  
  6. z2 = a1.dot(W2) + b2  
  7. exp_scores = np.exp(z2)  
  8. probs = exp_scores / np.sum (exp_scores、axis=1、keepdims= True )  
  9. np.argmax(probs, axis=1)を返します

最後に、ニューラルネットワークをトレーニングする機能があります。これは、上で見つけた逆伝播導関数を使用してバッチ勾配降下法を実装します。

この関数は、ニューラル ネットワークのパラメータを学習した後のモデルを返します。

nn_hdim: 隠し層のノード数。

num_passes: 勾配降下法のトレーニング データを通過する回数。

print_loss: True の場合、1000 回の反復ごとに損失を出力します。

  1. def build_model(X, y, nn_hdim, num_passes=20000, print_loss= False ):  
  2. # パラメータをランダムな初期化します。これらを学習する必要があります  
  3. num_examples = len(X)  
  4. np.ランダムシード(0)  
  5. W1 = np.random.randn(Config.nn_input_dim, nn_hdim) / np.sqrt(Config.nn_input_dim)  
  6. b1 = np.zeros((1, nn_hdim))  
  7. W2 = np.random.randn(nn_hdim, Config.nn_output_dim) / np.sqrt(nn_hdim)  
  8. b2 = np.zeros((1, Config.nn_output_dim)) # これが返されるです 最後   
  9. model = {}# 勾配降下法。バッチごと...  
  10. for i in range(0, num_passes): #順方向伝播 
  11. z1 = X.dot(W1) + b1  
  12. a1 = np.tanh(z1)  
  13. z2 = a1.dot(W2) + b2  
  14. exp_scores = np.exp(z2)  
  15. probs = exp_scores / np.sum (exp_scores, axis=1, keepdims= True ) # バックプロパゲーション 
  16. delta3 = 問題 
  17. delta3[範囲(num_examples), y] -= 1  
  18. dW2 = (a1.T).dot(デルタ3)  
  19. db2 = np.sum (デルタ3、軸=0、keepdims= True )  
  20. デルタ2 = デルタ3.dot(W2.T) * (1 - np.power(a1, 2))  
  21. dW1 = np.dot(XT, デルタ2)  
  22. db1 = np.sum (delta2, axis=0)#正規化項を追加します(b1b2 には正規化項はありません)  
  23. dW2 += Config.reg_lambda * W2  
  24. dW1 += Config.reg_lambda * W1# 勾配降下法パラメータの更新   
  25. W1 += -Config.epsilon * dW1  
  26. b1 += -Config.epsilon * db1  
  27. W2 += -Config.epsilon * dW2  
  28. b2 += -Config.epsilon * db2#モデル新しいパラメータを割り当てる 
  29. model = { 'W1' : W1, 'b1' : b1, 'W2' : W2, 'b2' : b2} # オプションで損失を出力します。  
  30. # これはデータセット全体を使用するためコストかかるため、あまり頻繁に実行たくありません  
  31. print_lossかつi % 1000 == 0 の場合:  
  32. print( "反復後の損失 %i: %f" % (i, calculate_loss(model, X, y))) return model

最後に、主な方法:

  1. main() を定義します:  
  2. X, y = generate_data()  
  3. モデル = build_model(X, y, 3, print_loss= True )  
  4. 視覚化(X, y, モデル)

1000 回の反復ごとに損失を出力します。

図3

隠れ層のノード数が3の場合の分類

次に、異なる隠し層のサイズが結果にどのように影響するかを見てみましょう。

  1. 隠しレイヤーの寸法 = [1, 2, 3, 4, 5, 20, 50]  
  2. i 、nn_hdim をenumerate(hidden_​​layer_dimensions)指定します:  
  3. plt.サブプロット(5, 2, i+1)  
  4. plt.title( '隠しレイヤーのサイズ %d' % nn_hdim)  
  5. モデル = build_model(X, y,nn_hdim, 20000, print_loss= False )  
  6. plot_decision_boundary(lambda x:predict(モデル,x), X, y) をプロットします。  
  7. plt.show()

図4

低次元の隠し層がデータの全体的な傾向を非常によく捉えていることがわかります。次元が高くなると、過剰適合が発生しやすくなります。全体的な形状を合わせるのではなく、データを「記憶」しているのです。

別のテスト セットでモデルを評価すると、隠し層のサイズが小さいモデルの方が一般化が優れているため、パフォーマンスが向上する可能性があります。より強力な正規化によってオーバーフィッティングに対抗できますが、隠れ層に適切なサイズを選択することは非常に「経済的な」解決策です。

完全なコードは、この GitHub リポジトリから入手できます。

nageshsinghc4/Python による人工ニューラル ネットワークの構築

結論は

この記事では、1 つの隠し層を持つニューラル ネットワークを数学的に導出する方法と、Numpy Python を使用して 1 つの隠し層を持つニューラル ネットワークを作成する方法を説明しました。

人工ニューラル ネットワークをゼロから構築する: パート 2

[51CTOによる翻訳。パートナーサイトに転載する場合は、元の翻訳者と出典を51CTO.comとして明記してください]

<<:  アリババはどうやって1分で会話型ロボットを作ったのでしょうか?

>>:  量子機械学習モデルを構築するための Google の新しいフレームワーク、TensorFlow Quantum を探索する

ブログ    
ブログ    

推薦する

ファーウェイ、セキュリティ業界を洞察から先見へと進化させる2019年スマートセキュリティ事業戦略を発表

[51CTO.comより引用] 2019年8月8日、ファーウェイの2019年スマートセキュリティビジ...

...

2021 年の人工知能の最新動向を示す 15 のグラフ

2021年AIインデックスレポートは、スタンフォード大学の人間中心AI研究所と、ハーバード大学、経済...

「AI as a Service」は、業界における人工知能の応用シナリオです。

「AI as a Service」は、多次元統合と3次元浸透を備えたプラットフォームです。人工知能...

人工知能応用シナリオのレビューと展望

2020 年は特別で忘れられない年であり、人工知能にとっても同じことが言えます。 [[374502]...

2022 年に予測されるロボット技術のトレンド トップ 10

COVID-19パンデミックは、物流やスーパーマーケットなどの分野に問題と機会の両方をもたらしまし...

偏見と不平等にノーと言いましょう!マイクロソフト、物議を醸していた顔認識サービスの提供を停止

マイクロソフトは、動画や画像に基づいて感情を識別するサービスを含む、人工知能を活用した顔認識ツールの...

スタンフォード大学は、GPT-4 が愚かになったことを確認しました。 OpenAIの最新の回答: 確かに「知能の低下」は起きている

写真大型模型天井GPT-4、だんだんと鈍くなってきているのでしょうか?これまでにも多くのユーザーが疑...

OccNeRF: LIDARデータの監視は不要

この記事は、Heart of Autonomous Driving の公開アカウントから許可を得て転...

...

ヘルスケアにおける6つの新たなテクノロジートレンド

ヘルスケア業界におけるテクノロジーの浸透は、この分野の専門家のほぼすべての業務に影響を及ぼしています...

画像セグメンテーションのためのディープラーニング: ネットワークアーキテクチャ設計の概要

この論文では、画像セマンティックセグメンテーションに CNN を使用する際のネットワーク構造の革新に...

エッジコンピューティング時代の到来は AI にどのような影響を与えるのでしょうか?

[[270736]]近年、人工知能はテクノロジー界で注目されている分野です。中国では、Megvii...

...