From 4abc0413dd1c253e4fc72651c7c25ec803f68815 Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 13:11:08 +0200 Subject: [PATCH 1/7] First commit of tensorflow2 compatibility --- .github/workflows/main.yml | 26 +++++++++++++++- dcase_models/data/data_generator.py | 8 ++++- dcase_models/data/features.py | 6 ++-- dcase_models/model/container.py | 22 ++++++++++--- dcase_models/model/models.py | 48 +++++++++++++++++++++-------- dcase_models/util/callbacks.py | 9 +++++- setup.py | 23 ++++++-------- tests/test_container.py | 12 ++++++-- tests/test_features.py | 12 ++++++++ tests/test_models.py | 19 +++++++++--- 10 files changed, 141 insertions(+), 44 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 2032fa6..f45b305 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -48,4 +48,28 @@ jobs: name: codecov-umbrella fail_ci_if_error: false path_to_write_report: ./coverage/codecov_report.txt - verbose: true \ No newline at end of file + verbose: true + + build_tf2: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.6, 3.7] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + sudo apt-get install -y wget libsndfile-dev sox + python -m pip install "tensorflow>2.0" + - name: Install library + run: | + python -m pip install .[tests] + - name: Test with pytest + run: | + pytest --cov-report term-missing --cov-report=xml --cov dcase_models ./tests diff --git a/dcase_models/data/data_generator.py b/dcase_models/data/data_generator.py index 44400bc..91cbd64 100644 --- a/dcase_models/data/data_generator.py +++ b/dcase_models/data/data_generator.py @@ -3,7 +3,13 @@ import inspect import random -from keras.utils import Sequence +import tensorflow as tf +tensorflow2 = tf.__version__.split('.')[0] == '2' + +if tensorflow2: + from tensorflow.keras.utils import Sequence +else: + from keras.utils import Sequence from dcase_models.data.feature_extractor import FeatureExtractor from dcase_models.data.dataset_base import Dataset diff --git a/dcase_models/data/features.py b/dcase_models/data/features.py index e1106e7..9194a27 100644 --- a/dcase_models/data/features.py +++ b/dcase_models/data/features.py @@ -1,6 +1,5 @@ import numpy as np import librosa -import openl3 import inspect import sys @@ -415,7 +414,9 @@ def __init__(self, sequence_time=1.0, sequence_hop_time=0.5, sequence_hop_time=sequence_hop_time, audio_win=audio_win, audio_hop=audio_hop, sr=sr) - + if tensorflow2: + raise ImportError("Openl3 requires tensorflow1") + import openl3 self.content_type = content_type self.input_repr = input_repr self.embedding_size = embedding_size @@ -423,6 +424,7 @@ def __init__(self, sequence_time=1.0, sequence_hop_time=0.5, input_repr, content_type, embedding_size) def calculate(self, file_name): + import openl3 audio = self.load_audio(file_name, change_sampling_rate=False) emb, ts = openl3.get_audio_embedding( audio, self.sr, diff --git a/dcase_models/model/container.py b/dcase_models/model/container.py index 9e2fe6d..bcc9b36 100644 --- a/dcase_models/model/container.py +++ b/dcase_models/model/container.py @@ -2,10 +2,19 @@ import os import json -import keras.backend as K -from keras.callbacks import CSVLogger, ModelCheckpoint -from keras.models import model_from_json, Model -from keras.layers import Dense, Input +import tensorflow as tf +tensorflow2 = tf.__version__.split('.')[0] == '2' + +if tensorflow2: + import tensorflow.keras.backend as K + from tensorflow.keras.callbacks import CSVLogger, ModelCheckpoint + from tensorflow.keras.models import model_from_json, Model + from tensorflow.keras.layers import Dense, Input +else: + import keras.backend as K + from keras.callbacks import CSVLogger, ModelCheckpoint + from keras.models import model_from_json, Model + from keras.layers import Dense, Input from dcase_models.util.files import save_json from dcase_models.util.metrics import evaluate_metrics @@ -197,7 +206,10 @@ def train(self, data_train, data_val, weights_path='./', Verbose mode for fit method of Keras model """ - import keras.optimizers as optimizers + if tensorflow2: + import tensorflow.keras.optimizers as optimizers + else: + import keras.optimizers as optimizers optimizer_function = getattr(optimizers, optimizer) opt = optimizer_function(lr=learning_rate) diff --git a/dcase_models/model/models.py b/dcase_models/model/models.py index 59070da..490769f 100644 --- a/dcase_models/model/models.py +++ b/dcase_models/model/models.py @@ -3,19 +3,37 @@ import sys import os -from keras.layers import GRU, Bidirectional -from keras.layers import TimeDistributed, Activation, Reshape -from keras.layers import GlobalAveragePooling2D -from keras.layers import GlobalMaxPooling2D -from keras.layers import Input, Lambda, Conv2D, MaxPooling2D -from keras.layers import Conv1D -from keras.layers import Dropout, Dense, Flatten -from keras.layers import BatchNormalization -from keras.layers import Layer -from keras.models import Model -from keras.regularizers import l2 -import keras.backend as K -from autopool import AutoPool1D +import tensorflow as tf +tensorflow2 = tf.__version__.split('.')[0] == '2' + +if tensorflow2: + from tensorflow.keras.layers import GRU, Bidirectional + from tensorflow.keras.layers import TimeDistributed, Activation, Reshape + from tensorflow.keras.layers import GlobalAveragePooling2D + from tensorflow.keras.layers import GlobalMaxPooling2D + from tensorflow.keras.layers import Input, Lambda, Conv2D, MaxPooling2D + from tensorflow.keras.layers import Conv1D + from tensorflow.keras.layers import Dropout, Dense, Flatten + from tensorflow.keras.layers import BatchNormalization + from tensorflow.keras.layers import Layer + from tensorflow.keras.models import Model + from tensorflow.keras.regularizers import l2 + import tensorflow.keras.backend as K +else: + from keras.layers import GRU, Bidirectional + from keras.layers import TimeDistributed, Activation, Reshape + from keras.layers import GlobalAveragePooling2D + from keras.layers import GlobalMaxPooling2D + from keras.layers import Input, Lambda, Conv2D, MaxPooling2D + from keras.layers import Conv1D + from keras.layers import Dropout, Dense, Flatten + from keras.layers import BatchNormalization + from keras.layers import Layer + from keras.models import Model + from keras.regularizers import l2 + import keras.backend as K + + from tensorflow import clip_by_value from dcase_models.model.container import KerasModelContainer @@ -167,6 +185,10 @@ def build(self): elif self.temporal_integration == 'sum': y = Lambda(lambda x: K.sum(x, 1), name='temporal_integration')(y) elif self.temporal_integration == 'autopool': + try: + from autopool import AutoPool1D + except: + raise ImportError("Autopool is not installed") y = AutoPool1D(axis=1, name='output')(y) # Create model diff --git a/dcase_models/util/callbacks.py b/dcase_models/util/callbacks.py index d47020e..8c31b6b 100644 --- a/dcase_models/util/callbacks.py +++ b/dcase_models/util/callbacks.py @@ -2,7 +2,14 @@ """Callback functions""" from dcase_models.util.metrics import evaluate_metrics -from keras.callbacks import Callback + +import tensorflow as tf +tensorflow2 = tf.__version__.split('.')[0] == '2' + +if tensorflow2: + from tensorflow.keras.callbacks import Callback +else: + from keras.callbacks import Callback eps = 1e-6 diff --git a/setup.py b/setup.py index ac39b1c..e3e3419 100644 --- a/setup.py +++ b/setup.py @@ -19,20 +19,15 @@ download_url='http://github.com/pzinemanas/DCASE-models/releases', packages=setuptools.find_packages(), install_requires=[ - 'numpy==1.17.4', - 'pandas==0.25.3', - 'SoundFile==0.10.3.post1', - 'PyYAML==5.2', - 'numba==0.48.0', - 'librosa==0.7.1', - 'openl3==0.3.1', - 'scikit-learn==0.22.1', - 'keras==2.2.4', - # 'tensorflow-gpu==1.12.0', - 'autopool==0.1.0', - 'wget==3.2', - 'sox==1.3.7', - 'sed_eval==0.2.1', + 'numpy>=1.1', + 'pandas>=0.25', + 'SoundFile>=0.1', + 'PyYAML>=5.0', + 'librosa>=0.7', + 'scikit-learn>=0.20', + 'wget>=3.0', + 'sox>=1.3', + 'sed_eval>=0.2', ], extras_require={ 'docs': ['numpydoc', 'sphinx!=1.3.1', 'sphinx_rtd_theme'], diff --git a/tests/test_container.py b/tests/test_container.py index 19632ea..f7d17d2 100644 --- a/tests/test_container.py +++ b/tests/test_container.py @@ -1,8 +1,16 @@ from dcase_models.model.container import ModelContainer, KerasModelContainer from dcase_models.data.data_generator import KerasDataGenerator -from keras.layers import Input, Dense -from keras.models import Model +import tensorflow as tf + +tensorflow2 = tf.__version__.split(".")[0] == "2" + +if tensorflow2: + from tensorflow.keras.layers import Input, Dense + from tensorflow.keras.models import Model +else: + from keras.layers import Input, Dense + from keras.models import Model import os import numpy as np diff --git a/tests/test_features.py b/tests/test_features.py index d77ada7..8a72a1f 100644 --- a/tests/test_features.py +++ b/tests/test_features.py @@ -5,12 +5,22 @@ from dcase_models.data.data_generator import DataGenerator from dcase_models.util.files import load_json, mkdir_if_not_exists + +try: + import openl3 +except: + Openl3 = None + import os import numpy as np import pytest import shutil import librosa +import tensorflow as tf + +tensorflow2 = tf.__version__.split(".")[0] == "2" + def test_spectrogram(): feature_extractor = Spectrogram(pad_mode="constant") @@ -60,6 +70,8 @@ def test_mfcc(): assert shape == (1, 32, 20) +@pytest.mark.skipif(tensorflow2, reason="Openl3 requires tensorflow1") +@pytest.mark.skipif(Openl3 is None, reason="Openl3 is not installed") def test_openl3(): feature_extractor = Openl3() shape = feature_extractor.get_shape(2.0) diff --git a/tests/test_models.py b/tests/test_models.py index 93a3580..b320d71 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -16,6 +16,14 @@ import os import numpy as np import pytest +import tensorflow as tf + +tensorflow2 = tf.__version__.split(".")[0] == "2" + +try: + import autopool +except: + autopool = None def test_mlp(): @@ -37,11 +45,12 @@ def test_mlp(): outputs = model_container.model.predict(inputs) assert outputs.shape == (3, 10) - model_container = MLP(temporal_integration="autopool") - assert len(model_container.model.layers) == 7 - inputs = np.zeros((3, 64, 12)) - outputs = model_container.model.predict(inputs) - assert outputs.shape == (3, 10) + if (not tensorflow2) & (autopool is not None): + model_container = MLP(temporal_integration="autopool") + assert len(model_container.model.layers) == 7 + inputs = np.zeros((3, 64, 12)) + outputs = model_container.model.predict(inputs) + assert outputs.shape == (3, 10) def test_sb_cnn(): From 967269bec4cc4d69109227f6e20c232dde6d5747 Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 15:06:40 +0200 Subject: [PATCH 2/7] Change version of dependendencies --- .github/workflows/main.yml | 4 ++-- setup.py | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f45b305..1febb42 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,11 +22,11 @@ jobs: - name: Install dependencies run: | sudo apt-get install -y wget libsndfile-dev sox - python -m pip install "tensorflow<1.14" python -m pip install flake8 python -m pip install 'h5py==2.10.0' --force-reinstall - name: Install library run: | + python -m pip install .[keras_tf] python -m pip install .[tests] - name: Lint with flake8 run: | @@ -66,9 +66,9 @@ jobs: - name: Install dependencies run: | sudo apt-get install -y wget libsndfile-dev sox - python -m pip install "tensorflow>2.0" - name: Install library run: | + python -m pip install .[tf2] python -m pip install .[tests] - name: Test with pytest run: | diff --git a/setup.py b/setup.py index e3e3419..abfb422 100644 --- a/setup.py +++ b/setup.py @@ -26,10 +26,14 @@ 'librosa>=0.7', 'scikit-learn>=0.20', 'wget>=3.0', - 'sox>=1.3', + 'sox<1.4', 'sed_eval>=0.2', ], extras_require={ + 'keras_tf': ['tensorflow<1.14', 'keras==2.2.4'], + 'tf2': ['tensorflow>2.0'], + 'openl3': ['openl3==0.3.1'], + 'autopool': ['autopool==0.1.0'], 'docs': ['numpydoc', 'sphinx!=1.3.1', 'sphinx_rtd_theme'], 'tests': ['pytest >= 5.4.3', 'pytest-cov >= 2.11.1'], 'visualization': [ From 75e225387523f2ec1115eb9e533fb0e426ab87c1 Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 15:10:35 +0200 Subject: [PATCH 3/7] Fix minor bug --- dcase_models/data/features.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dcase_models/data/features.py b/dcase_models/data/features.py index 9194a27..a70f41a 100644 --- a/dcase_models/data/features.py +++ b/dcase_models/data/features.py @@ -414,6 +414,8 @@ def __init__(self, sequence_time=1.0, sequence_hop_time=0.5, sequence_hop_time=sequence_hop_time, audio_win=audio_win, audio_hop=audio_hop, sr=sr) + import tensorflow as tf + tensorflow2 = tf.__version__.split('.')[0] == '2' if tensorflow2: raise ImportError("Openl3 requires tensorflow1") import openl3 From 3bf260fc6de1f0153f292d6b0eaf098708ceaac1 Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 15:32:39 +0200 Subject: [PATCH 4/7] Update README and add option in setup.py for tf1-gpu --- README.md | 10 ++++------ setup.py | 1 + 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8bc92d3..9de68fa 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,13 @@ DCASE-models uses [SoX](http://sox.sourceforge.net/) for functions related to th ``` conda install -c conda-forge sox ``` -Before installing the library, you must install only one of the Tensorflow variants: CPU-only or GPU. +When installing the library, you must select only one of the Tensorflow variants: tensorflow v1 CPU-only or GPU; or tensorflow v. 2. ``` -pip install "tensorflow<1.14" # for CPU-only version -pip install "tensorflow-gpu<1.14" # for GPU version +pip install DCASE-models[keras_tf] # for tensorflow 1 CPU-only version +pip install DCASE-models[keras_tf_gpu] # for tensorflow 1 GPU version +pip install DCASE-models[tf2] # for tensorflow 2 ``` -Then to install the package: -``` -pip install DCASE-models ``` To include visualization related dependencies, run the following instead: ``` diff --git a/setup.py b/setup.py index abfb422..7b9000e 100644 --- a/setup.py +++ b/setup.py @@ -31,6 +31,7 @@ ], extras_require={ 'keras_tf': ['tensorflow<1.14', 'keras==2.2.4'], + 'keras_tf_gpu': ['tensorflow-gpu<1.14', 'keras==2.2.4'], 'tf2': ['tensorflow>2.0'], 'openl3': ['openl3==0.3.1'], 'autopool': ['autopool==0.1.0'], From e5093130e9348ad039869212f5393c9d6a1f8d0e Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 15:58:57 +0200 Subject: [PATCH 5/7] Update README.md --- README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9de68fa..30d3a55 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ +![example workflow](https://github.com/MTG/DCASE-models/actions/workflows/main.yml/badge.svg) +[![codecov](https://codecov.io/gh/MTG/DCASE-models/branch/master/graph/badge.svg?token=xOOVldiH0J)](https://codecov.io/gh/MTG/DCASE-models) [![PyPI](https://img.shields.io/pypi/v/DCASE-models)](https://pypi.org/project/DCASE-models/) [![GitHub license](https://img.shields.io/github/license/pzinemanas/DCASE-models)](https://github.com/pzinemanas/DCASE-models/blob/master/LICENSE) @@ -31,14 +33,13 @@ DCASE-models uses [SoX](http://sox.sourceforge.net/) for functions related to th ``` conda install -c conda-forge sox ``` -When installing the library, you must select only one of the Tensorflow variants: tensorflow v1 CPU-only or GPU; or tensorflow v. 2. +When installing the library, you must select the tensorflow variant: version 1 (CPU-only or GPU) or version 2. ``` pip install DCASE-models[keras_tf] # for tensorflow 1 CPU-only version pip install DCASE-models[keras_tf_gpu] # for tensorflow 1 GPU version pip install DCASE-models[tf2] # for tensorflow 2 ``` -``` To include visualization related dependencies, run the following instead: ``` pip install DCASE-models[visualization] From 8f3d64ffd2db45398ff07646ac22eb9f81e82be7 Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Thu, 29 Apr 2021 16:25:08 +0200 Subject: [PATCH 6/7] Update main.yml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1febb42..34c602a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -3,7 +3,7 @@ name: Python package -on: [push, pull_request] +on: [push] jobs: build: From 701a9b7845aab6996f0cf62e226c643e9104b71a Mon Sep 17 00:00:00 2001 From: Pablo Zinemanas Date: Fri, 30 Apr 2021 14:06:13 +0200 Subject: [PATCH 7/7] Add build for py38 --- .github/workflows/main.yml | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 34c602a..2fd313b 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -6,12 +6,12 @@ name: Python package on: [push] jobs: - build: + build_py36: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7] + python-version: [3.6] steps: - uses: actions/checkout@v2 @@ -26,7 +26,9 @@ jobs: python -m pip install 'h5py==2.10.0' --force-reinstall - name: Install library run: | - python -m pip install .[keras_tf] + python -m pip install .[keras_tf] + python -m pip install .[openl3] + python -m pip install .[autopool] python -m pip install .[tests] - name: Lint with flake8 run: | @@ -50,12 +52,39 @@ jobs: path_to_write_report: ./coverage/codecov_report.txt verbose: true + build_py37: + + runs-on: ubuntu-latest + strategy: + matrix: + python-version: [3.7] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + sudo apt-get install -y wget libsndfile-dev sox + python -m pip install flake8 + python -m pip install 'h5py==2.10.0' --force-reinstall + - name: Install library + run: | + python -m pip install .[keras_tf] + python -m pip install .[tests] + - name: Test with pytest + run: | + pytest --cov-report term-missing --cov-report=xml --cov dcase_models ./tests + + build_tf2: runs-on: ubuntu-latest strategy: matrix: - python-version: [3.6, 3.7] + python-version: [3.6, 3.7, 3.8] steps: - uses: actions/checkout@v2