Javaのニューラルネットワークに関するいくつかの単純な概念を試すことにしました。フォーラムで見つけたやや役に立たないコードを採用することで、典型的な初心者のXORシミュレーション用の非常に単純なモデルを作成できました。
public class MainApp {
public static void main (String [] args) {
Neuron xor = new Neuron(0.5f);
Neuron left = new Neuron(1.5f);
Neuron right = new Neuron(0.5f);
left.setWeight(-1.0f);
right.setWeight(1.0f);
xor.connect(left, right);
for (String val : args) {
Neuron op = new Neuron(0.0f);
op.setWeight(Boolean.parseBoolean(val));
left.connect(op);
right.connect(op);
}
xor.fire();
System.out.println("Result: " + xor.isFired());
}
}
public class Neuron {
private ArrayList inputs;
private float weight;
private float threshhold;
private boolean fired;
public Neuron (float t) {
threshhold = t;
fired = false;
inputs = new ArrayList();
}
public void connect (Neuron ... ns) {
for (Neuron n : ns) inputs.add(n);
}
public void setWeight (float newWeight) {
weight = newWeight;
}
public void setWeight (boolean newWeight) {
weight = newWeight ? 1.0f : 0.0f;
}
public float getWeight () {
return weight;
}
public float fire () {
if (inputs.size() > 0) {
float totalWeight = 0.0f;
for (Neuron n : inputs) {
n.fire();
totalWeight += (n.isFired()) ? n.getWeight() : 0.0f;
}
fired = totalWeight > threshhold;
return totalWeight;
}
else if (weight != 0.0f) {
fired = weight > threshhold;
return weight;
}
else {
return 0.0f;
}
}
public boolean isFired () {
return fired;
}
}
私のメインクラスでは、Jeff Heatonの図をモデリングする簡単なシミュレーションを作成しました。
ただし、Neuronクラスの実装が正しいことを確認したかったので、すべての可能な入力([true true]、[true false]、[false true]、[false false])をすでにテストしました。私の手動検証。さらに、このプログラムは入力を引数として受け入れるため、[true false false]、[true true false]などの入力の手動検証にも合格するようです。
しかし、概念的に言えば、この実装は正しいのでしょうか?または、このトピックについてさらに開発と研究を始める前に、どうすれば改善できるでしょうか?
ありがとうございました!
それは良い出発点のように見えます。私はいくつかの提案をしています:
スケーラビリティーのために、fire()を再構成して、現在の入力セットですでに起動されているニューロンが毎回再計算する必要がないようにする必要があります。これは、別の非表示レイヤー、または複数の出力ノードがある場合に当てはまります。
しきい値計算を独自のメソッドに分割することを検討してください。次に、Neuronをサブクラス化して、さまざまなタイプの活性化関数(双極シグモイド、RBF、線形など)を使用できます。
より複雑な関数を学習するには、各ニューロンにバイアス入力を追加します。基本的には独自の重み値を持つ別の入力と同じですが、入力は常に1(または-1)に固定されます。
トレーニング方法を許可することを忘れないでください。バックプロパゲーションには、ターゲット出力を取得し、各レイヤーを通じてウェイト変更をリップルするために、fire()の逆のようなものが必要になります。
私がニューラルネットで行った(制限された)作業から、その実装とモデルは私には正しいように見えます-出力は私が期待するものであり、ソースは確かに見えます。