>  Docs Center  >  ENVI API  >  Classification Framework  >  Code Example: Softmax Regression Classification Using ENVITasks

Code Example: Softmax Regression Classification Using ENVITasks

Code Example: Softmax Regression Classification Using ENVITasks

This code example performs end-to-end classification using ENVITasks. It performs the following steps:

  • Extracts an ENVIExamples object from an attribute image and training data ROIs.
  • Normalizes the examples to a common range of data values.
  • Shuffles the examples to create a random distribution of data.
  • Splits the examples into training and evaluation sets.
  • Uses a gradient descent algorithm to train a Softmax Regression supervised classifier.
  • Plots a loss profile.
  • Prints a confusion matrix and accuracy metrics from the trained classifier.
  • Runs the classifier.
  • Displays the classification image.

Follow these steps to run the code example:

  1. Get the sample data files from our website or from the ENVI Resource DVD in the classification directory. Copy these files to your local drive.
  2. Copy and paste the code into the IDL Editor.
  3. Save the file as SoftmaxClassificationUsingTasks.pro.
  4. Update the following lines to include the full path where you saved the sample data:
    • file = 'AttributeImage.dat'
    • ROIfile = 'TrainingDataROIs.xml'
  5. Update the following line to include the full path where you wil save the trained classifier:
    • classifierURI = 'TrainedSoftmaxClassifierTasks.epo'
  6. Compile and run the code.
PRO SoftmaxClassificationUsingTasks
COMPILE_OPT IDL2
 
; Start the application
e = ENVI()
 
; Open an attribute raster to classify
file = 'AttributeImage.dat'
raster = e.OpenRaster(file)
 
; Open training data ROIs
ROIfile = 'TrainingDataROIs.xml'
rois = e.OpenROI(ROIfile)
 
; Extract examples and labels
extractTask = ENVITask('ExtractExamplesFromRaster')
extractTask.INPUT_RASTER = raster
extractTask.INPUT_ROIS = rois
extractTask.Execute
outExamples = extractTask.OUTPUT_EXAMPLES
 
; Normalize the data
normalizeTask = ENVITask('ApplyGainOffsetToExamples')
normalizeTask.INPUT_EXAMPLES = outExamples
normalizeTask.Execute
gain = normalizeTask.OUTPUT_GAIN
offset = normalizeTask.OUTPUT_OFFSET
normalizedExamples = normalizeTask.OUTPUT_EXAMPLES
Print, 'Gain: ',gain
Print, 'Offset: ',offset
 
; Shuffle the examples to create a normal distribution
shuffleTask = ENVITask('ShuffleExamples')
shuffleTask.INPUT_EXAMPLES = normalizedExamples
shuffleTask.Execute
shuffledExamples = shuffleTask.OUTPUT_EXAMPLES
 
; Split the examples into training and evaluation sets
splitTask = ENVITask('SplitExamples')
splitTask.INPUT_EXAMPLES = shuffledExamples
splitTask.SPLIT_FRACTION = 0.8
splitTask.Execute
splitExamples = splitTask.OUTPUT_EXAMPLES
 
; Define the Softmax classifier input properties
softmaxTask = ENVITask('CreateSoftmaxRegressionClassifier')
softmaxTask.CLASS_NAMES = outExamples.CLASS_NAMES
softmaxTask.NATTRIBUTES = outExamples.NATTRIBUTES
softmaxTask.NCLASSES = outExamples.NCLASSES
softmaxTask.Execute
 
; Run the Gradient Descent trainer
GDTask = ENVITask('CreateGradientDescentTrainer')
GDTask.CONVERGENCE_CRITERION = 1e-7
GDTask.LEARNING_RATE = 100
GDTask.MAXIMUM_ITERATIONS = 60
GDTask.Execute
 
; Train the classifier
trainTask = ENVITask('TrainClassifier')
trainTask.CLASSIFIER = softmaxTask.OUTPUT_CLASSIFIER
trainTask.EXAMPLES = splitExamples[0]
trainTask.TRAINER = GDTask.OUTPUT_TRAINER
trainTask.Execute
lossProfile = trainTask.LOSS_PROFILE
classifier = trainTask.TRAINED_CLASSIFIER
 
; save the trained classifier to disk
classifierURI = 'TrainedSoftmaxClassifierTasks.epo'
classifier.Save, URI=classifierURI
 
; Plot a cost profile and make adjustments as needed
p = PLOT(lossProfile, $
  TITLE='Loss Profile', $
  XTITLE='Iterations', $
  YTITLE='Loss', $
  COLOR='red', $
  THICK=2)
 
; Evaluate the result
evaluateTask = ENVITask('EvaluateClassifier')
evaluateTask.CLASSIFIER = classifier
evaluateTask.EXAMPLES = splitExamples[1]
evaluateTask.Execute
confusionMatrix = evaluateTask.OUTPUT_CONFUSION_MATRIX
 
; Print the confusion matrix
Print, confusionMatrix
 
; Print the column totals
columnTotals = confusionMatrix.ColumnTotals()
FOR i=0, (softmaxTask.NCLASSES)-1 DO $
  Print, 'Ground truth total for ', $
  softmaxTask.CLASS_NAMES[i],': ', $
  columnTotals[i]
 
; Print the row totals
rowTotals = confusionMatrix.RowTotals()
FOR i=0, (softmaxTask.NCLASSES)-1 DO $
  Print, 'Predicted total for ', $
  softmaxTask.CLASS_NAMES[i],': ', $
  rowTotals[i]
 
; Print the accuracy metrics
accuracy = confusionMatrix.Accuracy()
Print, 'Overall accuracy: ', accuracy
kappa = confusionMatrix.KappaCoefficient()
Print, 'Kappa coefficient: ', kappa
commissionError = confusionMatrix.CommissionError()
Print, 'Error of commission: ', commissionError
omissionError = confusionMatrix.OmissionError()
Print, 'Error of omission: ', omissionError
F1 = confusionMatrix.F1()
Print, 'F1 value: ', F1
precision = confusionMatrix.Precision()
Print, 'Precision: ', precision
producerAccuracy = confusionMatrix.ProducerAccuracy()
Print, 'Producer accuracy: ', producerAccuracy
recall = confusionMatrix.Recall()
Print, 'Recall: ', recall
userAccuracy = confusionMatrix.UserAccuracy()
Print, 'User accuracy: ', userAccuracy
 
; Normalize the data
normalizedRaster = ENVIGainOffsetRaster(raster, gain, offset)
 
; Classify the normalized attribute image
classifyTask = ENVITask('ClassifyRaster')
classifyTask.CLASSIFIER = classifier
classifyTask.INPUT_RASTER = normalizedRaster
classifyTask.Execute
classRaster = classifyTask.OUTPUT_RASTER
 
; Display the result
view = e.GetView()
layer = view.CreateLayer(raster)
layer2 = view.CreateLayer(classRaster)
view.Zoom, /FULL_EXTENT
 
END

This code saves the trained classifier to a binary file named TrainedSoftmaxClassifierTasks.epo. You can apply this classifier to other similar datasets that have the same attributes and data representation. The following example shows how to do this.

Tip: When using your own datasets, be sure to record the gain and offset values from the first code example, then define them in the next code example.

Follow these steps to run the next code example.

  1. Get the sample data file (AttributeImage2.dat) from our website or from the ENVI Resource DVD in the classification directory. Copy this file to your local drive.
  2. Copy and paste the code into the IDL Editor.
  3. Update the following line to include the full path where you saved the sample data:
    • file = 'AttributeImage2.dat'
  4. Update the following line to include the full path where you saved the trained classifier:
    • trainedClassifierURI = 'TrainedSoftmaxClassifierTasks.epo'
  5. Save the file as ApplySoftmaxTrainedClassifierTasks.pro.
  6. Compile and run the code.

Tip: The classification image in this example overlaps with the image in the first example. As long as the ENVI application is still open from the first example, you can compare the results where they overlap. The classification in the overlapping region will not be exactly the same because the attribute values are different in each image; however, the results should be similar.

PRO ApplySoftmaxTrainedClassifierTasks
COMPILE_OPT IDL2
 
; Start the application
e = ENVI()
 
; Open an attribute raster to classify
file = 'AttributeImage2.dat'
raster = e.OpenRaster(file)
 
; Normalize the attribute image using the
; previously recorded gains and offsets
gain = [0.68837909, 0.039032014, 1.3670539, $
  1.2792631, 1.2774655, 1.0320982]
offset = [-0.14015123, -0.13057724, -0.12848703, $
  -0.16770373, -0.18784684, -0.28932331]
normalizedRaster = ENVIGainOffsetRaster(raster, gain, offset)
 
; Get the trained classifier. This is a persistable object
; in the form of an IDL save file that needs to be restored
; from disk
trainedClassifierURI = 'TrainedSoftmaxClassifierTasks.epo'
trainedClassifier = ENVIRestoreObject(trainedClassifierURI)
 
; Classify a different attribute image
classifyTask = ENVITask('ClassifyRaster')
classifyTask.CLASSIFIER = trainedClassifier
classifyTask.INPUT_RASTER = normalizedRaster
classifyTask.Execute
classRaster = classifyTask.OUTPUT_RASTER
 
; Get the classification raster metadata
numClasses = classRaster.Metadata['Classes']
classNames = classRaster.Metadata['Class Names']
 
; Display the result
view = e.GetView()
layer = view.CreateLayer(raster)
layer2 = view.CreateLayer(classRaster)
view.Zoom, /FULL_EXTENT
 
END

You can optionally use ENVICalculateConfusionMatrixFromRasterTask to evaluate the classifier. This function takes in a classification raster and training ROIs, and it calculates a confusion matrix and accuracy metrics. Add the following lines of code to the previous code example, after classifying the attribute image and before displaying the results. Update the ROIfile variable to include the full path where you saved the sample data:

; Open an ROI file that will be used to 
; evaluate the classifier
ROIfile = 'TrainingDataROIs.xml'
rois = e.OpenROI(ROIfile)
 
; Evaluate the classifier
evaluateTask = ENVITask('CalculateConfusionMatrixFromRaster')
evaluateTask.INPUT_RASTER = classRaster
evaluateTask.INPUT_ROIS = rois
evaluateTask.Execute
confusionMatrix = evaluateTask.OUTPUT_CONFUSION_MATRIX
 
; Print the confusion matrix
Print, confusionMatrix.Confusion_Matrix
 
; Print the column totals
columnTotals = confusionMatrix.ColumnTotals()
FOR i=0, (numClasses)-1 DO $
  Print, 'Ground truth total for ', $
  classNames[i],': ', $
  columnTotals[i]
 
; Print the row totals
rowTotals = confusionMatrix.RowTotals()
FOR i=0, (numClasses)-1 DO $
  Print, 'Predicted total for ', $
  classNames[i],': ', $
  rowTotals[i]
 
; Print the accuracy metrics
accuracy = confusionMatrix.Accuracy()
Print, 'Overall accuracy: ', accuracy
kappa = confusionMatrix.KappaCoefficient()
Print, 'Kappa coefficient: ', kappa
commissionError = confusionMatrix.CommissionError()
Print, 'Error of commission: ', commissionError
omissionError = confusionMatrix.OmissionError()
Print, 'Error of omission: ', omissionError
F1 = confusionMatrix.F1()
Print, 'F1 value: ', F1
precision = confusionMatrix.Precision()
Print, 'Precision: ', precision
producerAccuracy = confusionMatrix.ProducerAccuracy()
Print, 'Producer accuracy: ', producerAccuracy
recall = confusionMatrix.Recall()
Print, 'Recall: ', recall
userAccuracy = confusionMatrix.UserAccuracy()
Print, 'User accuracy: ', userAccuracy



© 2019 Harris Geospatial Solutions, Inc. |  Legal
My Account    |    Store    |    Contact Us