シンプルな人工ニューラル ネットワークをゼロから構築する: 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 を探索する

ブログ    
ブログ    

推薦する

メンガー: 大規模分散強化学習アーキテクチャ

過去 10 年間で、強化学習 (RL) は機械学習で最も人気のある研究分野の 1 つになりました。R...

カメラの前で指をタップすることでパーキンソン病の症状を遠隔で評価するAIツールが開発される

9月10日、ロチェスター大学の研究者らは、パーキンソン病患者が数分で遠隔から症状の重症度を評価できる...

...

時速55キロ!寧波杭州湾新区のスマート道路に無人車が走行

「無人運転車が次々とゆっくりと停止し、住民が乗車すると、自動的にショッピングモール、オフィス、学校な...

Sitechi スマートオペレーションプラットフォームがスマートシティの求心力を生み出す

デジタル トレントは、さまざまな新興テクノロジーが成熟し、新しいビジネスや新しいアプリケーションが出...

朱磊博士が自動運転技術の現状と今後の動向について語る

熱狂が冷め、合理性が戻った後、自動運転業界は再び混乱に陥っています。過去1年間、資金調達、量産計画、...

テスラとモメンタの「自動運転アルゴリズム」の秘密を研究した

現在、自動運転技術は研究室を抜け出し、量産段階に入っており、大手自動車メーカーや部品サプライヤー、ハ...

仕事とAIの未来

[[340645]] [51CTO.com クイック翻訳] 人工知能が雇用に与える影響は、現在、さま...

マイクロソフトは、人間と同じようにニュースを翻訳できるAIの画期的な進歩を主張している

米国現地時間3月14日、マイクロソフトの研究者らは、人間と同等の精度でテキストを翻訳できる人工知能を...

AIと自動化革命に備える10の方法

人工知能と自動化はもはやSFの世界の話ではなく、ビジネスの世界と消費者の世界の両方で非常に現実的かつ...

...

電子商取引用に作成されたナレッジグラフは、ユーザーのニーズをどのように感知するのでしょうか?

[[243140]] 1. 背景2017年6月に電子商取引認知マップが発表されて以来、実践から体系...

...

IBM WatsonX: AIを企業の生産性の中核に

「象は踊れるの?」もちろん踊れますよ!かつての人々の考え方では、伝統的な大企業は、組織の肥大化や閉鎖...

Baidu Brain EasyDL Professional Editionは、Baiduの超大規模事前学習済みモデルをリリースしました

ディープラーニングの分野では、「転移学習」という用語がますます注目を集めています。パフォーマンスが優...