Example #1
0
        public SOM(AppSettings appSettings )
        {
            _appSettings = appSettings;
            _netState = NET_STATE.init;
            _trainingPhase = TRAINING_PHASE.phase_1;
            _currentIteration = 1;
            _totalMapError = 0.0f;
            _isNeuronSelected = false;
            _selectedNeuronCoords = new Point( 0, 0 );
            _isTrained = false;

            _timeConstant_P1 = (float)_appSettings.numIterations_P1 / (float)Math.Log( _appSettings.mapRadius );
            _learningRate_P1 = _appSettings.startLearningRate_P1;
            _learningRate_P2 = _appSettings.startLearningRate_P2;

            // Allocate memory.
            _competitionLayer = new Neuron[ SOMConstants.NUM_NODES_DOWN, SOMConstants.NUM_NODES_ACROSS ];
            for ( int i = 0; i < SOMConstants.NUM_NODES_DOWN; ++i ) {
                for ( int j = 0; j < SOMConstants.NUM_NODES_ACROSS; ++j ) {
                    _competitionLayer[ i,j ] = new Neuron( i, j );
                }
            }
            _errorMap = new float[ SOMConstants.NUM_NODES_DOWN, SOMConstants.NUM_NODES_ACROSS, 3 ];

            Run();
        }
Example #2
0
        private bool Epoch()
        {
            if (_trainingPhase == TRAINING_PHASE.phase_1 && _currentIteration > _appSettings.numIterations_P1)
            {
                _trainingPhase = TRAINING_PHASE.phase_2;
                _currentIteration = 1;
            }
            else if (_trainingPhase == TRAINING_PHASE.phase_2 && _currentIteration > _appSettings.numIterations_P2)
            {
                return true;
            }

            /************************************************************************/
            /* STEP 2: Choose a random input vector from the set of training data.
            /************************************************************************/
            int randomNum = SOMHelper.Random_Int(_appSettings.images.Count);
            ImageData thisImage = (ImageData)_appSettings.images[randomNum];
            thisImage.numGotPickup++;
            InputVector inVec = thisImage.inputVector;

            /************************************************************************/
            /* STEP 3: Find the BMU.
            /************************************************************************/
            Neuron bmu = FindBMU(inVec);

            // Update this image's most recent BMU for later identification.
            thisImage.m_BMU.X = bmu.X;
            thisImage.m_BMU.Y = bmu.Y;

            /************************************************************************/
            /* STEP 4: Calculate the radius of the BMU's neighborhood.
            /************************************************************************/
            if (_trainingPhase == TRAINING_PHASE.phase_1)
                _neighborhoodRadius = _appSettings.mapRadius * (float)Math.Exp(-(float)_currentIteration / _timeConstant_P1);
            else if (_trainingPhase == TRAINING_PHASE.phase_2)
                _neighborhoodRadius = 1.0f;

            /************************************************************************/
            /* STEP 5: Each neighboring node's weights are adjusted to make them more
             *         like the input vector.
            /************************************************************************/
            for (int i = 0; i < SOMConstants.NUM_NODES_DOWN; ++i)
            {
                for (int j = 0; j < SOMConstants.NUM_NODES_ACROSS; ++j)
                {
                    float distToNodeSquared = 0.0f;

                    // Get the Euclidean distance (squared) to this node[i,j] from the BMU. Use
                    //  this formula to account for base 0 arrays, and the fact that our neighborhood
                    //  radius is actually HALF of the DRAWING WINDOW.
                    float bmuX = (float)(bmu.X + 1) * _appSettings.nodeHeight;
                    float bmuY = (float)(bmu.Y + 1) * _appSettings.nodeWidth;
                    float nodeX = (float)(_competitionLayer[i, j].Y + 1) * _appSettings.nodeHeight;
                    float nodeY = (float)(_competitionLayer[i, j].Y + 1) * _appSettings.nodeWidth;
                    distToNodeSquared = (bmuX - nodeX) *
                        (bmuX - nodeX) +
                        (bmuY - nodeY) *
                        (bmuY - nodeY);

                    float widthSquared = _neighborhoodRadius * _neighborhoodRadius;

                    // If within the neighborhood radius, adjust this nodes' weights.
                    if (distToNodeSquared < widthSquared)
                    {
                        // Calculate how much it's weights are adjusted.
                        float influence = (float)Math.Exp(-distToNodeSquared / (2.0f * widthSquared));

                        if (_trainingPhase == TRAINING_PHASE.phase_1)
                            _competitionLayer[i, j].AdjustWeights(inVec, _learningRate_P1, influence);
                        else if (_trainingPhase == TRAINING_PHASE.phase_2)
                            _competitionLayer[i, j].AdjustWeights(inVec, _learningRate_P2, influence);
                    }
                } // End for each column.
            } // End for each row.

            // Reduce the learning rate.
            if (_trainingPhase == TRAINING_PHASE.phase_1)
            {
                _learningRate_P1 = _appSettings.startLearningRate_P1 * (float)Math.Exp(-(float)_currentIteration / (float)_appSettings.numIterations_P1);
            }
            else if (_trainingPhase == TRAINING_PHASE.phase_2)
            {
                _learningRate_P2 = _appSettings.startLearningRate_P2 * (float)Math.Exp(-(float)_currentIteration / (float)_appSettings.numIterations_P2);
            }
             ++_currentIteration;

            return false;
        }