102 lines
3.2 KiB
C#
102 lines
3.2 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using Random = UnityEngine.Random;
|
|
|
|
public sealed class NeuralNetwork : IComparable<NeuralNetwork> {
|
|
|
|
public float Fitness { get; set; }
|
|
private readonly int[] _layers;
|
|
private readonly float[][] _neurons;
|
|
private float[][][] _weights;
|
|
|
|
public NeuralNetwork(int[] layers) {
|
|
_layers = layers.ToArray();
|
|
_neurons = _layers.Select(layer => new float[layer]).ToArray();
|
|
InitWeights();
|
|
}
|
|
|
|
public NeuralNetwork(NeuralNetwork network) {
|
|
_layers = network._layers.ToArray();
|
|
_neurons = _layers.Select(layer => new float[layer]).ToArray();
|
|
InitWeights();
|
|
CopyWeights(network._weights);
|
|
}
|
|
|
|
private void CopyWeights(float[][][] weights) {
|
|
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++) {
|
|
_weights[i][j][k] = weights[i][j][k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void InitWeights() {
|
|
var weights = new List<float[][]>();
|
|
|
|
for (int i = 1; i < _layers.Length; i++) {
|
|
var layerWeights = new List<float[]>();
|
|
int previousNeurons = _layers[i - 1];
|
|
|
|
for (int j = 0; j < _neurons[i].Length; j++) {
|
|
var neuronWeights = new float[previousNeurons];
|
|
|
|
for (int k = 0; k < previousNeurons; k++) {
|
|
neuronWeights[k] = Random.Range(-0.5f, 0.5f);
|
|
}
|
|
|
|
layerWeights.Add(neuronWeights);
|
|
}
|
|
|
|
weights.Add(layerWeights.ToArray());
|
|
}
|
|
|
|
_weights = weights.ToArray();
|
|
}
|
|
|
|
public float[] FeedForward(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++) {
|
|
var 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] = MathF.Tanh(value);
|
|
}
|
|
}
|
|
|
|
return _neurons[^1];
|
|
}
|
|
|
|
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++) {
|
|
var weight = _weights[i][j][k];
|
|
var random = Random.Range(0.0f, 1000.0f);
|
|
|
|
if (random <= 2.0f) weight *= -1.0f;
|
|
else if (random <= 4.0f) weight = Random.Range(-0.5f, 0.5f);
|
|
else if (random <= 6.0f) weight *= Random.Range(0.0f, 1.0f) + 1.0f;
|
|
else if (random <= 8.0f) weight *= Random.Range(0.0f, 1.0f);
|
|
|
|
_weights[i][j][k] = weight;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public int CompareTo(NeuralNetwork other) {
|
|
if (ReferenceEquals(this, other)) return 0;
|
|
if (ReferenceEquals(null, other)) return 1;
|
|
return Fitness.CompareTo(other.Fitness);
|
|
}
|
|
} |