Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding compatibility with tensorflow2 #17

Merged
merged 7 commits into from
Apr 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 58 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@

name: Python package

on: [push, pull_request]
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
Expand All @@ -22,11 +22,13 @@ 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 .[openl3]
python -m pip install .[autopool]
python -m pip install .[tests]
- name: Lint with flake8
run: |
Expand All @@ -48,4 +50,55 @@ jobs:
name: codecov-umbrella
fail_ci_if_error: false
path_to_write_report: ./coverage/codecov_report.txt
verbose: true
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, 3.8]

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
- name: Install library
run: |
python -m pip install .[tf2]
python -m pip install .[tests]
- name: Test with pytest
run: |
pytest --cov-report term-missing --cov-report=xml --cov dcase_models ./tests
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

</pre>

![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)

Expand All @@ -31,16 +33,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 the tensorflow variant: version 1 (CPU-only or GPU) or version 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
Comment on lines +38 to +40
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool :)

```

Then to install the package:
```
pip install DCASE-models
```
To include visualization related dependencies, run the following instead:
```
pip install DCASE-models[visualization]
Expand Down
8 changes: 7 additions & 1 deletion dcase_models/data/data_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 6 additions & 2 deletions dcase_models/data/features.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import numpy as np
import librosa
import openl3
import inspect
import sys

Expand Down Expand Up @@ -415,14 +414,19 @@ 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
self.content_type = content_type
self.input_repr = input_repr
self.embedding_size = embedding_size
self.openl3 = openl3.models.load_audio_embedding_model(
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,
Expand Down
22 changes: 17 additions & 5 deletions dcase_models/model/container.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)

Expand Down
48 changes: 35 additions & 13 deletions dcase_models/model/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
9 changes: 8 additions & 1 deletion dcase_models/util/callbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
28 changes: 14 additions & 14 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,22 @@
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',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need pandas?

Copy link
Collaborator Author

@pzinemanas pzinemanas Apr 30, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we have to implement a read_csv function which is the only thing we are using from pandas (see #18 )

'SoundFile>=0.1',
'PyYAML>=5.0',
'librosa>=0.7',
'scikit-learn>=0.20',
'wget>=3.0',
'sox<1.4',
'sed_eval>=0.2',
],
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'],
'docs': ['numpydoc', 'sphinx!=1.3.1', 'sphinx_rtd_theme'],
'tests': ['pytest >= 5.4.3', 'pytest-cov >= 2.11.1'],
'visualization': [
Expand Down
12 changes: 10 additions & 2 deletions tests/test_container.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down
12 changes: 12 additions & 0 deletions tests/test_features.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand Down Expand Up @@ -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)
Expand Down
19 changes: 14 additions & 5 deletions tests/test_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -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():
Expand All @@ -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():
Expand Down