Exemplo n.º 1
0
        //private void DoWidths(double[][] centroids)
        //{
        //  // this version uses a common width which is dmax / sqrt(2*numHidden)
        //  double maxDist = double.MinValue;
        //  for (int i = 0; i < centroids.Length - 1; ++i)
        //  {
        //    for (int j = i + 1; j < centroids.Length; ++j)
        //    {
        //      double dist = EuclideanDist(centroids[i], centroids[j], centroids[i].Length);
        //      if (dist > maxDist)
        //        maxDist = dist;
        //    }
        //  }

        //  double width = maxDist / Math.Sqrt(2.0 * numHidden);
        //  Console.WriteLine("The common width is: " + width.ToString("F4"));
        //  for (int i = 0; i < this.widths.Length; ++i) // all widths the same
        //    this.widths[i] = width;
        //}

        private double[] DoWeights(double[][] trainData, int maxIterations)
        {
            // use PSO to find weights and bias values that produce a RBF network
            // that best matches training data
            int numberParticles = trainData.Length / 3;

            int    Dim  = (numHidden * numOutput) + numOutput; // dimensions is num weights + num biases
            double minX = -10.0;                               // implicitly assumes data has been normalizzed
            double maxX = 10.0;
            double minV = minX;
            double maxV = maxX;

            Particle[] swarm = new Particle[numberParticles];
            double[]   bestGlobalPosition   = new double[Dim]; // best solution found by any particle in the swarm. implicit initialization to all 0.0
            double     smallesttGlobalError = double.MaxValue; // smaller values better

            // initialize swarm
            for (int i = 0; i < swarm.Length; ++i) // initialize each Particle in the swarm
            {
                double[] randomPosition = new double[Dim];
                for (int j = 0; j < randomPosition.Length; ++j)
                {
                    double lo = minX;
                    double hi = maxX;
                    randomPosition[j] = (hi - lo) * rnd.NextDouble() + lo; //
                }

                double   err            = MeanSquaredError(trainData, randomPosition); // error associated with the random position/solution
                double[] randomVelocity = new double[Dim];

                for (int j = 0; j < randomVelocity.Length; ++j)
                {
                    double lo = -1.0 * Math.Abs(maxV - minV);
                    double hi = Math.Abs(maxV - minV);
                    randomVelocity[j] = (hi - lo) * rnd.NextDouble() + lo;
                }
                swarm[i] = new Particle(randomPosition, err, randomVelocity, randomPosition, err);

                // does current Particle have global best position/solution?
                if (swarm[i].error < smallesttGlobalError)
                {
                    smallesttGlobalError = swarm[i].error;
                    swarm[i].position.CopyTo(bestGlobalPosition, 0);
                }
            } // initialization

            // main PSO algorithm
            // compute new velocity -> compute new position -> check if new best

            double w = 0.729;                          // inertia weight
            double c1 = 1.49445;                       // cognitive/local weight
            double c2 = 1.49445;                       // social/global weight
            double r1, r2;                             // cognitive and social randomizations

            int[] sequence = new int[numberParticles]; // process particles in random order
            for (int i = 0; i < sequence.Length; ++i)
            {
                sequence[i] = i;
            }

            int iteration = 0;

            while (iteration < maxIterations)
            {
                if (smallesttGlobalError < 0.060)
                {
                    break;                                // early exit (MSE)
                }
                double[] newVelocity = new double[Dim];   // step 1
                double[] newPosition = new double[Dim];   // step 2
                double   newError;                        // step 3

                Shuffle(sequence);                        // move particles in random sequence

                for (int pi = 0; pi < swarm.Length; ++pi) // each Particle (index)
                {
                    int      i     = sequence[pi];
                    Particle currP = swarm[i]; // for coding convenience

                    // 1. compute new velocity
                    for (int j = 0; j < currP.velocity.Length; ++j) // each x value of the velocity
                    {
                        r1 = rnd.NextDouble();
                        r2 = rnd.NextDouble();

                        // velocity depends on old velocity, best position of parrticle, and
                        // best position of any particle
                        newVelocity[j] = (w * currP.velocity[j]) +
                                         (c1 * r1 * (currP.bestPosition[j] - currP.position[j])) +
                                         (c2 * r2 * (bestGlobalPosition[j] - currP.position[j]));

                        if (newVelocity[j] < minV)
                        {
                            newVelocity[j] = minV;
                        }
                        else if (newVelocity[j] > maxV)
                        {
                            newVelocity[j] = maxV;     // crude way to keep velocity in range
                        }
                    }

                    newVelocity.CopyTo(currP.velocity, 0);

                    // 2. use new velocity to compute new position
                    for (int j = 0; j < currP.position.Length; ++j)
                    {
                        newPosition[j] = currP.position[j] + newVelocity[j];  // compute new position
                        if (newPosition[j] < minX)
                        {
                            newPosition[j] = minX;
                        }
                        else if (newPosition[j] > maxX)
                        {
                            newPosition[j] = maxX;
                        }
                    }

                    newPosition.CopyTo(currP.position, 0);

                    // 3. use new position to compute new error
                    // consider cross-entropy error instead of MSE
                    newError    = MeanSquaredError(trainData, newPosition); // makes next check a bit cleaner
                    currP.error = newError;

                    if (newError < currP.smallestError) // new particle best?
                    {
                        newPosition.CopyTo(currP.bestPosition, 0);
                        currP.smallestError = newError;
                    }

                    if (newError < smallesttGlobalError) // new global best?
                    {
                        newPosition.CopyTo(bestGlobalPosition, 0);
                        smallesttGlobalError = newError;
                    }

                    // consider using weight decay, particle death here
                } // each Particle

                ++iteration;
            } // while (main PSO processing loop)

            //Console.WriteLine("\n\nFinal training MSE = " + smallesttGlobalError.ToString("F4") + "\n\n");

            // copy best weights found into RBF network, and also return them
            this.SetWeights(bestGlobalPosition);
            double[] returnResult = new double[(numHidden * numOutput) + numOutput];
            Array.Copy(bestGlobalPosition, returnResult, bestGlobalPosition.Length);

            Console.WriteLine("The best weights and bias values found are:\n");
            Helpers.ShowVector(bestGlobalPosition, 3, 10, true);
            return(returnResult);
        } // DoWeights