/// <summary> /// Constructeur des données. Récupère les Chandeliers et les différents indicateurs. /// </summary> public Donnees(MonnaieBTC monnaie, String monnaieReference = "BTC", String interval = "1h", String limit = "500") { // Récupération de la monnaie. Monnaie = monnaie; MonnaieReference = monnaieReference; Interval = interval; Limit = limit; RecuperationMaxDonnees(); // Récupération de l'indicateur MA. MA = new IndicatorMA(this); // Récupération de l'indicateur MACD. MACD = new IndicatorMACD(this); // Récupération de l'indicateur DMI. DMI = new IndicatorDMI(this); // Récupération de l'indicateur BOLL. BOLL = new IndicatorBOLL(this); // Récupération de l'indicateur RSI. RSI = new IndicatorRSI(this); // Récupération de l'indicateur MTM. MTM = new IndicatorMTM(this); // Création du réseau de neurones. Neurone = new Neurone(this); }
/// <summary> /// Cacule la matrice des erreurs effectuées par le réseau sur le jeu de tests fournis /// </summary> /// <param name="tests">Jeu de tests</param> /// <param name="cibles">Cible pour chaque jeu de test</param> /// <returns> /// Matrice des erreurs contenant l'erreur commise par chaque neurone de la couche de sortie /// </returns> private double[] CalculerErreur(double[][] tests, double[] cibles) { Couche coucheSortie = Couches[Couches.Length - 1]; double[] erreurs = new double[coucheSortie.Neurones.Length]; for (int n = 0; n < coucheSortie.Neurones.Length; n++) { Neurone neurone = coucheSortie.Neurones[n]; double somme = 0.0; for (int i = 0; i < tests.Length; i++) { double sortie = neurone.CalculerSortie(tests[i]); double ecart = cibles[i] - sortie; // calcule l'erreur faite par le réseau lors de l'estimation de la cible // sur le neurone en cours de la dernière couche somme += ecart * ecart; } erreurs[n] = 0.5 * somme; } return(erreurs); }
private Neurone RechercherGagnant(double[] entree) { double distanceMin = double.MaxValue; Neurone gagnant = null; for (int n = 0; n < Grille.Length; n++) { Neurone neurone = Grille.GetValue(n) as Neurone; // pour chaque neurone on calcule sa distance euclidienne avec l'entrée double somme = 0.0; for (int i = 0; i < NbEntrees; i++) { double ecart = entree[i] - neurone.Poids[i]; somme += ecart * ecart; } double distance = Math.Sqrt(somme); if (distance < distanceMin) { distanceMin = distance; gagnant = neurone; } } return gagnant; }
public static void ChangeNeuroneValue(Neurone _neurone, double variable) { foreach (Liaison _liaison in _neurone.Liaisons) { _liaison.Variable = variable; } }
public ReseauNeural(int nbEntree, int nbSortie, int nbCouche) { Entree = new float[nbEntree]; Sortie = new float[nbSortie]; NeuroneSortie = new Neurone[nbSortie]; for (int i = 0; i < nbSortie; i++) { NeuroneSortie[i] = new Neurone(nbEntree); } if (nbCouche < 0) { nbCouche = 1; } NbNeuronneMax = nbEntree > nbSortie ? nbEntree : nbSortie; LesCoucheNeural = new Couche[nbCouche]; for (int i = 0; i < nbCouche; i++) { if (i == 0) { LesCoucheNeural[i] = new Couche(nbEntree, NbNeuronneMax); } else { LesCoucheNeural[i] = new Couche(NbNeuronneMax, NbNeuronneMax); } } }
/// <summary> /// Effectue une prédiction sur un modèle /// </summary> /// <param name="dataVector"></param> /// <returns>true si le vecteur d'entrée correspond au modèle pour lequel le réseau a été entraîné</returns> public override bool Predire(double[] dataVector) { Neurone neurone = Couches[0].Neurones[0]; double sortie = neurone.CalculerSortie(dataVector); return(sortie > Couches[0].Seuil); }
public static void CreateLiaison(Neurone _neurone, double variable) { if (_neurone.Liaisons == null) { _neurone.Liaisons = new List <Liaison>(); } _neurone.Liaisons.Add(new Liaison(variable, RandomHelper.GetRandomNumber())); }
public static void CreateLiaison(Neurone _neurone, Neurone _previousNeurone) { if (_neurone.Liaisons == null) { _neurone.Liaisons = new List <Liaison>(); } _neurone.Liaisons.Add(new Liaison(_previousNeurone, RandomHelper.GetRandomNumber())); }
public Couche(int nbEntrees, int nbSorties) { LesNeurones = new Neurone[nbSorties]; for (int i = 0; i < nbSorties; i++) { LesNeurones[i] = new Neurone(nbEntrees); } }
protected override void CreationCouche() { int IndexPoids; var rdm = new Random(); if (NombreNeurones > 0 || neurones != null) { neurones = null; NombreNeurones = 0; } if (NombrePoids > 0 || poids != null) { poids = null; NombrePoids = 0; } if (CouchePrecedente != null) { NombreNeurones = nombreFeatureMaps * featureMapSize.Width * featureMapSize.Height; neurones = new List <Neurone>(); poids = new List <Poids>(); for (int i = 0; i < NombreNeurones; i++) { String lb = String.Format("Layer {0}, Neuron {1}", Label, i); neurones.Add(new Neurone(lb)); } rdm = new Random(); NombrePoids = NombreNeurones * (CouchePrecedente.NombreNeurones + 1); for (int j = 0; j < NombrePoids; j++) { String lb = String.Format("Layer {0}, Poids {1}", Label, j); double initPoids = 0.05 * (2.0 * rdm.NextDouble() - 1.0); poids.Add(new Poids(lb, initPoids)); } IndexPoids = 0; for (int j = 0; j < NombreNeurones; j++) { Neurone n = neurones[j]; int connCount = CouchePrecedente.NombreNeurones + 1; n.nombreConnections = connCount; n.AddConnection((uint)0xffffffff, (uint)IndexPoids); // Biais for (int i = 0; i < CouchePrecedente.NombreNeurones; i++) { n.AddConnection((uint)i, (uint)IndexPoids++, (uint)i + 1); } } } }
public static void CalcErreurPreviousNeurones(Neurone _neurone) { foreach (Liaison _liaison in _neurone.Liaisons) { if (_liaison.PreviousNeurone != null) { _liaison.PreviousNeurone.Erreur = _neurone.Erreur * _liaison.Weight; } } }
/// <summary> /// Entraine le réseau /// </summary> /// <param name="maxIteration">Nombre d'itérations max</param> /// <param name="pas">Pas d'apprentissage</param> /// <param name="lettreCible">Lettre pour laquelle on entraîne le réseau</param> /// <param name="jeuEssai">Jeu d'essai pour entraîner le réseau</param> /// <param name="biais">Biais initial</param> /// <returns>L'erreur du réseau à la fin de son entraînement</returns> public double[] Entrainer(Dictionary <string, double[]> jeuEssai, string lettreCible, int maxIteration, double pas, double biais) { // on entraîne le réseau Neurone neurone = Couches[0].Neurones[0]; // un seul neurone dans le Perceptron double erreurCible = 0; double[] erreurCourante = new double[] { double.MaxValue }; int iteration = 0; // valeurs initiales neurone.Poids = new double[neurone.NbEntrees]; neurone.Biais = biais; while (iteration < maxIteration && erreurCourante[0] > erreurCible) { // pour chaque élément de test foreach (string lettre in jeuEssai.Keys) { // récupère le jeu d'entraînement courant double[] entraineur = jeuEssai[lettre]; // détermine si c'est la valeur cible (1) ou pas (-1) int valeurCible = (lettre == lettreCible) ? 1 : 0; // la fonction de transfert doit donc produire des -1 ou des 1 double sortie = neurone.CalculerSortie(entraineur); // de combien la sortie s'écarte de la cible double ecart = valeurCible - sortie; if (ecart != 0) { // réévalue le poids de chaque entrée (règle de RosenBlatt) for (int p = 0; p < neurone.NbEntrees; p++) { neurone.Poids[p] = neurone.Poids[p] + (pas * ecart * entraineur[p]); } // réévalue le biais // le biais est considéré comme une entrée supplémentaire avec un coefficient toujours égal à 1 neurone.Biais = neurone.Biais + (pas * ecart); } } ++iteration; Debug.WriteLine("Itération: " + iteration.ToString()); // on a un biais et un jeu de poids candidat // calcule l'erreur faite par le réseau dans l'estimation de notre jeu d'essai avec notre candidat double[][] tests = jeuEssai.Select(jeu => jeu.Value).ToArray(); double[] cibles = jeuEssai.Select(jeu => (jeu.Key == lettreCible) ? 1.0 : 0.0).ToArray(); double[][] c = jeuEssai.Select(jeu => cibles).ToArray(); erreurCourante = CalculerErreur(tests, cibles); } return(erreurCourante); }
/// <summary> /// Coloriage de l’image suivant les appartenances des pixels aux 6 classes /// </summary> private void Coloriage_Button_Click(object sender, EventArgs e) { List <Color> Couleurs = new List <Color> { Color.Red, Color.Blue, Color.Green, Color.Brown, Color.Orange, Color.Purple }; for (int i = 0; i < 800; i++) { for (int j = 0; j < 800; j++) { // Définition du neurone (= pixel) Neurone Pixel = new Neurone(2, 800); Pixel.ModifierPoids(i, j); // Modification du pixel en fonction du numéro de classe Image.SetPixel(i, j, Couleurs[RechercherClasse(Pixel)]); } } // Calcul du pourcentage de bonne classification et de mauvaise int BonneClassification = 0; int MauvaiseClassification = 0; for (int i = 0; i < 6; i++) { Neurone Observation = new Neurone(2, 800); Observation.ModifierPoids((int)Math.Floor(ObservationsTriees[i * 500].Ligne), (int)Math.Floor(ObservationsTriees[i * 500].Colonne)); int NumeroClasse = RechercherClasse(Observation); for (int j = 0; j < 500; j++) { Observation = new Neurone(2, 800); Observation.ModifierPoids((int)Math.Floor(ObservationsTriees[i * 500 + j].Ligne), (int)Math.Floor(ObservationsTriees[i * 500 + j].Colonne)); if (NumeroClasse != RechercherClasse(Observation)) { MauvaiseClassification++; } else { BonneClassification++; } } } // Affichage du résultat AfficherDonnees(); Resultat_PictureBox.Refresh(); MessageBox.Show("Pourcentage de bonne classification : " + Math.Round(BonneClassification / 3000.0, 2) + "\nPourcentage de mauvaise classification : " + Math.Round(MauvaiseClassification / 3000.0, 2), "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); }
/// <summary> /// Propagation des erreurs entre couche1 et couche2 sur les poids et les biais /// </summary> /// <param name="pas">Pas d'apprentissage</param> /// <param name="couche1"></param> /// <param name="couche2"></param> /// <remarks> /// couche1 => couche2 /// </remarks> private void Propager(Couche couche1, Couche couche2, double pas) { for (int c2 = 0; c2 < couche2.Neurones.Length; c2++) { Neurone neurone2 = couche2.Neurones[c2]; for (int c1 = 0; c1 < couche1.Neurones.Length; c1++) { neurone2.Poids[c1] += pas * neurone2.Erreur * couche1.Neurones[c1].Sortie; } neurone2.Biais += pas * neurone2.Erreur; } }
public void Init(int nbInput, int nbOutput, int nbLayers, int nbNeurones) { Debug.Log("Initialising Layers " + nbInput + " " + nbOutput + " " + nbLayers + " " + nbNeurones); input = gameObject.AddComponent <Layer>(); output = gameObject.AddComponent <Layer>(); input.Init(0, nbInput, 0, nbNeurones); output.Init(nbLayers - 1, nbOutput, nbNeurones, 0); layer = new Layer[nbLayers]; layer[0] = input; layer[nbLayers - 1] = output; Debug.Log("Building Layers"); for (int i = 1; i < nbLayers - 1; i++) { layer[i] = gameObject.AddComponent <Layer>(); if (i == 1) { layer[i].Init(i, nbNeurones, nbInput, nbNeurones); } else if (i == nbLayers - 2) { layer[i].Init(i, nbNeurones, nbNeurones, nbOutput); } else { layer[i].Init(i, nbNeurones, nbNeurones, nbNeurones); } } Debug.Log("Building Links"); for (int i = 0; i < nbLayers - 1; i++) { Layer l = layer[i]; Layer p = layer[i + 1]; for (int j = 0; j < l.neurones.Length; j++) { Neurone n = l.neurones[j]; for (int k = 0; k < p.neurones.Length; k++) { Debug.Log("create links for " + l.ToString() + " AND " + p.ToString()); Neurone m = p.neurones[k]; Link li = gameObject.AddComponent <Link>(); li.Init(n, m); Debug.Log("adding output link to " + n.ToString()); n.output[k] = li; Debug.Log("adding input link to " + m.ToString()); m.input[j] = li; } } } }
/// <summary> /// Calcule des erreurs (gradiant local) des neurones de la couche de sortie /// </summary> /// <param name="tests">Jeu de tests</param> /// <param name="cible">Cible (valeur désirée) pour chaque jeu de test</param> private void CalculerDeltaO(double[] cible) { Couche coucheSortie = Couches[Couches.Length - 1]; for (int k = 0; k < coucheSortie.Neurones.Length; k++) { Neurone neuroneO = coucheSortie.Neurones[k]; double ecart = 0.0; ecart = cible[k] - neuroneO.Sortie; neuroneO.Erreur = neuroneO.TransfertDerivee(neuroneO.Somme + neuroneO.Biais) * ecart; //Debug.WriteLine("Gradiant O: " + neuroneO.Erreur.ToString()); } }
/// <summary> /// /// </summary> /// <param name="entree"></param> public void Entrainer(double[] entree,int iteration) { // recherche du meilleur neurone Neurone gagnant = RechercherGagnant(entree); // récupère le voisinage du gagnant CalculerRayon(gagnant, iteration, 100); }
private void CalculerRayon(Neurone neuroneCible,int totalIteration, int iterationCourante) { // on commence par calculer le rayon double lambda = totalIteration / Math.Log(RayonCarte); double rayon = RayonCarte * Math.Exp(-1 * iterationCourante / lambda); // on recherche les neurones présents dans le rayon // leurs poids seront ajustés foreach (Neurone neurone in Grille) { } }
public static void UpdateWeights(Neurone _neurone) { foreach (Liaison _liaison in _neurone.Liaisons) { if (_liaison.PreviousNeurone != null) { _liaison.Weight = _liaison.Weight + NetworkConstants.ConstApprentissage * _neurone.Erreur * _neurone.Sortie * (1 - _neurone.Sortie) * _liaison.PreviousNeurone.Sortie; } else { _liaison.Weight = _liaison.Weight + NetworkConstants.ConstApprentissage * _neurone.Erreur * _neurone.Sortie * (1 - _neurone.Sortie) * _liaison.Variable; } } _neurone.WeightBiais = _neurone.WeightBiais + NetworkConstants.ConstApprentissage * _neurone.Erreur * _neurone.Sortie * (1 - _neurone.Sortie) * _neurone.Biais; }
/// <summary> /// Calcule de l'erreur (gradiant local) des neurones des couches cachées /// </summary> /// <param name="couche1">Couche cachée N</param> /// <param name="couche2">Couche N + 1</param> /// <returns></returns> private void CalculerDeltaH(Couche couche1, Couche couche2) { for (int k = 0; k < couche1.Neurones.Length; k++) { Neurone neuroneH = couche1.Neurones[k]; double somme = 0.0; for (int i = 0; i < couche2.Neurones.Length; i++) { Neurone neurone2 = couche2.Neurones[i]; somme += neurone2.Poids[k] * neurone2.Erreur; } neuroneH.Erreur = neuroneH.TransfertDerivee(neuroneH.Somme + neuroneH.Biais) * somme; //Debug.WriteLine("Gradiant H: " + neuroneH.Erreur.ToString()); } }
private static double SommePonderee(Neurone _neurone) { double somme = 0; foreach (Liaison liaison in _neurone.Liaisons) { if (liaison.PreviousNeurone != null) { somme += liaison.PreviousNeurone.Sortie * liaison.Weight; } else { somme += liaison.Variable * liaison.Weight; } } somme += _neurone.Biais * _neurone.WeightBiais; return(somme); }
private void Initialiser(int nbEntrees, int x, int y) { Grille = new Neurone[x, y]; Random rnd = new Random(); for (int i = 0; i < Grille.Length; i++) { Neurone neurone = new Neurone(nbEntrees, null); for (int p = 0; p < neurone.Poids.Length; p++) { neurone.Poids[p] = rnd.NextDouble(); } } // rayon du réseau RayonCarte = 0.5 * Math.Max(x, y); }
/// <summary> /// Evaluer une entrée fournie par le réseau /// </summary> /// <param name="jeuEssai"></param> public void Calculer(double[] jeuEssai) { // on en fait une copie locale double[] entraineur = new double[jeuEssai.Length]; Array.Copy(jeuEssai, entraineur, jeuEssai.Length); // première dimension: une valeur par neurone de la couche // deuxième dimension: le vecteur des entrées appliquée au neurone double[][] testeurs = new double[Couches[0].Neurones.Length][]; for (int i = 0; i < Couches[0].Neurones.Length; i++) { testeurs[i] = new double[] { entraineur[i] }; } foreach (Couche couche in Couches) { if (testeurs == null) { // on réamorce la boucle de calcul testeurs = new double[couche.Neurones.Length][]; for (int i = 0; i < couche.Neurones.Length; i++) { // les neurones de chaque couche interne reçoivent le même jeu d'entrée contrairement aux neurones de la couche d'entrée testeurs[i] = entraineur; } } for (int n = 0; n < couche.Neurones.Length; n++) { Neurone neurone = couche.Neurones[n]; neurone.CalculerSortie(testeurs[n]); } // on récupère les sorties des neurones de la couche courante entraineur = new double[couche.Neurones.Length]; for (int i = 0; i < couche.Neurones.Length; i++) { Neurone neurone = couche.Neurones[i]; entraineur[i] = neurone.Sortie; } testeurs = null; } }
public void Init(Neurone n, Neurone m) { inNeurone = n; outNeurone = m; weight = Random.Range(-1.0f, 1.0f); Debug.Log("Weight=" + weight); GameObject obj = new GameObject("line"); LineRenderer lineRenderer = obj.AddComponent <LineRenderer>(); lineRenderer.material = Resources.Load("Unlit/Link") as Material;// new Material(Shader.Find("Particles/Additive")); //Debug.Log("Material " + lineRenderer.material.ToString()); lineRenderer.widthMultiplier = 0.01f; lineRenderer.positionCount = 2; // A simple 2 color gradient with a fixed alpha of 1.0f. Color c1 = Color.yellow; Color c2 = Color.red; /* float alpha = 1.0f; * Gradient gradient = new Gradient(); * gradient.SetKeys( * new GradientColorKey[] { * new GradientColorKey(c1, 0.0f), * new GradientColorKey(c2, 1.0f), * // new GradientColorKey(Color.HSVToRGB(180.0f, weight * 1.0f, 1.0f), 0.0f), * // new GradientColorKey(Color.HSVToRGB(0.0f, weight * 1.0f, 1.0f), 1.0f) * }, * new GradientAlphaKey[] { * new GradientAlphaKey(alpha, 0.0f), * new GradientAlphaKey(alpha, 1.0f) * } * ); * lineRenderer.colorGradient = gradient;*/ //Debug.Log("ColorGradient = " + lineRenderer.colorGradient.ToString()); lineRenderer.material.color = Color.HSVToRGB(0.0f, weight, 1.0f); lineRenderer.SetPosition(0, new Vector3(inNeurone.GetPosx(), inNeurone.GetPosy(), 0.0f)); lineRenderer.SetPosition(1, new Vector3(outNeurone.GetPosx(), outNeurone.GetPosy(), 0.0f)); }
/// <summary> /// Sauvegarde un réseau de Kohonen 2D dans un bitmap /// </summary> /// <param name="name">Nom du fichier sans extension ni chemin</param> public string ToBitmap(string name) { int X = Grille.GetLength(0); int Y = Grille.GetLength(1); Bitmap bitMap = new Bitmap(X, Y); for (int x = 0; x < X; x++) { for (int y = 0; y < Y; y++) { Neurone neurone = Grille[x, y]; Color couleur = Color.FromArgb((int)neurone.Poids[0], (int)neurone.Poids[1], (int)neurone.Poids[2]); bitMap.SetPixel(x, y, couleur); } } string modele = @"c:\temp\{0}.bmp"; string fichier = string.Format(modele, name); bitMap.Save(fichier); return fichier; }
/// <summary> /// Recherche à quelle classe appartient un neurone donné /// </summary> /// <param name="Neurone">Neurone dont on cherche la classe</param> /// <returns>Numéro de la classe à laquelle appartient le neurone</returns> private int RechercherClasse(Neurone Neurone) { // Recherche de la classe gagnante int NumeroClasseGagnante = 0; double DistanceMin = Neurone.CalculerDistance(Classes[0].ListeNeurones[0]); // On recherche le neurone qui a la plus faible distance du pixel // dans chacune des 6 classes. La classe gagnante est celle à laquelle // appartient le neurone ayant la plus faible distance avec le pixel for (int k = 0; k < Classes.Count; k++) { for (int l = 0; l < Classes[k].ListeNeurones.Count; l++) { if (DistanceMin > Neurone.CalculerDistance(Classes[k].ListeNeurones[l])) { DistanceMin = Neurone.CalculerDistance(Classes[k].ListeNeurones[l]); NumeroClasseGagnante = k; } } } // Renvoi du numéro de la classe gagnante return(NumeroClasseGagnante); }
protected override void CreationCouche() { int IndexPoids; var rdm = new Random(); if (NombreNeurones > 0 || neurones != null) { neurones = null; NombreNeurones = 0; } if (NombrePoids > 0 || poids != null) { poids = null; NombrePoids = 0; } neurones = new List <Neurone>(); poids = new List <Poids>(); if (CouchePrecedente != null) { NombreNeurones = nombreFeatureMaps * featureMapSize.Width * featureMapSize.Height; NombrePoids = nombreFeatureMaps * (kernelsize * kernelsize * CouchePrecedente.nombreFeatureMaps + 1); for (int i = 0; i < NombreNeurones; i++) { String lb = String.Format("Layer {0} , Neuron {1}", Label, i); neurones.Add(new Neurone(lb)); } rdm = new Random(); for (int j = 0; j < NombrePoids; j++) { String lb = String.Format("Layer {0}, Poids {1}", Label, j); double initPoids = 0.05 * (2.0 * rdm.NextDouble() - 1.0); poids.Add(new Poids(lb, initPoids)); } int[] kernelTemplate = CreateKernelTemplate(kernelsize, CouchePrecedente.featureMapSize.Width); for (int indexFeatureMap = 0; indexFeatureMap < nombreFeatureMaps; indexFeatureMap++) { for (int hauteur = 0; hauteur < featureMapSize.Height; hauteur++) { for (int largeur = 0; largeur < featureMapSize.Width; largeur++) { IndexPoids = indexFeatureMap * ((int)Math.Pow(kernelsize, 2) * CouchePrecedente.nombreFeatureMaps + 1); Neurone n = neurones[largeur + hauteur * featureMapSize.Width + indexFeatureMap * featureMapSize.Width * featureMapSize.Height]; int nombreConnection = ((kernelsize * kernelsize * CouchePrecedente.nombreFeatureMaps) + 1); n.nombreConnections = nombreConnection; // 26 connections n.AddConnection((uint)0xffffffff, (uint)IndexPoids); // Biais for (int k = 0; k < kernelsize * kernelsize; k++) { for (int l = 0; l < CouchePrecedente.nombreFeatureMaps; l++) { int iNeurons = (2 * largeur + (2 * hauteur * CouchePrecedente.featureMapSize.Width) + kernelTemplate[k] + l * CouchePrecedente.featureMapSize.Width * CouchePrecedente.featureMapSize.Height); int connID = 1 + l + k * CouchePrecedente.nombreFeatureMaps; n.AddConnection((uint)iNeurons, (uint)IndexPoids++, (uint)connID); // n.AddConnection((uint)iNeurons, (uint)IndexPoids++, connID); } } } } } } }
public static void CalcErreurLastNeurone(Neurone _neurone) { _neurone.Erreur = NetworkConstants.SortieSouhaitee - _neurone.Sortie; }
public static void CalcSortieNeurone(Neurone _neurone) { double sommePonderee = SommePonderee(_neurone); _neurone.Sortie = Sigmoide(sommePonderee); }
/// <summary> /// Checks that the neural network data is consistent with its size. /// Note: only happens in-engine; no checking in production builds. /// </summary> public void CheckNetwork() { #if UNITY_EDITOR if (inputLayerSize <= 0 || hiddenLayerSize <= 0 || outputLayerSize <= 0) { Debug.LogError("Neural network has layer size <= 0. This will result in a runtime error."); } bool ok = true; //flag will be set to false if anything was wrong with the network if (inputLayer == null || inputLayer.Length != inputLayerSize) { inputLayer = new float[inputLayerSize]; ok = false; } //Check both layers for identical neurones if (hiddenLayer != null && outputLayer != null) { foreach (Neurone a in hiddenLayer) { foreach (Neurone b in outputLayer) { if (a == b) { Debug.LogError("Error: Same neurone in both layers!"); return; } } } } //Do we have the correct amount of neurones in the hidden layer? if (hiddenLayer == null || hiddenLayer.Length != hiddenLayerSize) { hiddenLayer = new Neurone[hiddenLayerSize]; for (int j = 0; j < hiddenLayerSize; ++j) { hiddenLayer[j] = new Neurone(); } ok = false; } //Do neurones in the hidden layer have the correct amount of weights? for (int j = 0; j < hiddenLayerSize; ++j) { if (hiddenLayer[j].weights == null || hiddenLayer[j].weights.Length != inputLayerSize + 1) { hiddenLayer[j].weights = new float[inputLayerSize + 1]; //assign random weights for (int i = 0; i < inputLayerSize + 1; ++i) { hiddenLayer[j].weights[i] = UnityEngine.Random.Range(-1.0f, 1.0f); } ok = false; } } //Do we have the correct amount of neurones in the output layer? if (outputLayer == null || outputLayer.Length != outputLayerSize) { outputLayer = new Neurone[outputLayerSize]; for (int k = 0; k < outputLayerSize; ++k) { outputLayer[k] = new Neurone(); } ok = false; } //Do neurones in the output layer have the correct amount of weights? for (int k = 0; k < outputLayerSize; ++k) { if (outputLayer[k].weights == null || outputLayer[k].weights.Length != hiddenLayerSize + 1) { outputLayer[k].weights = new float[hiddenLayerSize + 1]; //assign random weights for (int j = 0; j < hiddenLayerSize + 1; ++j) { outputLayer[k].weights[j] = UnityEngine.Random.Range(-1.0f, 1.0f); } ok = false; } } if (!ok) { Debug.LogWarning("Refreshed Neural Network " + name + "."); save(); } #endif }