Skip to content

Commit

Permalink
Migrate from TravisCI to Github Actions (#162)
Browse files Browse the repository at this point in the history
* First workflow conifg

* Exclude impossible combinations

* Add opencv

* Fix gradcam graph

* Fix linter

* black pass

* Remove Travis and tox
  • Loading branch information
RaphaelMeudec authored Feb 2, 2021
1 parent c8322d9 commit 7ad1f5d
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 58 deletions.
66 changes: 66 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions

name: Python package

on:
push:
branches: [ master ]
pull_request:
branches: [ master ]

jobs:
lint:

runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- name: Set up Python 3.7
uses: actions/setup-python@v1
with:
python-version: 3.7
- name: Update pip
run: python -m pip install --upgrade pip
- name: Cache dependencies
id: cache
uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-3.7-${{ hashFiles('setup.py') }}-2.2.0
- name: Install dependencies
run: pip install -e ".[tests]" && pip install tensorflow==2.2.0
- name: Lint with pylint and black
run: make lint
- name: Check black
run: black tf_explain tests --check

tests:

runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8]
tensorflow-version: [2.1.0, 2.2.0, 2.3.0, 2.4.0]
exclude:
- tensorflow-version: 2.1.0
python-version: 3.8

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v1
with:
python-version: ${{ matrix.python-version }}
- name: Update pip
run: python -m pip install --upgrade pip
- name: Cache dependencies
id: cache
uses: actions/cache@v1
with:
path: ~/.cache/pip
key: ${{ runner.os }}-${{ matrix.python-version }}-${{ hashFiles('setup.py') }}-${{ matrix.tensorflow-version }}
- name: Install dependencies
run: pip install -e ".[tests]" && pip install opencv-python && pip install tensorflow==${{ matrix.tensorflow-version }}
- name: Test with pytest
run: make test
3 changes: 2 additions & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ disable=bad-continuation,
import-error,
too-few-public-methods,
too-many-arguments,
unused-argument
unused-argument,
not-context-manager

# Enable the message, report, category or checker with the given id(s). You can
# either give multiple identifier separated by comma (,) or put this option
Expand Down
27 changes: 0 additions & 27 deletions .travis.yml

This file was deleted.

15 changes: 9 additions & 6 deletions tests/core/test_occlusion_sensitivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ def test_should_get_sensitivity_map(convolutional_model, random_data, mocker):
x, y = random_data
patch_size = 4

predict_return_value = np.ones(
(
math.ceil(x[0].shape[0] / patch_size)
* math.ceil(x[0].shape[1] / patch_size),
1,
predict_return_value = (
np.ones(
(
math.ceil(x[0].shape[0] / patch_size)
* math.ceil(x[0].shape[1] / patch_size),
1,
)
)
) * np.expand_dims([0.6, 0.4], axis=0)
* np.expand_dims([0.6, 0.4], axis=0)
)
convolutional_model.predict = mocker.MagicMock(return_value=predict_return_value)
mocker.patch(
"tf_explain.core.occlusion_sensitivity.apply_grey_patch",
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/activations_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def __init__(
layers_name (List[str]): List of layer names to inspect
output_dir (str): Output directory path
"""
super(ActivationsVisualizationCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.layers_name = layers_name
self.output_dir = Path(output_dir) / datetime.now().strftime("%Y%m%d-%H%M%S.%f")
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/grad_cam.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(
layer_name (str): Targeted layer for GradCAM
output_dir (str): Output directory path
"""
super(GradCAMCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.layer_name = layer_name
self.class_index = class_index
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/integrated_gradients.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def __init__(
n_steps (int): Number of steps in the path
output_dir (str): Output directory path
"""
super(IntegratedGradientsCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.class_index = class_index
self.n_steps = n_steps
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/occlusion_sensitivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(
patch_size (int): Size of patch to apply on the image
output_dir (str): Output directory path
"""
super(OcclusionSensitivityCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.class_index = class_index
self.patch_size = patch_size
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/smoothgrad.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ def __init__(
noise (float): Standard deviation for noise normal distribution
output_dir (str): Output directory path
"""
super(SmoothGradCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.class_index = class_index
self.num_samples = num_samples
Expand Down
2 changes: 1 addition & 1 deletion tf_explain/callbacks/vanilla_gradients.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ def __init__(self, validation_data, class_index, output_dir=None):
class_index (int): Index of targeted class
num_samples (int): Number of noisy samples to generate for each input image
"""
super(VanillaGradientsCallback, self).__init__()
super().__init__()
self.validation_data = validation_data
self.class_index = class_index
if not output_dir:
Expand Down
1 change: 0 additions & 1 deletion tf_explain/core/grad_cam.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,6 @@ def infer_grad_cam_target_layer(model):
)

@staticmethod
@tf.function
def get_gradients_and_filters(
model, images, layer_name, class_index, use_guided_grads
):
Expand Down
7 changes: 6 additions & 1 deletion tf_explain/core/smoothgrad.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,12 @@ def get_averaged_gradients(noisy_images, model, class_index, num_samples):
"""
num_classes = model.output.shape[1]

expected_output = tf.one_hot([class_index] * noisy_images.shape[0], num_classes)
expected_output = tf.one_hot(
[class_index] * noisy_images.shape[0],
num_classes,
on_value=None,
off_value=None,
)

with tf.GradientTape() as tape:
inputs = tf.cast(noisy_images, tf.float32)
Expand Down
7 changes: 6 additions & 1 deletion tf_explain/core/vanilla_gradients.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ def compute_gradients(images, model, class_index):
"""
num_classes = model.output.shape[1]

expected_output = tf.one_hot([class_index] * images.shape[0], num_classes)
expected_output = tf.one_hot(
[class_index] * images.shape[0],
num_classes,
on_value=None,
off_value=None,
)

with tf.GradientTape() as tape:
inputs = tf.cast(images, tf.float32)
Expand Down
15 changes: 0 additions & 15 deletions tox.ini

This file was deleted.

0 comments on commit 7ad1f5d

Please sign in to comment.