Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
anas-awadalla committed Aug 1, 2020
2 parents 349aa9d + 72f5b9d commit 49176f7
Show file tree
Hide file tree
Showing 125 changed files with 61 additions and 15 deletions.
8 changes: 8 additions & 0 deletions docs/html/modeling.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,14 @@ <h1 id="cq">convolutional_query()</h1>
<td>augmentation=True</td>
<td>Magnifies dataset to add small variation to images before training in the model.</td>
</tr>
<tr>
<td>custom_arch=None</td>
<td>File path to a custom Keras model architecture configuration in JSON format. </td>
</tr>
<tr>
<td>pretrained=None</td>
<td>Load a state-of-the-art model architecture through dictionary with keys 'arch' and 'weights'. Current values supported for 'arch' key are 'vggnet16', 'vggnet19', 'resnet50', 'resnet101', 'resnet152'. Possible values for 'weights' key include 'imagenet' and 'random'. </td>
</tr>
<tr>
<td>epochs=10</td>
<td>Number of epochs for every model attempted.</td>
Expand Down
1 change: 1 addition & 0 deletions libra/queries.py
Original file line number Diff line number Diff line change
Expand Up @@ -745,6 +745,7 @@ def convolutional_query(self,
read_mode=None,
verbose=0,
preprocess=True,
data_path = None,
new_folders=True,
image_column=None,
test_size=0.2,
Expand Down
33 changes: 20 additions & 13 deletions libra/query/feedforward_nn.py
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,9 @@ def convolutional(instruction=None,
:param many parameters: used to preprocess, tune, plot generation, and parameterizing the convolutional neural network trained.
:return dictionary that holds all the information for the finished model.
'''
# data_path = get_folder_dir()

#data_path = get_folder_dir()

logger("Generating datasets for classes")

if pretrained:
Expand All @@ -503,11 +505,11 @@ def convolutional(instruction=None,
if not width:
width = 224
if height != 224 or width != 224:
raise ValueError("For pretrained models, height must be 224 and width must be 224.")
raise ValueError("For pretrained models, both 'height' and 'width' must be 224.")

if preprocess:
if custom_arch:
raise ValueError("If custom_arch is not None, preprocess must be set to false.")
raise ValueError("If 'custom_arch' is not None, 'preprocess' must be set to false.")

read_mode_info = set_distinguisher(data_path, read_mode)
read_mode = read_mode_info["read_mode"]
Expand Down Expand Up @@ -556,11 +558,15 @@ def convolutional(instruction=None,
input_single = (processInfo["height"], processInfo["width"])
num_classes = processInfo["num_categories"]
loss_func = ""
output_layer_activation = ""

if num_classes > 2:
loss_func = "categorical_crossentropy"
output_layer_activation = "softmax"
elif num_classes == 2:
num_classes = 1
loss_func = "binary_crossentropy"
output_layer_activation = "sigmoid"

logger("Creating convolutional neural netwwork dynamically")

Expand Down Expand Up @@ -588,7 +594,7 @@ def convolutional(instruction=None,
x = Dropout(0.5)(x)
x = Dense(4096)(x)
x = Dropout(0.5)(x)
pred = Dense(num_classes, activation='softmax')(x)
pred = Dense(num_classes, activation=output_layer_activation)(x)
model = Model(base_model.input, pred)
elif arch_lower == "vggnet19":
base_model = VGG19(include_top=False, weights='imagenet', input_shape=input_shape)
Expand All @@ -597,36 +603,36 @@ def convolutional(instruction=None,
x = Dropout(0.5)(x)
x = Dense(4096)(x)
x = Dropout(0.5)(x)
pred = Dense(num_classes, activation='softmax')(x)
pred = Dense(num_classes, activation=output_layer_activation)(x)
model = Model(base_model.input, pred)
elif arch_lower == "resnet50":
base_model = ResNet50(include_top=False, weights='imagenet', input_shape=input_shape)
x = Flatten()(base_model.output)
x = GlobalAveragePooling2D()(base_model.output)
x = Dropout(0.5)(x)
pred = Dense(num_classes, activation='softmax')(x)
pred = Dense(num_classes, activation=output_layer_activation)(x)
model = Model(base_model.input, pred)
elif arch_lower == "resnet101":
base_model = ResNet101(include_top=False, weights='imagenet', input_shape=input_shape)
x = GlobalAveragePooling2D()(base_model.output)
x = Dropout(0.5)(x)
pred = Dense(num_classes, activation='softmax')(x)
pred = Dense(num_classes, activation=output_layer_activation)(x)
model = Model(base_model.input, pred)
elif arch_lower == "resnet152":
base_model = ResNet152(include_top=False, weights='imagenet', input_shape=input_shape)
x = GlobalAveragePooling2D()(base_model.output)
x = Dropout(0.5)(x)
pred = Dense(num_classes, activation='softmax')(x)
pred = Dense(num_classes, activation=output_layer_activation)(x)
model = Model(base_model.input, pred)
else:
raise ModuleNotFoundError("arch \'" + pretrained.get('arch') + "\' not supported.")

else:
# Randomly initialized weights
if arch_lower == "vggnet16":
model = VGG16(include_top=True, weights=None, classes=num_classes)
model = VGG16(include_top=True, weights=None, classes=num_classes, classifier_activation = output_layer_activation)
elif arch_lower == "vggnet19":
model = VGG19(include_top=True, weights=None, classes=num_classes)
model = VGG19(include_top=True, weights=None, classes=num_classes, classifier_activation = output_layer_activation)
elif arch_lower == "resnet50":
model = ResNet50(include_top=True, weights=None, classes=num_classes)
elif arch_lower == "resnet101":
Expand Down Expand Up @@ -679,6 +685,7 @@ def convolutional(instruction=None,
activation="softmax"
))


model.compile(
optimizer="adam",
loss=loss_func,
Expand All @@ -702,15 +709,15 @@ def convolutional(instruction=None,
X_train = train_data.flow_from_directory(data_path + training_path,
target_size=input_single,
color_mode=color_mode,
batch_size=(32 if processInfo["train_size"] >= 32 else 1),
batch_size=(16 if processInfo["train_size"] >= 16 else 1),
class_mode=loss_func[:loss_func.find("_")])
X_test = test_data.flow_from_directory(data_path + testing_path,
target_size=input_single,
color_mode=color_mode,
batch_size=(32 if processInfo["test_size"] >= 32 else 1),
batch_size=(16 if processInfo["test_size"] >= 16 else 1),
class_mode=loss_func[:loss_func.find("_")])

if epochs < 0:
if epochs <= 0:
raise BaseException("Number of epochs has to be greater than 0.")
logger('Training image model')
history = model.fit_generator(
Expand Down
33 changes: 31 additions & 2 deletions tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ def compare(a, b):

class TestQueries(unittest.TestCase):
newClient = client('tools/data/structured_data/housing.csv')

"""
TEST QUERIES
Expand Down Expand Up @@ -53,6 +52,35 @@ def test_nn_query(self):
# see if properly chooses classification with a categorical target column
self.newClient.neural_network_query('predict ocean proximity', epochs=3)
self.assertTrue('classification_ANN' in self.newClient.models)
'''
@ordered
def test_convolutional_query(self):
client_image = client("tools/data/image_data/character_dataset_mini")
client_image.convolutional_query("predict character", epochs=2)
self.assertTrue('convolutional_NN' in client_image.models)
'''

@ordered
def test_convolutional_query_customarch(self):
data_path = "tools/data/image_data/character_dataset_mini_preprocessed"
client_image_customarch = client(data_path)
custom_arch_path = "tools/data/custom_model_config/custom_CNN.json"

client_image_customarch.convolutional_query("predict character", data_path = data_path, custom_arch=custom_arch_path, preprocess=False, epochs=2)
self.assertTrue('convolutional_NN' in client_image_customarch.models)


@ordered
def test_convolutional_query_pretrained(self):
client_image = client("tools/data/image_data/character_dataset_mini")
client_image.convolutional_query(
"predict character",
pretrained={
'arch': 'vggnet19',
'weights': 'imagenet'
},
epochs=2)
self.assertTrue('convolutional_NN' in client_image.models)

# Tests whether decision_tree_query works without errors, and creates a key in models dictionary
@ordered
Expand Down Expand Up @@ -117,6 +145,8 @@ def test_content_recommender(self):
x.content_recommender_query()
assert ('recommendations' in x.recommend('Coco'))



"""
TEST ANALYZE() FUNCTION
Expand Down Expand Up @@ -173,6 +203,5 @@ def test_invalid_model(self):
with self.assertRaises(NameError):
self.newClient.analyze(model='I dont exist')


if __name__ == '__main__':
unittest.main()
Loading

0 comments on commit 49176f7

Please sign in to comment.