Esempio n. 1
0
        public override void Learning(double[] args, double[] expectedRes)
        {
            if ((args.Length != NeuronsNetwork[0].Length) ||
                expectedRes.Length != NeuronsNetwork[NeuronsNetwork.Length - 1].Length)
            {
                throw new ArgumentException("Количество входных данных не соответсвует размеру (выходного слоя + ожидаемых результатов)");
            }

            GetResult(args);

            if (WriteLog)
            {
                Outputter.Log("Обучение...");
            }
            Task.Run(() =>
            {
                Parallel.ForEach(NeuronsNetwork[NeuronsNetwork.Length - 1], outputNeuron =>
                {
                    outputNeuron.RecieveErrorSigmoid(null, LearningNorm, InertialTerm,
                                                     expectedRes[(outputNeuron as OutputNeuron).NeuronId]);
                }
                                 );
            }
                     ).Wait();
            if (WriteLog)
            {
                Outputter.Log("Обучение завершено.");
            }
        }
        public virtual void RecieveErrorSigmoid(Neuron errorNeuron,
                                                double learningNorm, double inertialTerm, double?expectedValue = null)
        {
            Interlocked.Exchange(ref ErrorSummary, ErrorSummary + errorNeuron.ErrorSummary);
            Interlocked.Decrement(ref ErrorsLeft);

            if (ErrorsLeft == 0)
            {
                ErrorSummary = Value * (1 - Value) * ErrorSummary * NextNeurons[errorNeuron];

                if (WriteLog)
                {
                    Outputter.Log($"Вес {NeuronName} - {errorNeuron.NeuronName} изменён {NextNeurons[errorNeuron]} - ");
                }

                errorNeuron.LastNeurons[this] = NextNeurons[errorNeuron] = NextNeurons[errorNeuron] * inertialTerm
                                                                           + learningNorm * Value * errorNeuron.ErrorSummary;

                if (WriteLog)
                {
                    Outputter.Log($"{NextNeurons[errorNeuron]}");
                }

                if (LastNeurons.Count != 0)
                {
                    for (int i = 0; i < LastNeurons.Keys.Count; i++)
                    {
                        LastNeurons.Keys.ElementAt(i).RecieveErrorSigmoid(this, learningNorm, inertialTerm);
                    }
                }
            }
        }
 public override void SendSignal(Network.ActivateFunction activFunc)
 {
     Parallel.ForEach(NextNeurons, nextNeuron =>
     {
         nextNeuron.Key.RecieveSignal(nextNeuron.Value * Value, activFunc);
         if (WriteLog)
         {
             Outputter.Log($"Сигнал {NeuronName} - {nextNeuron.Key.NeuronName} отправлен = {nextNeuron.Value * Value}");
         }
     });
 }
        public double[] GetResult(params double[] args)
        {
            ClearNeurons();

            if (args.Length != NeuronsNetwork[0].Length)
            {
                throw new ArgumentException("Количество входных данных не соответсвует размеру входного слоя.");
            }

            if (WriteLog)
            {
                Outputter.Log($"Входные данные: ");
            }

            for (int i = 0; i < args.Length; i++)
            {
                if (WriteLog)
                {
                    Outputter.Log($"{NeuronsNetwork[0][i].NeuronName} = {args[i]}");
                }
            }
            Task.Run(() =>
            {
                Parallel.ForEach(NeuronsNetwork[0], inputNeuron =>
                {
                    inputNeuron.RecieveSignal(args[(inputNeuron as InputNeuron).NeuronId], NetFunctions.ActivateFunc);
                }
                                 );
            }
                     ).Wait();

            Task.Run(() =>
            {
                for (int i = 1; i < NeuronsNetwork.Length - 1; i++)
                {
                    Parallel.ForEach(NeuronsNetwork[i].Where(t => t.GetRemainingSignals() == 0), hiddenNeuron =>
                    {
                        hiddenNeuron.SendSignal(NetFunctions.ActivateFunc);
                    }
                                     );
                }
            }
                     ).Wait();

            double[] result = new double[NeuronsNetwork[NeuronsNetwork.Length - 1].Length];
            for (int i = 0; i < result.Length; i++)
            {
                result[i] = NeuronsNetwork[NeuronsNetwork.Length - 1][i].GetValue();
            }
            return(result);
        }
 public virtual void AddLastNeuron(Neuron neuron, double weight)
 {
     if (LastNeurons.ContainsKey(neuron))
     {
         if (WriteLog)
         {
             Outputter.Warning($"Нейроны {NeuronName} и {neuron.NeuronName} уже обьединены обратной связью.");
         }
     }
     else
     {
         LastNeurons.Add(neuron, weight);
     }
 }
        public virtual void SendSignal(Network.ActivateFunction activFunc)
        {
            Parallel.ForEach(NextNeurons, nextNeuron =>
            {
                double res = activFunc(Value);
                nextNeuron.Key.RecieveSignal(res * nextNeuron.Value, activFunc);
                if (WriteLog)
                {
                    Outputter.Log($"Сигнал {NeuronName} - {nextNeuron.Key.NeuronName} отправлен = {Value} * {nextNeuron.Value} -> {res} * {nextNeuron.Value}");
                }

                Value = res;
            }
                             );
        }
        public virtual void AddNextNeuron(Neuron neuron, double?weight = null)
        {
            if (NextNeurons.ContainsKey(neuron))
            {
                if (WriteLog)
                {
                    Outputter.Warning($"Нейроны {NeuronName} и {neuron.NeuronName} уже обьединены прямой связью.");
                }
            }

            else
            {
                Random rand = new Random();
                weight = weight == null?rand.NextDouble() : weight;

                NextNeurons.Add(neuron, weight.Value);
                neuron.AddLastNeuron(this, weight.Value);
                neuron.AdmissionsLeft = ++neuron.MaxAdmissionsLeft;
            }
        }
        public override void AsOffset()
        {
            IsOffset          = true;
            NeuronName       += " (OFFSET)";
            MaxAdmissionsLeft = AdmissionsLeft = 0;
            Value             = 1;

            if (LastNeurons.Keys.Count != 0)
            {
                if (WriteLog)
                {
                    Outputter.Warning($"При изменении свойства IsOffset нейрон {NeuronName} потерял связи с" +
                                      $" {LastNeurons.Keys.Count} нейронами!");
                }
            }

            while (LastNeurons.Keys.Count != 0)
            {
                LastNeurons.ElementAt(0).Key.RemoveNextNeuron(this);
                LastNeurons.Remove(LastNeurons.ElementAt(0).Key);
            }
        }