From 7ce170ffbdc8b643eebf6bc843c326534f512270 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sat, 19 Jan 2019 15:03:36 +0100 Subject: [PATCH 1/5] BUG: allow to import keras from tensorflow --- doc/whats_new/v0.5.rst | 8 ++++++++ imblearn/keras/_generator.py | 13 ++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/doc/whats_new/v0.5.rst b/doc/whats_new/v0.5.rst index 964a4ad7b..0f2a83583 100644 --- a/doc/whats_new/v0.5.rst +++ b/doc/whats_new/v0.5.rst @@ -22,3 +22,11 @@ Maintenance - Make it possible to ``import imblearn`` and access submodule. :issue:`500` by :user:`Guillaume Lemaitre `. + + +Bug +... + +- Allow to import ``keras`` directly from ``tensorflow`` in the + :mod:`imblearn.keras`. + :issue:`352` by :user:`Guillaume Lemaitre `. diff --git a/imblearn/keras/_generator.py b/imblearn/keras/_generator.py index 4ac793b5e..d387d885b 100644 --- a/imblearn/keras/_generator.py +++ b/imblearn/keras/_generator.py @@ -5,12 +5,19 @@ # avoid the error when importing the package raise the error at the moment of # creating the instance. try: - import keras + # try to import keras from tensorflow + from tensorflow import keras ParentClass = keras.utils.Sequence HAS_KERAS = True except ImportError: - ParentClass = object - HAS_KERAS = False + try: + # if no present in tensorflow, try to import keras directly + import keras + ParentClass = keras.utils.Sequence + HAS_KERAS = True + except ImportError: + ParentClass = object + HAS_KERAS = False from scipy.sparse import issparse From b3863ee30ffcdd48678fa6fda2027e9d83756b41 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Sat, 19 Jan 2019 16:55:49 +0100 Subject: [PATCH 2/5] add duck-typing flag for keras --- imblearn/keras/_generator.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/imblearn/keras/_generator.py b/imblearn/keras/_generator.py index d387d885b..c22c65af0 100644 --- a/imblearn/keras/_generator.py +++ b/imblearn/keras/_generator.py @@ -109,6 +109,10 @@ class BalancedBatchGenerator(ParentClass): ... epochs=10, verbose=0) """ + + # flag for keras sequence duck-typing + use_sequence_api = True + def __init__(self, X, y, sample_weight=None, sampler=None, batch_size=32, keep_sparse=False, random_state=None): if not HAS_KERAS: From 4a6a618b90dcf59fafe6318ef200cb2a3c97142f Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Wed, 12 Jun 2019 23:21:39 +0200 Subject: [PATCH 3/5] iter --- imblearn/keras/_generator.py | 52 +++++++++++++++++++++++++----------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/imblearn/keras/_generator.py b/imblearn/keras/_generator.py index c22c65af0..12f08e9df 100644 --- a/imblearn/keras/_generator.py +++ b/imblearn/keras/_generator.py @@ -1,23 +1,43 @@ """Implement generators for ``keras`` which will balance the data.""" -from __future__ import division + # This is a trick to avoid an error during tests collection with pytest. We # avoid the error when importing the package raise the error at the moment of # creating the instance. -try: - # try to import keras from tensorflow - from tensorflow import keras - ParentClass = keras.utils.Sequence - HAS_KERAS = True -except ImportError: - try: - # if no present in tensorflow, try to import keras directly - import keras - ParentClass = keras.utils.Sequence - HAS_KERAS = True - except ImportError: - ParentClass = object - HAS_KERAS = False +def import_keras(): + """Try to import keras from keras and tensorflow. + + This is possible to import the sequence from keras or tensorflow. + Keras is not ducktyping ``Sequence`` before 2.3 and we need import from + all possible library to ensure that the ``isinstance(...)`` is not going + to fail. This function can be modified when we support Keras 2.3. + """ + + def import_from_keras(): + try: + import keras + return (keras.utils.Sequence,), True + except ImportError: + return tuple(), False + + def import_from_tensforflow(): + try: + from tensorflow import keras + return (keras.utils.Sequence,), True + except ImportError: + return tuple(), False + + ParentClassKeras, has_keras_k = import_from_keras() + ParentClassTensorflow, has_keras_tf = import_from_tensforflow() + has_keras = has_keras_k or has_keras_tf + if has_keras: + ParentClass = (ParentClassKeras + ParentClassTensorflow) + else: + ParentClass = tuple(object) + return ParentClass, has_keras + + +ParentClass, HAS_KERAS = import_keras() from scipy.sparse import issparse @@ -36,7 +56,7 @@ 'NeighbourhoodCleaningRule', 'TomekLinks') -class BalancedBatchGenerator(ParentClass): +class BalancedBatchGenerator(*ParentClass): """Create balanced batches when training a keras model. Create a keras ``Sequence`` which is given to ``fit_generator``. The From 5c8b122f6d3ffa178b4e2927bf3b0f43ef9a4591 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Wed, 12 Jun 2019 23:26:30 +0200 Subject: [PATCH 4/5] iter --- doc/whats_new/v0.5.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/whats_new/v0.5.rst b/doc/whats_new/v0.5.rst index b1787d4cf..0c01d561c 100644 --- a/doc/whats_new/v0.5.rst +++ b/doc/whats_new/v0.5.rst @@ -58,7 +58,7 @@ Bug ``porto_seguro_keras_under_sampling.py`` example. The batch normalization was moved before the activation function and the bias was removed from the dense layer. - :issue:`531` by :user:`Guillaume Lemaitre `. + :pr:`531` by :user:`Guillaume Lemaitre `. - Fix bug which converting to COO format sparse when stacking the matrices in :class:`imblearn.over_sampling.SMOTENC`. This bug was only old scipy version. From cb4008b8cede5cb9199526961c7062b2edd86d21 Mon Sep 17 00:00:00 2001 From: Guillaume Lemaitre Date: Wed, 12 Jun 2019 23:34:53 +0200 Subject: [PATCH 5/5] iter --- imblearn/keras/_generator.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/imblearn/keras/_generator.py b/imblearn/keras/_generator.py index 12f08e9df..75f371e5e 100644 --- a/imblearn/keras/_generator.py +++ b/imblearn/keras/_generator.py @@ -33,7 +33,7 @@ def import_from_tensforflow(): if has_keras: ParentClass = (ParentClassKeras + ParentClassTensorflow) else: - ParentClass = tuple(object) + ParentClass = (object,) return ParentClass, has_keras