bool KNN::train_(const ClassificationData &trainingData,const UINT K){ //Set the dimensionality of the input data this->K = K; //Flag that the algorithm has been trained so we can compute the rejection thresholds trained = true; //If null rejection is enabled then compute the null rejection thresholds if( useNullRejection ){ //Set the null rejection to false so we can compute the values for it (this will be set back to its current value later) useNullRejection = false; nullRejectionThresholds.clear(); //Compute the rejection thresholds for each of the K classes VectorFloat counter(numClasses,0); trainingMu.resize( numClasses, 0 ); trainingSigma.resize( numClasses, 0 ); nullRejectionThresholds.resize( numClasses, 0 ); //Compute Mu for each of the classes const unsigned int numTrainingExamples = trainingData.getNumSamples(); Vector< IndexedDouble > predictionResults( numTrainingExamples ); for(UINT i=0; i<numTrainingExamples; i++){ predict( trainingData[i].getSample(), K); UINT classLabelIndex = 0; for(UINT k=0; k<numClasses; k++){ if( predictedClassLabel == classLabels[k] ){ classLabelIndex = k; break; } } predictionResults[ i ].index = classLabelIndex; predictionResults[ i ].value = classDistances[ classLabelIndex ]; trainingMu[ classLabelIndex ] += predictionResults[ i ].value; counter[ classLabelIndex ]++; } for(UINT j=0; j<numClasses; j++){ trainingMu[j] /= counter[j]; } //Compute Sigma for each of the classes for(UINT i=0; i<numTrainingExamples; i++){ trainingSigma[predictionResults[i].index] += SQR(predictionResults[i].value - trainingMu[predictionResults[i].index]); } for(UINT j=0; j<numClasses; j++){ Float count = counter[j]; if( count > 1 ){ trainingSigma[ j ] = sqrt( trainingSigma[j] / (count-1) ); }else{ trainingSigma[ j ] = 1.0; } } //Check to see if any of the mu or sigma values are zero or NaN bool errorFound = false; for(UINT j=0; j<numClasses; j++){ if( trainingMu[j] == 0 ){ warningLog << "TrainingMu[ " << j << " ] is zero for a K value of " << K << std::endl; } if( trainingSigma[j] == 0 ){ warningLog << "TrainingSigma[ " << j << " ] is zero for a K value of " << K << std::endl; } if( grt_isnan( trainingMu[j] ) ){ errorLog << "TrainingMu[ " << j << " ] is NAN for a K value of " << K << std::endl; errorFound = true; } if( grt_isnan( trainingSigma[j] ) ){ errorLog << "TrainingSigma[ " << j << " ] is NAN for a K value of " << K << std::endl; errorFound = true; } } if( errorFound ){ trained = false; return false; } //Compute the rejection thresholds for(unsigned int j=0; j<numClasses; j++){ nullRejectionThresholds[j] = trainingMu[j] + (trainingSigma[j]*nullRejectionCoeff); } //Restore the actual state of the null rejection useNullRejection = true; }else{ //Resize the rejection thresholds but set the values to 0 nullRejectionThresholds.clear(); nullRejectionThresholds.resize( numClasses, 0 ); } return true; }
bool LinearRegression::train_(RegressionData &trainingData){ const unsigned int M = trainingData.getNumSamples(); const unsigned int N = trainingData.getNumInputDimensions(); const unsigned int K = trainingData.getNumTargetDimensions(); trained = false; trainingResults.clear(); if( M == 0 ){ errorLog << "train_(RegressionData &trainingData) - Training data has zero samples!" << std::endl; return false; } if( K == 0 ){ errorLog << "train_(RegressionData &trainingData) - The number of target dimensions is not 1!" << std::endl; return false; } numInputDimensions = N; numOutputDimensions = 1; //Logistic Regression will have 1 output inputVectorRanges.clear(); targetVectorRanges.clear(); //Scale the training and validation data, if needed if( useScaling ){ //Find the ranges for the input data inputVectorRanges = trainingData.getInputRanges(); //Find the ranges for the target data targetVectorRanges = trainingData.getTargetRanges(); //Scale the training data trainingData.scale(inputVectorRanges,targetVectorRanges,0.0,1.0); } //Reset the weights Random rand; w0 = rand.getRandomNumberUniform(-0.1,0.1); w.resize(N); for(UINT j=0; j<N; j++){ w[j] = rand.getRandomNumberUniform(-0.1,0.1); } Float error = 0; Float lastError = 0; Float delta = 0; UINT iter = 0; bool keepTraining = true; Vector< UINT > randomTrainingOrder(M); TrainingResult result; trainingResults.reserve(M); //In most cases, the training data is grouped into classes (100 samples for class 1, followed by 100 samples for class 2, etc.) //This can cause a problem for stochastic gradient descent algorithm. To avoid this issue, we randomly shuffle the order of the //training samples. This random order is then used at each epoch. for(UINT i=0; i<M; i++){ randomTrainingOrder[i] = i; } std::random_shuffle(randomTrainingOrder.begin(), randomTrainingOrder.end()); //Run the main stochastic gradient descent training algorithm while( keepTraining ){ //Run one epoch of training using stochastic gradient descent totalSquaredTrainingError = 0; for(UINT m=0; m<M; m++){ //Select the random sample UINT i = randomTrainingOrder[m]; //Compute the error, given the current weights VectorFloat x = trainingData[i].getInputVector(); VectorFloat y = trainingData[i].getTargetVector(); Float h = w0; for(UINT j=0; j<N; j++){ h += x[j] * w[j]; } error = y[0] - h; totalSquaredTrainingError += SQR( error ); //Update the weights for(UINT j=0; j<N; j++){ w[j] += learningRate * error * x[j]; } w0 += learningRate * error; } //Compute the error delta = fabs( totalSquaredTrainingError-lastError ); lastError = totalSquaredTrainingError; //Check to see if we should stop if( delta <= minChange ){ keepTraining = false; } if( grt_isinf( totalSquaredTrainingError ) || grt_isnan( totalSquaredTrainingError ) ){ errorLog << "train_(RegressionData &trainingData) - Training failed! Total squared training error is NAN. If scaling is not enabled then you should try to scale your data and see if this solves the issue." << std::endl; return false; } if( ++iter >= maxNumEpochs ){ keepTraining = false; } //Store the training results rootMeanSquaredTrainingError = sqrt( totalSquaredTrainingError / Float(M) ); result.setRegressionResult(iter,totalSquaredTrainingError,rootMeanSquaredTrainingError,this); trainingResults.push_back( result ); //Notify any observers of the new result trainingResultsObserverManager.notifyObservers( result ); trainingLog << "Epoch: " << iter << " SSE: " << totalSquaredTrainingError << " Delta: " << delta << std::endl; } //Flag that the algorithm has been trained regressionData.resize(1,0); trained = true; return trained; }