*
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class Perceptron : MonoBehaviour
|
||||
{
|
||||
public List<Layer> Layers;
|
||||
public List<Synapses> _synapses;
|
||||
|
||||
[System.Serializable]
|
||||
public class Layer {
|
||||
public int Size;
|
||||
public bool AddOffsetNeuron;
|
||||
public int TotalSize {
|
||||
get {
|
||||
return AddOffsetNeuron ? (Size + 1) : Size;
|
||||
}
|
||||
}
|
||||
public void Init() {
|
||||
Values = new float[TotalSize];
|
||||
Errors = new float[TotalSize];
|
||||
|
||||
|
||||
if (AddOffsetNeuron) {
|
||||
Values[Values.Length - 1] = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
public float[] Values;
|
||||
public float[] Errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
[System.Serializable]
|
||||
public class Synapses {
|
||||
public float[,] Values;
|
||||
public int InSize;
|
||||
public int OutSize;
|
||||
|
||||
public Synapses(int inSize, int outSize) {
|
||||
InSize = inSize;
|
||||
OutSize = outSize;
|
||||
Values = new float[inSize, outSize];
|
||||
SetRandom();
|
||||
// SetOne();
|
||||
Debug.Log($"Make synapses: {inSize}x{outSize}");
|
||||
}
|
||||
|
||||
public void SetOne() {
|
||||
|
||||
for (int i = 0; i < InSize; ++i) {
|
||||
for (int j = 0; j < OutSize; ++j) {
|
||||
Values[i, j] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void SetRandom() {
|
||||
|
||||
for(int i = 0; i < InSize; ++i) {
|
||||
for (int j = 0; j < OutSize; ++j) {
|
||||
Values[i, j] = UnityEngine.Random.value * 2.0f - 1.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const float FxCapDerivative = 0.01f;
|
||||
//float Fx(float x) {
|
||||
// if(x > 1.0f) {
|
||||
// return 1.0f + FxCapDerivative * (x - 1.0f);
|
||||
// }else if(x < 0.0f) {
|
||||
// return FxCapDerivative * x;
|
||||
// }
|
||||
// return x;
|
||||
//}
|
||||
//
|
||||
//float FxDerivative(float x) {
|
||||
// if (x > 1.0f) {
|
||||
// return FxCapDerivative;
|
||||
// } else if (x < 0.0f) {
|
||||
// return FxCapDerivative;
|
||||
// }
|
||||
// return 1.0f;
|
||||
//}
|
||||
|
||||
float Fx(float x) {
|
||||
return 1.0f / (1.0f + Mathf.Exp(-x));
|
||||
}
|
||||
|
||||
float FxDerivative(float x) {
|
||||
return x * (1.0f - x);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void PropagateErrors() {
|
||||
for (int inLayerId = Layers.Count - 2; inLayerId >= 0; --inLayerId) {
|
||||
int outLayerId = inLayerId + 1;
|
||||
|
||||
var inLayer = Layers[inLayerId];
|
||||
var outLayer = Layers[outLayerId];
|
||||
var weights = _synapses[inLayerId];
|
||||
|
||||
for(int i = 0; i < inLayer.Size; ++i) {
|
||||
float err = 0.0f;
|
||||
for (int o = 0; o < outLayer.Size; ++o) {
|
||||
err += outLayer.Errors[o] * weights.Values[i, o];
|
||||
}
|
||||
inLayer.Errors[i] = err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RecalculateWeights(float learnRate) {
|
||||
for (int inLayerId = 0; inLayerId < Layers.Count - 1; ++inLayerId) {
|
||||
int outLayerId = inLayerId + 1;
|
||||
|
||||
var inLayer = Layers[inLayerId];
|
||||
var outLayer = Layers[outLayerId];
|
||||
var weights = _synapses[inLayerId];
|
||||
for (int i = 0; i < inLayer.TotalSize; ++i) {
|
||||
|
||||
for (int o = 0; o < outLayer.Size; ++o) {
|
||||
|
||||
weights.Values[i, o] += (learnRate * outLayer.Errors[o]) * FxDerivative(outLayer.Values[o]) * inLayer.Values[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void CalculateOutputs() {
|
||||
for (int inLayerId = 0; inLayerId < Layers.Count - 1; ++inLayerId) {
|
||||
int outLayerId = inLayerId + 1;
|
||||
|
||||
var inLayer = Layers[inLayerId];
|
||||
var outLayer = Layers[outLayerId];
|
||||
var weights = _synapses[inLayerId];
|
||||
for (int o = 0; o < outLayer.Size; ++o) {
|
||||
|
||||
float sum = 0;
|
||||
for (int i = 0; i < inLayer.TotalSize; ++i) {
|
||||
sum += weights.Values[i, o] * inLayer.Values[i];
|
||||
}
|
||||
outLayer.Values[o] = Fx(sum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void Learn(float learnRate) {
|
||||
PropagateErrors();
|
||||
RecalculateWeights(learnRate);
|
||||
}
|
||||
|
||||
void Start()
|
||||
{
|
||||
foreach(var layer in Layers) {
|
||||
layer.Init();
|
||||
}
|
||||
|
||||
_synapses = new List<Synapses>();
|
||||
for (int i = 0; i < Layers.Count - 1; ++i) {
|
||||
_synapses.Add(new Synapses(Layers[i].TotalSize, Layers[i + 1].Size));
|
||||
}
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user