146 lines
3.7 KiB
C#
146 lines
3.7 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEditor.PackageManager;
|
|
using UnityEngine;
|
|
using UnityEngine.UI;
|
|
using static UnityEditor.PlayerSettings;
|
|
|
|
public class PointsClassificationTask : MonoBehaviour
|
|
{
|
|
public Perceptron Net;
|
|
|
|
private Agent[] _class0Agents;
|
|
private Agent[] _class1Agents;
|
|
|
|
|
|
|
|
public float LearnRate = 0.1f;
|
|
public int IterationsPerFrame = 50;
|
|
|
|
public Texture2D Texture;
|
|
|
|
struct Color {
|
|
public byte a;
|
|
public byte r;
|
|
public byte g;
|
|
public byte b;
|
|
|
|
|
|
public static Color Red {
|
|
get {
|
|
return new Color() { a = 0xff, r = 0xff, g = 0, b = 0 };
|
|
}
|
|
}
|
|
|
|
public static Color Green {
|
|
get {
|
|
return new Color() { a = 0xff, r = 0x0, g = 0xff, b = 0 };
|
|
}
|
|
}
|
|
}
|
|
Color[] colors = new Color[256 * 256];
|
|
|
|
// Start is called before the first frame update
|
|
void Start()
|
|
{
|
|
var img = GetComponent<Image>();
|
|
|
|
Texture = new Texture2D(256, 256, TextureFormat.ARGB32, false, true);
|
|
img.material.mainTexture = Texture;
|
|
for(int i = 0; i < colors.Length; ++i) {
|
|
colors[i] = Color.Red;
|
|
}
|
|
|
|
Texture.SetPixelData<Color>(colors, 0);
|
|
Texture.Apply();
|
|
// img.material = new Material()
|
|
|
|
|
|
int children = transform.childCount;
|
|
for(int i = 0; i < children; i++) {
|
|
var child = transform.GetChild(i);
|
|
|
|
if(child.name == "Class0") {
|
|
_class0Agents = child.GetComponentsInChildren<Agent>();
|
|
Debug.Log($"Add Class0 children: {_class0Agents.Length}");
|
|
}else if (child.name == "Class1") {
|
|
_class1Agents = child.GetComponentsInChildren<Agent>();
|
|
Debug.Log($"Add Class1 children: {_class1Agents.Length}");
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
// Update is called once per frame
|
|
void Update()
|
|
{
|
|
for(int i = 0; i < IterationsPerFrame; ++i) {
|
|
Learn();
|
|
}
|
|
RepaintTexture();
|
|
}
|
|
|
|
|
|
void Learn() {
|
|
LearnClass(true);
|
|
LearnClass(false);
|
|
}
|
|
|
|
void RepaintTexture() {
|
|
var inLayer = Net.Layers[0];
|
|
var outLayer = Net.Layers[Net.Layers.Count - 1];
|
|
|
|
for (int y = 0; y < 256; ++y) {
|
|
for (int x = 0; x < 256; ++x) {
|
|
inLayer.Values[0] = x / 255.0f;
|
|
inLayer.Values[1] = y / 255.0f;
|
|
Net.CalculateOutputs();
|
|
|
|
var c0 = Mathf.Clamp01(outLayer.Values[0]);
|
|
var c1 = Mathf.Clamp01(outLayer.Values[1]);
|
|
colors[(255-y) * 256 + x] = new Color() { a=0xff, r = (byte)(c1 * 255.0f), g = 0, b = (byte)(c0 * 255.0f) };
|
|
}
|
|
}
|
|
|
|
Texture.SetPixelData<Color>(colors, 0);
|
|
Texture.Apply();
|
|
}
|
|
|
|
public float Error;
|
|
|
|
void LearnClass(bool zero) {
|
|
var agents = zero ? _class0Agents : _class1Agents;
|
|
|
|
var inLayer = Net.Layers[0];
|
|
var outLayer = Net.Layers[Net.Layers.Count - 1];
|
|
|
|
float expected0 = zero ? 1 : 0;
|
|
float expected1 = zero ? 0 : 1;
|
|
|
|
for (int i = 0; i < agents.Length; i++) {
|
|
|
|
var pos = agents[i].ImageSpacePositionNormalized;
|
|
inLayer.Values[0] = pos.x;
|
|
inLayer.Values[1] = pos.y;
|
|
|
|
Net.CalculateOutputs();
|
|
|
|
|
|
var e0 = expected0 - outLayer.Values[0];
|
|
var e1 = expected1 - outLayer.Values[1];
|
|
|
|
Error = Mathf.Sqrt(e0 * e0 + e1 * e1);
|
|
|
|
//if(i == 0)
|
|
// Debug.Log($"Error: {Error}");
|
|
|
|
outLayer.Errors[0] = e0;
|
|
outLayer.Errors[1] = e1;
|
|
|
|
Net.Learn(LearnRate);
|
|
|
|
}
|
|
}
|
|
}
|