内容:
みなさん、こんにちは、私はスタンフォード大学のコンピューターサイエンスの大学院生です。 数年間、私の研究の一環として、私は綿密なトレーニングに取り組みました。それに関連する私のお気に入りのプロジェクトのいくつか-ConvNetJS-ニューラルネットワークをトレーニングするためのJavascriptライブラリ。 Javascriptを使用すると、何がうまくいっているのかを視覚化でき、ハイパーパラメーターのさまざまな設定に対処する機会が得られますが、このトピックをより詳細に検討したいという意見を今でもよく聞きます。 この記事(私は徐々にいくつかの章に拡張する予定です)は、そうするための私の謙虚な試みです。 書籍のようにPDF形式で作成するのではなく、ネットワークに投稿します。最終的にはアニメーションやデモンストレーションなどを含める必要があるためです(そうすることを望みます)。
ニューラルネットワークでの私の個人的な経験から、ページ全体、エラーの逆伝播の方程式の密な導関数を無視し、コードを書き始めると、すべてがより明確になることがわかります。 したがって、このマニュアルには数学がほとんど含まれていません(これが必要であるとは思えません。一部の場所では、単純な概念の理解が複雑になる場合もあります)。 私の専門はコンピューターサイエンスと物理学なので、代わりにハッカーの観点からこのトピックを作成します。 私のプレゼンテーションでは、数学的な微分ではなく、コードと物理的な直感に焦点を当てます。 基本的に、始めたばかりのときに使用したい方法でアルゴリズムを提示しようとします。
「...コードを書き始めたとき、すべてがより明確になりました」
すぐに飛び越えて、すぐにニューラルネットワーク、実際にそれらを使用する方法などの研究を始めたいと思うでしょう。しかし、これを取り上げる前に、このすべてを忘れてほしいと思います。 一歩後退して、本質的に何が起こっているのかを把握しましょう。 最初に実際の値スキームについて話しましょう。
第1章:実際の価値の図
私の意見では、ニューラルネットワークを想像する最良の方法は、実際の値(ブール{0,1}ではなく)が境界に沿って「流れ」、論理要素で相互作用する実際の値の回路です。 ただし、AND、OR、NOTなどの論理要素の代わりに、*(乗算)、+(加算)、maxなどのバイナリ論理要素、またはexpなどの単項論理要素があります。ただし、 、通常のブール回路とは異なり、最終的には同じ回路の境界に沿って逆方向に流れる勾配もあります。 しかし、私たちは自分自身に先んじています。 集中して、シンプルから始めましょう。
基本シナリオ:回路内の単純な論理要素
最初に、1つの論理要素を持つ単一の単純な回路を見てみましょう。 以下に例を示します。
回路は、xとyの2つの初期実数値を取り、論理要素*を使用してx * yを乗算します。
この方程式のjavascriptバージョンは、たとえば次のように非常に単純に見えます。
var forwardMultiplyGate = function(x, y) { return x * y; }; forwardMultiplyGate(-2, 3); // returns -6.
そして数学的形式では、この論理要素を実際の値を持つ関数の複製と考えることができます。
f(x、y)= xy
この例のように、すべてのロジック要素は1つまたは2つのソース値を取り、1つの出力値を生成します。
目的
私たちが勉強したい問題は次のとおりです。
1.特定の初期値を特定の図に導入します(たとえば、x = -2、y = 3)
2.回路は出力値を計算します(たとえば、-6)
3.この結果、重要な疑問が生じます。結果を向上させるには、初期値をわずかに変更する必要がありますか?
この場合、-6より大きい数を得るためにx、yをどのように変更する必要がありますか? たとえば、x = -1.99およびy = 2.99はx * y = -5.95を与えることに注意してください。これは既に-6.0を超えています。 心配しないでください:-5.95は-6.0より優れています(高い)。 -5.95(ゼロからの距離)の値は時々低くなりますが、これは0.05の改善です。
戦略#1:カスタムローカル検索
いいね 回路があり、いくつかの初期値があり、出力値を増やすためにそれらを少し変更する必要がありますか? 難しさは何ですか? 回路がxおよびyの任意の値の結果を計算するのを簡単に「助ける」ことができます。 簡単ではないですか? xとyを任意に変更し、どの変更が最良の結果をもたらすかを追跡しないのはなぜですか。
// , var forwardMultiplyGate = function(x, y) { return x * y; }; var x = -2, y = 3; // some input values // x,y , var tweak_amount = 0.01; var best_out = -Infinity; var best_x = x, best_y = y; for(var k = 0; k < 100; k++) { var x_try = x + tweak_amount * (Math.random() * 2 - 1); // x var y_try = y + tweak_amount * (Math.random() * 2 - 1); // y var out = forwardMultiplyGate(x_try, y_try); if(out > best_out) { // ! x y best_out = out; best_x = x_try, best_y = y_try; } }
これを実行すると、best_x = -1.9928、best_y = 2.9901、およびbest_out = -5.9588になりました。 繰り返しますが、-5.9588は-6.0よりも高くなっています。 さて、これで完了です。 そうではありません:計算する時間があれば、これは少数の論理要素を持つ小さな問題には理想的な戦略ですが、数百万の初期値を持つ大規模な回路を扱う場合は機能しません。 さらに多くのことができることがわかりましたが、次のパートでさらに詳しく説明します。