AIプログラムとかUnityゲーム開発について

探索や学習などを活用したAI系ゲームを作りたいと思います。

.netのC#コンパイラーでXORの学習

しつこく、chatGPTにXORの学習のC#コードをお願いして(聞くたびに違うプログラムを吐くのが凄いw)、やっと動くコードができた。
Unityじゃなくて、Windowsの.NetFrameworkのC#コンパイラーのコンソールアプリでやってみたけど。
XORだけじゃなくて、ANDやORもちゃんと学習出来た
sigmoid dSigmoidを ReLU dReLUに変えても学習出来た
入力を3入力のXORにしても学習出来たので、大丈夫っぽい
これをUnity上で動かせるようにすれば、ゲーム上で、自前でなにか学習できるかも
フレームワークを使うとメモリーとかもかなり食いそうなんで、スマホゲームは自前でやってみてもいいかなと

using System;

namespace NeuralNetwork
{
    class Program
    {
        static void Main(string[] args)
        {
          // ニューラルネットワークの作成
            int[] layerSizes = { 2, 4, 1 };
            NeuralNetwork nn = new NeuralNetwork(layerSizes);

	        double[][] inputs =
	         {
	            new double[] { 0, 0 },
	            new double[] { 0, 1 },
	            new double[] { 1, 0 },
	            new double[] { 1, 1 }
	        };
	        double[][] targets =
	        {
	            new double[] { 0 },
	            new double[] { 1 },
	            new double[] { 1 },
	            new double[] { 0 }
	        };

          // 学習
            nn.Train(inputs, targets, 10000, 0.1);
            
        }
    }

    class NeuralNetwork
    {
        private int[] layerSizes;
        private double[][] activations;
		private double[][] outputs;
        private double[][][] weights;
        private double[][] biases;
        private Random rand = new Random();

        public NeuralNetwork( int[] layerSizes)
        {
            this.layerSizes = layerSizes;
			activations = new double[layerSizes.Length][];
            outputs = new double[layerSizes.Length][];
            weights = new double[layerSizes.Length - 1][][];
            biases = new double[layerSizes.Length - 1][];
            for (int l = 0; l < layerSizes.Length; l++)
            {
                activations[l] = new double[layerSizes[l]];
                outputs[l] = new double[layerSizes[l]];
                if( l > 0)
                {
                    weights[l-1] = new double[layerSizes[l]][];
                    biases[l-1] = new double[layerSizes[l]];
                    for (int i = 0; i < layerSizes[l]; i++)
                    {
                        weights[l - 1][i] = new double[layerSizes[l-1]];
                        for (int j = 0; j < layerSizes[l - 1]; j++)
                        {
                            weights[l - 1][i][j] = rand.NextDouble() * 2 - 1;
                        }
                        biases[l - 1][i] = rand.NextDouble() * 2 - 1;	                        
                    }
	            }
            }
        }

        public double sigmoid(double x)
        {
			return 1.0 / ( 1.0 +Math.Exp(-x) );
        }
        public double dSigmoid(double x)
        {
            return x * (1.0 - x);
        }

        public double ReLU(double x)
        {
			return  Math.Max(0,x) ;
        }
        public double dReLU(double x)
        {
            return x >0 ? 1 : 0;
        }

        public double[] FeedForward(double[] input)
        {
            for (int i = 0; i < layerSizes[0]; i++)
            {
                activations[0][i] = input[i];
                outputs[0][i] = input[i];
            }

	        // 順伝播
	        for (int l = 1; l < layerSizes.Length; l++)
	        {
	            for (int i = 0; i < layerSizes[l]; i++)
	            {
	                double sum = biases[l - 1][i];
	                for (int j = 0; j < layerSizes[l - 1]; j++)
	                {
	                    sum += weights[l - 1][i][j] * outputs[l - 1][j];
	                }
	                activations[l][i] = sum;
	                outputs[l][i] = sigmoid(sum);
	            }
            }
	        // 出力を返す
    		return outputs[layerSizes.Length - 1];
        }


	    private void BackPropagation(double[] target, double learningRate)
	    {
	        // 出力層の誤差を計算
	        for (int i = 0; i < layerSizes[layerSizes.Length - 1]; i++)
	        {
	            double output = outputs[layerSizes.Length - 1][i];
	            double error = target[i] - output;
	            double derivative = dSigmoid( output );
	            activations[layerSizes.Length - 1][i] = error * derivative;
	        }
	
	        // 逆伝播
	        for (int l = layerSizes.Length - 2; l >= 1; l--)
	        {
	            for (int i = 0; i < layerSizes[l]; i++)
	            {
	                double output = outputs[l][i];
	                double derivative = dSigmoid( output );
	                double sum = 0;
	                for (int j = 0; j < layerSizes[l + 1]; j++)
	                {
	                    sum += activations[l + 1][j] * weights[l][j][i];
	                }
	                activations[l][i] = sum * derivative;
	            }
	        }
	
	        // 重みとバイアスの更新
	        for (int l = 0; l < layerSizes.Length - 1; l++)
	        {
	            for (int i = 0; i < layerSizes[l + 1]; i++)
	            {
	                for (int j = 0; j < layerSizes[l]; j++)
	                {
	                    double output = outputs[l][j];
	                    double delta = learningRate * activations[l + 1][i] * output;
	                    weights[l][i][j] += delta;
	                }
	                biases[l][i] += learningRate * activations[l + 1][i];
	            }
	        }
	    }
	
	    // 学習
	    public void Train(double[][] inputs, double[][] targets, int iterations, double learningRate)
	    {
	        for (int i = 0; i < iterations; i++)
	        {
	            for (int j = 0; j < inputs.Length; j++)
	            {
	                double[] output = FeedForward(inputs[j]);
	                BackPropagation(targets[j], learningRate);
	            }

	           // テスト
				if( (i%1000) == 0)
				{
		            String str = "";
		            for (int j = 0; j < 4; j++)
		            {
		                str += inputs[j][0]+"x"+inputs[j][1]+" = "+FeedForward(inputs[j])[0]+", ";
		            }

		            Console.WriteLine( "#"+i+" " + str);
				}
	        }
	    }
    }
}