This commit is contained in:
2025-05-13 02:53:08 +03:00
parent 581ede2f41
commit 785fbedeeb
44 changed files with 5906 additions and 0 deletions
+38
View File
@@ -0,0 +1,38 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Agent : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
}
public Vector2 ImageSpacePosition {
get {
var thisTransform = GetComponent<RectTransform>();
return new Vector3(thisTransform.anchoredPosition.x, -thisTransform.anchoredPosition.y);
}
}
public Vector2 ImageSpacePositionNormalized {
get {
var localPos = ImageSpacePosition;
var parentTransform = transform.parent.GetComponent<RectTransform>();
var parentSize = parentTransform.rect.size;
return new Vector2(localPos.x / parentSize.x, localPos.y / parentSize.y);
}
}
// Update is called once per frame
void Update()
{
if (transform.hasChanged) {
Debug.Log(ImageSpacePositionNormalized);
transform.hasChanged = false;
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 7702dc5fe2d825345aa9e1fad9aa9f0b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+174
View File
@@ -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()
{
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fad4601af2d840146a88aefa97c2947a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+145
View File
@@ -0,0 +1,145 @@
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);
}
}
}
+11
View File
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e6015504cae23b14398f2ee5705f952a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 6ea315d0fd7389c41b19996891e99ae3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
File diff suppressed because it is too large Load Diff
+7
View File
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9fc0d4010bbf28b4594072e72b8655ab
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
+80
View File
@@ -0,0 +1,80 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TextureView
m_Shader: {fileID: 4800000, guid: b86c37b293849804e88fd1a08722b27e, type: 3}
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
+8
View File
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 4a532ce263722b948ac9761044f13463
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:
+58
View File
@@ -0,0 +1,58 @@
Shader "Unlit/TextureView"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
}
SubShader
{
Tags { "RenderType"="Opaque" }
LOD 100
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
// make fog work
#pragma multi_compile_fog
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
UNITY_TRANSFER_FOG(o,o.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
// sample the texture
fixed4 col = tex2D(_MainTex, i.uv);
// apply fog
UNITY_APPLY_FOG(i.fogCoord, col);
return col;
}
ENDCG
}
}
}
+10
View File
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: b86c37b293849804e88fd1a08722b27e
ShaderImporter:
externalObjects: {}
defaultTextures: []
nonModifiableTextures: []
preprocessorOverride: 0
userData:
assetBundleName:
assetBundleVariant: