Skip to content

Commit

Permalink
Confusion matrix is saved as an image.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ragav Venkatesan committed Mar 5, 2017
1 parent fb68da9 commit dd5fdf0
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 18 deletions.
76 changes: 68 additions & 8 deletions yann/modules/resultor.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
from abstract import module
import matplotlib.pyplot as plt

class resultor(module):
"""
Expand All @@ -17,7 +18,6 @@ class resultor(module):
"results" : "<results_file_name>.txt",
"errors" : "<error_file_name>.txt",
"costs" : "<cost_file_name>.txt",
"confusion" : "<confusion_file_name>.txt",
"learning_rate" : "<learning_rate_file_name>.txt"
"momentum" : <momentum_file_name>.txt
"visualize" : <bool>
Expand All @@ -30,6 +30,9 @@ class resultor(module):
Returns:
yann.modules.resultor: A resultor object
TODO:
Remove the input file names, assume file names as default.
"""
def __init__( self, resultor_init_args, verbose = 1):
if "id" in resultor_init_args.keys():
Expand All @@ -54,7 +57,7 @@ def __init__( self, resultor_init_args, verbose = 1):
resultor_init_args["costs"] = "costs.txt"

if not "confusion" in resultor_init_args.keys():
resultor_init_args["confusion"] = "confusion.txt"
resultor_init_args["confusion"] = "confusion"

if not "learning_rate" in resultor_init_args.keys():
resultor_init_args["learning_rate"] = "learning_rate.txt"
Expand Down Expand Up @@ -130,14 +133,71 @@ def process_results( self,
f.write('\n')
f.close()

def plot (self, verbose = 2):
def update_plot (self, verbose = 2):
"""
This method will (should) plot all the values in the files.
TODO:
This method should update the open plots with costs and other values. Ideally, a browser
based system should be implemented, such as using mpl3d or using bokeh. This system
should open opne browser where it should update realtime the cost of training, validation
and testing accuracies per epoch, display the visualizations of filters, some indication
of the weight of gradient trained, confusion matrices, learning rate and momentum plots
etc.
"""
print "TBD"
print "TBD"

def print_confusion (self, epoch=0, train = None, valid = None, verbose = 2):
"""
This method will print the confusion matrix down in files.
def update_plot (self, verbose = 2):
Args:
epoch: This is used merely to create a directory for each epoch so that there is a copy.
train: training confusion matrix as gained by the validate method.
valid: validation confusion amtrix as gained by the validate method.
verbose: As usual.
"""
This method should update the open plots with costs and other values.
if verbose >=3:
print ("... Printing confusion matrix")
if not os.path.exists(self.root + '/confusion'):
if verbose >= 3:
print "... Creating a root directory for saving confusions"
os.makedirs(self.root + '/confusion')

location = self.root + '/confusion/' + '/epoch_' + str(epoch)
if not os.path.exists( location ):
if verbose >=3 :
print "... Making the epoch directory"
os.makedirs (location)

if verbose >=3 :
print ("... Saving down the confusion matrix")

self._store_confusion_img (confusion = train,
filename = location + '/train_confusion.png',
verbose = 2)

self._store_confusion_img (confusion = valid,
filename = location + '/valid_confusion.png',
verbose = 2)

def _store_confusion_img (self, confusion, filename, verbose = 2):
"""
print "TBD"
Convert a normalized confusion matrix into an image and save it down.
Args:
confusion: confusion matrix.
filename: save the image at the location as a png file.
verbose: as usual.
"""
if verbose >= 3:
print ("... Saving the file down")
confusion = confusion / confusion.max()
fig = plt.figure()
plt.matshow(confusion)
plt.title('Confusion matrix')
plt.set_cmap('Greens')
plt.colorbar()
plt.ylabel('True labels')
plt.xlabel('Predicated labels')
plt.savefig(filename)
plt.close('all')
33 changes: 23 additions & 10 deletions yann/network.py
Original file line number Diff line number Diff line change
Expand Up @@ -1724,8 +1724,14 @@ def _initialize_confusion (self, classifier = None, verbose = 2):
if verbose>=3 :
print("... initializing confusion matrix function")

_classes = T.scalar('num_classes')
_predictions = self.inference_layers[classifier].predictions
confusion = T.dot(self.y.T,_predictions)
_labels = self.y

confusion = T.dot( T.eq( _predictions.dimshuffle(0, 'x'), \
T.arange(self.num_classes_to_classify).astype('int32')).T, \
T.eq( _labels.dimshuffle(0,'x'), \
T.arange(self.num_classes_to_classify).astype('int32')))

index = T.lscalar('index')
self.mini_batch_confusion = theano.function(
Expand Down Expand Up @@ -2506,9 +2512,9 @@ def validate(self, epoch = 0, training_accuracy = False, show_progress = False,
self._cache_data ( batch = batch , type = 'valid', verbose = verbose )
for minibatch in xrange(self.mini_batches_per_batch[1]):
validation_errors = validation_errors + self.mini_batch_test (minibatch)
# if self.network_type == 'classifier':
# valid_confusion_matrix = valid_confusion_matrix + \
# self.mini_batch_confusion (minibatch)
if self.network_type == 'classifier':
valid_confusion_matrix = valid_confusion_matrix + \
self.mini_batch_confusion (minibatch)
if verbose >= 3:
print("... validation error after mini batch " + str(batch_counter) + \
" is " + str(validation_errors))
Expand All @@ -2526,9 +2532,9 @@ def validate(self, epoch = 0, training_accuracy = False, show_progress = False,

for minibatch in xrange(self.mini_batches_per_batch[0]):
training_errors = training_errors + self.mini_batch_test (minibatch)
# if self.network_type == 'classifier':
# train_confusion_matrix = train_confusion_matrix + \
# self.mini_batch_confusion (minibatch)
if self.network_type == 'classifier':
train_confusion_matrix = train_confusion_matrix + \
self.mini_batch_confusion (minibatch)
if verbose >= 3:
print("... training error after mini batch " + str(batch_counter) + \
" is " + str(training_errors))
Expand All @@ -2540,6 +2546,9 @@ def validate(self, epoch = 0, training_accuracy = False, show_progress = False,
if show_progress is True:
bar.finish()

"""
TODO: The following piece of code should move to resultor
"""
total_valid_samples = (self.batches2validate*self.mini_batches_per_batch[1]* \
self.mini_batch_size)
total_train_samples = (self.batches2train*self.mini_batches_per_batch[0]* \
Expand Down Expand Up @@ -2594,6 +2603,10 @@ def validate(self, epoch = 0, training_accuracy = False, show_progress = False,
if verbose >= 2:
print(".. Best validation error")

self.cooked_resultor.print_confusion (epoch = epoch,
train = train_confusion_matrix,
valid = valid_confusion_matrix,
verbose = verbose)
return best


Expand Down Expand Up @@ -2652,12 +2665,12 @@ def train(self, verbose = 2, **kwargs):
training_accuracy = kwargs["training_accuracy"]

if not 'early_terminate' in kwargs.keys():
patience = 5
patience = 2
else:
if kwargs["early_terminate"] is True:
if kwargs["early_terminate"] is False:
patience = numpy.inf
else:
patience = 5
patience = 2
# (initial_learning_rate, fine_tuning_learning_rate, annealing)
if not 'learning_rates' in kwargs.keys():
learning_rates = (0.05, 0.01, 0.001)
Expand Down

0 comments on commit dd5fdf0

Please sign in to comment.