3

ニューラルネットを実装しようとしていますが、各ニューロンには他のニューロンへの参照が必要です。私はこのリファレンスをアトムを介して実装しようとしています。

コードを検討してください

(def neuron1 {:connections [(atom 0)])
(def neuron2 {:connections [(atom neuron1)]})

(update-in neuron1 [:connections 0] #(reset! % neuron2))

その最後はスタックを爆破します。

そのため、アトムは単にそれらを参照するのではなく、その内容を含んでいるように見えます。

ポインタに相当するものを渡したい場合はどうすればよいですか?次のような関数を使用する必要がありますか?

(def neuron1 {:connections [(fn [] neuron2)]})

アトムを使用して逆参照するのではなく、それを呼び出しますか?

4

3 に答える 3

5

あなたのコードは問題ありません。スタックを吹き飛ばしている理由は、REPL で update-in コマンドを実行しているためです。これにより、result が出力されます。各ニューロンは他のニューロン内にネストされているため、print ステートメントでスタック オーバーフローが発生します。update-in コマンドを (type) などの別のステートメントに入れるか、別の関数内で実行してみてください。

于 2013-03-01T04:07:10.643 に答える
3

単純な Clojure データ構造を使用したい場合は、アトムのきめの細かい使用を忘れるのがおそらく最善です。代わりに、次のように、ネットワーク全体を表す巨大なマップを作成します。

(def ann {1 {:connections [1 2 3] :weights [0.1 -0.3 0.5] :state 0.3} 2 {:connections [1 2 3] :weights [0.1 -0.3 0.5] :state 0.13} 3 {:connections [2 3] :weights [0.5 0.2] :state 0.31}})

次に、update-in などを使用してノードを更新します。テストを容易にするため、すべての更新関数が不変のデータ構造を取るようにします。

確かに、これよりも良い方法があります。おそらく、@ mikera が行列で何をしてきたかを最もよく見ているでしょう。

または、非同期にしたい場合は、Lamina または新しい Plumbing/Graph ライブラリを使用できます。

于 2013-03-01T04:39:25.837 に答える
3

WolfeFan は、「なぜスタックオーバーフローが発生するのか」という質問の部分に既に回答しています。ポインター/参照の種類の機能に関する限り、(ニューロンにバインドされている) var をニューロン オブジェクト自体ではなくアトムに格納できます。また、おそらく複数のスレッドから接続オブジェクトを変更することになるため、個々の接続を原子としてではなく、接続をベクトルの原子にすることをお勧めします。

例:

(def neuron1 {:connections (atom [])})
(def neuron2 {:connections (atom [#'neuron1])})

(update-in neuron1 [:connections] #(swap! % conj #'neuron2))

接続されたニューロンを取得する必要がある場合は、次を使用する必要がありますvar-get

(-> neuron1 :connections deref (get 0) var-get)

Var 自体はスレッド セーフであり、使用する必要がある var のルート バインディングを変更しますalter-var-root。これはアトミック操作です。

于 2013-03-01T04:33:57.527 に答える