Compare commits

..
9 Commits
Author SHA1 Message Date
Jake Miller 005294d88d Added a GPU check for NVIDIA in Makefile
This fix will only work on Linux. We would need to use 'ioreg' for Mac
2019-06-05 17:46:40 -04:00
Dan Petro a9a94ffa30 Merge branch 'test_cases' 2019-05-21 13:43:03 -07:00
Dan Petro 0cff91ba67 Changed dependency to tensorflow-gpu in the conda setup
- You probably wanted the GPU version
2019-05-20 09:17:25 -07:00
Dan Petro 7893a93545 de-linted 2019-05-17 15:03:34 -07:00
Dan Petro ea2dfec47e Removed extraneous print statement 2019-05-17 14:13:38 -07:00
Dan Petro ca3b280217 Add evaluation metrics for the "none of the above" data 2019-05-16 16:16:15 -07:00
Dan Petro 66c43d7b0f Merge branch 'master' into loud_errors 2019-05-15 14:55:23 -07:00
Dan Petro b2abff1b30 De-linted 2019-05-15 14:50:00 -07:00
Jake Miller 65bb9efa0d Fail more loudly when model file has an error
FileNotFound and invalid models will now throw errors
2019-05-15 11:21:10 -04:00
5 changed files with 61 additions and 14 deletions

No files matched your search

+5 -1
View File
@@ -32,7 +32,11 @@ endif
$(PIP) install --upgrade -r $(REQUIREMENTS)
@echo -e $(TAG)Installing Eyeballer$(END)
$(PIP) install --upgrade --editable .
ifeq ($(shell lspci | grep NVIDIA),NVIDIA))
$(PIP) install --upgrade --editable .[tf_gpu]
else
$(PIP) install --upgrade --editable .[tf]
endif
ifeq ($(strip $(MAKECMDGOALS)),conda)
@echo -e $(TAG)Activate virtualenv to run eyeballer: $(END)
+3 -1
View File
@@ -65,8 +65,10 @@ def pretty_print_evaluation(results):
for label in DATA_LABELS:
print(f"{label} Precision Score: {results[label]['precision']:4.2%}")
print(f"{label} Recall Score: {results[label]['recall']:4.2%}")
print(f"'None of the above' Precision: {results['none_of_the_above_precision']:4.2%}")
print(f"'None of the above' Recall: {results['none_of_the_above_recall']:4.2%}")
print(f"All or nothing Accuracy: {results['all_or_nothing_accuracy']:4.2%}")
print(f"Overall Binary Accuracy: {results['total_binary_accuracy']:4.2%}")
print(f"All or nothing accuracy: {results['all_or_nothing_accuracy']:4.2%}")
print(f"Top 10 worst predictions: {results['top_10_worst'][1]}")
+40 -3
View File
@@ -1,5 +1,6 @@
import os
import random
import sys
# Prevent Tkinter Dependency
import matplotlib
@@ -50,7 +51,7 @@ class EyeballModel:
image_width, image_height = 224, 224
input_shape = (image_width, image_height, 3)
def __init__(self, print_summary=False, weights_file="weights.h5", seed=None):
def __init__(self, weights_file, print_summary=False, seed=None):
"""Constructor for model class.
Keyword arguments:
@@ -95,10 +96,16 @@ class EyeballModel:
self.training_labels = self.training_labels.sample(frac=1)
if weights_file is not None and os.path.isfile(weights_file):
self.model.load_weights(weights_file)
try:
self.model.load_weights(weights_file)
except OSError:
print(f"ERROR: Unable to open weights file '{weights_file}'")
sys.exit(-1)
print("Loaded model from file.")
else:
print("No model loaded from file")
if weights_file is not None:
raise FileNotFoundError
print("WARN: No model loaded from file. Generating random model")
# Data augmentation
augmentor = Augmentor.Pipeline()
@@ -306,8 +313,38 @@ class EyeballModel:
stats["all_or_nothing_accuracy"] = accuracy_score(ground_truth, predictions)
stats["top_10_best"] = self._top_images(evaluation_generator, predictions, best=True)
stats["top_10_worst"] = self._top_images(evaluation_generator, predictions, best=False)
stats["none_of_the_above_recall"] = self._none_of_the_above_recall(ground_truth, predictions)
stats["none_of_the_above_precision"] = self._none_of_the_above_precision(ground_truth, predictions)
return stats
def _none_of_the_above_recall(self, labels, predictions):
"""Returns the recall score for the 'none of the above' images.
That means, all the images that don't have a category.
"""
total_count = 0
correct_count = 0
for item in zip(labels.astype(int), predictions.astype(int)):
# Is this a none of the above?
if not item[0].any():
total_count += 1
if not item[1].any():
correct_count += 1
return correct_count / total_count
def _none_of_the_above_precision(self, labels, predictions):
"""Returns the precision score for the 'none of the above' images.
That means, all the images that don't have a category.
"""
total_count = 0
correct_count = 0
for item in zip(labels.astype(int), predictions.astype(int)):
# Is this a none of the above prediction?
if not item[1].any():
total_count += 1
if not item[0].any():
correct_count += 1
return correct_count / total_count
def _top_images(self, labels, predictions, top_k=10, best=False):
"""Collect top-k best or top-k worst predicted images
+5 -2
View File
@@ -6,7 +6,7 @@ setup(
packages=find_packages(exclude=["tests"]),
url='https://github.com/BishopFox/eyeballer',
license='GNU General Public License v3.0',
author='Daniel Petro',
author='Bishop Fox',
author_email='',
description='',
entry_points={
@@ -22,9 +22,12 @@ setup(
'pandas',
'pillow',
'sklearn',
'tensorflow',
'keras @ git+https://github.com/keras-team/keras',
],
extras_require={
'tf': ['tensorflow'],
'tf_gpu': ['tensorflow-gpu'],
},
dependency_links=[
],
)
+8 -7
View File
@@ -2,7 +2,8 @@ import errno
import os
import unittest
from eyeballer.model import EyeballModel, DATA_LABELS
from eyeballer.model import EyeballModel
class PredictTest(unittest.TestCase):
def setUp(self):
@@ -10,9 +11,9 @@ class PredictTest(unittest.TestCase):
if not os.path.isfile(weights_file):
print("Error: Symlink the latest weights file to 'latest_weights.h5'")
raise FileNotFoundError(
errno.ENOENT,
os.strerror(errno.ENOENT),
weights_file)
errno.ENOENT,
os.strerror(errno.ENOENT),
weights_file)
model_kwargs = {
"weights_file": weights_file,
@@ -51,15 +52,15 @@ class PredictTest(unittest.TestCase):
self.assertEquals(results_one, results_two)
def get_prediction_by_name(self,results):
def get_prediction_by_name(self, results):
prediction = None
max_val = 0.0
print(results)
for k, v in results[0].items():
if not isinstance(v, str) and v > max_val:
prediction = k
max_val = v
prediction = k
max_val = v
return prediction
def test_predict_custom404(self):