21 #define GRT_DLL_EXPORTS 27 const std::string Softmax::id =
"Softmax";
35 this->useScaling = useScaling;
36 this->learningRate = learningRate;
37 this->minChange = minChange;
38 this->maxNumEpochs = maxNumEpochs;
39 this->batchSize = batchSize;
40 classifierMode = STANDARD_CLASSIFIER_MODE;
45 classifierMode = STANDARD_CLASSIFIER_MODE;
55 this->batchSize = rhs.batchSize;
56 this->models = rhs.models;
66 if( classifier == NULL )
return false;
71 this->batchSize = ptr->batchSize;
72 this->models = ptr->models;
90 errorLog << __GRT_LOG__ <<
" Training data has zero samples!" << std::endl;
94 numInputDimensions = N;
95 numOutputDimensions = K;
105 trainingData.
scale(0, 1);
108 if( useValidationSet ){
109 validationData = trainingData.
split( 100-validationSetSize );
113 for(UINT k=0; k<numClasses; k++){
119 if( !trainSoftmaxModel(classLabels[k],models[k],trainingData) ){
120 errorLog << __GRT_LOG__ <<
" Failed to train model for class: " << classLabels[k] << std::endl;
130 trainingSetAccuracy = 0;
131 validationSetAccuracy = 0;
134 bool scalingState = useScaling;
139 errorLog << __GRT_LOG__ <<
" Failed to compute training set accuracy! Failed to fully train model!" << std::endl;
143 if( useValidationSet ){
147 errorLog << __GRT_LOG__ <<
" Failed to compute validation set accuracy! Failed to fully train model!" << std::endl;
152 trainingLog <<
"Training set accuracy: " << trainingSetAccuracy << std::endl;
154 if( useValidationSet ){
155 trainingLog <<
"Validation set accuracy: " << validationSetAccuracy << std::endl;
159 useScaling = scalingState;
167 errorLog << __GRT_LOG__ <<
" Model Not Trained!" << std::endl;
171 predictedClassLabel = 0;
172 maxLikelihood = -10000;
174 if( !trained )
return false;
176 if( inputVector.
getSize() != numInputDimensions ){
177 errorLog << __GRT_LOG__ <<
" The size of the input vector (" << inputVector.
getSize() <<
") does not match the num features in the model (" << numInputDimensions << std::endl;
182 for(UINT n=0; n<numInputDimensions; n++){
183 inputVector[n] =
scale(inputVector[n], ranges[n].minValue, ranges[n].maxValue, 0, 1);
187 if( classLikelihoods.size() != numClasses ) classLikelihoods.
resize(numClasses,0);
188 if( classDistances.size() != numClasses ) classDistances.
resize(numClasses,0);
194 for(UINT k=0; k<numClasses; k++){
195 Float estimate = models[k].compute( inputVector );
197 if( estimate > bestEstimate ){
198 bestEstimate = estimate;
202 classDistances[k] = estimate;
203 classLikelihoods[k] = estimate;
208 for(UINT k=0; k<numClasses; k++){
209 classLikelihoods[k] /= sum;
213 maxLikelihood = bestEstimate;
214 predictedClassLabel = GRT_DEFAULT_NULL_CLASS_LABEL;
217 maxLikelihood = classLikelihoods[bestIndex];
218 predictedClassLabel = classLabels[bestIndex];
227 Float lastErrorSum = 0;
232 bool keepTraining =
true;
240 model.init( classLabel, N );
243 for(UINT i=0; i<M; i++){
244 y[i] = data[i].getClassLabel()==classLabel ? 1.0 : 0;
250 for(UINT i=0; i<M; i++){
251 randomTrainingOrder[i] = i;
253 std::random_shuffle(randomTrainingOrder.begin(), randomTrainingOrder.end());
256 trainingResults.clear();
257 trainingResults.reserve( maxNumEpochs );
261 while( keepTraining ){
268 UINT roundSize = m+batchSize < M ? batchSize : M-m;
270 for(UINT i=0; i<roundSize; i++){
271 for(UINT j=0; j<N; j++){
272 batchData[i][j] = data[ randomTrainingOrder[m+i] ][j];
273 batchMean[j] += batchData[i][j];
277 for(UINT j=0; j<N; j++) batchMean[j] /= roundSize;
281 for(UINT i=0; i<roundSize; i++){
282 error += y[ randomTrainingOrder[m+i] ] - model.compute( batchData[i] );
288 for(UINT j=0; j<N; j++){
289 model.w[j] += learningRate * error * batchMean[j];
291 model.w0 += learningRate * error;
297 delta = fabs( errorSum-lastErrorSum );
298 lastErrorSum = errorSum;
301 if( delta <= minChange ){
302 keepTraining =
false;
305 if( ++iter >= maxNumEpochs ){
306 keepTraining =
false;
309 trainingLog <<
"Class: " << classLabel <<
" Epoch: " << iter <<
" TotalError: " << errorSum <<
" Delta: " << delta << std::endl;
311 trainingResults.push_back( epochResult );
332 errorLog << __GRT_LOG__ <<
" The file is not open!" << std::endl;
337 file<<
"GRT_SOFTMAX_MODEL_FILE_V2.0\n";
341 errorLog << __GRT_LOG__ <<
" Failed to save classifier base settings to file!" << std::endl;
347 for(UINT k=0; k<numClasses; k++){
348 file <<
"ClassLabel: " << models[k].classLabel << std::endl;
349 file <<
"Weights: " << models[k].w0;
350 for(UINT n=0; n<numInputDimensions; n++){
351 file <<
" " << models[k].w[n];
363 numInputDimensions = 0;
370 errorLog << __GRT_LOG__ <<
" Could not open file to load model" << std::endl;
379 if( word ==
"GRT_SOFTMAX_MODEL_FILE_V1.0" ){
384 if(word !=
"GRT_SOFTMAX_MODEL_FILE_V2.0"){
385 errorLog << __GRT_LOG__ <<
" Could not find Model File Header" << std::endl;
391 errorLog << __GRT_LOG__ <<
" Failed to load base settings from file!" << std::endl;
397 models.
resize(numClasses);
398 classLabels.
resize(numClasses);
402 if(word !=
"Models:"){
403 errorLog << __GRT_LOG__ <<
" Could not find the Models!" << std::endl;
407 for(UINT k=0; k<numClasses; k++){
409 if(word !=
"ClassLabel:"){
410 errorLog << __GRT_LOG__ <<
" Could not find the ClassLabel for model: " << k <<
"!" << std::endl;
413 file >> models[k].classLabel;
414 classLabels[k] = models[k].classLabel;
417 if(word !=
"Weights:"){
418 errorLog << __GRT_LOG__ <<
" Could not find the Weights for model: " << k <<
"!" << std::endl;
421 file >> models[k].w0;
423 models[k].N = numInputDimensions;
424 models[k].w.
resize( numInputDimensions );
425 for(UINT n=0; n<numInputDimensions; n++){
426 file >> models[k].w[n];
435 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
437 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
452 if(word !=
"NumFeatures:"){
453 errorLog << __GRT_LOG__ <<
" Could not find NumFeatures!" << std::endl;
456 file >> numInputDimensions;
459 if(word !=
"NumClasses:"){
460 errorLog << __GRT_LOG__ <<
" Could not find NumClasses!" << std::endl;
466 if(word !=
"UseScaling:"){
467 errorLog << __GRT_LOG__ <<
" Could not find UseScaling!" << std::endl;
473 if(word !=
"UseNullRejection:"){
474 errorLog << __GRT_LOG__ <<
" Could not find UseNullRejection!" << std::endl;
477 file >> useNullRejection;
482 ranges.
resize(numInputDimensions);
485 if(word !=
"Ranges:"){
486 errorLog << __GRT_LOG__ <<
" Could not find the Ranges!" << std::endl;
489 for(UINT n=0; n<ranges.
getSize(); n++){
490 file >> ranges[n].minValue;
491 file >> ranges[n].maxValue;
496 models.
resize(numClasses);
497 classLabels.
resize(numClasses);
501 if(word !=
"Models:"){
502 errorLog << __GRT_LOG__ <<
" Could not find the Models!" << std::endl;
506 for(UINT k=0; k<numClasses; k++){
508 if(word !=
"ClassLabel:"){
509 errorLog << __GRT_LOG__ <<
" Could not find the ClassLabel for model: " << k <<
"!" << std::endl;
512 file >> models[k].classLabel;
513 classLabels[k] = models[k].classLabel;
516 if(word !=
"Weights:"){
517 errorLog << __GRT_LOG__ <<
" Could not find the Weights for model: " << k <<
"!" << std::endl;
520 file >> models[k].w0;
522 models[k].N = numInputDimensions;
523 models[k].w.
resize( numInputDimensions );
524 for(UINT n=0; n<numInputDimensions; n++){
525 file >> models[k].w[n];
534 bestDistance = DEFAULT_NULL_DISTANCE_VALUE;
536 classDistances.
resize(numClasses,DEFAULT_NULL_DISTANCE_VALUE);
bool setClassificationResult(unsigned int trainingIteration, Float accuracy, MLBase *trainer)
bool saveBaseSettingsToFile(std::fstream &file) const
Softmax(const bool useScaling=false, const Float learningRate=0.1, const Float minChange=1.0e-10, const UINT maxNumEpochs=1000, const UINT batchSize=50)
std::string getId() const
static std::string getId()
virtual bool recomputeNullRejectionThresholds()
#define DEFAULT_NULL_LIKELIHOOD_VALUE
bool loadLegacyModelFromFile(std::fstream &file)
Vector< ClassTracker > getClassTracker() const
This file contains the Random class, a useful wrapper for generating cross platform random functions...
virtual bool resize(const unsigned int size)
Vector< SoftmaxModel > getModels() const
virtual bool predict_(VectorFloat &inputVector)
virtual bool computeAccuracy(const ClassificationData &data, Float &accuracy)
Softmax & operator=(const Softmax &rhs)
UINT getNumSamples() const
bool fill(const T &value)
bool copyBaseVariables(const Classifier *classifier)
bool loadBaseSettingsFromFile(std::fstream &file)
UINT getNumDimensions() const
UINT getNumClasses() const
virtual bool load(std::fstream &file)
Vector< MinMax > getRanges() const
ClassificationData split(const UINT splitPercentage, const bool useStratifiedSampling=false)
virtual bool deepCopyFrom(const Classifier *classifier)
bool scale(const Float minTarget, const Float maxTarget)
virtual bool train_(ClassificationData &trainingData)
virtual bool save(std::fstream &file) const
This is the main base class that all GRT Classification algorithms should inherit from...
Float scale(const Float &x, const Float &minSource, const Float &maxSource, const Float &minTarget, const Float &maxTarget, const bool constrain=false)