171 lines
5.2 KiB
C#
171 lines
5.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public class NeuralNetwork : IComparable<NeuralNetwork> {
|
|
|
|
private int[] _layers; //layers of the neural network
|
|
private float[][] _neurons; //neurons of the neural network
|
|
public float[][][] _weights; //weights of the neural network
|
|
private float _score; //score of the neural network
|
|
|
|
/// <summary>
|
|
/// Creates a new neural network with the given layers
|
|
/// </summary>
|
|
/// <param name="layers">The layers with the count of the individual neurons</param>
|
|
public NeuralNetwork(in int[] layers) {
|
|
_layers = new int[layers.Length];
|
|
for (int i = 0; i < layers.Length; i++) {
|
|
_layers[i] = layers[i];
|
|
}
|
|
|
|
InitializeNeurons();
|
|
InitializeWeights();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Copy a NeuralNetwork
|
|
/// </summary>
|
|
/// <param name="network">The NeuralNetwork you wanna copy</param>
|
|
public NeuralNetwork(in NeuralNetwork network) {
|
|
_layers = new int[network._layers.Length];
|
|
for (var i = 0; i < network._layers.Length; i++) {
|
|
_layers[i] = network._layers[i];
|
|
}
|
|
|
|
InitializeNeurons();
|
|
|
|
CopyWeights(network._weights);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate output based on ihe given input
|
|
/// </summary>
|
|
/// <param name="inputs">The values at the first layer</param>
|
|
/// <returns></returns>
|
|
public float[] FeedForward(in float[] inputs) {
|
|
for (int i = 0; i < inputs.Length; i++) {
|
|
_neurons[0][i] = inputs[i];
|
|
}
|
|
|
|
for (int i = 1; i < _layers.Length; i++) {
|
|
for (int j = 0; j < _neurons[i].Length; j++) {
|
|
float value = 0.25f;
|
|
|
|
for (int k = 0; k < _neurons[i - 1].Length; k++) {
|
|
value += _weights[i - 1][j][k] * _neurons[i - 1][k];
|
|
}
|
|
|
|
_neurons[i][j] = (float)Math.Tan(value);
|
|
}
|
|
}
|
|
|
|
return _neurons[_neurons.Length - 1];
|
|
}
|
|
|
|
/// <summary>
|
|
/// Randomize the weights of the neural network
|
|
/// </summary>
|
|
public void Mutate() {
|
|
for (int i = 0; i < _weights.Length; i++) {
|
|
for (int j = 0; j < _weights[i].Length; j++) {
|
|
for (int k = 0; k < _weights[i][j].Length; k++) {
|
|
float weight = _weights[i][j][k];
|
|
|
|
float random = Random.value * 100.0f;
|
|
|
|
switch (random) {
|
|
case 2.0f:
|
|
weight *= -1;
|
|
break;
|
|
|
|
case 4.0f:
|
|
weight = Random.Range(-0.5f, 0.5f);
|
|
break;
|
|
|
|
case 6.0f:
|
|
weight *= Random.Range(0.0f, 1.0f) + 1;
|
|
break;
|
|
|
|
case 8.0f:
|
|
weight *= Random.Range(0.0f, 1.0f);
|
|
break;
|
|
}
|
|
|
|
_weights[i][j][k] = weight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddScore(in float score) => _score += score;
|
|
public void SetScore(in float score) => _score = score;
|
|
public float GetScore() => _score;
|
|
|
|
private void InitializeNeurons() {
|
|
List<float[]> neurons = new List<float[]>();
|
|
|
|
for (int i = 0; i < _layers.Length; i++) {
|
|
neurons.Add(new float[_layers[i]]);
|
|
}
|
|
|
|
_neurons = neurons.ToArray();
|
|
}
|
|
|
|
private void InitializeWeights() {
|
|
List<float[][]> weights = new List<float[][]>();
|
|
|
|
for (int i = 1; i < _layers.Length; i++) {
|
|
List<float[]> layerWeights = new List<float[]>();
|
|
|
|
int neuronsInPreviousLayer = _layers[i - 1];
|
|
|
|
for (int j = 0; j < _neurons[i].Length; j++) {
|
|
float[] neuronWeights = new float[neuronsInPreviousLayer];
|
|
|
|
for (int k = 0; k < neuronsInPreviousLayer; k++) {
|
|
neuronWeights[k] = Random.value - 0.5f;
|
|
}
|
|
|
|
layerWeights.Add(neuronWeights);
|
|
}
|
|
|
|
weights.Add(layerWeights.ToArray());
|
|
}
|
|
|
|
_weights = weights.ToArray();
|
|
}
|
|
|
|
private void CopyWeights(in float[][][] weights) {
|
|
_weights = new float[weights.Length][][];
|
|
|
|
for (int i = 0; i < weights.Length; i++) {
|
|
_weights[i] = new float[weights[i].Length][];
|
|
|
|
for (int j = 0; j < weights[i].Length; j++) {
|
|
_weights[i][j] = new float[weights[i][j].Length];
|
|
|
|
for (int k = 0; k < weights[i][j].Length; k++) {
|
|
_weights[i][j][k] = weights[i][j][k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public int CompareTo(NeuralNetwork other) {
|
|
if (other == null) {
|
|
return 1;
|
|
}
|
|
|
|
if (other._score > _score) {
|
|
return -1;
|
|
}
|
|
|
|
if (other._score < _score) {
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|