Skip to content

Commit

Permalink
Adds compatibility with python 2.7 (#16)
Browse files Browse the repository at this point in the history
closes #16 

* Fixed Python 2.7 compatibility

* Removed residual debug print

* Fixed PEP8 compatibility

* added python 2.7 to travis config

* install python 2 requirements if python2.7

* addressing requested changes

* fixed bug in travis config
  • Loading branch information
wielandbrendel authored and jonasrauber committed Jun 19, 2017
1 parent 3b240cc commit 2498a0b
Show file tree
Hide file tree
Showing 25 changed files with 115 additions and 51 deletions.
4 changes: 3 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,19 @@ sudo: false
dist: trusty
language: python
python:
- 2.7
- 3.5
- 3.6
before_install:
- pip install -U pip
install:
- travis_wait travis_retry pip install --upgrade numpy
- travis_wait travis_retry pip install --upgrade scipy
- travis_wait travis_retry pip install -r requirements-dev.txt
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then travis_wait travis_retry pip install -r requirements-dev-py2.txt; else travis_wait travis_retry pip install -r requirements-dev.txt; fi
- travis_wait travis_retry pip install --upgrade tensorflow
- travis_wait travis_retry pip install --upgrade theano
- travis_wait travis_retry pip install --upgrade https://github.com/Lasagne/Lasagne/archive/master.zip
- if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install http://download.pytorch.org/whl/cu75/torch-0.1.12.post2-cp27-none-linux_x86_64.whl; fi
- if [[ $TRAVIS_PYTHON_VERSION == 3.5 ]]; then pip install http://download.pytorch.org/whl/cu75/torch-0.1.12.post2-cp35-cp35m-linux_x86_64.whl; fi
- if [[ $TRAVIS_PYTHON_VERSION == 3.6 ]]; then pip install http://download.pytorch.org/whl/cu75/torch-0.1.12.post2-cp36-cp36m-linux_x86_64.whl; fi
- travis_wait travis_retry pip install --upgrade keras
Expand Down
5 changes: 2 additions & 3 deletions foolbox/adversarial.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ def __init__(
criterion,
original_image,
original_class,
*,
distance=MSE):

self.__model = model
Expand Down Expand Up @@ -154,7 +153,7 @@ def in_bounds(self, input_):
min_, max_ = self.bounds()
return min_ <= input_.min() and input_.max() <= max_

def channel_axis(self, *, batch):
def channel_axis(self, batch):
"""Interface to model.channel_axis for attacks.
Parameters
Expand Down Expand Up @@ -202,7 +201,7 @@ def predictions(self, image, strict=True):
assert predictions.ndim == 1
return predictions, is_adversarial

def batch_predictions(self, images, *, increasing=False, strict=True):
def batch_predictions(self, images, increasing=False, strict=True):
"""Interface to model.batch_predictions for attacks.
Parameters
Expand Down
10 changes: 8 additions & 2 deletions foolbox/attacks/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import logging
from abc import ABC, abstractmethod
import sys
import abc
abstractmethod = abc.abstractmethod

if sys.version_info >= (3, 4):
ABC = abc.ABC
else:
ABC = abc.ABCMeta('ABC', (), {})

from ..adversarial import Adversarial
from ..criteria import Misclassification
Expand Down Expand Up @@ -36,7 +43,6 @@ def __call__(
self,
image,
label=None,
*,
unpack=True,
**kwargs):

Expand Down
1 change: 1 addition & 0 deletions foolbox/attacks/gradient.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import division
import numpy as np
from collections import Iterable

Expand Down
1 change: 1 addition & 0 deletions foolbox/attacks/gradientsign.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import division
import numpy as np
from collections import Iterable

Expand Down
15 changes: 11 additions & 4 deletions foolbox/attacks/lbfgs.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import division
import random
import logging

Expand Down Expand Up @@ -30,9 +31,14 @@ class LBFGSAttack(Attack):
"""

def __init__(self, *args, approximate_gradient=False, **kwargs):
super().__init__(*args, **kwargs)
self._approximate_gradient = approximate_gradient
def __init__(self, *args, **kwargs):
if 'approximate_gradient' in kwargs:
self._approximate_gradient = kwargs['approximate_gradient']
del kwargs['approximate_gradient']
super(LBFGSAttack, self).__init__(*args, **kwargs)
else:
self._approximate_gradient = False
super(LBFGSAttack, self).__init__(*args, **kwargs)

def name(self):
prefix = 'Approximate' if self._approximate_gradient else ''
Expand Down Expand Up @@ -212,4 +218,5 @@ class ApproximateLBFGSAttack(LBFGSAttack):

def __init__(self, *args, **kwargs):
assert 'approximate_gradient' not in kwargs
super().__init__(*args, approximate_gradient=True, **kwargs)
kwargs['approximate_gradient'] = True
super(ApproximateLBFGSAttack, self).__init__(*args, **kwargs)
8 changes: 4 additions & 4 deletions foolbox/attacks/localsearch.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import division
import numpy as np

from .base import Attack
Expand Down Expand Up @@ -117,7 +118,6 @@ def cyclic(r, Ibxy):
PxPy = random_locations()

for _ in range(R):

# Computing the function g using the neighborhood
L = [pert(Ii, p, x, y) for x, y in PxPy]

Expand Down Expand Up @@ -149,8 +149,8 @@ def score(It):
# Update a neighborhood of pixel locations for the next round
PxPy = [
(x, y)
for a, b in PxPy_star
for x in range(a - d, a + d + 1)
for y in range(b - d, b + d + 1)]
for _a, _b in PxPy_star
for x in range(_a - d, _a + d + 1)
for y in range(_b - d, _b + d + 1)]
PxPy = [(x, y) for x, y in PxPy if 0 <= x < w and 0 <= y < h]
PxPy = np.array(PxPy)
2 changes: 1 addition & 1 deletion foolbox/attacks/precomputed.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class PrecomputedImagesAttack(Attack):
"""

def __init__(self, input_images, output_images, *args, **kwargs):
super().__init__(*args, **kwargs)
super(PrecomputedImagesAttack, self).__init__(*args, **kwargs)

assert input_images.shape == output_images.shape

Expand Down
2 changes: 1 addition & 1 deletion foolbox/attacks/saltandpepper.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SaltAndPepperNoiseAttack(Attack):
"""

def _apply(self, a, *, epsilons=100, repetitions=10):
def _apply(self, a, epsilons=100, repetitions=10):
image = a.original_image
min_, max_ = a.bounds()
axis = a.channel_axis(batch=False)
Expand Down
2 changes: 1 addition & 1 deletion foolbox/attacks/slsqp.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class SLSQPAttack(Attack):
# is differentiable) and use this to provide constraint gradients

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
super(SLSQPAttack, self).__init__(*args, **kwargs)
self.last_result = None

def _apply(self, a):
Expand Down
22 changes: 14 additions & 8 deletions foolbox/criteria.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,14 @@
>>> criterion5 = criterion2 & criterion3
"""
import sys
import abc
abstractmethod = abc.abstractmethod

from abc import ABC, abstractmethod
if sys.version_info >= (3, 4):
ABC = abc.ABC
else:
ABC = abc.ABCMeta('ABC', (), {})

import numpy as np

Expand Down Expand Up @@ -127,7 +133,7 @@ class CombinedCriteria(Criterion):
"""

def __init__(self, *criteria):
super().__init__()
super(CombinedCriteria, self).__init__()
self._criteria = criteria

def name(self):
Expand Down Expand Up @@ -203,8 +209,8 @@ class TopKMisclassification(Criterion):
"""

def __init__(self, *, k):
super().__init__()
def __init__(self, k):
super(TopKMisclassification, self).__init__()
self.k = k

def name(self):
Expand Down Expand Up @@ -232,7 +238,7 @@ class TargetClass(Criterion):
"""

def __init__(self, target_class):
super().__init__()
super(TargetClass, self).__init__()
self._target_class = target_class

def target_class(self):
Expand Down Expand Up @@ -265,7 +271,7 @@ class OriginalClassProbability(Criterion):
"""

def __init__(self, p):
super().__init__()
super(OriginalClassProbability, self).__init__()
assert 0 <= p <= 1
self.p = p

Expand Down Expand Up @@ -299,8 +305,8 @@ class TargetClassProbability(Criterion):
"""

def __init__(self, target_class, *, p):
super().__init__()
def __init__(self, target_class, p):
super(TargetClassProbability, self).__init__()
self._target_class = target_class
assert 0 <= p <= 1
self.p = p
Expand Down
15 changes: 11 additions & 4 deletions foolbox/distances.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,16 @@
Distance
"""
from __future__ import division
import sys
import abc
abstractmethod = abc.abstractmethod

if sys.version_info >= (3, 4):
ABC = abc.ABC
else:
ABC = abc.ABCMeta('ABC', (), {})

from abc import ABC, abstractmethod
import functools
import numpy as np
from numbers import Number
Expand All @@ -50,7 +58,6 @@ def __init__(
self,
reference=None,
other=None,
*,
bounds=None,
value=None):

Expand Down Expand Up @@ -99,12 +106,12 @@ def __repr__(self):
def __eq__(self, other):
if other.__class__ != self.__class__:
raise TypeError('Comparisons are only possible between the same distance types.') # noqa: E501
return self.value.__eq__(other.value)
return self.value == other.value

def __lt__(self, other):
if other.__class__ != self.__class__:
raise TypeError('Comparisons are only possible between the same distance types.') # noqa: E501
return self.value.__lt__(other.value)
return self.value < other.value


class MeanSquaredDistance(Distance):
Expand Down
11 changes: 9 additions & 2 deletions foolbox/models/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import numpy as np
from abc import ABC, abstractmethod
import sys
import abc
abstractmethod = abc.abstractmethod

if sys.version_info >= (3, 4):
ABC = abc.ABC
else:
ABC = abc.ABCMeta('ABC', (), {})


class Model(ABC):
Expand All @@ -22,7 +29,7 @@ class Model(ABC):
"""

def __init__(self, *, bounds, channel_axis):
def __init__(self, bounds, channel_axis):
assert len(bounds) == 2
self._bounds = bounds
assert channel_axis in [0, 1, 2, 3]
Expand Down
6 changes: 3 additions & 3 deletions foolbox/models/keras.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import absolute_import
import warnings

import numpy as np

from .base import DifferentiableModel
Expand Down Expand Up @@ -28,13 +28,13 @@ class KerasModel(DifferentiableModel):
def __init__(
self,
model,
*,
bounds,
channel_axis=3,
predicts='probabilities',
preprocess_fn=None):

super().__init__(bounds=bounds, channel_axis=channel_axis)
super(KerasModel, self).__init__(bounds=bounds,
channel_axis=channel_axis)

from keras import backend as K

Expand Down
5 changes: 3 additions & 2 deletions foolbox/models/lasagne.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from __future__ import absolute_import
import numpy as np


Expand Down Expand Up @@ -25,11 +26,11 @@ def __init__(
self,
input_layer,
logits_layer,
*,
bounds,
channel_axis=1):

super().__init__(bounds=bounds, channel_axis=channel_axis)
super(LasagneModel, self).__init__(bounds=bounds,
channel_axis=channel_axis)

# delay import until class is instantiated
import theano as th
Expand Down
4 changes: 2 additions & 2 deletions foolbox/models/pytorch.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ class PyTorchModel(DifferentiableModel):
def __init__(
self,
model,
*,
bounds,
num_classes,
channel_axis=1,
cuda=True):

super().__init__(bounds=bounds, channel_axis=channel_axis)
super(PyTorchModel, self).__init__(bounds=bounds,
channel_axis=channel_axis)

self._num_classes = num_classes
self._model = model
Expand Down
6 changes: 3 additions & 3 deletions foolbox/models/tensorflow.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import absolute_import
import numpy as np

from .base import DifferentiableModel


Expand All @@ -24,11 +24,11 @@ def __init__(
self,
images,
logits,
*,
bounds,
channel_axis=3):

super().__init__(bounds=bounds, channel_axis=channel_axis)
super(TensorFlowModel, self).__init__(bounds=bounds,
channel_axis=channel_axis)

# delay import until class is instantiated
import tensorflow as tf
Expand Down
7 changes: 3 additions & 4 deletions foolbox/models/theano.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import absolute_import
import numpy as np


from .base import DifferentiableModel


Expand All @@ -27,12 +26,12 @@ def __init__(
self,
images,
logits,
*,
bounds,
num_classes,
channel_axis=1):

super().__init__(bounds=bounds, channel_axis=channel_axis)
super(TheanoModel, self).__init__(bounds=bounds,
channel_axis=channel_axis)

self._num_classes = num_classes

Expand Down
Loading

0 comments on commit 2498a0b

Please sign in to comment.