public override void LearnUnits() { //I should probably make this a float array. //I'm not sure what kind of memory restrictions we're looking at. //This list of arrays is going to be reclaimed after the method finishes, as is the trainingSet List <double[]> features = new List <double[]> (); int featureLength = -1; //Gets the relevant data out of the training set foreach (PhantomUnit u in trainingSet) { Texture tex = u.tex; if (tex is Texture2D) { Texture2D tex2D = (Texture2D)tex; Color[] pixels = tex2D.GetPixels(); if (featureLength == -1) { featureLength = pixels.Length * 3; unitWidth = tex2D.width; unitHeight = tex2D.height; } //I don't actually check that the width and height are correct, just that width*height is correct. I'm going to assume it'll work out. if (pixels.Length * 3 == featureLength) { //This is really IMPORTANT. //The last spot in unit features is reserved for the unit identity (0 for Enemy, 1 for Ally) //Don't iterate over unitFeatures or its full length. double[] unitFeatures = new double[featureLength + 1]; //Assigns the pixel values for each of the colors in the pattern {r,g,b,r,g,b,...) for (int i = 0; i < pixels.Length; i++) { Color c = pixels [i]; unitFeatures [3 * i] = c.r; unitFeatures [3 * i + 1] = c.g; unitFeatures [3 * i + 2] = c.b; } unitFeatures [featureLength] = u.identity; features.Add(unitFeatures); } else { Debug.Log("Unit has incorrect dimensions to be analyzed: " + u.ToString()); } } else if (tex is RenderTexture) { RenderTexture texRend = (RenderTexture)tex; Debug.Log("This is a RenderTexture"); //I don't have the code to get the pixels for this yet } else { Debug.Log("I'm not sure what Texture this is or what to do with it."); } } //for weights = new double[featureLength]; b = 0; for (int it = 0; it < iters; it++) { itersUsed = it + 1; int misses = 0; //Shuffles the feature list NeuralNode.Shuffle(features); foreach (double[] fs in features) { int trueIdentity = (int)Mathf.Round((float)fs [featureLength]); int f = (int)Unit.ALLY_IDENTITY; if (calculateZ(fs) < 0) { f = (int)Unit.ENEMY_IDENTITY; } misses += Mathf.Abs(f - trueIdentity); for (int i = 0; i < featureLength; i++) { weights [i] = weights [i] + learningRate * fs[i] * (trueIdentity - f); } b = b + learningRate * (trueIdentity - f); } //for each of the feature arrays if (misses == 0) { break; } } //for iterations actualWeights = new double[weights.Length]; System.Array.Copy(weights, actualWeights, weights.Length); actualB = b; SetNonzeroIndices(); //Notice that I am clearing out the training set here. //Keeping the references is not necessary and will just take up space. //Being able to get rid of them is sort of the point of making a model. foreach (PhantomUnit u in trainingSet) { Destroy(u); } trainingSet.Clear(); isAILearned = true; }