Skip to content

Commit

Permalink
Merge pull request #3 from Atashnezhad/feature/grad_cam_fix
Browse files Browse the repository at this point in the history
add layer name and test folder address
  • Loading branch information
Atashnezhad authored Jun 22, 2023
2 parents 1ecf33b + 3e82c1b commit f71e9ac
Show file tree
Hide file tree
Showing 13 changed files with 105 additions and 31 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,16 @@ on:
branches:
- main
- master
- '*'
- 'feature/*'
tags:
- "v*.*.*"
pull_request:
types:
- closed
branches:
- master
- main


jobs:
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@ neural_network_model/__pycache__/
tests/__pycache__/
/.coverage
__pycache__/
/dataset/
/dataset_augmented/
/dataset_train_test_val/
/deep_model/
Binary file modified figures/grad_cam_pdc_Image_1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures/history.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures/prediction_pdc_bit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified figures/prediction_rollercone_bit.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
77 changes: 54 additions & 23 deletions neural_network_model/bit_vision.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,21 @@
from tensorflow import keras
from tensorflow.keras.applications.resnet50 import decode_predictions, preprocess_input
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from tensorflow.keras.preprocessing.image import (
ImageDataGenerator,
img_to_array,
load_img,
)
from keras import Sequential
from keras.callbacks import ModelCheckpoint
from keras.layers import BatchNormalization, Conv2D, Dense, Dropout, Flatten, MaxPooling2D
from keras.layers import (
BatchNormalization,
Conv2D,
Dense,
Dropout,
Flatten,
MaxPooling2D,
)

from neural_network_model.model import SETTING

Expand Down Expand Up @@ -321,7 +332,8 @@ def _filter_out_list(
def predict(self, *args, **kwargs):
"""
This function is used to predict the test data.
:param args:
:param args: test_folder_dir needs to have a suborder called test and there needs to have categories folders
same structure as train_test_val directory
:param kwargs: fig_save_address: the address of the folder to save the figure,
model_path: the path of the model to be used for prediction
:return:
Expand All @@ -339,10 +351,10 @@ def predict(self, *args, **kwargs):
if model_path is None:
logger.info(f"model_path from SETTING is was used - {model_path}")

test_folder_address = kwargs.get(
"test_folder_address", SETTING.DATA_ADDRESS_SETTING.TEST_DIR_ADDRESS
test_folder_dir = kwargs.get(
"test_folder_dir", SETTING.DATA_ADDRESS_SETTING.TEST_DIR_ADDRESS
)
if test_folder_address is None:
if test_folder_dir is None:
raise ValueError("test_folder_address is None")

model = keras.models.load_model(model_path)
Expand All @@ -353,10 +365,17 @@ def predict(self, *args, **kwargs):
number_of_cols = SETTING.FIGURE_SETTING.NUM_COLS_IN_PRED_MODEL
number_of_rows = SETTING.FIGURE_SETTING.NUM_ROWS_IN_PRED_MODEL
number_of_test_to_pred = SETTING.MODEL_SETTING.NUMBER_OF_TEST_TO_PRED
train_test_val_dir = (
self.train_test_val_dir
or SETTING.PREPROCESSING_SETTING.TRAIN_TEST_VAL_SPLIT_DIR_ADDRESS
)
if test_folder_dir:
train_test_val_dir = (
test_folder_dir
or SETTING.PREPROCESSING_SETTING.TRAIN_TEST_VAL_SPLIT_DIR_ADDRESS
)
else:
train_test_val_dir = (
self.train_test_val_dir
or SETTING.PREPROCESSING_SETTING.TRAIN_TEST_VAL_SPLIT_DIR_ADDRESS
)

# get the list of test images
test_images_list = os.listdir(
train_test_val_dir
Expand Down Expand Up @@ -413,7 +432,7 @@ def predict(self, *args, **kwargs):

datagen = image.ImageDataGenerator(SETTING.DATA_GEN_SETTING.RESCALE)
DoubleCheck_generator = datagen.flow_from_directory(
directory=test_folder_address,
directory=test_folder_dir / "test",
target_size=SETTING.FLOW_FROM_DIRECTORY_SETTING.TARGET_SIZE,
color_mode=SETTING.FLOW_FROM_DIRECTORY_SETTING.COLOR_MODE,
classes=None,
Expand Down Expand Up @@ -448,22 +467,27 @@ def grad_cam_viz(self, *args, **kwargs):
"img_to_be_applied_path", SETTING.GRAD_CAM_SETTING.IMG_PATH
)

print_layer_names = kwargs.get("print_layer_names", False)

fig_address = fig_to_save_address / gradcam_fig_name
if model_path is None:
raise ValueError("model_path is None")

model = keras.models.load_model(model_path)
logger.info(f"Model loaded from {model_path}")

# print the model layers
for idx in range(len(model.layers)):
print(model.get_layer(index=idx).name)
if print_layer_names:
# print the model layers
for idx in range(len(model.layers)):
print(model.get_layer(index=idx).name)

# model_builder = keras.applications.xception.Xception
preprocess_input = keras.applications.xception.preprocess_input
# decode_predictions = keras.applications.xception.decode_predictions

last_conv_layer_name = SETTING.GRAD_CAM_SETTING.LAST_CONV_LAYER_NAME
conv_layer_name_tobe_used = kwargs.get(
"layer_name", SETTING.GRAD_CAM_SETTING.LAST_CONV_LAYER_NAME
)

# The local path to our target image
img_path = img_to_be_applied_path
Expand All @@ -490,7 +514,7 @@ def grad_cam_viz(self, *args, **kwargs):
# print("Predicted:", decode_predictions(preds, top=1)[0])
# Generate class activation heatmap
heatmap = BitVision._make_gradcam_heatmap(
img_array, model, last_conv_layer_name
img_array, model, conv_layer_name_tobe_used
)

# Display heatmap
Expand Down Expand Up @@ -611,11 +635,18 @@ def return_best_model_name(
obj = BitVision(
train_test_val_dir=Path(__file__).parent / ".." / "dataset_train_test_val"
)
print(obj.categories)
print(obj.data_details)
obj.plot_image_category()
obj.compile_model()
obj.train_model()
obj.plot_history()
# print(obj.categories)
# print(obj.data_details)
# obj.plot_image_category()
# obj.compile_model()
# obj.train_model(epochs=8)
# obj.plot_history()
obj.predict()
obj.grad_cam_viz(gradcam_fig_name="test.png")
obj.grad_cam_viz(
gradcam_fig_name="test.png",
print_layer_names=True,
test_folder_dir=Path(__file__).parent
/ ".."
/ "dataset_train_test_val"
/ "test",
)
4 changes: 2 additions & 2 deletions neural_network_model/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class DataAddressSetting(BaseModel):
Path(__file__).parent
/ ".."
/ "dataset_train_test_val"
/ "test" # check the TRAIN_TEST_SPLIT_DIR_NAMES in
# / "test" # check the TRAIN_TEST_SPLIT_DIR_NAMES in
# the PreprocessingSetting make sure test is in the list
)

Expand Down Expand Up @@ -75,7 +75,7 @@ class ModelSetting(BaseModel):

# fit generator
EPOCHS: int = 3
FIT_GEN_VERBOSE: int = 1
FIT_GEN_VERBOSE: int = 0
VALIDATION_STEPS: int = 4
CLASS_WEIGHT: dict = None
MAX_QUEUE_SIZE: int = 10
Expand Down
10 changes: 7 additions & 3 deletions neural_network_model/process_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

from bing_image_downloader import downloader
from tensorflow.keras.preprocessing import image
from tensorflow.keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
from tensorflow.keras.preprocessing.image import (
ImageDataGenerator,
img_to_array,
load_img,
)
from tqdm import tqdm

from neural_network_model.model import SETTING
Expand Down Expand Up @@ -354,7 +358,7 @@ def _copy_images(

if __name__ == "__main__":
obj = Preprocessing(dataset_address=Path(__file__).parent / ".." / "dataset")
# obj.download_images()
obj.download_images()

# or download the data from s3. this is after you have downloaded the data
# using Process.download_images() and uploaded it to s3
Expand All @@ -363,5 +367,5 @@ def _copy_images(
# obj.download_images(from_s3=True)

print(obj.image_dict)
obj.augment_data(number_of_images_tobe_gen=10)
obj.augment_data(number_of_images_tobe_gen=20)
obj.train_test_split()
File renamed without changes.
11 changes: 11 additions & 0 deletions tests/test_bitvision.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,16 @@
import pytest


import sys
from pathlib import Path

# Get the parent directory of the current file (assuming the script is in the test folder)
current_dir = Path(__file__).resolve().parent
# Get the parent directory of the current directory (assuming the test folder is one level below the main folder)
main_dir = current_dir.parent
# Add the main directory to the Python path
sys.path.append(str(main_dir))

from neural_network_model.bit_vision import BitVision


Expand Down
11 changes: 10 additions & 1 deletion tests/test_preprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,14 @@
from typing import List, Union
from unittest import mock
from unittest.mock import MagicMock, PropertyMock, patch

import sys

# Get the parent directory of the current file (assuming the script is in the test folder)
current_dir = Path(__file__).resolve().parent
# Get the parent directory of the current directory (assuming the test folder is one level below the main folder)
main_dir = current_dir.parent
# Add the main directory to the Python path
sys.path.append(str(main_dir))
import pytest

import neural_network_model
Expand Down Expand Up @@ -38,6 +45,8 @@ def test_download_images_2(_object):
assert mock_bing_downloader.download.call_count == 2


# skip this test
@pytest.mark.skip
def test_download_images_3(mocker, _object):
mock_bing_downloader_download = mocker.patch(
"neural_network_model.process_data.downloader.download"
Expand Down
11 changes: 9 additions & 2 deletions tests/test_run.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,24 @@
import argparse
import os
from pathlib import Path
import sys

# Get the parent directory of the current file (assuming the script is in the test folder)
current_dir = Path(__file__).resolve().parent
# Get the parent directory of the current directory (assuming the test folder is one level below the main folder)
main_dir = current_dir.parent
# Add the main directory to the Python path
sys.path.append(str(main_dir))
# skip this test TODO: fix this test later
import pytest

from neural_network_model.bit_vision import BitVision
from neural_network_model.process_data import Preprocessing


@pytest.mark.skip
@pytest.mark.skip(reason="no way of currently testing this")
def test_run():
# check if a dir name test_resouces exists if not create one
# check if a dir name test_resources exists if not create one
if not os.path.exists(Path(__file__).parent / "test_resources"):
os.mkdir(Path(__file__).parent / "test_resources")

Expand Down

0 comments on commit f71e9ac

Please sign in to comment.