开源AI系统AForge.NET学习:进化神经网络训练过程解析

进化神经网络用户调用层面样例:

            //选择训练算法
            var teacher = new EvolutionaryLearning(
                network,    //神经网络
                100,        //初始种群的数量
                fitnessFunction    //适应度函数
                );

            //进行训练
            for (int i = 0; i < 10000; i++)
            {
                var error=teacher.RunEpoch( );
                var fitness = 1 / error;
                Console.WriteLine($"迭代:{i};fitness:{fitness}");
            }
View Code

主要分为两个步骤,先生成进化学习对象(EvolutionaryLearning),再调用此对象的RunEpoch方法。

EvolutionaryLearning构造函数:保存了相关对象,比如:network、populationSize、fitnessFunction,同时计算了numberOfNetworksWeights,用于后续计算基因长度。

public EvolutionaryLearning( ActivationNetwork activationNetwork, int populationSize,IFitnessFunction fitnessFunction)
        {
            // Check of assumptions during debugging only
            Debug.Assert( activationNetwork != null );
            Debug.Assert( populationSize > 0 );

            // networks's parameters
            this.network = activationNetwork;
            this.numberOfNetworksWeights = CalculateNetworkSize( activationNetwork );

            // population parameters
            this.populationSize = populationSize;
            this.chromosomeGenerator = new UniformGenerator( new Range( -1, 1 ) );
            this.mutationMultiplierGenerator = new ExponentialGenerator( 1 );
            this.mutationAdditionGenerator = new UniformGenerator( new Range( -0.5f, 0.5f ) );
            
            //下面是我修改,修改为轮盘赌选择算法
            //this.selectionMethod = new EliteSelection( );
            this.selectionMethod=new RouletteWheelSelection();
            
            this.crossOverRate = 0.75;
            this.mutationRate = 0.25;
            this.randomSelectionRate = 0.2;
            
            //适应度函数
            this.fitnessFunction=fitnessFunction;
        }
View Code

EvolutionaryLearning.RunEpoch方法:先生成种群对象(Population),再调用种群对象的RunEpoch方法,然后用最好的基因计算适应度,其倒数作为偏差率返回。

public double RunEpoch( double[][] input, double[][] output )
        {
            //Debug.Assert( input.Length > 0 );
            //Debug.Assert( output.Length > 0 );
            //Debug.Assert( input.Length == output.Length );
            //Debug.Assert( network.InputsCount == input.Length );

            // check if it is a first run and create population if so
            if ( population == null )
            {
                // sample chromosome
                DoubleArrayChromosome chromosomeExample = new DoubleArrayChromosome(
                    chromosomeGenerator, mutationMultiplierGenerator, mutationAdditionGenerator,
                    numberOfNetworksWeights );

                // create population ...
                population = new Population( populationSize, chromosomeExample,
                    this.fitnessFunction, selectionMethod );
                // ... and configure it
                population.CrossoverRate = crossOverRate;
                population.MutationRate = mutationRate;
                population.RandomSelectionPortion = randomSelectionRate;
            }

            // run genetic epoch
            population.RunEpoch( );

            // get best chromosome of the population
            DoubleArrayChromosome chromosome = (DoubleArrayChromosome) population.BestChromosome;
            double[] chromosomeGenes = chromosome.Value;

            // put best chromosome's value into neural network's weights
            int v = 0;

            for ( int i = 0; i < network.Layers.Length; i++ )
            {
                Layer layer = network.Layers[i];

                for ( int j = 0; j < layer.Neurons.Length; j++ )
                {
                    ActivationNeuron neuron = layer.Neurons[j] as ActivationNeuron;

                    for ( int k = 0; k < neuron.Weights.Length; k++ )
                    {
                        neuron.Weights[k] = chromosomeGenes[v++];
                    }
                    neuron.Threshold = chromosomeGenes[v++];
                }
            }

            Debug.Assert( v == numberOfNetworksWeights );

            return 1.0 / chromosome.Fitness;
        }
View Code

生成种群对象过程:先生成一个样板基因(DoubleArrayChromosome),此样板基因的数据是随机的。然后调用种群对象构造函数,在种群对象构造函数中,主要是靠样板基因产生种群群体,在初始化的时候,种群群体全部是随机。

        public DoubleArrayChromosome(
            IRandomNumberGenerator chromosomeGenerator,
            IRandomNumberGenerator mutationMultiplierGenerator,
            IRandomNumberGenerator mutationAdditionGenerator,
            int length )
        {

            // save parameters
            this.chromosomeGenerator = chromosomeGenerator;
            this.mutationMultiplierGenerator = mutationMultiplierGenerator;
            this.mutationAdditionGenerator = mutationAdditionGenerator;
            this.length = Math.Max( 2, Math.Min( MaxLength, length ) ); ;

            // allocate array
            val = new double[length];

            // generate random chromosome
            Generate( );
        }
View Code
        public Population( int size,
                           IChromosome ancestor,
                           IFitnessFunction fitnessFunction,
                           ISelectionMethod selectionMethod )
        {
            if ( size < 2 )
                throw new ArgumentException( "Too small population's size was specified." );

            this.fitnessFunction = fitnessFunction;
            this.selectionMethod = selectionMethod;
            this.size = size;

            // add ancestor to the population
            ancestor.Evaluate( fitnessFunction );
            population.Add( ancestor.Clone( ) );
            // add more chromosomes to the population
            for ( int i = 1; i < size; i++ )
            {
                // create new chromosome
                IChromosome c = ancestor.CreateNew( );
                // calculate it's fitness
                c.Evaluate( fitnessFunction );
                // add it to population
                population.Add( c );
            }
        }
View Code

Population.RunEpoch方法:主要包括交叉、变异和选择三个过程,这些操作都是生成新的基因,然后每一个基因都通过执行Evaluate函数取得了适应度数据。在选择操作中,找到适应度最好的那个的基因,保存在属性BestChromosome中。

        public void RunEpoch( )
        {
            Crossover( );
            Mutate( );
            Selection( );

            if ( autoShuffling )
                Shuffle( );
        }
View Code

 

保存了相关对象,比如:networkpopulationSizefitnessFunction,同时计算了numberOfNetworksWeights,用于后续计算基因长度。

posted @ 2021-03-16 20:42  顺其自然,道法自然  阅读(267)  评论(0编辑  收藏  举报