(REALLY) simple neural network program This is a simple program to create neural networks. It only includes weighting of connections and activation values for the neurons. It doesn't include any learning feature of any kind, and it is really just a first attempt at creating something resembling a neural network. 

Main.java

package uniliniarnetwork;

public class Main {

public static void main(String[] args) {
    Neuron inputNode = new Neuron(0,1,"InputNode",1);

    Neuron hiddenNode_One = new Neuron(0.5f,0.9f,"HiddenNode_One",1);
    Neuron hiddenNode_Two = new Neuron(0.5f,0.9f,"HiddenNode_Two",1);
    Neuron hiddenNode_Three = new Neuron(0.5f,0.9f,"HiddenNode_Three",1);

    Neuron outputNode = new Neuron(0,0.9f,"OutputNode",3);

    inputNode.connect(hiddenNode_One);
    inputNode.connect(hiddenNode_Two);
    inputNode.connect(hiddenNode_Three);

    hiddenNode_One.connect(outputNode);
    hiddenNode_Two.connect(outputNode);
    hiddenNode_Three.connect(outputNode);

    inputNode.input(1);
}

}


Neuron.java

package uniliniarnetwork;

import java.util.ArrayList;

public class Neuron {
private float activationValue, weight;
private String neuronName;
private ArrayList&lt;Neuron&gt; outputs = new ArrayList&lt;Neuron&gt;();
private float[] inputs;
int inputCounter = 0, nInputs;

public Neuron(float activationValue, float weight, String neuronName, int nInputs){
    this.activationValue = activationValue;
    this.weight = weight;
    this.neuronName = neuronName;
    this.nInputs = nInputs;

    inputs = new float[nInputs];
}

public void connect(Neuron neuron){
    outputs.add(neuron);
}

public void input(float inputValue){
    inputs[inputCounter] = inputValue;
    inputCounter++;

    if(inputCounter == nInputs){
        fire();
    }
}

public void fire(){
    float sum = 0;
    for(int i = 0; i &lt; nInputs; i++){
        sum+=inputs[i];
    }

    float signal = sum*weight;

    if(signal &gt; activationValue){
        for(int i = 0; i &lt; outputs.size(); i++){
            outputs.get(i).input(signal);
        }
    } else{
        for(int i = 0; i &lt; outputs.size(); i++){
            outputs.get(i).input(0);
        }
    }
    System.out.println(neuronName + ":" + signal);
}
}


Basically main creates Neuron objects from the Neuron class which have an activationValue and a weight value. I know it's not perfect and it doesn't include most of the most important features of a neural network.

My question is whether this is a good place to build from towards more advanced neural networks, for example those which can classify images. It would be greatly appreciated if you could explain in terms a high-school student (with only a rudimentary understanding of calculus) would understand.
I'm not really into Neural Networks, but I do read code and I do have some suggesting for what to do next related to this code. 

Code and Style Comments


Number in variable names, not good – Even though you spelt out the number, still having numbers in a variable names indicates that you might be doing something wrong. I'm thinking of the hiddenNode_One&amp; co. 
Please fix your indentation – This excerpt is taken directly from your code:


public class Neuron {
private float activationValue, weight;
private String neuronName;
private ArrayList&lt;Neuron&gt; outputs = new ArrayList&lt;Neuron&gt;();
private float[] inputs;
int inputCounter = 0, nInputs;

public Neuron(float activationValue, float weight, String neuronName, int nInputs){
    this.activationValue = activationValue;



This looks like a list of variable declaraction outside of classes and methods, and only with a second look it's possible to see that you are actually declaring a class Neuron, its class variables, and a class constructor of public Neutron(). And finally you indent for the method definition.  Here is the same code with better indentation:


public class Neuron {
    private float activationValue, weight;
    private String neuronName;
    private ArrayList&lt;Neuron&gt; outputs = new ArrayList&lt;Neuron&gt;();
    private float[] inputs;
    int inputCounter = 0, nInputs;

    public Neuron(float activationValue, float weight, String neuronName, int nInputs){
        this.activationValue = activationValue;



This looks a lot better, and it's easier to follow the program flow.
Is it wise to lock the number of inputs? – In your constructor you lock the number of inputs for any given Neuron, which might lead to confusing situations later on if you want to reorder your network.
Feature: To many input()'s will trigger index error – Since you keep increasing the inputCounter whenever this method is called, you'll run out of array elements to update, and will finally trigger an index error.

In the same code, you'll only fire() once when the inputCounter exactly equals the preset number of inputs. So if the input of a Neuron changes afterwards, the network is never updated. Neither of these seems to be correct.
Always generate input() even when not over the activation value? – In light of preceding point, it seems kind of strange to do the input(0) sequence, as that might for some networks trigger the index error before it should. Wouldn't it be better to leave out the no input part?

That is, unless that is a requirement due to the value swapping from over and under the activationValue during the lifetime of the network, in which case you really need to address the case of connecting inputs to the Neuron receiving the input.
Why delay the summation of inputs, and the signal value – In my mind it would be better to update a sum and the signal value whenever receiving an input, instead of when doing the fire().

Imaging having a network of thousands of nodes, and you having to calculate this for each fire event you trigger, even though the input possibly didn't change?  To me it makes more sense to do this within the input() having a sum variable, and to have a class variable (or method) holding (or returning) the sum * weight.

Do however know that this would require proper knowledge of which input is being updated, so that if you receive a secondary input on that Neuron you'll correctly adjust the sum, and not blatantly keep adding the new value.
Order of calculation and output – Most likely your System.out.println(neuronName + ":" + signal) should be replaced with a call to some logger, but I would also put this one in front of the signal &gt; activationValue loops. As it is in a bigger network you would get the output of the latter nodes, before the first nodes. For the output to make sense, it would be wiser to have the output directly after the calculation of signal.


Some General Thoughts on Neural Networks

In my mind a neural network is something dynamic, which could/should easily be able to change and reconnect towards other neurons (or nodes). So here are some concerns I have related to your code:


No visualization of the neural network – It's not possible to visualize your network. I think it would've been nice to have a way to visualize it, so that you can see how it is connected with which triggers and so on.
No connection of the input towards the neurons – There is no connection between the neurons connected to another neuron and the input. In other words, if the hiddenNode_Two decides to change its input, and thusly it fires an output, you don't have a way to know which of the inputs of the outputNode actually changed. This doesn't seem correct.
No dynamic in neuron connection – You've got no methods to remove and change your network. In addition you've limited the neuron at construction time to a given set of inputs. Thusly disallowing a re-ordering of your network based on any future learning. 

Imaging having a network doing something related to alphabetic calculation. At the start you could start out with a few nodes, but after a while you see the need to split the a-e node as it is overworked. Your code as it stands, would require a full reconstruction, and not a simple replacement of that node with a few extra nodes.


One way to implement this interconnection, and related sums and signal values, could be to introduce a static list of Neurons, and extend each Neuron with dynamic lists of indexes into this list to describe its inputs and outputs.

This would allow for methods identifying all the inputs or outputs, by checking whether the input or output list for a given neuron is empty or not. You could also make static methods traversing based on input nodes describing the paths to new nodes (possibly with circular node connection detection) until you reaches the output nodes.