示例#1
0
    // Start is called before the first frame update
    void Start()
    {
        List <int> dims = new List <int>();

        dims.Add(3);
        dims.Add(2);

        NeuralNetwork nn = new NeuralNetwork(dims);

        Jatrix entered = new Jatrix(3, 2);

        entered[0, 0] = 1;
        entered[1, 0] = 0;
        entered[2, 0] = 0;

        entered[0, 1] = 0;
        entered[1, 1] = 1;
        entered[2, 1] = -1;

        nn.BeatPerceptronsWithHammer(1);

        Jatrix result = nn.GetOutputs(entered);

        Debug.Log(result.width + ", " + result.height);

        result.DebugMatrix();

        nn.DebugPerceptron(0);
    }
示例#2
0
    //Overloaded multiplication operator
    public static Jatrix operator *(Jatrix a, Jatrix b)
    {
        if (a.width != b.height)
        {
            Debug.LogError("ERROR: MATRIX DIMENSION MISMATCH!");
            return(null);
        }

        Jatrix toRet = new Jatrix(b.width, a.height);

        for (int i = 0; i < toRet.width; ++i)
        {
            for (int j = 0; j < toRet.height; ++j)
            {
                float sum = 0;

                for (int ii = 0; ii < a.width; ++ii)
                {
                    sum += a[ii, j] * b[i, ii];
                }

                toRet[i, j] = sum;
            }
        }

        return(toRet);
    }
示例#3
0
    //New neural network constructor
    //Takes in a list of ints, dictating size of each perceptron
    public NeuralNetwork(List <int> dimensions)
    {
        //Catch if less than 2 dimensions have been provided, as no weight matrices would be generated
        if (dimensions.Count <= 1)
        {
            isOk = false;
            Debug.LogError("ERROR: INSUFFICIENT DIMENSIONS FOR NEURAL NETWORK!");
            return;
        }

        //Sets the input and output sizes to be the beginning and end of the dimension list respectively
        inputSize  = dimensions[0];
        outputSize = dimensions[dimensions.Count - 1];

        //Generates a list of perceptrons and weight matrics accordingly
        perceptrons    = new Jatrix[dimensions.Count - 1];
        weightMatrices = new Jatrix[dimensions.Count - 1];

        //Create a series of weight matrices, so that they can be multiplied together, to form perceptrons
        //By making the previous' width equal the next height, we can ensure that they are able to be multiplied
        for (int i = 0; i < dimensions.Count - 1; ++i)
        {
            perceptrons[i]    = new Jatrix(dimensions[i + 1], 1);
            weightMatrices[i] = new Jatrix(dimensions[i + 1], dimensions[i]);
        }
    }
示例#4
0
    //Copy initialization.
    //Abuses the copy constructors of other classes to create a duplicate of the original matrix
    //No randomization here, for the sake of consistency.
    public void InitCar(CarController toCopy)
    {
        brain = new NeuralNetwork(toCopy.brain);

        inputData  = new Jatrix(toCopy.inputData);
        outputData = new Jatrix(toCopy.outputData);

        previousPosition = transform.position;
        rb.velocity      = transform.forward * carSpeedMedium;
    }
示例#5
0
    //Quickly makes an identity matrix
    public static Jatrix Identity(int rows)
    {
        Jatrix toReturn = new Jatrix(rows, rows);

        for (int i = 0; i < rows; ++i)
        {
            toReturn[i, i] = 1;
        }

        return(toReturn);
    }
示例#6
0
    //Overloaded multiplication operator, using a float
    public static Jatrix operator *(Jatrix a, float b)
    {
        Jatrix toRet = new Jatrix(a.width, a.height);

        for (int i = 0; i < toRet.width; ++i)
        {
            for (int j = 0; j < toRet.height; ++j)
            {
                toRet[i, j] = a[i, j] * b;
            }
        }

        return(toRet);
    }
示例#7
0
    //Non-Copy initialization of cars.
    //Forms input/output matrices as well as a neural network to compute them.
    //Also randomizes them slightly.
    public void InitCar(List <int> neuralNetworkShape, float randomizationStrength)
    {
        inputData = new Jatrix(neuralNetworkShape[0], 1);

        outputData = new Jatrix(neuralNetworkShape[neuralNetworkShape.Count - 1], 1);

        brain = new NeuralNetwork(neuralNetworkShape);

        //Alternate name for the weight randomization function. Same purpose.
        brain.BeatPerceptronsWithHammer(randomizationStrength);

        previousPosition = transform.position;
        rb.velocity      = transform.forward * carSpeedMedium;
    }
示例#8
0
    //Copy constructor, creates an exact copy of a neural network
    public NeuralNetwork(NeuralNetwork copy)
    {
        inputSize  = copy.inputSize;
        outputSize = copy.outputSize;

        weightMatrices = new Jatrix[copy.weightMatrices.Length];
        perceptrons    = new Jatrix[copy.perceptrons.Length];

        for (int i = 0; i < weightMatrices.Length; ++i)
        {
            weightMatrices[i] = new Jatrix(copy.weightMatrices[i]);
            perceptrons[i]    = new Jatrix(copy.perceptrons[i]);
        }
    }
示例#9
0
    //Also randomize the weight matrices
    public void RandomizeWeights(float range)
    {
        for (int i = 0; i < weightMatrices.Length; ++i)
        {
            Jatrix mat = weightMatrices[i];

            for (int j = 0; j < mat.width; ++j)
            {
                for (int k = 0; k < mat.height; ++k)
                {
                    //Offset every element of the weight matrices by a given range
                    mat[j, k] += Random.Range(-range, range);
                }
            }
        }
    }
示例#10
0
    //Copy constructor, allows us to efficiently duplicate matrics
    public Jatrix(Jatrix toCopy)
    {
        width  = toCopy.width;
        height = toCopy.height;

        elements = new float[width][];

        for (int i = 0; i < width; ++i)
        {
            elements[i] = new float[height];

            for (int j = 0; j < height; ++j)
            {
                elements[i][j] = toCopy[i, j];
            }
        }
    }
示例#11
0
    //Get outputs from inputs
    //Does the multiplication of all the weight matrices, and generates perceptrons
    public Jatrix GetOutputs(Jatrix inputs)
    {
        //Check if the network is ok before doing this
        if (!isOk)
        {
            Debug.LogError("ERROR: NEURAL NETWORK FAILED CREATION! OPERATION INVALID ON BAD NN!");
            return(null);
        }

        //Check if the input size matches what's expected
        if (inputs.width != inputSize)
        {
            Debug.LogError("ERROR: INPUT SIZE DIMENSION MISMATCH!");
            return(null);
        }

        //Matrix used to iterate through the weight matrices
        Jatrix combined = new Jatrix(inputs);

        for (int i = 0; i < weightMatrices.Length; ++i)
        {
            //Multiply by a weight matrix
            combined *= weightMatrices[i];

            for (int j = 0; j < combined.width; ++j)
            {
                //Shifted sigmoid, generates a value on [-1, 1] as opposed to [0, 1]
                combined[j, 0] = 2f / (1f + Mathf.Exp(-combined[j, 0])) - 1;

                //Below is the step function originally used

                //if (combined[j, 0] > 0.5f)
                //    combined[j, 0] = 1;
                //else if (combined[j, 0] < 0.5f)
                //    combined[j, 0] = -1;
                //else
                //    combined[j, 0] = 0;
            }

            //Save as a perceptron
            perceptrons[i] = new Jatrix(combined);
        }

        return(combined);
    }
示例#12
0
    //Overloaded matrix addition
    public static Jatrix operator+(Jatrix a, Jatrix b)
    {
        if (a.width != b.width || a.height != b.height)
        {
            Debug.LogError("ERROR: MATRIX DIMENSION MISMATCH!");
            return(null);
        }

        Jatrix toRet = new Jatrix(a.width, a.height);

        for (int i = 0; i < toRet.width; ++i)
        {
            for (int j = 0; j < toRet.height; ++j)
            {
                toRet[i, j] = a[i, j] + b[i, j];
            }
        }

        return(toRet);
    }
示例#13
0
    //Pseudo fixed update, used to offer more control of what executes and when
    //Originally was split up into several functions, to test them individually
    //Parts of it can return false to indicate something is wrong OR the car has crashed.
    public void PseudoFixedUpdateStep(CarManager cm)
    {
        if (!CalculateReward())
        {
            return;
        }

        //Gravity, to offer us more control should we want it
        rb.AddForce(Vector3.down * 30f, ForceMode.Force);

        if (!CreateInputs())
        {
            return;
        }

        //Prints the values of the perceptrons
        if (TagForDebug)
        {
            string bigData = "";

            for (int i = 0; i < brain.perceptrons.Length; ++i)
            {
                bigData += "\n";
                for (int j = 0; j < brain.perceptrons[i].width; ++j)
                {
                    bigData += ("\t " + brain.perceptrons[i][j, 0]);
                }
            }

            Debug.Log(bigData);
        }

        //Calculate output data from input data
        outputData = brain.GetOutputs(inputData);

        if (!PerformOutputs())
        {
            return;
        }
    }