ニューラル ネットワークはなぜ任意の関数を近似できるのでしょうか?

ニューラル ネットワークはなぜ任意の関数を近似できるのでしょうか?

この記事では、主にニューラル ネットワークの普遍近似理論を紹介し、PyTorch を使用して 2 つのケースを示し、ニューラル ネットワークの関数近似機能を説明します。

「関数」というと、「f(x)=2x」のような高度な代数の式を思い浮かべる人が多いですが、実際には関数は入力から出力へのマッピング関係にすぎず、その形式は多様です。

[[334670]]

個人の衣服のサイズ予測を例に挙げてみましょう。この機能は、個人の身長、体重、年齢を入力として、衣服のサイズを出力として、入力-出力マッピングを実現する機械学習を使用して実装されています。

具体的には、次の手順が必要です。

  • 主要なデータ(大規模な人口の身長/体重/年齢、および対応する実際の衣服のサイズ)を収集します。
  • モデルは、入力-出力マッピングを近似するようにトレーニングされます。
  • 未知のデータに対して予測を行ってモデルを検証します。

出力が入力特徴の線形マッピングである場合、モデルのトレーニングは比較的単純であることが多く、1 つの線形回帰のみで実現できます (サイズ = a*高さ + b*体重 + c*年齢 + d)。

ただし、出力は入力機能の線形マッピングであるという一般的な仮定は合理的ではなく、完全に正確ではありません。現実は複雑な場合が多く、特別なケースや例外もあります。一般的な問題 (フォント認識、画像分類など) には明らかに複雑なパターンが含まれており、高次元の入力機能からマッピング関係を学習する必要があります。

しかし、普遍近似理論によれば、単一の隠れ層を持つ人工ニューラル ネットワークは任意の関数を近似できるため、複雑な問題を解決するために使用できます。

人工ニューラルネットワーク

この記事では、入力層、単一の隠し層、および出力層を持つ完全接続ニューラル ネットワークのみについて説明します。衣服のサイズ予測の例では、入力層には 3 つのニューロン (身長、体重、年齢) があり、出力層には 1 つのニューロン (予測サイズ) のみがあります。その間には、多数のニューロン (下の画像では 5 個ですが、実際には 1024 個など、さらに大きい場合もあります) を持つ隠し層があります。

ネットワーク内の各接続には、調整可能な重みがあります。トレーニングとは、特定の入力セットに対して予測されるサイズと実際のサイズの差が小さくなるように適切な重みを見つけることを意味します。

各ニューロンは次の層のすべてのニューロンに接続されます。これらの接続には一定の重みがあります。各ニューロンの値は各接続に沿って渡され、重みが掛けられます。すべてのニューロンは出力層に送られ、出力層から結果が出力されます。モデルをトレーニングするには、すべての接続に対して適切な重みを見つける必要があります。普遍近似定理の核となる主張は、十分な数の隠れニューロンが与えられれば、その関数が f(x)=x² のように簡潔に記述できるものではないとしても、任意の関数を近似できる接続重みのセットが存在するというものです。 100 x 100 ピクセルの画像を入力として受け取り、「犬」または「猫」を出力するような非常に複雑な関数であっても、この定理の対象となります。

非線形関係

ニューラル ネットワークが任意の関数を近似できる理由は、非線形関係関数をネットワークに統合することが鍵となるためです。各層は活性化関数を設定して非線形マッピングを実現できます。つまり、人工ニューラル ネットワークは線形マッピング計算だけを実行するのではありません。一般的な非線形活性化関数には、ReLU、Tanh、Sigmoid などがあります。

ReLU は単純な区分線形関数であり、計算コストが安価です。他の 2 つは指数演算を伴うため、計算コストが高くなります。

人工ニューラル ネットワークの普遍的な近似機能を実証するために、PyTorch を使用して 2 つのケースを実装します。

ケース1: 任意の散布曲線のフィッティング

ニューラル ネットワークが直面する可能性のある最も基本的な状況の 1 つは、2 つの変数間のマッピングを学習することです。たとえば、x 値が時間を表し、y 座標が特定の道路の交通量を表すとします。一日のさまざまな時間にピークと谷があるため、直線的な関係ではありません。

次のコードは、まず正規分布に従うランダムなポイントを生成し、次に x 座標を入力として、y 座標を出力として受け取るネットワークをトレーニングします。各ステップの詳細については、コードのコメントを参照してください。

  1. 輸入トーチ
  2. plotly.graph_objectsをgoとしてインポートする
  3. numpyをnpとしてインポートする
  4.  
  5. # バッチサイズ、入力ニューロン、隠れニューロン、出力ニューロン
  6. N、D_in、H、D_out = 16、1、1024、1
  7.  
  8. #入力出力保持するランダムなテンソルを作成する
  9. x = torch.randn(N, D_in)
  10. y = torch.randn(N, D_out)
  11.  
  12. # nnパッケージを使用してモデルを定義します
  13. # 線形 (入力 -> 隠し)、ReLU (非線形)、線形 (隠し ->出力)
  14. モデル = torch.nn.Sequential(
  15. torch.nn.Linear(D_in, H)、
  16. torch.nn.ReLU()、
  17. torch.nn.Linear(H, D_out)、
  18.  
  19. # 損失関数を定義する: 平均二乗誤差
  20. #合計 予測値実際の値二乗
  21. loss_fn = torch.nn.MSELoss(削減= 'sum' )
  22.  
  23. # オプティマイザが多く作業行う 実際勾配を計算し  
  24. # ネットワークバックプロパゲーションを適用して 重みを更新する
  25. 学習率 = 1e-4
  26. オプティマイザー = torch.optim.Adam(model.parameters(), lr=learning_rate)
  27.  
  28. # 30000回のトレーニングステップを実行する
  29. t範囲(30000)内である場合:
  30. #フォワードパス: x をモデル渡し予測された y を計算します。
  31. y_pred = モデル(x)
  32.  
  33. # 損失を計算し定期的に出力する
  34. 損失 = loss_fn(y_pred, y)
  35. t % 100 == 0の場合:
  36. print(t, loss.item())
  37.  
  38. #損失勾配を使用してネットワークの重みを更新します
  39. オプティマイザ.zero_grad()
  40. 損失.後方()
  41. オプティマイザ.ステップ()
  42.  
  43. # 元のランダムポイントを散布図として描画する
  44. 図 = go.Figure()
  45. fig.add_trace(go.Scatter(x=x.flatten().numpy(), y=y.flatten().numpy(), mode= "markers" ))
  46.  
  47. #等間隔のx予測を生成する ミンクスマックスの間
  48. minx = min (リスト(x.numpy()))
  49. maxx = max (リスト(x.numpy()))
  50. c = torch.from_numpy(np.linspace(minx, maxx, num=640)).reshape(-1, 1) .float ()
  51. d = モデル(c)
  52.  
  53. # 予測された関数を折れ線グラフとして描画する
  54. fig.add_trace(go.Scatter(x=c.flatten().numpy(), y=d.flatten().detach().numpy(), mode= "lines" ))
  55. 図を表示()

モデルが完全に適合していない右側の 2 つのポイントに注意してください。これを解決するには、トレーニング ステップをさらに実行するか、隠しニューロンの数を増やします。

ケース2: バイナリ分類

関数は、必ずしも代数で見られる「1 つの数値を入力すると、別の数値が出力される」ような関数ではありません。それでは、バイナリ分類タスクを試してみましょう。データ ポイントには 2 つの特徴があり、2 つのラベルのいずれかに分類できます。おそらく、2 つの特徴は経度と緯度の座標であり、ラベルは環境汚染物質の存在です。あるいは、特徴は生徒の数学と読解のテストのスコアであり、ラベルは生徒が右利きか左利きかに対応している可能性があります。重要なのは、モデルが 2 つの入力を 1 つの出力 (0 または 1) にマッピングすることを実装する必要があることです。

次のコードは前のコードと非常に似ています。唯一の違いは、入力層に 2 つのニューロンがあり、出力層の後にシグモイド活性化が続き、すべての出力が範囲 (0, 1) に圧縮されることです。

  1. 輸入トーチ
  2. plotly.expressをpxとしてインポートする
  3. pandasをpdとしてインポートする
  4.  
  5. # バッチサイズ、入力ニューロン、隠れニューロン、出力ニューロン
  6. N、D_in、H、D_out = 128、2、1024、1
  7.  
  8. #入力出力保持するランダムなテンソルを作成する
  9. x = トーチ.rand(N, D_in)
  10. y = torch.randint(0, 2, (N, D_out))
  11.  
  12. # ランダムに生成されたポイントをプロットしラベルごとに色分けする
  13. df = pd.DataFrame({ "x" : x[:, 0].flatten(), "y" : x[:, 1].flatten(), "class" : y.flatten()})
  14. fig = px.scatter(df, x= "x" 、 y= "y" 、 color= "class" 、 color_continuous_scale= "tealrose" )
  15. 図を表示()
  16.  
  17. # モデルを定義: 線形 (入力-> 隠し変数)、ReLU、線形 (隠し変数->出力)、シグモイド
  18. モデル = torch.nn.Sequential(
  19. torch.nn.Linear(D_in, H)、
  20. torch.nn.ReLU()、
  21. torch.nn.Linear(H, D_out)、
  22. torch.nn.シグモイド()
  23.  
  24. # 損失関数を定義する:バイナリ クロスエントロピー損失  バイナリ分類タスク)
  25. loss_fn = torch.nn.BCELoss()
  26.  
  27. 学習率 = 0.002
  28. オプティマイザー = torch.optim.Adam(model.parameters(), lr=learning_rate)
  29.  
  30. #時間の経過に伴う店舗の損失 
  31. ts、損失 = ([]、[])
  32.  
  33. # トレーニングステップを実行する
  34. t範囲(60000)内である場合:
  35. y_pred = モデル(x)
  36.  
  37. 損失 = loss_fn( y_pred.float (), y.float ( ))
  38. t % 100 == 0の場合:
  39. ts.append(t)
  40. 損失.append(損失.data.numpy())
  41.  
  42. オプティマイザ.zero_grad()
  43. 損失.後方()
  44. オプティマイザ.ステップ()
  45.  
  46. #サンプル空間をカバーするためにランダムな点生成しモデルを呼び出す
  47. c = トーチ.rand(32000, D_in)
  48. d = モデル(c)
  49.  
  50. # ランダムデータ予測分類をDataFrame保存し Plotly Expressプロットします
  51. df2 = pd.DataFrame({ "x" : c[:, 0].flatten(),
  52. "y" : c[:, 1].flatten(),
  53. 「クラス」 : d.flatten().detach().numpy()})
  54. fig2 = px.scatter(df2, x= "x" 、 y= "y" 、 color= "class" 、 color_continuous_scale= "tealrose" )
  55. 図2.表示()
  56.  
  57. # 損失を関数としてプロットする トレーニング手順
  58. fig3 = px.scatter(x=ts, y=損失)
  59. 図3.表示()

単位正方形内でランダムに生成された均一なポイントは、ラベル 0 (シアン) とラベル 1 (ピンク) にランダムに割り当てられます。

まず、データ ポイントは単位正方形内で均一にランダムに生成され、各データ ポイントのラベルが 0/1 にランダムに割り当てられます。図からわかるように、線形関係がないことは明らかです。このケースの目的は、座標によってラベルを決定するようにモデルをトレーニングすることです。


モデル分類結果

過剰適合

上記の 2 つのケースは印象的な結果をもたらすように見えますが、これが本当に私たちが望んでいることでしょうか? どちらのケースも過剰適合の問題があることは注目に値します。オーバーフィッティングは、モデルがトレーニング データセットでは適切に機能するが、未知のデータセットでは適切に機能しない場合に発生します。

ケース 1 では、データ収集に誤りがあるために、ポイントの 1 つが外れ値であると想定します。学習するためのトレーニング データが非常に少ない場合、モデルはデータに過剰適合し、実際には単なるノイズであるにもかかわらず、信号として認識します。一方で、モデルがこの外れ値を考慮した関数を学習できることは印象的です。一方、このモデルを実際のデータに適用すると、その点に関して誤った予測が生成され、望ましくない結果が生じる可能性があります。

ケース 2 では、モデルは適切な分類予測を学習しました。ただし、右下隅に最も近い青緑色の点に注目してください。これは唯一のポイントですが、モデルは右下隅全体をシアン色でマークします。ほんの数個の誤ったデータ ポイントによって、モデルが著しく歪む可能性があります。モデルをテストデータに適用しようとすると、予想よりもはるかに悪い結果になる可能性があります。

過剰適合を回避するには、モデルが遭遇すると予想される例を代表する大量のトレーニング データを用意することが重要です。一般の人々の衣服のサイズを予測するツールを構築する場合は、大学の友人からトレーニング データだけを集めてはいけません。さらに、過剰適合を減らすのに役立つ高度なテクニックもいくつかあります (例: 重みの減少)。

結論

要約すると、ニューラル ネットワークは (理論的には) あらゆる関数を学習できるため、機械学習にとって強力なツールです。ただし、これによって、特定の問題に対する最適な重みが簡単に見つかるという保証はありません。実際には、妥当な時間内に正確なモデルをトレーニングできるかどうかは、オプティマイザー、モデル アーキテクチャ、データ品質など、多くの要因に依存します。特に、ディープラーニングには多くの隠れ層を持つニューラル ネットワークが含まれており、特定の難しいタスクの学習に非常に優れています。

<<:  2020 年の企業向け最高の AI プラットフォーム

>>:  データ サイエンティストまたは AI エンジニアになるために独学するにはどうすればよいでしょうか?これらの9つのポイントを克服する必要があります

ブログ    
ブログ    
ブログ    

推薦する

20B大型モデルの性能はLlama2-70Bに匹敵します!完全にオープンソースで、ベースからツールまですべてが明確に整理されています

たった今、国産オープンソースモデルのパラメータ数の記録がまた更新されました! 9月20日、上海人工知...

ChatGPT が個人情報を含むトレーニングデータを吐き出す: DeepMind が論争を巻き起こす大きなバグを発見

ChatGPT がおかしくなるまで 1 つのことを実行するように要求し続けると、どうなるでしょうか?...

初めてバーチャルヒューマンに関する業界の合意が成立

この記事はAI新メディアQuantum Bit(公開アカウントID:QbitAI)より許可を得て転載...

旅行業界における機械学習と AI: 5 つの重要な業界ユースケース

この利便性は、近年旅行、観光、ホスピタリティ業界が積極的に導入している機械学習と人工知能の技術がなけ...

Googleの人工知能部門DeepMindが想像力を駆使した新システムを開発

北京時間8月19日のreadwriteによると、2014年にGoogleに買収された英国の人工知能企...

...

OSPFはSPFアルゴリズムを使用してルートを伝播します

SPF アルゴリズムは、各ルータをルートとして使用して、各宛先ルータまでの距離を計算します。各ルータ...

...

...

2019年の人工知能予測

[[253703]]プライバシーやデータバイアス規制などの問題から、モデルのトレーニングやセルフサー...

職場におけるAIとARの進化

[[434145]]職場における支援/拡張現実 (AR) と人工知能 (AI) の可能性を最大限に引...

探索的データ分析: 人工知能と機械学習の有効性を判断するための第一歩

データ品質の低さは、人工知能 (AI) および機械学習 (ML) テクノロジの実際のパフォーマンスを...

...

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

[[195952]] 1. ディープラーニングディープラーニングといえば、一度でも触れたことがある人...

ブロックチェーン、自動運転、人工知能の戦いが始まった。次にホットスポットになるのはどれか?

近年、ブロックチェーン、自動運転、人工知能といった概念がテクノロジーの世界で頻繁に話題になっています...