├── .coveragerc ├── .gitignore ├── .travis.yml ├── .travis └── install_cntk.sh ├── CODEOWNERS ├── CONTRIBUTING.md ├── GUIDELINES.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── contrib_docs ├── README.md ├── pydocmd.yml └── theme │ ├── 404.html │ ├── base.html │ ├── breadcrumbs.html │ ├── css │ ├── theme.css │ └── theme_extra.css │ ├── footer.html │ ├── js │ ├── jquery-2.1.1.min.js │ ├── modernizr-2.8.3.min.js │ └── theme.js │ ├── main.html │ ├── nav.html │ ├── search.html │ ├── searchbox.html │ ├── toc.html │ └── versions.html ├── convert_to_tf_keras.py ├── examples ├── .gitkeep ├── cifar10_clr.py ├── cifar10_densenet.py ├── cifar10_nasnet.py ├── cifar10_resnet.py ├── cifar10_ror.py ├── cifar10_wide_resnet.py ├── conll2000_chunking_crf.py ├── improved_wgan.py └── jaccard_loss.py ├── keras_contrib ├── __init__.py ├── activations │ ├── __init__.py │ └── squash.py ├── applications │ ├── __init__.py │ ├── densenet.py │ ├── nasnet.py │ ├── resnet.py │ └── wide_resnet.py ├── backend │ ├── __init__.py │ ├── cntk_backend.py │ ├── numpy_backend.py │ ├── tensorflow_backend.py │ └── theano_backend.py ├── callbacks │ ├── __init__.py │ ├── cyclical_learning_rate.py │ ├── dead_relu_detector.py │ ├── snapshot.py │ └── tensorboard.py ├── constraints │ ├── __init__.py │ └── clip.py ├── datasets │ ├── __init__.py │ ├── coco.py │ ├── conll2000.py │ └── pascal_voc.py ├── initializers │ ├── __init__.py │ └── convaware.py ├── layers │ ├── __init__.py │ ├── advanced_activations │ │ ├── __init__.py │ │ ├── pelu.py │ │ ├── sinerelu.py │ │ ├── srelu.py │ │ └── swish.py │ ├── capsule.py │ ├── convolutional │ │ ├── __init__.py │ │ ├── cosineconvolution2d.py │ │ └── subpixelupscaling.py │ ├── core.py │ ├── crf.py │ └── normalization │ │ ├── __init__.py │ │ ├── groupnormalization.py │ │ └── instancenormalization.py ├── losses │ ├── __init__.py │ ├── crf_losses.py │ ├── dssim.py │ └── jaccard.py ├── metrics │ ├── __init__.py │ └── crf_accuracies.py ├── optimizers │ ├── __init__.py │ ├── ftml.py │ ├── lars.py │ ├── padam.py │ └── yogi.py ├── preprocessing │ └── __init__.py ├── regularizers │ └── __init__.py ├── tests │ ├── __init__.py │ ├── activations.py │ ├── metrics.py │ ├── optimizers.py │ └── regularizers.py ├── utils │ ├── __init__.py │ ├── conv_utils.py │ ├── save_load_utils.py │ └── test_utils.py └── wrappers │ └── __init__.py ├── pytest.ini ├── setup.py └── tests ├── conftest.py ├── keras_contrib ├── activations │ ├── .gitkeep │ └── test_squash.py ├── backend │ └── backend_test.py ├── callbacks │ ├── cyclical_learning_rate_test.py │ ├── dead_relu_detector_test.py │ └── tensorboard_test.py ├── constraints_test.py ├── datasets │ └── test_datasets.py ├── initializers_test.py ├── layers │ ├── advanced_activations │ │ ├── test_pelu.py │ │ ├── test_sinerelu.py │ │ ├── test_srelu.py │ │ └── test_swish.py │ ├── convolutional │ │ ├── test_cosineconvolution2d.py │ │ └── test_subpixelupscaling.py │ ├── normalization │ │ ├── test_groupnormalization.py │ │ └── test_instancenormalization.py │ ├── test_capsule.py │ ├── test_core.py │ └── test_crf.py ├── losses │ ├── dssim_test.py │ └── jaccard_test.py ├── metrics │ └── .gitkeep ├── optimizers │ ├── ftml_test.py │ ├── lars_test.py │ ├── padam_test.py │ └── yogi_test.py ├── preprocessing │ └── .gitkeep ├── regularizers │ └── .gitkeep ├── utils │ └── save_load_utils_test.py └── wrappers │ └── .gitkeep └── tooling ├── test_codeowners.py ├── test_doc_auto_generation.py └── test_documentation.py /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | # Regexes for lines to exclude from consideration 3 | exclude_lines = 4 | os.remove 5 | except ImportError 6 | # Don't complain if tests don't hit defensive assertion code: 7 | raise ImportError 8 | raise NotImplementedError 9 | 10 | # Don't complain if legacy support codes are not performed: 11 | if original_keras_version == '1': 12 | 13 | show_missing = True 14 | omit = 15 | keras_contrib/backend/theano_backend.py 16 | keras_contrib/backend/tensorflow_backend.py 17 | keras_contrib/backend/cntk_backend.py 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # PyCharms 38 | *.xml 39 | *.iml 40 | .idea/ 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *,cover 51 | .hypothesis/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | 61 | # Flask stuff: 62 | instance/ 63 | .webassets-cache 64 | 65 | # Scrapy stuff: 66 | .scrapy 67 | 68 | # Sphinx documentation 69 | docs/_build/ 70 | 71 | # PyBuilder 72 | target/ 73 | 74 | # IPython Notebook 75 | .ipynb_checkpoints 76 | 77 | # pyenv 78 | .python-version 79 | 80 | # celery beat schedule file 81 | celerybeat-schedule 82 | 83 | # dotenv 84 | .env 85 | 86 | # virtualenv 87 | venv/ 88 | ENV/ 89 | 90 | # Spyder project settings 91 | .spyderproject 92 | 93 | # Rope project settings 94 | .ropeproject 95 | 96 | # developer environments 97 | .idea 98 | 99 | *.DS_Store 100 | 101 | contrib_docs/site/* 102 | contrib_docs/sources/* 103 | contrib_docs/theme/fonts/* 104 | contrib_docs/theme/img/* 105 | 106 | .pytest_cache/* 107 | 108 | contrib_docs/_build/ 109 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | dist: trusty 3 | language: python 4 | cache: 5 | directories: 6 | - $HOME/.theano 7 | matrix: 8 | include: 9 | - python: 3.6 10 | env: KERAS_BACKEND=tensorflow TEST_MODE=PEP8_DOC 11 | - python: 2.7 12 | env: KERAS_BACKEND=tensorflow 13 | - python: 3.6 14 | env: KERAS_BACKEND=tensorflow 15 | - python: 3.6 16 | env: KERAS_BACKEND=tensorflow USE_TF_KERAS=1 PYTEST_IGNORE='--ignore=tests/test_doc_auto_generation.py --ignore=tests/keras_contrib/backend --ignore=tests/keras_contrib/utils/save_load_utils_test.py' 17 | - python: 3.6 18 | env: KERAS_BACKEND=theano THEANO_FLAGS=optimizer=fast_compile 19 | # - python: 3.6 20 | # env: KERAS_BACKEND=cntk PYTHONWARNINGS=ignore 21 | install: 22 | # code below is taken from http://conda.pydata.org/docs/travis.html 23 | # We do this conditionally because it saves us some downloading if the 24 | # version is the same. 25 | - if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then 26 | wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh; 27 | else 28 | wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 29 | fi 30 | - bash miniconda.sh -b -p $HOME/miniconda 31 | - export PATH="$HOME/miniconda/bin:$PATH" 32 | - hash -r 33 | - conda config --set always_yes yes --set changeps1 no 34 | - conda update -q conda 35 | # Useful for debugging any issues with conda 36 | - conda info -a 37 | 38 | - travis_retry conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION 39 | - source activate test-environment 40 | 41 | - travis_retry pip install --only-binary=numpy,scipy,pandas numpy nose scipy h5py theano pydoc-markdown pytest pytest-pep8 pandas pygithub --progress-bar off 42 | - if [[ "$USE_TF_KERAS" == "" ]]; then 43 | pip install git+https://github.com/keras-team/keras.git --progress-bar off; 44 | fi 45 | 46 | # set library path 47 | - export LD_LIBRARY_PATH=$HOME/miniconda/envs/test-environment/lib/:$LD_LIBRARY_PATH 48 | 49 | - if [[ "$KERAS_BACKEND" == "theano" ]]; then 50 | travis_retry conda install -q mkl mkl-service; 51 | fi 52 | 53 | - if [[ "$USE_TF_KERAS" == "1" ]]; then 54 | python convert_to_tf_keras.py; 55 | fi 56 | - pip install -e .[tests] --progress-bar off 57 | 58 | # install TensorFlow (CPU version). 59 | - pip install tensorflow==1.12 --progress-bar off 60 | 61 | # install cntk 62 | - ./.travis/install_cntk.sh 63 | 64 | # Remove the current backend from the coverage exclusion. 65 | - sed -i "\/keras\/backend\/${KERAS_BACKEND}_backend.py/d" .coveragerc 66 | 67 | # command to run tests 68 | script: 69 | - export MKL_THREADING_LAYER="GNU" 70 | # run keras backend init to initialize backend config 71 | - python -c "import keras_contrib.backend" 72 | # create dataset directory to avoid concurrent directory creation at runtime 73 | - mkdir ~/.keras/datasets 74 | # set up keras backend 75 | - sed -i -e 's/"backend":[[:space:]]*"[^"]*/"backend":\ "'$KERAS_BACKEND'/g' ~/.keras/keras.json; 76 | - echo -e "Running tests with the following config:\n$(cat ~/.keras/keras.json)" 77 | - if [[ "$TEST_MODE" == "PEP8_DOC" ]]; then 78 | PYTHONPATH=$PWD:$PYTHONPATH py.test --pep8 -m pep8 -n0 && py.test tests/tooling/ convert_to_tf_keras.py && cd contrib_docs && pydocmd build; 79 | else 80 | PYTHONPATH=$PWD:$PYTHONPATH py.test tests/ $PYTEST_IGNORE --ignore=tests/tooling/ 81 | --cov-config .coveragerc --cov=keras_contrib tests/; 82 | fi 83 | -------------------------------------------------------------------------------- /.travis/install_cntk.sh: -------------------------------------------------------------------------------- 1 | set -e 2 | pip install cntk --progress-bar off 3 | 4 | # open mpi is needed for cntk 5 | rm -rf ~/mpi 6 | mkdir ~/mpi 7 | pushd ~/mpi 8 | wget http://cntk.ai/PythonWheel/ForKeras/depends/openmpi_1.10-3.zip 9 | unzip ./openmpi_1.10-3.zip 10 | sudo dpkg -i openmpi_1.10-3.deb 11 | popd 12 | -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # examples 2 | 3 | 4 | # activations 5 | keras_contrib/activations/squash.py @SriRangaTarun 6 | 7 | # applications 8 | keras_contrib/applications/densenet.py @titu1994 9 | keras_contrib/applications/nasnet.py @titu1994 10 | keras_contrib/applications/wide_resnet.py @titu1994 11 | 12 | # backend 13 | 14 | 15 | # callbacks 16 | keras_contrib/callbacks/tensorboard.py @gabrieldemarmiesse 17 | keras_contrib/callbacks/snapshot.py @titu1994 18 | 19 | # constraints 20 | 21 | 22 | # datasets 23 | 24 | 25 | # initializers 26 | 27 | 28 | # layers 29 | keras_contrib/layers/advanced_activations/sinerelu.py @wilderrodrigues 30 | keras_contrib/layers/advanced_activations/swish.py @gabrieldemarmiesse 31 | keras_contrib/layers/convolutional/subpixelupscaling.py @titu1994 32 | keras_contrib/layers/normalization/groupnormalization.py @titu1994 33 | keras_contrib/layers/capsule.py @SriRangaTarun 34 | 35 | # losses 36 | 37 | 38 | # metrics 39 | 40 | 41 | # optimizers 42 | keras_contrib/optimizers/yogi.py @MarcoAndreaBuchmann 43 | keras_contrib/optimizers/padam.py @MFreidank 44 | 45 | # preprocessing 46 | 47 | 48 | # regularizers 49 | 50 | 51 | # utils 52 | 53 | 54 | # wrappers 55 | -------------------------------------------------------------------------------- /GUIDELINES.md: -------------------------------------------------------------------------------- 1 | # Maintainer Guidelines 2 | 3 | ## Maintainers: 4 | Following are the users with write-access to this repository (maintainers) : 5 | * [athundt](https://www.github.com/athundt) 6 | * [bstriner](https://www.github.com/bstriner) 7 | * [farizrahman4u](https://www.github.com/farizrahman4u) 8 | * [fchollet](https://www.github.com/fchollet) 9 | * [kemaswill](https://www.github.com/kemaswill) 10 | * [lukedeo](https://www.github.com/lukedeo) 11 | * [patyork](https://www.github.com/patyork) 12 | * [tboquet](https://www.github.com/tboquet) 13 | * [the-moliver](https://www.github.com/the-moliver) 14 | 15 | ## Addition of new features 16 | * Addition of new features require submitting a pull request, even for those who have write access to this repository. 17 | * Maintainers should not merge their own pull requests. 18 | * Whenever possible, multiple Maintainers should review a pull requests before it is merged. 19 | * All incoming new features should be accompanied by documentation and unit tests. 20 | 21 | ## Becoming a maintainer 22 | * To become a maintainer, you should be a recognized contributor to either Keras-contrib or Keras core. 23 | * If you think you are eligible to be a maintainer, you can contact one of the existing maintainers to join the team. 24 | 25 | ## Versioning 26 | * Keras-contrib is tested only against the bleeding-edge version of Keras. 27 | * In case the Travis build fails due to a change in Keras core, the maintainers are responsible of rectifying the issue. 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Fariz Rahman 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 5 | 6 | **- What I did** 7 | 8 | 9 | **- How I did it** 10 | 11 | 12 | **- How you can verify it** 13 | 17 | 18 | 19 | 20 | --- 21 | This pull request fixes #issue_number_here 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # keras-contrib : Keras community contributions 2 | 3 | Keras-contrib is deprecated. Use [TensorFlow Addons](https://github.com/tensorflow/addons). 4 | 5 | ## The future of Keras-contrib: 6 | 7 | We're migrating to [tensorflow/addons](https://github.com/tensorflow/addons). See the announcement [here](https://github.com/keras-team/keras-contrib/issues/519). 8 | 9 | [![Build Status](https://travis-ci.org/keras-team/keras-contrib.svg?branch=master)](https://travis-ci.org/keras-team/keras-contrib) 10 | 11 | This library is the official extension repository for the python deep learning library [Keras](http://www.keras.io). It contains additional layers, activations, loss functions, optimizers, etc. which are not yet available within Keras itself. All of these additional modules can be used in conjunction with core Keras models and modules. 12 | 13 | As the community contributions in Keras-Contrib are tested, used, validated, and their utility proven, they may be integrated into the Keras core repository. In the interest of keeping Keras succinct, clean, and powerfully simple, only the most useful contributions make it into Keras. This contribution repository is both the proving ground for new functionality, and the archive for functionality that (while useful) may not fit well into the Keras paradigm. 14 | 15 | 16 | 17 | 18 | 19 | --- 20 | ## Installation 21 | 22 | #### Install keras_contrib for keras-team/keras 23 | For instructions on how to install Keras, 24 | see [the Keras installation page](https://keras.io/#installation). 25 | 26 | ```shell 27 | git clone https://www.github.com/keras-team/keras-contrib.git 28 | cd keras-contrib 29 | python setup.py install 30 | ``` 31 | 32 | Alternatively, using pip: 33 | 34 | ```shell 35 | sudo pip install git+https://www.github.com/keras-team/keras-contrib.git 36 | ``` 37 | 38 | to uninstall: 39 | ```pip 40 | pip uninstall keras_contrib 41 | ``` 42 | 43 | #### Install keras_contrib for tensorflow.keras 44 | 45 | ```shell 46 | git clone https://www.github.com/keras-team/keras-contrib.git 47 | cd keras-contrib 48 | python convert_to_tf_keras.py 49 | USE_TF_KERAS=1 python setup.py install 50 | ``` 51 | 52 | to uninstall: 53 | ```shell 54 | pip uninstall tf_keras_contrib 55 | ``` 56 | 57 | For contributor guidelines see [CONTRIBUTING.md](https://github.com/keras-team/keras-contrib/blob/master/CONTRIBUTING.md) 58 | 59 | --- 60 | ## Example Usage 61 | 62 | Modules from the Keras-Contrib library are used in the same way as modules within Keras itself. 63 | 64 | ```python 65 | from keras.models import Sequential 66 | from keras.layers import Dense 67 | import numpy as np 68 | 69 | # I wish Keras had the Parametric Exponential Linear activation.. 70 | # Oh, wait..! 71 | from keras_contrib.layers.advanced_activations import PELU 72 | 73 | # Create the Keras model, including the PELU advanced activation 74 | model = Sequential() 75 | model.add(Dense(100, input_shape=(10,))) 76 | model.add(PELU()) 77 | 78 | # Compile and fit on random data 79 | model.compile(loss='mse', optimizer='adam') 80 | model.fit(x=np.random.random((100, 10)), y=np.random.random((100, 100)), epochs=5, verbose=0) 81 | 82 | # Save our model 83 | model.save('example.h5') 84 | ``` 85 | 86 | 87 | ### A Common "Gotcha" 88 | 89 | As Keras-Contrib is external to the Keras core, loading a model requires a bit more work. While a pure Keras model is loadable with nothing more than an import of `keras.models.load_model`, a model which contains a contributed module requires an additional import of `keras_contrib`: 90 | 91 | ```python 92 | # Required, as usual 93 | from keras.models import load_model 94 | 95 | # Recommended method; requires knowledge of the underlying architecture of the model 96 | from keras_contrib.layers import PELU 97 | from keras_contrib.layers import GroupNormalization 98 | 99 | # Load our model 100 | custom_objects = {'PELU': PELU, 'GroupNormalization': GroupNormalization} 101 | model = load_model('example.h5', custom_objects) 102 | ``` 103 | -------------------------------------------------------------------------------- /contrib_docs/README.md: -------------------------------------------------------------------------------- 1 | # Keras-contrib Documentation 2 | 3 | The source for Keras-contrib documentation is in this directory under `sources/`. 4 | Our documentation uses extended Markdown, as implemented by [MkDocs](http://mkdocs.org). 5 | 6 | ## Building the documentation 7 | 8 | - install pydoc-markdown: `pip install pydoc-markdown` 9 | - `cd` to the `contrib_docs/` folder and run: 10 | - `pydocmd serve` # Starts a local webserver: [localhost:8000](localhost:8000) 11 | - `pydocmd build` # Builds a static site in "site" directory 12 | -------------------------------------------------------------------------------- /contrib_docs/pydocmd.yml: -------------------------------------------------------------------------------- 1 | site_name: "Keras-contrib Documentation" 2 | 3 | 4 | generate: 5 | - layers/core.md: 6 | - keras_contrib.layers.CosineDense 7 | - layers/convolutional.md: 8 | - keras_contrib.layers.CosineConv2D 9 | - keras_contrib.layers.SubPixelUpscaling 10 | - layers/normalization.md: 11 | - keras_contrib.layers.InstanceNormalization 12 | - keras_contrib.layers.GroupNormalization 13 | - layers/advanced-activations.md: 14 | - keras_contrib.layers.SineReLU 15 | - keras_contrib.layers.SReLU 16 | - keras_contrib.layers.Swish 17 | - keras_contrib.layers.PELU 18 | - layers/crf.md: 19 | - keras_contrib.layers.CRF 20 | - losses.md: 21 | - keras_contrib.losses: 22 | - keras_contrib.losses.DSSIMObjective 23 | - keras_contrib.losses.jaccard_distance 24 | - keras_contrib.losses.crf_loss 25 | - keras_contrib.losses.crf_nll 26 | - optimizers.md: 27 | - keras_contrib.optimizers: 28 | - keras_contrib.optimizers.FTML 29 | - keras_contrib.optimizers.Padam 30 | - keras_contrib.optimizers.Yogi 31 | - keras_contrib.optimizers.LARS 32 | - callbacks.md: 33 | - keras_contrib.callbacks: 34 | - keras_contrib.callbacks.TensorBoardGrouped 35 | - keras_contrib.callbacks.CyclicLR 36 | - keras_contrib.callbacks.SnapshotCallbackBuilder 37 | - keras_contrib.callbacks.SnapshotModelCheckpoint 38 | - keras_contrib.callbacks.DeadReluDetector 39 | 40 | 41 | pages: 42 | - Home: index.md << ../README.md 43 | - layers: 44 | - Core layers: layers/core.md 45 | - Convolutional layers: layers/convolutional.md 46 | - normalization layers: layers/normalization.md 47 | - Advanced activations layers: layers/advanced-activations.md 48 | - CRF layers: layers/crf.md 49 | - Losses: losses.md 50 | - Optimizers: optimizers.md 51 | - Callbacks: callbacks.md 52 | 53 | 54 | 55 | headers: html 56 | -------------------------------------------------------------------------------- /contrib_docs/theme/404.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |

404

6 | 7 |

Page not found

8 | 9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /contrib_docs/theme/breadcrumbs.html: -------------------------------------------------------------------------------- 1 |
2 | 29 | {% if config.theme.prev_next_buttons_location|lower in ['top', 'both'] 30 | and page and (page.next_page or page.previous_page) %} 31 | 39 | {% endif %} 40 |
41 |
42 | -------------------------------------------------------------------------------- /contrib_docs/theme/css/theme_extra.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Wrap inline code samples otherwise they shoot of the side and 3 | * can't be read at all. 4 | * 5 | * https://github.com/mkdocs/mkdocs/issues/313 6 | * https://github.com/mkdocs/mkdocs/issues/233 7 | * https://github.com/mkdocs/mkdocs/issues/834 8 | */ 9 | .rst-content code { 10 | white-space: pre-wrap; 11 | word-wrap: break-word; 12 | padding: 2px 5px; 13 | } 14 | 15 | /** 16 | * Make code blocks display as blocks and give them the appropriate 17 | * font size and padding. 18 | * 19 | * https://github.com/mkdocs/mkdocs/issues/855 20 | * https://github.com/mkdocs/mkdocs/issues/834 21 | * https://github.com/mkdocs/mkdocs/issues/233 22 | */ 23 | .rst-content pre code { 24 | white-space: pre; 25 | word-wrap: normal; 26 | display: block; 27 | padding: 12px; 28 | font-size: 12px; 29 | } 30 | 31 | /* 32 | * Fix link colors when the link text is inline code. 33 | * 34 | * https://github.com/mkdocs/mkdocs/issues/718 35 | */ 36 | a code { 37 | color: #2980B9; 38 | } 39 | a:hover code { 40 | color: #3091d1; 41 | } 42 | a:visited code { 43 | color: #9B59B6; 44 | } 45 | 46 | /* 47 | * The CSS classes from highlight.js seem to clash with the 48 | * ReadTheDocs theme causing some code to be incorrectly made 49 | * bold and italic. 50 | * 51 | * https://github.com/mkdocs/mkdocs/issues/411 52 | */ 53 | pre .cs, pre .c { 54 | font-weight: inherit; 55 | font-style: inherit; 56 | } 57 | 58 | /* 59 | * Fix some issues with the theme and non-highlighted code 60 | * samples. Without and highlighting styles attached the 61 | * formatting is broken. 62 | * 63 | * https://github.com/mkdocs/mkdocs/issues/319 64 | */ 65 | .rst-content .no-highlight { 66 | display: block; 67 | padding: 0.5em; 68 | color: #333; 69 | } 70 | 71 | 72 | /* 73 | * Additions specific to the search functionality provided by MkDocs 74 | */ 75 | 76 | .search-results { 77 | margin-top: 23px; 78 | } 79 | 80 | .search-results article { 81 | border-top: 1px solid #E1E4E5; 82 | padding-top: 24px; 83 | } 84 | 85 | .search-results article:first-child { 86 | border-top: none; 87 | } 88 | 89 | form .search-query { 90 | width: 100%; 91 | border-radius: 50px; 92 | padding: 6px 12px; /* csslint allow: box-model */ 93 | border-color: #D1D4D5; 94 | } 95 | 96 | /* 97 | * Improve inline code blocks within admonitions. 98 | * 99 | * https://github.com/mkdocs/mkdocs/issues/656 100 | */ 101 | .rst-content .admonition code { 102 | color: #404040; 103 | border: 1px solid #c7c9cb; 104 | border: 1px solid rgba(0, 0, 0, 0.2); 105 | background: #f8fbfd; 106 | background: rgba(255, 255, 255, 0.7); 107 | } 108 | 109 | /* 110 | * Account for wide tables which go off the side. 111 | * Override borders to avoid wierdness on narrow tables. 112 | * 113 | * https://github.com/mkdocs/mkdocs/issues/834 114 | * https://github.com/mkdocs/mkdocs/pull/1034 115 | */ 116 | .rst-content .section .docutils { 117 | width: 100%; 118 | overflow: auto; 119 | display: block; 120 | border: none; 121 | } 122 | 123 | td, th { 124 | border: 1px solid #e1e4e5 !important; /* csslint allow: important */ 125 | border-collapse: collapse; 126 | } 127 | 128 | /*Keras extras*/ 129 | 130 | .keras-logo { 131 | max-height: 55px; 132 | width: 100%; 133 | background: #d00000; 134 | font-size: 140%; 135 | color: white; 136 | font-family: "Source Sans Pro", "ff-tisa-web-pro", "Georgia", Arial, sans-serif; 137 | } 138 | 139 | .keras-logo-img { 140 | max-width: 45px; 141 | margin: 10px; 142 | } 143 | 144 | h1, h2, h3, h4, h5, h6, legend { 145 | font-family: "Source Sans Pro", "ff-tisa-web-pro", "Georgia", Arial, sans-serif;, 146 | } 147 | 148 | -------------------------------------------------------------------------------- /contrib_docs/theme/footer.html: -------------------------------------------------------------------------------- 1 | 27 | -------------------------------------------------------------------------------- /contrib_docs/theme/js/theme.js: -------------------------------------------------------------------------------- 1 | /* sphinx_rtd_theme version 0.4.1 | MIT license */ 2 | /* Built 20180727 10:07 */ 3 | require=function n(e,i,t){function o(s,a){if(!i[s]){if(!e[s]){var l="function"==typeof require&&require;if(!a&&l)return l(s,!0);if(r)return r(s,!0);var c=new Error("Cannot find module '"+s+"'");throw c.code="MODULE_NOT_FOUND",c}var u=i[s]={exports:{}};e[s][0].call(u.exports,function(n){var i=e[s][1][n];return o(i||n)},u,u.exports,n,e,i,t)}return i[s].exports}for(var r="function"==typeof require&&require,s=0;s"),n("table.docutils.footnote").wrap("
"),n("table.docutils.citation").wrap("
"),n(".wy-menu-vertical ul").not(".simple").siblings("a").each(function(){var i=n(this);expand=n(''),expand.on("click",function(n){return e.toggleCurrent(i),n.stopPropagation(),!1}),i.prepend(expand)})},reset:function(){var n=encodeURI(window.location.hash)||"#";try{var e=$(".wy-menu-vertical"),i=e.find('[href="'+n+'"]');if(0===i.length){var t=$('.document [id="'+n.substring(1)+'"]').closest("div.section");0===(i=e.find('[href="#'+t.attr("id")+'"]')).length&&(i=e.find('[href="#"]'))}i.length>0&&($(".wy-menu-vertical .current").removeClass("current"),i.addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l1").parent().addClass("current"),i.closest("li.toctree-l1").addClass("current"),i.closest("li.toctree-l2").addClass("current"),i.closest("li.toctree-l3").addClass("current"),i.closest("li.toctree-l4").addClass("current"))}catch(o){console.log("Error expanding nav for anchor",o)}},onScroll:function(){this.winScroll=!1;var n=this.win.scrollTop(),e=n+this.winHeight,i=this.navBar.scrollTop()+(n-this.winPosition);n<0||e>this.docHeight||(this.navBar.scrollTop(i),this.winPosition=n)},onResize:function(){this.winResize=!1,this.winHeight=this.win.height(),this.docHeight=$(document).height()},hashChange:function(){this.linkScroll=!0,this.win.one("hashchange",function(){this.linkScroll=!1})},toggleCurrent:function(n){var e=n.closest("li");e.siblings("li.current").removeClass("current"),e.siblings().find("li.current").removeClass("current"),e.find("> ul li.current").removeClass("current"),e.toggleClass("current")}},"undefined"!=typeof window&&(window.SphinxRtdTheme={Navigation:e.exports.ThemeNav,StickyNav:e.exports.ThemeNav}),function(){for(var n=0,e=["ms","moz","webkit","o"],i=0;i{{ nav_item.title }} 2 | {%- set navlevel = navlevel + 1 %} 3 | {%- if navlevel <= config.theme.navigation_depth 4 | and ((nav_item.is_page and nav_item.toc.items 5 | and (not config.theme.titles_only 6 | and (nav_item == page or not config.theme.collapse_navigation))) 7 | or (nav_item.is_section and nav_item.children)) %} 8 | 9 | {%- if nav_item.is_page %} 10 | {#- Skip first level of toc which is page title. #} 11 | {%- set toc_item = nav_item.toc.items[0] %} 12 | {%- include 'toc.html' %} 13 | {%- elif nav_item.is_section %} 14 | {%- for nav_item in nav_item.children %} 15 | 18 | {%- endfor %} 19 | {%- endif %} 20 | 21 | {%- endif %} 22 | {%- set navlevel = navlevel - 1 %} 23 | -------------------------------------------------------------------------------- /contrib_docs/theme/search.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block content %} 4 | 5 |

Search Results

6 | 7 | 11 | 12 |
13 | Searching... 14 |
15 | 16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /contrib_docs/theme/searchbox.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 |
6 | -------------------------------------------------------------------------------- /contrib_docs/theme/toc.html: -------------------------------------------------------------------------------- 1 | 2 | {%- for toc_item in toc_item.children %} 3 | 12 | {%- endfor %} 13 | -------------------------------------------------------------------------------- /contrib_docs/theme/versions.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | {% if config.repo_name == 'GitHub' %} 4 | GitHub 5 | {% elif config.repo_name == 'Bitbucket' %} 6 | BitBucket 7 | {% elif config.repo_name == 'GitLab' %} 8 | GitLab 9 | {% endif %} 10 | {% if page.previous_page %} 11 | « Previous 12 | {% endif %} 13 | {% if page.next_page %} 14 | Next » 15 | {% endif %} 16 | 17 |
18 | -------------------------------------------------------------------------------- /convert_to_tf_keras.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | list_conversions = [('import keras.', 'import tensorflow.keras.'), 5 | ('import keras ', 'from tensorflow import keras '), 6 | ('import keras\n', 'from tensorflow import keras\n'), 7 | ('from keras.', 'from tensorflow.keras.'), 8 | ('from keras ', 'from tensorflow.keras ')] 9 | 10 | 11 | def replace_imports_in_text(string, revert): 12 | if revert: 13 | list_imports_to_change = [x[::-1] for x in list_conversions] 14 | else: 15 | list_imports_to_change = list_conversions 16 | 17 | text_updated = string 18 | for old_str, new_str in list_imports_to_change: 19 | text_updated = text_updated.replace(old_str, new_str) 20 | return text_updated 21 | 22 | 23 | def replace_imports_in_file(file_path, revert): 24 | if not file_path.endswith('.py'): 25 | return False 26 | if os.path.abspath(file_path) == os.path.abspath(__file__): 27 | return False 28 | with open(file_path, 'r') as f: 29 | text = f.read() 30 | 31 | text_updated = replace_imports_in_text(text, revert) 32 | 33 | with open(file_path, 'w+') as f: 34 | f.write(text_updated) 35 | 36 | return text_updated != text 37 | 38 | 39 | def convert_codebase(revert): 40 | nb_of_files_changed = 0 41 | keras_dir = os.path.dirname(os.path.abspath(__file__)) 42 | for root, dirs, files in os.walk(keras_dir): 43 | for name in files: 44 | if replace_imports_in_file(os.path.join(root, name), revert): 45 | nb_of_files_changed += 1 46 | print('Changed imports in ' + str(nb_of_files_changed) + ' files.') 47 | print('Those files were found in the directory ' + keras_dir) 48 | 49 | 50 | def convert_to_tf_keras(): 51 | """Convert the codebase to tf.keras""" 52 | convert_codebase(False) 53 | 54 | 55 | def convert_to_keras_team_keras(): 56 | """Convert the codebase from tf.keras to keras-team/keras""" 57 | convert_codebase(True) 58 | 59 | 60 | def test_replace_imports(): 61 | python_code = """ 62 | import keras 63 | from keras import backend as K 64 | import os 65 | import keras_contrib 66 | import keras_contrib.layers as lay 67 | import keras.layers 68 | from keras.layers import Dense 69 | 70 | if K.backend() == 'tensorflow': 71 | import tensorflow as tf 72 | function = tf.max 73 | """ 74 | 75 | expected_code = """ 76 | from tensorflow import keras 77 | from tensorflow.keras import backend as K 78 | import os 79 | import keras_contrib 80 | import keras_contrib.layers as lay 81 | import tensorflow.keras.layers 82 | from tensorflow.keras.layers import Dense 83 | 84 | if K.backend() == 'tensorflow': 85 | import tensorflow as tf 86 | function = tf.max 87 | """ 88 | 89 | code_with_replacement = replace_imports_in_text(python_code, False) 90 | assert expected_code == code_with_replacement 91 | assert python_code == replace_imports_in_text(code_with_replacement, True) 92 | 93 | 94 | if __name__ == '__main__': 95 | if '--revert' in sys.argv: 96 | convert_to_keras_team_keras() 97 | else: 98 | convert_to_tf_keras() 99 | -------------------------------------------------------------------------------- /examples/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/examples/.gitkeep -------------------------------------------------------------------------------- /examples/cifar10_clr.py: -------------------------------------------------------------------------------- 1 | '''Train a simple deep CNN on the CIFAR10 small images dataset using 2 | a triangular cyclic learning rate (CLR) policy. 3 | It gets to 75% validation accuracy in 15 epochs, and 79% after 40 epochs; 4 | compare to 25 and 50 epochs respectively without CLR. 5 | ''' 6 | 7 | from __future__ import print_function 8 | from __future__ import absolute_import 9 | import keras 10 | from keras.datasets import cifar10 11 | from keras.preprocessing.image import ImageDataGenerator 12 | from keras.models import Sequential 13 | from keras.layers import Dense, Dropout, Activation, Flatten 14 | from keras.layers import Conv2D, MaxPooling2D 15 | from keras_contrib.callbacks import CyclicLR 16 | 17 | import os 18 | 19 | batch_size = 100 20 | epochs = 50 21 | num_classes = 10 22 | data_augmentation = True 23 | num_predictions = 20 24 | save_dir = os.path.join(os.getcwd(), 'saved_models') 25 | model_name = 'keras_cifar10_trained_model.h5' 26 | 27 | # The data, split between train and test sets: 28 | (x_train, y_train), (x_test, y_test) = cifar10.load_data() 29 | print('x_train shape:', x_train.shape) 30 | print(x_train.shape[0], 'train samples') 31 | print(x_test.shape[0], 'test samples') 32 | 33 | # Convert class vectors to binary class matrices. 34 | y_train = keras.utils.to_categorical(y_train, num_classes) 35 | y_test = keras.utils.to_categorical(y_test, num_classes) 36 | 37 | model = Sequential() 38 | model.add(Conv2D(32, (3, 3), padding='same', 39 | input_shape=x_train.shape[1:])) 40 | model.add(Activation('relu')) 41 | model.add(Conv2D(32, (3, 3))) 42 | model.add(Activation('relu')) 43 | model.add(MaxPooling2D(pool_size=(2, 2))) 44 | model.add(Dropout(0.25)) 45 | 46 | model.add(Conv2D(64, (3, 3), padding='same')) 47 | model.add(Activation('relu')) 48 | model.add(Conv2D(64, (3, 3))) 49 | model.add(Activation('relu')) 50 | model.add(MaxPooling2D(pool_size=(2, 2))) 51 | model.add(Dropout(0.25)) 52 | 53 | model.add(Flatten()) 54 | model.add(Dense(512)) 55 | model.add(Activation('relu')) 56 | model.add(Dropout(0.5)) 57 | model.add(Dense(num_classes)) 58 | model.add(Activation('softmax')) 59 | 60 | # initiate RMSprop optimizer 61 | opt = keras.optimizers.rmsprop(lr=0.0001, decay=1e-6) 62 | 63 | # initiate CyclicLR LR scheduler 64 | clr = CyclicLR( 65 | base_lr=0.0001, 66 | max_lr=0.0005, 67 | step_size=2000, 68 | mode='triangular') 69 | 70 | 71 | # Let's train the model using RMSprop 72 | model.compile(loss='categorical_crossentropy', 73 | optimizer=opt, 74 | metrics=['accuracy']) 75 | 76 | x_train = x_train.astype('float32') 77 | x_test = x_test.astype('float32') 78 | x_train /= 255 79 | x_test /= 255 80 | 81 | if not data_augmentation: 82 | print('Not using data augmentation.') 83 | model.fit(x_train, y_train, 84 | batch_size=batch_size, 85 | epochs=epochs, 86 | validation_data=(x_test, y_test), 87 | callbacks=[clr], 88 | shuffle=True) 89 | else: 90 | print('Using real-time data augmentation.') 91 | # This will do preprocessing and realtime data augmentation: 92 | datagen = ImageDataGenerator( 93 | featurewise_center=False, # set input mean to 0 over the dataset 94 | samplewise_center=False, # set each sample mean to 0 95 | featurewise_std_normalization=False, # divide inputs by std of the dataset 96 | samplewise_std_normalization=False, # divide each input by its std 97 | zca_whitening=False, # apply ZCA whitening 98 | zca_epsilon=1e-06, # epsilon for ZCA whitening 99 | rotation_range=0, 100 | # randomly rotate images in the range (degrees, 0 to 180) 101 | # randomly shift images horizontally (fraction of total width) 102 | width_shift_range=0.1, 103 | # randomly shift images vertically (fraction of total height) 104 | height_shift_range=0.1, 105 | shear_range=0., # set range for random shear 106 | zoom_range=0., # set range for random zoom 107 | channel_shift_range=0., # set range for random channel shifts 108 | # set mode for filling points outside the input boundaries 109 | fill_mode='nearest', 110 | cval=0., # value used for fill_mode = "constant" 111 | horizontal_flip=True, # randomly flip images 112 | vertical_flip=False, # randomly flip images 113 | # set rescaling factor (applied before any other transformation) 114 | rescale=None, 115 | # set function that will be applied on each input 116 | preprocessing_function=None, 117 | # image data format, either "channels_first" or "channels_last" 118 | data_format=None, 119 | # fraction of images reserved for validation (strictly between 0 and 1) 120 | validation_split=0.0) 121 | 122 | # Compute quantities required for feature-wise normalization 123 | # (std, mean, and principal components if ZCA whitening is applied). 124 | datagen.fit(x_train) 125 | 126 | # Fit the model on the batches generated by datagen.flow(). 127 | 128 | model.fit_generator(datagen.flow(x_train, y_train, 129 | batch_size=batch_size), 130 | epochs=epochs, 131 | validation_data=(x_test, y_test), 132 | callbacks=[clr], 133 | workers=4) 134 | 135 | # Save model and weights 136 | if not os.path.isdir(save_dir): 137 | os.makedirs(save_dir) 138 | model_path = os.path.join(save_dir, model_name) 139 | model.save(model_path) 140 | print('Saved trained model at %s ' % model_path) 141 | 142 | # Score trained model. 143 | scores = model.evaluate(x_test, y_test, verbose=1) 144 | print('Test loss:', scores[0]) 145 | print('Test accuracy:', scores[1]) 146 | -------------------------------------------------------------------------------- /examples/cifar10_densenet.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Trains a DenseNet-40-12 model on the CIFAR-10 Dataset. 3 | 4 | Gets a 94.84% accuracy score after 100 epochs. 5 | ''' 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | from __future__ import division 9 | 10 | import numpy as np 11 | 12 | from keras import backend as K 13 | from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping 14 | from keras.datasets import cifar10 15 | from keras.optimizers import Adam 16 | from keras.preprocessing.image import ImageDataGenerator 17 | from keras.utils import np_utils 18 | from keras_contrib.applications import DenseNet 19 | 20 | batch_size = 64 21 | nb_classes = 10 22 | epochs = 100 23 | 24 | img_rows, img_cols = 32, 32 25 | img_channels = 3 26 | 27 | # Parameters for the DenseNet model builder 28 | if K.image_data_format() == 'channels_first': 29 | img_dim = (img_channels, img_rows, img_cols) 30 | else: 31 | img_dim = (img_rows, img_cols, img_channels) 32 | depth = 40 33 | nb_dense_block = 3 34 | growth_rate = 12 35 | nb_filter = 16 36 | dropout_rate = 0.0 # 0.0 for data augmentation 37 | 38 | # Create the model (without loading weights) 39 | model = DenseNet(depth=depth, nb_dense_block=nb_dense_block, 40 | growth_rate=growth_rate, nb_filter=nb_filter, 41 | dropout_rate=dropout_rate, 42 | input_shape=img_dim, 43 | weights=None) 44 | print('Model created') 45 | 46 | model.summary() 47 | 48 | optimizer = Adam(lr=1e-3) # Using Adam instead of SGD to speed up training 49 | model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['acc']) 50 | print('Finished compiling') 51 | 52 | (trainX, trainY), (testX, testY) = cifar10.load_data() 53 | 54 | trainX = trainX.astype('float32') 55 | testX = testX.astype('float32') 56 | 57 | trainX /= 255. 58 | testX /= 255. 59 | 60 | Y_train = np_utils.to_categorical(trainY, nb_classes) 61 | Y_test = np_utils.to_categorical(testY, nb_classes) 62 | 63 | generator = ImageDataGenerator(rotation_range=15, 64 | width_shift_range=5. / 32, 65 | height_shift_range=5. / 32) 66 | 67 | generator.fit(trainX, seed=0) 68 | 69 | weights_file = 'DenseNet-40-12-CIFAR-10.h5' 70 | 71 | lr_reducer = ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.1), 72 | cooldown=0, patience=10, min_lr=0.5e-6) 73 | early_stopper = EarlyStopping(monitor='val_acc', min_delta=1e-4, patience=20) 74 | model_checkpoint = ModelCheckpoint(weights_file, monitor='val_acc', 75 | save_best_only=True, 76 | save_weights_only=True, mode='auto') 77 | 78 | callbacks = [lr_reducer, early_stopper, model_checkpoint] 79 | 80 | model.fit_generator(generator.flow(trainX, Y_train, batch_size=batch_size), 81 | steps_per_epoch=len(trainX) // batch_size, 82 | epochs=epochs, 83 | callbacks=callbacks, 84 | validation_data=(testX, Y_test), 85 | verbose=2) 86 | 87 | scores = model.evaluate(testX, Y_test, batch_size=batch_size) 88 | print('Test loss : ', scores[0]) 89 | print('Test accuracy : ', scores[1]) 90 | -------------------------------------------------------------------------------- /examples/cifar10_nasnet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adapted from keras example cifar10_cnn.py 3 | Train NASNet-CIFAR on the CIFAR10 small images dataset. 4 | """ 5 | from __future__ import print_function 6 | from keras.datasets import cifar10 7 | from keras.preprocessing.image import ImageDataGenerator 8 | from keras.utils import np_utils 9 | from keras.callbacks import ModelCheckpoint 10 | from keras.callbacks import ReduceLROnPlateau 11 | from keras.callbacks import CSVLogger 12 | from keras.optimizers import Adam 13 | from keras_contrib.applications.nasnet import NASNetCIFAR, preprocess_input 14 | 15 | import numpy as np 16 | 17 | 18 | weights_file = 'NASNet-CIFAR-10.h5' 19 | lr_reducer = ReduceLROnPlateau(factor=np.sqrt(0.5), 20 | cooldown=0, 21 | patience=5, 22 | min_lr=0.5e-5) 23 | csv_logger = CSVLogger('NASNet-CIFAR-10.csv') 24 | model_checkpoint = ModelCheckpoint(weights_file, 25 | monitor='val_predictions_acc', 26 | save_best_only=True, 27 | save_weights_only=True, mode='max') 28 | 29 | batch_size = 128 30 | nb_classes = 10 31 | nb_epoch = 600 32 | data_augmentation = True 33 | 34 | # input image dimensions 35 | img_rows, img_cols = 32, 32 36 | # The CIFAR10 images are RGB. 37 | img_channels = 3 38 | 39 | # The data, shuffled and split between train and test sets: 40 | (X_train, y_train), (X_test, y_test) = cifar10.load_data() 41 | 42 | # Convert class vectors to binary class matrices. 43 | Y_train = np_utils.to_categorical(y_train, nb_classes) 44 | Y_test = np_utils.to_categorical(y_test, nb_classes) 45 | 46 | X_train = X_train.astype('float32') 47 | X_test = X_test.astype('float32') 48 | 49 | # preprocess input 50 | X_train = preprocess_input(X_train) 51 | X_test = preprocess_input(X_test) 52 | 53 | # For training, the auxilary branch must be used to correctly train NASNet 54 | model = NASNetCIFAR((img_rows, img_cols, img_channels), use_auxilary_branch=True) 55 | model.summary() 56 | 57 | optimizer = Adam(lr=1e-3, clipnorm=5) 58 | model.compile(loss=['categorical_crossentropy', 'categorical_crossentropy'], 59 | optimizer=optimizer, metrics=['accuracy'], loss_weights=[1.0, 0.4]) 60 | 61 | # model.load_weights('NASNet-CIFAR-10.h5', by_name=True) 62 | 63 | if not data_augmentation: 64 | print('Not using data augmentation.') 65 | model.fit(X_train, [Y_train, Y_train], 66 | batch_size=batch_size, 67 | epochs=nb_epoch, 68 | validation_data=(X_test, [Y_test, Y_test]), 69 | shuffle=True, 70 | verbose=2, 71 | callbacks=[lr_reducer, csv_logger, model_checkpoint]) 72 | else: 73 | print('Using real-time data augmentation.') 74 | # This will do preprocessing and realtime data augmentation: 75 | datagen = ImageDataGenerator( 76 | featurewise_center=False, # set input mean to 0 over the dataset 77 | samplewise_center=False, # set each sample mean to 0 78 | featurewise_std_normalization=False, # divide inputs by std of the dataset 79 | samplewise_std_normalization=False, # divide each input by its std 80 | zca_whitening=False, # apply ZCA whitening 81 | rotation_range=0, # randomly rotate images in the range (degrees, 0 to 180) 82 | width_shift_range=0.1, 83 | height_shift_range=0.1, 84 | horizontal_flip=True, # randomly flip images 85 | vertical_flip=False) # randomly flip images 86 | 87 | # Compute quantities required for featurewise normalization 88 | # (std, mean, and principal components if ZCA whitening is applied). 89 | datagen.fit(X_train) 90 | 91 | # wrap the ImageDataGenerator to yield 92 | # two label batches [y, y] for each input batch X 93 | # When training a NASNet model, we have to use its auxilary training head 94 | # Therefore the model is technically a 1 input - 2 output model, and requires 95 | # the label to be duplicated for the auxilary head 96 | def image_data_generator_wrapper(image_datagenerator, batch_size): 97 | iterator = datagen.flow(X_train, Y_train, batch_size=batch_size) 98 | 99 | while True: 100 | X, y = next(iterator) # get the next batch 101 | yield X, [y, y] # duplicate the labels for each batch 102 | 103 | # Fit the model on the batches generated by datagen.flow(). 104 | model.fit_generator(image_data_generator_wrapper(datagen, batch_size), 105 | steps_per_epoch=X_train.shape[0] // batch_size, 106 | validation_data=(X_test, [Y_test, Y_test]), 107 | epochs=nb_epoch, verbose=2, 108 | callbacks=[lr_reducer, csv_logger, model_checkpoint]) 109 | 110 | scores = model.evaluate(X_test, [Y_test, Y_test], batch_size=batch_size) 111 | for score, metric_name in zip(scores, model.metrics_names): 112 | print("%s : %0.4f" % (metric_name, score)) 113 | -------------------------------------------------------------------------------- /examples/cifar10_resnet.py: -------------------------------------------------------------------------------- 1 | """ 2 | Adapted from keras example cifar10_cnn.py and github.com/raghakot/keras-resnet 3 | Train ResNet-18 on the CIFAR10 small images dataset. 4 | 5 | GPU run command with Theano backend (with TensorFlow, the GPU is automatically used): 6 | THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python cifar10.py 7 | """ 8 | from __future__ import print_function 9 | from keras.datasets import cifar10 10 | from keras.preprocessing.image import ImageDataGenerator 11 | from keras.utils import np_utils 12 | from keras.callbacks import ModelCheckpoint 13 | from keras.callbacks import ReduceLROnPlateau 14 | from keras.callbacks import CSVLogger 15 | from keras.callbacks import EarlyStopping 16 | from keras_contrib.applications.resnet import ResNet18 17 | 18 | import numpy as np 19 | 20 | 21 | weights_file = 'ResNet18v2-CIFAR-10.h5' 22 | lr_reducer = ReduceLROnPlateau(factor=np.sqrt(0.1), cooldown=0, 23 | patience=5, min_lr=0.5e-6) 24 | early_stopper = EarlyStopping(min_delta=0.001, patience=10) 25 | csv_logger = CSVLogger('ResNet18v2-CIFAR-10.csv') 26 | model_checkpoint = ModelCheckpoint(weights_file, monitor='val_acc', save_best_only=True, 27 | save_weights_only=True, mode='auto') 28 | 29 | batch_size = 32 30 | nb_classes = 10 31 | nb_epoch = 200 32 | data_augmentation = True 33 | 34 | # input image dimensions 35 | img_rows, img_cols = 32, 32 36 | # The CIFAR10 images are RGB. 37 | img_channels = 3 38 | 39 | # The data, shuffled and split between train and test sets: 40 | (X_train, y_train), (X_test, y_test) = cifar10.load_data() 41 | 42 | # Convert class vectors to binary class matrices. 43 | Y_train = np_utils.to_categorical(y_train, nb_classes) 44 | Y_test = np_utils.to_categorical(y_test, nb_classes) 45 | 46 | X_train = X_train.astype('float32') 47 | X_test = X_test.astype('float32') 48 | 49 | # subtract mean and normalize 50 | mean_image = np.mean(X_train, axis=0) 51 | X_train -= mean_image 52 | X_test -= mean_image 53 | X_train /= 128. 54 | X_test /= 128. 55 | 56 | model = ResNet18((img_rows, img_cols, img_channels), nb_classes) 57 | model.compile(loss='categorical_crossentropy', 58 | optimizer='adam', 59 | metrics=['accuracy']) 60 | 61 | if not data_augmentation: 62 | print('Not using data augmentation.') 63 | model.fit(X_train, Y_train, 64 | batch_size=batch_size, 65 | nb_epoch=nb_epoch, 66 | validation_data=(X_test, Y_test), 67 | shuffle=True, 68 | callbacks=[lr_reducer, early_stopper, csv_logger, model_checkpoint]) 69 | else: 70 | print('Using real-time data augmentation.') 71 | # This will do preprocessing and realtime data augmentation: 72 | datagen = ImageDataGenerator( 73 | featurewise_center=False, # set input mean to 0 over the dataset 74 | samplewise_center=False, # set each sample mean to 0 75 | featurewise_std_normalization=False, # divide inputs by std of the dataset 76 | samplewise_std_normalization=False, # divide each input by its std 77 | zca_whitening=False, # apply ZCA whitening 78 | rotation_range=0, # randomly rotate images in the range (degrees, 0 to 180) 79 | width_shift_range=0.1, # randomly shift images horizontally 80 | height_shift_range=0.1, # randomly shift images vertically 81 | horizontal_flip=True, # randomly flip images 82 | vertical_flip=False) # randomly flip images 83 | 84 | # Compute quantities required for featurewise normalization 85 | # (std, mean, and principal components if ZCA whitening is applied). 86 | datagen.fit(X_train) 87 | 88 | callbacks = [lr_reducer, early_stopper, csv_logger, model_checkpoint] 89 | # Fit the model on the batches generated by datagen.flow(). 90 | model.fit_generator(datagen.flow(X_train, Y_train, batch_size=batch_size), 91 | steps_per_epoch=X_train.shape[0] // batch_size, 92 | validation_data=(X_test, Y_test), 93 | epochs=nb_epoch, verbose=2, 94 | callbacks=callbacks) 95 | 96 | scores = model.evaluate(X_test, Y_test, batch_size=batch_size) 97 | print('Test loss : ', scores[0]) 98 | print('Test accuracy : ', scores[1]) 99 | -------------------------------------------------------------------------------- /examples/cifar10_ror.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Trains a Residual-of-Residual Network (WRN-40-2) model on the CIFAR-10 Dataset. 3 | 4 | Gets a 94.53% accuracy score after 150 epochs. 5 | ''' 6 | 7 | import keras.callbacks as callbacks 8 | import keras.utils.np_utils as kutils 9 | from keras.datasets import cifar10 10 | from keras.preprocessing.image import ImageDataGenerator 11 | from keras.optimizers import Adam 12 | 13 | from keras_contrib.applications import ResidualOfResidual 14 | 15 | batch_size = 64 16 | epochs = 150 17 | img_rows, img_cols = 32, 32 18 | 19 | (trainX, trainY), (testX, testY) = cifar10.load_data() 20 | 21 | trainX = trainX.astype('float32') 22 | testX = testX.astype('float32') 23 | 24 | trainX /= 255 25 | testX /= 255 26 | 27 | tempY = testY 28 | trainY = kutils.to_categorical(trainY) 29 | testY = kutils.to_categorical(testY) 30 | 31 | generator = ImageDataGenerator(rotation_range=15, 32 | width_shift_range=5. / 32, 33 | height_shift_range=5. / 32) 34 | 35 | generator.fit(trainX, seed=0) 36 | 37 | model = ResidualOfResidual(depth=40, width=2, dropout_rate=0.0, weights=None) 38 | 39 | optimizer = Adam(lr=1e-3) 40 | 41 | model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['acc']) 42 | print('Finished compiling') 43 | 44 | checkpoint = callbacks.ModelCheckpoint('weights/RoR-WRN-40-2-Weights.h5', 45 | monitor='val_acc', 46 | save_best_only=True, 47 | save_weights_only=True) 48 | model.fit_generator(generator.flow(trainX, trainY, batch_size=batch_size), 49 | steps_per_epoch=len(trainX) // batch_size, 50 | epochs=epochs, 51 | callbacks=[checkpoint], 52 | validation_data=(testX, testY), 53 | verbose=2) 54 | 55 | scores = model.evaluate(testX, testY, batch_size) 56 | print('Test loss : ', scores[0]) 57 | print('Test accuracy : ', scores[1]) 58 | -------------------------------------------------------------------------------- /examples/cifar10_wide_resnet.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Trains a WRN-28-8 model on the CIFAR-10 Dataset. 3 | 4 | Performance is slightly less than the paper, since 5 | they use WRN-28-10 model (95.83%). 6 | 7 | Gets a 95.54% accuracy score after 300 epochs. 8 | ''' 9 | from __future__ import absolute_import 10 | from __future__ import print_function 11 | from __future__ import division 12 | 13 | from keras.datasets import cifar10 14 | import keras.callbacks as callbacks 15 | import keras.utils.np_utils as kutils 16 | from keras.preprocessing.image import ImageDataGenerator 17 | 18 | from keras_contrib.applications.wide_resnet import WideResidualNetwork 19 | 20 | batch_size = 64 21 | epochs = 300 22 | img_rows, img_cols = 32, 32 23 | 24 | (trainX, trainY), (testX, testY) = cifar10.load_data() 25 | 26 | trainX = trainX.astype('float32') 27 | trainX /= 255.0 28 | testX = testX.astype('float32') 29 | testX /= 255.0 30 | 31 | tempY = testY 32 | trainY = kutils.to_categorical(trainY) 33 | testY = kutils.to_categorical(testY) 34 | 35 | generator = ImageDataGenerator(rotation_range=10, 36 | width_shift_range=5. / 32, 37 | height_shift_range=5. / 32, 38 | horizontal_flip=True) 39 | 40 | generator.fit(trainX, seed=0, augment=True) 41 | 42 | # We will be training the model, therefore no need to load weights 43 | model = WideResidualNetwork(depth=28, width=8, dropout_rate=0.0, weights=None) 44 | 45 | model.summary() 46 | 47 | model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['acc']) 48 | print('Finished compiling') 49 | model_checkpoint = callbacks.ModelCheckpoint('WRN-28-8 Weights.h5', 50 | monitor='val_acc', 51 | save_best_only=True, 52 | save_weights_only=True) 53 | model.fit_generator(generator.flow(trainX, trainY, batch_size=batch_size), 54 | steps_per_epoch=len(trainX) // batch_size, 55 | epochs=epochs, 56 | callbacks=[model_checkpoint], 57 | validation_data=(testX, testY)) 58 | 59 | scores = model.evaluate(testX, testY, batch_size) 60 | print('Test loss : %0.5f' % (scores[0])) 61 | print('Test accuracy = %0.5f' % (scores[1])) 62 | -------------------------------------------------------------------------------- /examples/conll2000_chunking_crf.py: -------------------------------------------------------------------------------- 1 | """Train CRF and BiLSTM-CRF on CONLL2000 chunking data, 2 | similar to https://arxiv.org/pdf/1508.01991v1.pdf. 3 | """ 4 | from __future__ import absolute_import 5 | from __future__ import print_function 6 | from __future__ import division 7 | 8 | import numpy 9 | from collections import Counter 10 | 11 | from keras.models import Sequential 12 | from keras.layers import Embedding, Bidirectional, LSTM 13 | from keras_contrib.layers import CRF 14 | from keras_contrib.losses import crf_loss 15 | from keras_contrib.metrics import crf_viterbi_accuracy 16 | from keras_contrib.datasets import conll2000 17 | 18 | EPOCHS = 10 19 | EMBED_DIM = 200 20 | BiRNN_UNITS = 200 21 | 22 | 23 | def classification_report(y_true, y_pred, labels): 24 | '''Similar to the one in sklearn.metrics, 25 | reports per classs recall, precision and F1 score''' 26 | y_true = numpy.asarray(y_true).ravel() 27 | y_pred = numpy.asarray(y_pred).ravel() 28 | corrects = Counter(yt for yt, yp in zip(y_true, y_pred) if yt == yp) 29 | y_true_counts = Counter(y_true) 30 | y_pred_counts = Counter(y_pred) 31 | report = ((lab, # label 32 | corrects[i] / max(1, y_true_counts[i]), # recall 33 | corrects[i] / max(1, y_pred_counts[i]), # precision 34 | y_true_counts[i] # support 35 | ) for i, lab in enumerate(labels)) 36 | report = [(l, r, p, 2 * r * p / max(1e-9, r + p), s) for l, r, p, s in report] 37 | 38 | print('{:<15}{:>10}{:>10}{:>10}{:>10}\n'.format('', 39 | 'recall', 40 | 'precision', 41 | 'f1-score', 42 | 'support')) 43 | formatter = '{:<15}{:>10.2f}{:>10.2f}{:>10.2f}{:>10d}'.format 44 | for r in report: 45 | print(formatter(*r)) 46 | print('') 47 | report2 = list(zip(*[(r * s, p * s, f1 * s) for l, r, p, f1, s in report])) 48 | N = len(y_true) 49 | print(formatter('avg / total', 50 | sum(report2[0]) / N, 51 | sum(report2[1]) / N, 52 | sum(report2[2]) / N, N) + '\n') 53 | 54 | 55 | # ------ 56 | # Data 57 | # ----- 58 | 59 | # conll200 has two different targets, here will only use 60 | # IBO like chunking as an example 61 | train, test, voc = conll2000.load_data() 62 | (train_x, _, train_y) = train 63 | (test_x, _, test_y) = test 64 | (vocab, _, class_labels) = voc 65 | 66 | # -------------- 67 | # 1. Regular CRF 68 | # -------------- 69 | 70 | print('==== training CRF ====') 71 | 72 | model = Sequential() 73 | model.add(Embedding(len(vocab), EMBED_DIM, mask_zero=True)) # Random embedding 74 | crf = CRF(len(class_labels), sparse_target=True) 75 | model.add(crf) 76 | model.summary() 77 | 78 | # The default `crf_loss` for `learn_mode='join'` is negative log likelihood. 79 | model.compile('adam', loss=crf_loss, metrics=[crf_viterbi_accuracy]) 80 | model.fit(train_x, train_y, epochs=EPOCHS, validation_data=[test_x, test_y]) 81 | 82 | test_y_pred = model.predict(test_x).argmax(-1)[test_x > 0] 83 | test_y_true = test_y[test_x > 0] 84 | 85 | print('\n---- Result of CRF ----\n') 86 | classification_report(test_y_true, test_y_pred, class_labels) 87 | 88 | # ------------- 89 | # 2. BiLSTM-CRF 90 | # ------------- 91 | 92 | print('==== training BiLSTM-CRF ====') 93 | 94 | model = Sequential() 95 | model.add(Embedding(len(vocab), EMBED_DIM, mask_zero=True)) # Random embedding 96 | model.add(Bidirectional(LSTM(BiRNN_UNITS // 2, return_sequences=True))) 97 | crf = CRF(len(class_labels), sparse_target=True) 98 | model.add(crf) 99 | model.summary() 100 | 101 | model.compile('adam', loss=crf_loss, metrics=[crf_viterbi_accuracy]) 102 | model.fit(train_x, train_y, epochs=EPOCHS, validation_data=[test_x, test_y]) 103 | 104 | test_y_pred = model.predict(test_x).argmax(-1)[test_x > 0] 105 | test_y_true = test_y[test_x > 0] 106 | 107 | print('\n---- Result of BiLSTM-CRF ----\n') 108 | classification_report(test_y_true, test_y_pred, class_labels) 109 | -------------------------------------------------------------------------------- /examples/jaccard_loss.py: -------------------------------------------------------------------------------- 1 | import keras 2 | from keras import backend as K 3 | from keras_contrib.losses.jaccard import jaccard_distance 4 | import numpy as np 5 | 6 | # Test and plot 7 | y_pred = np.array([np.arange(-10, 10 + 0.1, 0.1)]).T 8 | y_true = np.zeros(y_pred.shape) 9 | name = 'jaccard_distance_loss' 10 | try: 11 | loss = jaccard_distance_loss( 12 | K.variable(y_true), K.variable(y_pred) 13 | ).eval(session=K.get_session()) 14 | except Exception as e: 15 | print("error plotting", name, e) 16 | else: 17 | plt.title(name) 18 | plt.plot(y_pred, loss) 19 | plt.show() 20 | 21 | print("TYPE |Almost_right |half right |all_wrong") 22 | y_true = np.array([[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1., 0.]]) 23 | y_pred = np.array([[0, 0, 0.9, 0], [0, 0, 0.1, 0], [1, 1, 0.1, 1.]]) 24 | 25 | r = jaccard_distance( 26 | K.variable(y_true), 27 | K.variable(y_pred), 28 | ).eval(session=K.get_session()) 29 | print('jaccard_distance_loss', r) 30 | assert r[0] < r[1] 31 | assert r[1] < r[2] 32 | 33 | r = keras.losses.binary_crossentropy( 34 | K.variable(y_true), 35 | K.variable(y_pred), 36 | ).eval(session=K.get_session()) 37 | print('binary_crossentropy', r) 38 | print('binary_crossentropy_scaled', r / r.max()) 39 | assert r[0] < r[1] 40 | assert r[1] < r[2] 41 | 42 | """ 43 | TYPE |Almost_right |half right |all_wrong 44 | jaccard_distance_loss [ 0.09900928 0.89108944 3.75000238] 45 | binary_crossentropy [ 0.02634021 0.57564634 12.53243446] 46 | binary_crossentropy_scaled [ 0.00210176 0.04593252 1. ] 47 | """ 48 | -------------------------------------------------------------------------------- /keras_contrib/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from . import backend 3 | from . import datasets 4 | from . import layers 5 | from . import preprocessing 6 | from . import utils 7 | from . import wrappers 8 | from . import callbacks 9 | from . import constraints 10 | from . import initializers 11 | from . import metrics 12 | from . import losses 13 | from . import optimizers 14 | from . import regularizers 15 | 16 | __version__ = '0.0.2' 17 | -------------------------------------------------------------------------------- /keras_contrib/activations/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .squash import squash 4 | -------------------------------------------------------------------------------- /keras_contrib/activations/squash.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | 3 | 4 | def squash(x, axis=-1): 5 | """ 6 | Squash activation function (generally used in Capsule layers). 7 | """ 8 | s_squared_norm = K.sum(K.square(x), axis, keepdims=True) + K.epsilon() 9 | scale = K.sqrt(s_squared_norm) / (0.5 + s_squared_norm) 10 | return scale * x 11 | -------------------------------------------------------------------------------- /keras_contrib/applications/__init__.py: -------------------------------------------------------------------------------- 1 | from .densenet import DenseNet 2 | from .resnet import ResNet, ResNet18, ResNet34, ResNet50, ResNet101, ResNet152 3 | from .wide_resnet import WideResidualNetwork 4 | from .nasnet import NASNet, NASNetLarge, NASNetMobile 5 | -------------------------------------------------------------------------------- /keras_contrib/backend/__init__.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | 3 | # We import all keras backend functions here, 4 | # so that files in this repo can import both 5 | # core and contrib backend functions with a 6 | # single import statement. 7 | 8 | if K.backend() == 'theano': 9 | from .theano_backend import * 10 | elif K.backend() == 'tensorflow': 11 | from .tensorflow_backend import * 12 | elif K.backend() == 'cntk': 13 | from .cntk_backend import * 14 | -------------------------------------------------------------------------------- /keras_contrib/backend/cntk_backend.py: -------------------------------------------------------------------------------- 1 | from keras.backend import cntk_backend as KCN 2 | 3 | 4 | def moments(x, axes, shift=None, keep_dims=False): 5 | ''' Calculates and returns the mean and variance of the input ''' 6 | mean, variant = KCN._moments(x, axes=axes, shift=shift, keep_dims=keep_dims) 7 | return mean, variant 8 | -------------------------------------------------------------------------------- /keras_contrib/backend/numpy_backend.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from keras import backend as K 3 | 4 | 5 | def extract_image_patches(X, ksizes, strides, 6 | padding='valid', 7 | data_format='channels_first'): 8 | raise NotImplementedError 9 | 10 | 11 | def depth_to_space(input, scale, data_format=None): 12 | raise NotImplementedError 13 | 14 | 15 | def moments(x, axes, shift=None, keep_dims=False): 16 | mean_batch = np.mean(x, axis=tuple(axes), keepdims=keep_dims) 17 | var_batch = np.var(x, axis=tuple(axes), keepdims=keep_dims) 18 | return mean_batch, var_batch 19 | -------------------------------------------------------------------------------- /keras_contrib/backend/tensorflow_backend.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | try: 4 | from tensorflow.python.ops import ctc_ops as ctc 5 | except ImportError: 6 | import tensorflow.contrib.ctc as ctc 7 | import keras.backend as K 8 | 9 | py_all = all 10 | 11 | 12 | def _preprocess_conv2d_input(x, data_format): 13 | """Transpose and cast the input before the conv2d. 14 | 15 | # Arguments 16 | x: input tensor. 17 | data_format: string, `"channels_last"` or `"channels_first"`. 18 | 19 | # Returns 20 | A tensor. 21 | """ 22 | if K.dtype(x) == 'float64': 23 | x = tf.cast(x, 'float32') 24 | if data_format == 'channels_first': 25 | # TF uses the last dimension as channel dimension, 26 | # instead of the 2nd one. 27 | # TH input shape: (samples, input_depth, rows, cols) 28 | # TF input shape: (samples, rows, cols, input_depth) 29 | x = tf.transpose(x, (0, 2, 3, 1)) 30 | return x 31 | 32 | 33 | def _postprocess_conv2d_output(x, data_format): 34 | """Transpose and cast the output from conv2d if needed. 35 | 36 | # Arguments 37 | x: A tensor. 38 | data_format: string, `"channels_last"` or `"channels_first"`. 39 | 40 | # Returns 41 | A tensor. 42 | """ 43 | 44 | if data_format == 'channels_first': 45 | x = tf.transpose(x, (0, 3, 1, 2)) 46 | 47 | if K.floatx() == 'float64': 48 | x = tf.cast(x, 'float64') 49 | return x 50 | 51 | 52 | def _preprocess_padding(padding): 53 | """Convert keras' padding to tensorflow's padding. 54 | 55 | # Arguments 56 | padding: string, `"same"` or `"valid"`. 57 | 58 | # Returns 59 | a string, `"SAME"` or `"VALID"`. 60 | 61 | # Raises 62 | ValueError: if `padding` is invalid. 63 | """ 64 | if padding == 'same': 65 | padding = 'SAME' 66 | elif padding == 'valid': 67 | padding = 'VALID' 68 | else: 69 | raise ValueError('Invalid padding:', padding) 70 | return padding 71 | 72 | 73 | def conv2d(x, kernel, strides=(1, 1), padding='valid', data_format='channels_first', 74 | image_shape=None, filter_shape=None): 75 | """2D convolution. 76 | 77 | # Arguments 78 | x: Input tensor 79 | kernel: kernel tensor. 80 | strides: strides tuple. 81 | padding: string, "same" or "valid". 82 | data_format: 'channels_first' or 'channels_last'. 83 | Whether to use Theano or TensorFlow dimension 84 | ordering in inputs/kernels/ouputs. 85 | image_shape: Optional, the input tensor shape 86 | filter_shape: Optional, the kernel shape. 87 | 88 | # Returns 89 | x convolved with the kernel. 90 | 91 | # Raises 92 | Exception: In case of invalid border mode or data format. 93 | """ 94 | return K.conv2d(x, kernel, strides, padding, data_format) 95 | 96 | 97 | def extract_image_patches(x, ksizes, ssizes, padding='same', 98 | data_format='channels_last'): 99 | """Extract the patches from an image. 100 | 101 | # Arguments 102 | x: The input image 103 | ksizes: 2-d tuple with the kernel size 104 | ssizes: 2-d tuple with the strides size 105 | padding: 'same' or 'valid' 106 | data_format: 'channels_last' or 'channels_first' 107 | 108 | # Returns 109 | The (k_w,k_h) patches extracted 110 | TF ==> (batch_size,w,h,k_w,k_h,c) 111 | TH ==> (batch_size,w,h,c,k_w,k_h) 112 | """ 113 | kernel = [1, ksizes[0], ksizes[1], 1] 114 | strides = [1, ssizes[0], ssizes[1], 1] 115 | padding = _preprocess_padding(padding) 116 | if data_format == 'channels_first': 117 | x = K.permute_dimensions(x, (0, 2, 3, 1)) 118 | bs_i, w_i, h_i, ch_i = K.int_shape(x) 119 | patches = tf.extract_image_patches(x, kernel, strides, [1, 1, 1, 1], 120 | padding) 121 | # Reshaping to fit Theano 122 | bs, w, h, ch = K.int_shape(patches) 123 | reshaped = tf.reshape(patches, [-1, w, h, tf.floordiv(ch, ch_i), ch_i]) 124 | final_shape = [-1, w, h, ch_i, ksizes[0], ksizes[1]] 125 | patches = tf.reshape(tf.transpose(reshaped, [0, 1, 2, 4, 3]), final_shape) 126 | if data_format == 'channels_last': 127 | patches = K.permute_dimensions(patches, [0, 1, 2, 4, 5, 3]) 128 | return patches 129 | 130 | 131 | def depth_to_space(input, scale, data_format=None): 132 | """ Uses phase shift algorithm to convert channels/depth for spatial resolution. 133 | 134 | # Arguments 135 | input: Input tensor 136 | scale: n `int` that is `>= 2`. The size of the spatial block. 137 | data_format: 'channels_first' or 'channels_last'. 138 | Whether to use Theano or TensorFlow dimension 139 | ordering in inputs/kernels/ouputs. 140 | 141 | # Returns 142 | TODO (PR welcome): Filling this section. 143 | """ 144 | if data_format is None: 145 | data_format = K.image_data_format() 146 | data_format = data_format.lower() 147 | input = _preprocess_conv2d_input(input, data_format) 148 | out = tf.depth_to_space(input, scale) 149 | out = _postprocess_conv2d_output(out, data_format) 150 | return out 151 | 152 | 153 | def moments(x, axes, shift=None, keep_dims=False): 154 | ''' Wrapper over tensorflow backend call ''' 155 | 156 | return tf.nn.moments(x, axes, shift=shift, keep_dims=keep_dims) 157 | -------------------------------------------------------------------------------- /keras_contrib/backend/theano_backend.py: -------------------------------------------------------------------------------- 1 | from theano import tensor as T 2 | from theano.sandbox.neighbours import images2neibs 3 | 4 | try: 5 | import theano.sparse as th_sparse_module 6 | except ImportError: 7 | th_sparse_module = None 8 | try: 9 | from theano.tensor.nnet.nnet import softsign as T_softsign 10 | except ImportError: 11 | from theano.sandbox.softsign import softsign as T_softsign 12 | from keras.backend import theano_backend as KTH 13 | from keras.backend.common import image_data_format 14 | from keras.backend.theano_backend import _preprocess_conv2d_input 15 | from keras.backend.theano_backend import _postprocess_conv2d_output 16 | 17 | py_all = all 18 | 19 | 20 | def conv2d(x, kernel, strides=(1, 1), padding='valid', data_format='channels_first', 21 | image_shape=None, filter_shape=None): 22 | ''' 23 | padding: string, "same" or "valid". 24 | ''' 25 | if data_format not in {'channels_first', 'channels_last'}: 26 | raise Exception('Unknown data_format ' + str(data_format)) 27 | 28 | if data_format == 'channels_last': 29 | # TF uses the last dimension as channel dimension, 30 | # instead of the 2nd one. 31 | # TH input shape: (samples, input_depth, rows, cols) 32 | # TF input shape: (samples, rows, cols, input_depth) 33 | # TH kernel shape: (depth, input_depth, rows, cols) 34 | # TF kernel shape: (rows, cols, input_depth, depth) 35 | x = x.dimshuffle((0, 3, 1, 2)) 36 | kernel = kernel.dimshuffle((3, 2, 0, 1)) 37 | if image_shape: 38 | image_shape = (image_shape[0], image_shape[3], 39 | image_shape[1], image_shape[2]) 40 | if filter_shape: 41 | filter_shape = (filter_shape[3], filter_shape[2], 42 | filter_shape[0], filter_shape[1]) 43 | 44 | if padding == 'same': 45 | th_padding = 'half' 46 | np_kernel = kernel.eval() 47 | elif padding == 'valid': 48 | th_padding = 'valid' 49 | else: 50 | raise Exception('Border mode not supported: ' + str(padding)) 51 | 52 | # Theano might not accept long type 53 | def int_or_none(value): 54 | try: 55 | return int(value) 56 | except TypeError: 57 | return None 58 | 59 | if image_shape is not None: 60 | image_shape = tuple(int_or_none(v) for v in image_shape) 61 | 62 | if filter_shape is not None: 63 | filter_shape = tuple(int_or_none(v) for v in filter_shape) 64 | 65 | conv_out = T.nnet.conv2d(x, kernel, 66 | border_mode=th_padding, 67 | subsample=strides, 68 | input_shape=image_shape, 69 | filter_shape=filter_shape) 70 | 71 | if padding == 'same': 72 | if np_kernel.shape[2] % 2 == 0: 73 | end = (x.shape[2] + strides[0] - 1) // strides[0] 74 | conv_out = conv_out[:, :, :end, :] 75 | if np_kernel.shape[3] % 2 == 0: 76 | end = (x.shape[3] + strides[1] - 1) // strides[1] 77 | conv_out = conv_out[:, :, :, :end] 78 | 79 | if data_format == 'channels_last': 80 | conv_out = conv_out.dimshuffle((0, 2, 3, 1)) 81 | return conv_out 82 | 83 | 84 | def extract_image_patches(X, ksizes, strides, 85 | padding='valid', 86 | data_format='channels_first'): 87 | ''' 88 | Extract the patches from an image 89 | Parameters 90 | ---------- 91 | X : The input image 92 | ksizes : 2-d tuple with the kernel size 93 | strides : 2-d tuple with the strides size 94 | padding : 'same' or 'valid' 95 | data_format : 'channels_last' or 'channels_first' 96 | Returns 97 | ------- 98 | The (k_w,k_h) patches extracted 99 | TF ==> (batch_size,w,h,k_w,k_h,c) 100 | TH ==> (batch_size,w,h,c,k_w,k_h) 101 | ''' 102 | patch_size = ksizes[1] 103 | if padding == 'same': 104 | padding = 'ignore_borders' 105 | if data_format == 'channels_last': 106 | X = KTH.permute_dimensions(X, [0, 3, 1, 2]) 107 | # Thanks to https://github.com/awentzonline for the help! 108 | batch, c, w, h = KTH.shape(X) 109 | xs = KTH.shape(X) 110 | num_rows = 1 + (xs[-2] - patch_size) // strides[1] 111 | num_cols = 1 + (xs[-1] - patch_size) // strides[1] 112 | num_channels = xs[-3] 113 | patches = images2neibs(X, ksizes, strides, padding) 114 | # Theano is sorting by channel 115 | new_shape = (batch, num_channels, num_rows * num_cols, patch_size, patch_size) 116 | patches = KTH.reshape(patches, new_shape) 117 | patches = KTH.permute_dimensions(patches, (0, 2, 1, 3, 4)) 118 | # arrange in a 2d-grid (rows, cols, channels, px, py) 119 | new_shape = (batch, num_rows, num_cols, num_channels, patch_size, patch_size) 120 | patches = KTH.reshape(patches, new_shape) 121 | if data_format == 'channels_last': 122 | patches = KTH.permute_dimensions(patches, [0, 1, 2, 4, 5, 3]) 123 | return patches 124 | 125 | 126 | def depth_to_space(input, scale, data_format=None): 127 | """Uses phase shift algorithm to convert 128 | channels/depth for spatial resolution 129 | """ 130 | if data_format is None: 131 | data_format = image_data_format() 132 | data_format = data_format.lower() 133 | input = _preprocess_conv2d_input(input, data_format) 134 | 135 | b, k, row, col = input.shape 136 | out_channels = k // (scale ** 2) 137 | x = T.reshape(input, (b, scale, scale, out_channels, row, col)) 138 | x = T.transpose(x, (0, 3, 4, 1, 5, 2)) 139 | out = T.reshape(x, (b, out_channels, row * scale, col * scale)) 140 | 141 | out = _postprocess_conv2d_output(out, input, None, None, None, data_format) 142 | return out 143 | 144 | 145 | def moments(x, axes, shift=None, keep_dims=False): 146 | ''' Calculates and returns the mean and variance of the input ''' 147 | 148 | mean_batch = KTH.mean(x, axis=axes, keepdims=keep_dims) 149 | var_batch = KTH.var(x, axis=axes, keepdims=keep_dims) 150 | 151 | return mean_batch, var_batch 152 | -------------------------------------------------------------------------------- /keras_contrib/callbacks/__init__.py: -------------------------------------------------------------------------------- 1 | from .snapshot import SnapshotCallbackBuilder, SnapshotModelCheckpoint 2 | from .dead_relu_detector import DeadReluDetector 3 | from .cyclical_learning_rate import CyclicLR 4 | from .tensorboard import TensorBoardGrouped 5 | -------------------------------------------------------------------------------- /keras_contrib/callbacks/dead_relu_detector.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from keras.callbacks import Callback 4 | from keras import backend as K 5 | 6 | 7 | class DeadReluDetector(Callback): 8 | """Reports the number of dead ReLUs after each training epoch 9 | ReLU is considered to be dead if it did not fire once for entire training set 10 | 11 | # Arguments 12 | x_train: Training dataset to check whether or not neurons fire 13 | verbose: verbosity mode 14 | True means that even a single dead neuron triggers a warning message 15 | False means that only significant number of dead neurons (10% or more) 16 | triggers a warning message 17 | """ 18 | 19 | def __init__(self, x_train, verbose=False): 20 | super(DeadReluDetector, self).__init__() 21 | self.x_train = x_train 22 | self.verbose = verbose 23 | self.dead_neurons_share_threshold = 0.1 24 | 25 | @staticmethod 26 | def is_relu_layer(layer): 27 | # Should work for all layers with relu 28 | # activation. Tested for Dense and Conv2D 29 | return layer.get_config().get('activation', None) == 'relu' 30 | 31 | def get_relu_activations(self): 32 | model_input = self.model.input 33 | is_multi_input = isinstance(model_input, list) 34 | if not is_multi_input: 35 | model_input = [model_input] 36 | 37 | funcs = {} 38 | for index, layer in enumerate(self.model.layers): 39 | if not layer.get_weights(): 40 | continue 41 | funcs[index] = K.function(model_input 42 | + [K.learning_phase()], [layer.output]) 43 | 44 | if is_multi_input: 45 | list_inputs = [] 46 | list_inputs.extend(self.x_train) 47 | list_inputs.append(1.) 48 | else: 49 | list_inputs = [self.x_train, 1.] 50 | 51 | layer_outputs = {} 52 | for index, func in funcs.items(): 53 | layer_outputs[index] = func(list_inputs)[0] 54 | 55 | for layer_index, layer_activations in layer_outputs.items(): 56 | if self.is_relu_layer(self.model.layers[layer_index]): 57 | layer_name = self.model.layers[layer_index].name 58 | # layer_weight is a list [W] (+ [b]) 59 | layer_weight = self.model.layers[layer_index].get_weights() 60 | 61 | # with kernel and bias, the weights are saved as a list [W, b]. 62 | # If only weights, it is [W] 63 | if type(layer_weight) is not list: 64 | raise ValueError("'Layer_weight' should be a list, " 65 | "but was {}".format(type(layer_weight))) 66 | 67 | # there are no weights for current layer; skip it 68 | # this is only legitimate if layer is "Activation" 69 | if len(layer_weight) == 0: 70 | continue 71 | 72 | layer_weight_shape = np.shape(layer_weight[0]) 73 | yield [layer_index, 74 | layer_activations, 75 | layer_name, 76 | layer_weight_shape] 77 | 78 | def on_epoch_end(self, epoch, logs={}): 79 | for relu_activation in self.get_relu_activations(): 80 | layer_index = relu_activation[0] 81 | activation_values = relu_activation[1] 82 | layer_name = relu_activation[2] 83 | layer_weight_shape = relu_activation[3] 84 | 85 | shape_act = activation_values.shape 86 | 87 | weight_len = len(layer_weight_shape) 88 | act_len = len(shape_act) 89 | 90 | # should work for both Conv and Flat 91 | if K.image_data_format() == 'channels_last': 92 | # features in last axis 93 | axis_filter = -1 94 | else: 95 | # features before the convolution axis, for weight_ 96 | # len the input and output have to be subtracted 97 | axis_filter = -1 - (weight_len - 2) 98 | 99 | total_featuremaps = shape_act[axis_filter] 100 | 101 | axis = [] 102 | for i in range(act_len): 103 | if (i != axis_filter) and (i != (len(shape_act) + axis_filter)): 104 | axis.append(i) 105 | axis = tuple(axis) 106 | 107 | dead_neurons = np.sum(np.sum(activation_values, axis=axis) == 0) 108 | 109 | dead_neurons_share = float(dead_neurons) / float(total_featuremaps) 110 | if ((self.verbose and dead_neurons > 0) 111 | or dead_neurons_share >= self.dead_neurons_share_threshold): 112 | str_warning = ('Layer {} (#{}) has {} ' 113 | 'dead neurons ({:.2%})!').format(layer_name, 114 | layer_index, 115 | dead_neurons, 116 | dead_neurons_share) 117 | print(str_warning) 118 | -------------------------------------------------------------------------------- /keras_contrib/callbacks/snapshot.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | 6 | import numpy as np 7 | 8 | from keras.callbacks import Callback, ModelCheckpoint, LearningRateScheduler 9 | 10 | try: 11 | import requests 12 | except ImportError: 13 | requests = None 14 | 15 | 16 | class SnapshotModelCheckpoint(Callback): 17 | """Callback that saves the snapshot weights of the model. 18 | 19 | Saves the model weights on certain epochs (which can be considered the 20 | snapshot of the model at that epoch). 21 | 22 | Should be used with the cosine annealing learning rate schedule to save 23 | the weight just before learning rate is sharply increased. 24 | 25 | # Arguments: 26 | nb_epochs: total number of epochs that the model will be trained for. 27 | nb_snapshots: number of times the weights of the model will be saved. 28 | fn_prefix: prefix for the filename of the weights. 29 | """ 30 | 31 | def __init__(self, nb_epochs, nb_snapshots, fn_prefix='Model'): 32 | super(SnapshotModelCheckpoint, self).__init__() 33 | 34 | self.check = nb_epochs // nb_snapshots 35 | self.fn_prefix = fn_prefix 36 | 37 | def on_epoch_end(self, epoch, logs={}): 38 | if epoch != 0 and (epoch + 1) % self.check == 0: 39 | filepath = self.fn_prefix + '-%d.h5' % ((epoch + 1) // self.check) 40 | self.model.save_weights(filepath, overwrite=True) 41 | # print("Saved snapshot at weights/%s_%d.h5" % (self.fn_prefix, epoch)) 42 | 43 | 44 | class SnapshotCallbackBuilder: 45 | """Callback builder for snapshot ensemble training of a model. 46 | From the paper "Snapshot Ensembles: Train 1, Get M For Free" ( 47 | https://openreview.net/pdf?id=BJYwwY9ll) 48 | 49 | Creates a list of callbacks, which are provided when training a model 50 | so as to save the model weights at certain epochs, and then sharply 51 | increase the learning rate. 52 | """ 53 | 54 | def __init__(self, nb_epochs, nb_snapshots, init_lr=0.1): 55 | """ 56 | Initialize a snapshot callback builder. 57 | 58 | # Arguments: 59 | nb_epochs: total number of epochs that the model will be trained for. 60 | nb_snapshots: number of times the weights of the model will be saved. 61 | init_lr: initial learning rate 62 | """ 63 | self.T = nb_epochs 64 | self.M = nb_snapshots 65 | self.alpha_zero = init_lr 66 | 67 | def get_callbacks(self, model_prefix='Model'): 68 | """ 69 | Creates a list of callbacks that can be used during training to create a 70 | snapshot ensemble of the model. 71 | 72 | Args: 73 | model_prefix: prefix for the filename of the weights. 74 | 75 | Returns: list of 3 callbacks [ModelCheckpoint, LearningRateScheduler, 76 | SnapshotModelCheckpoint] which can be provided to the 'fit' function 77 | """ 78 | if not os.path.exists('weights/'): 79 | os.makedirs('weights/') 80 | 81 | callback_list = [ModelCheckpoint('weights/%s-Best.h5' % model_prefix, 82 | monitor='val_acc', 83 | save_best_only=True, save_weights_only=True), 84 | LearningRateScheduler(schedule=self._cosine_anneal_schedule), 85 | SnapshotModelCheckpoint(self.T, 86 | self.M, 87 | fn_prefix='weights/%s' % model_prefix)] 88 | 89 | return callback_list 90 | 91 | def _cosine_anneal_schedule(self, t): 92 | cos_inner = np.pi * (t % (self.T // self.M)) 93 | cos_inner /= self.T // self.M 94 | cos_out = np.cos(cos_inner) + 1 95 | return float(self.alpha_zero / 2 * cos_out) 96 | -------------------------------------------------------------------------------- /keras_contrib/callbacks/tensorboard.py: -------------------------------------------------------------------------------- 1 | from keras.callbacks import TensorBoard 2 | import numpy as np 3 | import os 4 | 5 | 6 | class TensorBoardGrouped(TensorBoard): 7 | """TensorBoard basic visualizations. 8 | 9 | [TensorBoard](https://www.tensorflow.org/guide/summaries_and_tensorboard) 10 | is a visualization tool provided with TensorFlow. 11 | 12 | This callback is a subclass of `keras.callbacks.TensorBoard`. 13 | The only difference is that the training and validation logs are 14 | grouped and written to the same plot. 15 | 16 | It's a drop-in replacement for the keras callback. 17 | The arguments are the same. 18 | """ 19 | 20 | def __init__(self, log_dir='./logs', *args, **kwargs): 21 | self.base_log_dir = log_dir 22 | self.train_log_dir = os.path.join(log_dir, 'train') 23 | self.val_log_dir = os.path.join(log_dir, 'val') 24 | super(TensorBoardGrouped, self).__init__(self.train_log_dir, 25 | *args, 26 | **kwargs) 27 | 28 | def set_model(self, model): 29 | super(TensorBoardGrouped, self).set_model(model) 30 | import tensorflow as tf 31 | self.val_writer = tf.summary.FileWriter(self.val_log_dir) 32 | 33 | def _write_logs(self, logs, index): 34 | import tensorflow as tf 35 | for name, value in logs.items(): 36 | if name in ['batch', 'size']: 37 | continue 38 | if name.startswith('val_'): 39 | writer = self.val_writer 40 | name = name[4:] # remove val_ 41 | else: 42 | writer = self.writer 43 | summary = tf.Summary() 44 | summary_value = summary.value.add() 45 | if isinstance(value, np.ndarray): 46 | summary_value.simple_value = value.item() 47 | else: 48 | summary_value.simple_value = value 49 | summary_value.tag = name 50 | writer.add_summary(summary, index) 51 | self.writer.flush() 52 | self.val_writer.flush() 53 | 54 | def on_train_end(self, _): 55 | self.writer.close() 56 | self.val_writer.flush() 57 | -------------------------------------------------------------------------------- /keras_contrib/constraints/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .clip import Clip 4 | 5 | # Aliases. 6 | 7 | clip = Clip 8 | -------------------------------------------------------------------------------- /keras_contrib/constraints/clip.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from keras import backend as K 3 | from keras.constraints import Constraint 4 | 5 | 6 | class Clip(Constraint): 7 | """Clips weights to [-c, c]. 8 | 9 | # Arguments 10 | c: Clipping parameter. 11 | """ 12 | 13 | def __init__(self, c=0.01): 14 | self.c = c 15 | 16 | def __call__(self, p): 17 | return K.clip(p, -self.c, self.c) 18 | 19 | def get_config(self): 20 | return {'name': self.__class__.__name__, 21 | 'c': self.c} 22 | -------------------------------------------------------------------------------- /keras_contrib/datasets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/datasets/__init__.py -------------------------------------------------------------------------------- /keras_contrib/datasets/conll2000.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy 3 | from keras.utils.data_utils import get_file 4 | from zipfile import ZipFile 5 | from collections import Counter 6 | from keras.preprocessing.sequence import pad_sequences 7 | 8 | 9 | def load_data(path='conll2000.zip', min_freq=2): 10 | path = get_file(path, 11 | origin='https://raw.githubusercontent.com/nltk' 12 | '/nltk_data/gh-pages/packages/corpora/conll2000.zip') 13 | print(path) 14 | archive = ZipFile(path, 'r') 15 | train = _parse_data(archive.open('conll2000/train.txt')) 16 | test = _parse_data(archive.open('conll2000/test.txt')) 17 | archive.close() 18 | 19 | word_counts = Counter(row[0].lower() for sample in train for row in sample) 20 | vocab = ['', ''] 21 | vocab += [w for w, f in iter(word_counts.items()) if f >= min_freq] 22 | # in alphabetic order 23 | pos_tags = sorted(list(set(row[1] for sample in train + test for row in sample))) 24 | # in alphabetic order 25 | chunk_tags = sorted(list(set(row[2] for sample in train + test for row in sample))) 26 | 27 | train = _process_data(train, vocab, pos_tags, chunk_tags) 28 | test = _process_data(test, vocab, pos_tags, chunk_tags) 29 | return train, test, (vocab, pos_tags, chunk_tags) 30 | 31 | 32 | def _parse_data(fh): 33 | string = fh.read() 34 | data = [] 35 | for sample in string.decode().strip().split('\n\n'): 36 | data.append([row.split() for row in sample.split('\n')]) 37 | fh.close() 38 | return data 39 | 40 | 41 | def _process_data(data, vocab, pos_tags, chunk_tags, maxlen=None, onehot=False): 42 | if maxlen is None: 43 | maxlen = max(len(s) for s in data) 44 | word2idx = dict((w, i) for i, w in enumerate(vocab)) 45 | # set to (index 1) if not in vocab 46 | x = [[word2idx.get(w[0].lower(), 1) for w in s] for s in data] 47 | 48 | y_pos = [[pos_tags.index(w[1]) for w in s] for s in data] 49 | y_chunk = [[chunk_tags.index(w[2]) for w in s] for s in data] 50 | 51 | x = pad_sequences(x, maxlen) # left padding 52 | 53 | # lef padded with -1. Indeed, any integer works as it will be masked 54 | y_pos = pad_sequences(y_pos, maxlen, value=-1) 55 | y_chunk = pad_sequences(y_chunk, maxlen, value=-1) 56 | 57 | if onehot: 58 | y_pos = numpy.eye(len(pos_tags), dtype='float32')[y] 59 | y_chunk = numpy.eye(len(chunk_tags), dtype='float32')[y] 60 | else: 61 | y_pos = numpy.expand_dims(y_pos, 2) 62 | y_chunk = numpy.expand_dims(y_chunk, 2) 63 | return x, y_pos, y_chunk 64 | -------------------------------------------------------------------------------- /keras_contrib/initializers/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .convaware import ConvolutionAware 4 | -------------------------------------------------------------------------------- /keras_contrib/initializers/convaware.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import numpy as np 3 | from keras import backend as K 4 | from keras.initializers import Initializer, Orthogonal 5 | 6 | 7 | class ConvolutionAware(Initializer): 8 | """ 9 | Initializer that generates orthogonal convolution filters in the fourier 10 | space. If this initializer is passed a shape that is not 3D or 4D, 11 | orthogonal initialization will be used. 12 | # Arguments 13 | eps_std: Standard deviation for the random normal noise used to break 14 | symmetry in the inverse fourier transform. 15 | seed: A Python integer. Used to seed the random generator. 16 | # References 17 | Armen Aghajanyan, https://arxiv.org/abs/1702.06295 18 | """ 19 | 20 | def __init__(self, eps_std=0.05, seed=None): 21 | self.eps_std = eps_std 22 | self.seed = seed 23 | self.orthogonal = Orthogonal() 24 | 25 | def __call__(self, shape): 26 | rank = len(shape) 27 | 28 | if self.seed is not None: 29 | np.random.seed(self.seed) 30 | 31 | fan_in, fan_out = _compute_fans(shape, K.image_data_format()) 32 | variance = 2 / fan_in 33 | 34 | if rank == 3: 35 | row, stack_size, filters_size = shape 36 | 37 | transpose_dimensions = (2, 1, 0) 38 | kernel_shape = (row,) 39 | correct_ifft = lambda shape, s=[None]: np.fft.irfft(shape, s[0]) 40 | correct_fft = np.fft.rfft 41 | 42 | elif rank == 4: 43 | row, column, stack_size, filters_size = shape 44 | 45 | transpose_dimensions = (2, 3, 0, 1) 46 | kernel_shape = (row, column) 47 | correct_ifft = np.fft.irfft2 48 | correct_fft = np.fft.rfft2 49 | 50 | elif rank == 5: 51 | x, y, z, stack_size, filters_size = shape 52 | 53 | transpose_dimensions = (3, 4, 0, 1, 2) 54 | kernel_shape = (x, y, z) 55 | correct_fft = np.fft.rfftn 56 | correct_ifft = np.fft.irfftn 57 | else: 58 | return K.variable(self.orthogonal(shape), dtype=K.floatx()) 59 | 60 | kernel_fourier_shape = correct_fft(np.zeros(kernel_shape)).shape 61 | 62 | init = [] 63 | for i in range(filters_size): 64 | basis = self._create_basis( 65 | stack_size, np.prod(kernel_fourier_shape)) 66 | basis = basis.reshape((stack_size,) + kernel_fourier_shape) 67 | 68 | filters = [correct_ifft(x, kernel_shape) + 69 | np.random.normal(0, self.eps_std, kernel_shape) for 70 | x in basis] 71 | 72 | init.append(filters) 73 | 74 | # Format of array is now: filters, stack, row, column 75 | init = np.array(init) 76 | init = self._scale_filters(init, variance) 77 | return init.transpose(transpose_dimensions) 78 | 79 | def _create_basis(self, filters, size): 80 | if size == 1: 81 | return np.random.normal(0.0, self.eps_std, (filters, size)) 82 | 83 | nbb = filters // size + 1 84 | li = [] 85 | for i in range(nbb): 86 | a = np.random.normal(0.0, 1.0, (size, size)) 87 | a = self._symmetrize(a) 88 | u, _, v = np.linalg.svd(a) 89 | li.extend(u.T.tolist()) 90 | p = np.array(li[:filters], dtype=K.floatx()) 91 | return p 92 | 93 | def _symmetrize(self, a): 94 | return a + a.T - np.diag(a.diagonal()) 95 | 96 | def _scale_filters(self, filters, variance): 97 | c_var = np.var(filters) 98 | p = np.sqrt(variance / c_var) 99 | return filters * p 100 | 101 | def get_config(self): 102 | return { 103 | 'eps_std': self.eps_std, 104 | 'seed': self.seed 105 | } 106 | 107 | 108 | def _compute_fans(shape, data_format='channels_last'): 109 | """Computes the number of input and output units for a weight shape. 110 | 111 | # Arguments 112 | shape: Integer shape tuple. 113 | data_format: Image data format to use for convolution kernels. 114 | Note that all kernels in Keras are standardized on the 115 | `channels_last` ordering (even when inputs are set 116 | to `channels_first`). 117 | 118 | # Returns 119 | A tuple of scalars, `(fan_in, fan_out)`. 120 | 121 | # Raises 122 | ValueError: in case of invalid `data_format` argument. 123 | """ 124 | if len(shape) == 2: 125 | fan_in = shape[0] 126 | fan_out = shape[1] 127 | elif len(shape) in {3, 4, 5}: 128 | # Assuming convolution kernels (1D, 2D or 3D). 129 | # TH kernel shape: (depth, input_depth, ...) 130 | # TF kernel shape: (..., input_depth, depth) 131 | if data_format == 'channels_first': 132 | receptive_field_size = np.prod(shape[2:]) 133 | fan_in = shape[1] * receptive_field_size 134 | fan_out = shape[0] * receptive_field_size 135 | elif data_format == 'channels_last': 136 | receptive_field_size = np.prod(shape[:-2]) 137 | fan_in = shape[-2] * receptive_field_size 138 | fan_out = shape[-1] * receptive_field_size 139 | else: 140 | raise ValueError('Invalid data_format: ' + data_format) 141 | else: 142 | # No specific assumptions. 143 | fan_in = np.sqrt(np.prod(shape)) 144 | fan_out = np.sqrt(np.prod(shape)) 145 | return fan_in, fan_out 146 | -------------------------------------------------------------------------------- /keras_contrib/layers/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from .advanced_activations.pelu import PELU 4 | from .advanced_activations.srelu import SReLU 5 | from .advanced_activations.swish import Swish 6 | from .advanced_activations.sinerelu import SineReLU 7 | 8 | from .convolutional.cosineconvolution2d import CosineConv2D 9 | from .convolutional.cosineconvolution2d import CosineConvolution2D 10 | from .convolutional.subpixelupscaling import SubPixelUpscaling 11 | 12 | from .core import CosineDense 13 | 14 | from .crf import CRF 15 | 16 | from .capsule import Capsule 17 | 18 | from .normalization.instancenormalization import InstanceNormalization 19 | from .normalization.groupnormalization import GroupNormalization 20 | -------------------------------------------------------------------------------- /keras_contrib/layers/advanced_activations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/layers/advanced_activations/__init__.py -------------------------------------------------------------------------------- /keras_contrib/layers/advanced_activations/pelu.py: -------------------------------------------------------------------------------- 1 | from keras.layers import Layer, InputSpec 2 | from keras import initializers, regularizers, constraints 3 | import keras.backend as K 4 | from keras_contrib.utils.test_utils import to_tuple 5 | 6 | 7 | class PELU(Layer): 8 | """Parametric Exponential Linear Unit. 9 | 10 | It follows: 11 | `f(x) = alphas * (exp(x / betas) - 1) for x < 0`, 12 | `f(x) = (alphas / betas) * x for x >= 0`, 13 | where `alphas` & `betas` are learned arrays with the same shape as x. 14 | 15 | # Input shape 16 | Arbitrary. Use the keyword argument `input_shape` 17 | (tuple of integers, does not include the samples axis) 18 | when using this layer as the first layer in a model. 19 | 20 | # Output shape 21 | Same shape as the input. 22 | 23 | # Arguments 24 | alphas_initializer: initialization function for the alpha variable weights. 25 | betas_initializer: initialization function for the beta variable weights. 26 | weights: initial weights, as a list of a single Numpy array. 27 | shared_axes: the axes along which to share learnable 28 | parameters for the activation function. 29 | For example, if the incoming feature maps 30 | are from a 2D convolution 31 | with output shape `(batch, height, width, channels)`, 32 | and you wish to share parameters across space 33 | so that each filter only has one set of parameters, 34 | set `shared_axes=[1, 2]`. 35 | 36 | # References 37 | - [Parametric exponential linear unit for deep convolutional neural networks]( 38 | https://arxiv.org/abs/1605.09332v3) 39 | """ 40 | 41 | def __init__(self, alpha_initializer='ones', 42 | alpha_regularizer=None, 43 | alpha_constraint=None, 44 | beta_initializer='ones', 45 | beta_regularizer=None, 46 | beta_constraint=None, 47 | shared_axes=None, 48 | **kwargs): 49 | super(PELU, self).__init__(**kwargs) 50 | self.supports_masking = True 51 | self.alpha_initializer = initializers.get(alpha_initializer) 52 | self.alpha_regularizer = regularizers.get(alpha_regularizer) 53 | self.alpha_constraint = constraints.get(alpha_constraint) 54 | self.beta_initializer = initializers.get(beta_initializer) 55 | self.beta_regularizer = regularizers.get(beta_regularizer) 56 | self.beta_constraint = constraints.get(beta_constraint) 57 | if shared_axes is None: 58 | self.shared_axes = None 59 | elif not isinstance(shared_axes, (list, tuple)): 60 | self.shared_axes = [shared_axes] 61 | else: 62 | self.shared_axes = list(shared_axes) 63 | 64 | def build(self, input_shape): 65 | input_shape = to_tuple(input_shape) 66 | param_shape = list(input_shape[1:]) 67 | self.param_broadcast = [False] * len(param_shape) 68 | if self.shared_axes is not None: 69 | for i in self.shared_axes: 70 | param_shape[i - 1] = 1 71 | self.param_broadcast[i - 1] = True 72 | 73 | param_shape = tuple(param_shape) 74 | # Initialised as ones to emulate the default ELU 75 | self.alpha = self.add_weight(shape=param_shape, 76 | name='alpha', 77 | initializer=self.alpha_initializer, 78 | regularizer=self.alpha_regularizer, 79 | constraint=self.alpha_constraint) 80 | self.beta = self.add_weight(shape=param_shape, 81 | name='beta', 82 | initializer=self.beta_initializer, 83 | regularizer=self.beta_regularizer, 84 | constraint=self.beta_constraint) 85 | 86 | # Set input spec 87 | axes = {} 88 | if self.shared_axes: 89 | for i in range(1, len(input_shape)): 90 | if i not in self.shared_axes: 91 | axes[i] = input_shape[i] 92 | self.input_spec = InputSpec(ndim=len(input_shape), axes=axes) 93 | self.built = True 94 | 95 | def call(self, x, mask=None): 96 | if K.backend() == 'theano': 97 | pos = K.relu(x) * (K.pattern_broadcast(self.alpha, self.param_broadcast) / 98 | K.pattern_broadcast(self.beta, self.param_broadcast)) 99 | neg = (K.pattern_broadcast(self.alpha, self.param_broadcast) * 100 | (K.exp((-K.relu(-x)) 101 | / K.pattern_broadcast(self.beta, self.param_broadcast)) - 1)) 102 | else: 103 | pos = K.relu(x) * self.alpha / self.beta 104 | neg = self.alpha * (K.exp((-K.relu(-x)) / self.beta) - 1) 105 | return neg + pos 106 | 107 | def get_config(self): 108 | config = { 109 | 'alpha_initializer': initializers.serialize(self.alpha_initializer), 110 | 'alpha_regularizer': regularizers.serialize(self.alpha_regularizer), 111 | 'alpha_constraint': constraints.serialize(self.alpha_constraint), 112 | 'beta_initializer': initializers.serialize(self.beta_initializer), 113 | 'beta_regularizer': regularizers.serialize(self.beta_regularizer), 114 | 'beta_constraint': constraints.serialize(self.beta_constraint), 115 | 'shared_axes': self.shared_axes 116 | } 117 | base_config = super(PELU, self).get_config() 118 | return dict(list(base_config.items()) + list(config.items())) 119 | 120 | def compute_output_shape(self, input_shape): 121 | return input_shape 122 | -------------------------------------------------------------------------------- /keras_contrib/layers/advanced_activations/sinerelu.py: -------------------------------------------------------------------------------- 1 | import keras.backend as K 2 | from keras.layers import Layer 3 | 4 | 5 | class SineReLU(Layer): 6 | """Sine Rectified Linear Unit to generate oscilations. 7 | 8 | It allows an oscilation in the gradients when the weights are negative. 9 | The oscilation can be controlled with a parameter, which makes it be close 10 | or equal to zero. The functional is diferentiable at any point due to 11 | its derivative. 12 | For instance, at 0, the derivative of 'sin(0) - cos(0)' 13 | is 'cos(0) + sin(0)' which is 1. 14 | 15 | # Input shape 16 | Arbitrary. Use the keyword argument `input_shape` 17 | (tuple of integers, does not include the samples axis) 18 | when using this layer as the first layer in a model. 19 | 20 | # Output shape 21 | Same shape as the input. 22 | 23 | # Arguments 24 | epsilon: float. Hyper-parameter used to control the amplitude of the 25 | sinusoidal wave when weights are negative. 26 | The default value, 0.0025, since it works better for CNN layers and 27 | those are the most used layers nowadays. 28 | When using Dense Networks, try something around 0.006. 29 | 30 | # References: 31 | - [SineReLU: An Alternative to the ReLU Activation Function]( 32 | https://medium.com/@wilder.rodrigues/sinerelu-an-alternative-to-the-relu-activation-function-e46a6199997d). 33 | 34 | This function was 35 | first introduced at the Codemotion Amsterdam 2018 and then at 36 | the DevDays, in Vilnius, Lithuania. 37 | It has been extensively tested with Deep Nets, CNNs, 38 | LSTMs, Residual Nets and GANs, based 39 | on the MNIST, Kaggle Toxicity and IMDB datasets. 40 | 41 | # Performance: 42 | 43 | - Fashion MNIST 44 | * Mean of 6 runs per Activation Function 45 | * Fully Connection Network 46 | - SineReLU: loss mean -> 0.3522; accuracy mean -> 89.18; 47 | mean of std loss -> 0.08375204467435822 48 | - LeakyReLU: loss mean-> 0.3553; accuracy mean -> 88.98; 49 | mean of std loss -> 0.0831161868455245 50 | - ReLU: loss mean -> 0.3519; accuracy mean -> 88.84; 51 | mean of std loss -> 0.08358816501301362 52 | * Convolutional Neural Network 53 | - SineReLU: loss mean -> 0.2180; accuracy mean -> 92.49; 54 | mean of std loss -> 0.0781155784858847 55 | - LeakyReLU: loss mean -> 0.2205; accuracy mean -> 92.37; 56 | mean of std loss -> 0.09273670474788205 57 | - ReLU: loss mean -> 0.2144; accuracy mean -> 92.45; 58 | mean of std loss -> 0.09396114585977 59 | - MNIST 60 | * Mean of 6 runs per Activation Function 61 | * Fully Connection Network 62 | - SineReLU: loss mean -> 0.0623; accuracy mean -> 98.53; 63 | mean of std loss -> 0.06012015231824904 64 | - LeakyReLU: loss mean-> 0.0623; accuracy mean -> 98.50; 65 | mean of std loss -> 0.06052147632835356 66 | - ReLU: loss mean -> 0.0605; accuracy mean -> 98.49; 67 | mean of std loss -> 0.059599885665016096 68 | * Convolutional Neural Network 69 | - SineReLU: loss mean -> 0.0198; accuracy mean -> 99.51; 70 | mean of std loss -> 0.0425338329550847 71 | - LeakyReLU: loss mean -> 0.0216; accuracy mean -> 99.40; 72 | mean of std loss -> 0.04834468835196667 73 | - ReLU: loss mean -> 0.0185; accuracy mean -> 99.49; 74 | mean of std loss -> 0.05503719489690131 75 | 76 | # Jupyter Notebooks 77 | - https://github.com/ekholabs/DLinK/blob/master/notebooks/keras 78 | 79 | # Examples 80 | The Advanced Activation function SineReLU have to be imported from the 81 | keras_contrib.layers package. 82 | 83 | To see full source-code of this architecture and other examples, 84 | please follow this link: https://github.com/ekholabs/DLinK 85 | 86 | ```python 87 | model = Sequential() 88 | model.add(Dense(128, input_shape = (784,))) 89 | model.add(SineReLU()) 90 | model.add(Dropout(0.2)) 91 | 92 | model.add(Dense(256)) 93 | model.add(SineReLU()) 94 | model.add(Dropout(0.3)) 95 | 96 | model.add(Dense(1024)) 97 | model.add(SineReLU()) 98 | model.add(Dropout(0.5)) 99 | 100 | model.add(Dense(10, activation = 'softmax')) 101 | ``` 102 | """ 103 | 104 | def __init__(self, epsilon=0.0025, **kwargs): 105 | super(SineReLU, self).__init__(**kwargs) 106 | self.supports_masking = True 107 | self.epsilon = K.cast_to_floatx(epsilon) 108 | 109 | def call(self, Z): 110 | m = self.epsilon * (K.sin(Z) - K.cos(Z)) 111 | A = K.maximum(m, Z) 112 | return A 113 | 114 | def get_config(self): 115 | config = {'epsilon': float(self.epsilon)} 116 | base_config = super(SineReLU, self).get_config() 117 | return dict(list(base_config.items()) + list(config.items())) 118 | 119 | def compute_output_shape(self, input_shape): 120 | return input_shape 121 | -------------------------------------------------------------------------------- /keras_contrib/layers/advanced_activations/srelu.py: -------------------------------------------------------------------------------- 1 | from keras.layers import Layer, InputSpec 2 | from keras import initializers 3 | import keras.backend as K 4 | from keras_contrib.utils.test_utils import to_tuple 5 | 6 | 7 | class SReLU(Layer): 8 | """S-shaped Rectified Linear Unit. 9 | 10 | It follows: 11 | `f(x) = t^r + a^r(x - t^r) for x >= t^r`, 12 | `f(x) = x for t^r > x > t^l`, 13 | `f(x) = t^l + a^l(x - t^l) for x <= t^l`. 14 | 15 | # Input shape 16 | Arbitrary. Use the keyword argument `input_shape` 17 | (tuple of integers, does not include the samples axis) 18 | when using this layer as the first layer in a model. 19 | 20 | # Output shape 21 | Same shape as the input. 22 | 23 | # Arguments 24 | t_left_initializer: initializer function for the left part intercept 25 | a_left_initializer: initializer function for the left part slope 26 | t_right_initializer: initializer function for the right part intercept 27 | a_right_initializer: initializer function for the right part slope 28 | shared_axes: the axes along which to share learnable 29 | parameters for the activation function. 30 | For example, if the incoming feature maps 31 | are from a 2D convolution 32 | with output shape `(batch, height, width, channels)`, 33 | and you wish to share parameters across space 34 | so that each filter only has one set of parameters, 35 | set `shared_axes=[1, 2]`. 36 | 37 | # References 38 | - [Deep Learning with S-shaped Rectified Linear Activation Units]( 39 | http://arxiv.org/abs/1512.07030) 40 | """ 41 | 42 | def __init__(self, t_left_initializer='zeros', 43 | a_left_initializer=initializers.RandomUniform(minval=0, maxval=1), 44 | t_right_initializer=initializers.RandomUniform(minval=0, maxval=5), 45 | a_right_initializer='ones', 46 | shared_axes=None, 47 | **kwargs): 48 | super(SReLU, self).__init__(**kwargs) 49 | self.supports_masking = True 50 | self.t_left_initializer = initializers.get(t_left_initializer) 51 | self.a_left_initializer = initializers.get(a_left_initializer) 52 | self.t_right_initializer = initializers.get(t_right_initializer) 53 | self.a_right_initializer = initializers.get(a_right_initializer) 54 | if shared_axes is None: 55 | self.shared_axes = None 56 | elif not isinstance(shared_axes, (list, tuple)): 57 | self.shared_axes = [shared_axes] 58 | else: 59 | self.shared_axes = list(shared_axes) 60 | 61 | def build(self, input_shape): 62 | input_shape = to_tuple(input_shape) 63 | param_shape = list(input_shape[1:]) 64 | self.param_broadcast = [False] * len(param_shape) 65 | if self.shared_axes is not None: 66 | for i in self.shared_axes: 67 | param_shape[i - 1] = 1 68 | self.param_broadcast[i - 1] = True 69 | 70 | param_shape = tuple(param_shape) 71 | 72 | self.t_left = self.add_weight(shape=param_shape, 73 | name='t_left', 74 | initializer=self.t_left_initializer) 75 | 76 | self.a_left = self.add_weight(shape=param_shape, 77 | name='a_left', 78 | initializer=self.a_left_initializer) 79 | 80 | self.t_right = self.add_weight(shape=param_shape, 81 | name='t_right', 82 | initializer=self.t_right_initializer) 83 | 84 | self.a_right = self.add_weight(shape=param_shape, 85 | name='a_right', 86 | initializer=self.a_right_initializer) 87 | 88 | # Set input spec 89 | axes = {} 90 | if self.shared_axes: 91 | for i in range(1, len(input_shape)): 92 | if i not in self.shared_axes: 93 | axes[i] = input_shape[i] 94 | self.input_spec = InputSpec(ndim=len(input_shape), axes=axes) 95 | self.built = True 96 | 97 | def call(self, x, mask=None): 98 | # ensure the the right part is always to the right of the left 99 | t_right_actual = self.t_left + K.abs(self.t_right) 100 | 101 | if K.backend() == 'theano': 102 | t_left = K.pattern_broadcast(self.t_left, self.param_broadcast) 103 | a_left = K.pattern_broadcast(self.a_left, self.param_broadcast) 104 | a_right = K.pattern_broadcast(self.a_right, self.param_broadcast) 105 | t_right_actual = K.pattern_broadcast(t_right_actual, 106 | self.param_broadcast) 107 | else: 108 | t_left = self.t_left 109 | a_left = self.a_left 110 | a_right = self.a_right 111 | 112 | y_left_and_center = t_left + K.relu(x - t_left, 113 | a_left, 114 | t_right_actual - t_left) 115 | y_right = K.relu(x - t_right_actual) * a_right 116 | return y_left_and_center + y_right 117 | 118 | def get_config(self): 119 | config = { 120 | 't_left_initializer': self.t_left_initializer, 121 | 'a_left_initializer': self.a_left_initializer, 122 | 't_right_initializer': self.t_right_initializer, 123 | 'a_right_initializer': self.a_right_initializer, 124 | 'shared_axes': self.shared_axes 125 | } 126 | base_config = super(SReLU, self).get_config() 127 | return dict(list(base_config.items()) + list(config.items())) 128 | 129 | def compute_output_shape(self, input_shape): 130 | return input_shape 131 | -------------------------------------------------------------------------------- /keras_contrib/layers/advanced_activations/swish.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.layers import Layer 3 | 4 | 5 | class Swish(Layer): 6 | """ Swish (Ramachandranet al., 2017) 7 | 8 | # Input shape 9 | Arbitrary. Use the keyword argument `input_shape` 10 | (tuple of integers, does not include the samples axis) 11 | when using this layer as the first layer in a model. 12 | 13 | # Output shape 14 | Same shape as the input. 15 | 16 | # Arguments 17 | beta: float >= 0. Scaling factor 18 | if set to 1 and trainable set to False (default), 19 | Swish equals the SiLU activation (Elfwing et al., 2017) 20 | trainable: whether to learn the scaling factor during training or not 21 | 22 | # References 23 | - [Searching for Activation Functions](https://arxiv.org/abs/1710.05941) 24 | - [Sigmoid-weighted linear units for neural network function 25 | approximation in reinforcement learning](https://arxiv.org/abs/1702.03118) 26 | """ 27 | 28 | def __init__(self, beta=1.0, trainable=False, **kwargs): 29 | super(Swish, self).__init__(**kwargs) 30 | self.supports_masking = True 31 | self.beta = beta 32 | self.trainable = trainable 33 | 34 | def build(self, input_shape): 35 | self.scaling_factor = K.variable(self.beta, 36 | dtype=K.floatx(), 37 | name='scaling_factor') 38 | if self.trainable: 39 | self._trainable_weights.append(self.scaling_factor) 40 | super(Swish, self).build(input_shape) 41 | 42 | def call(self, inputs, mask=None): 43 | return inputs * K.sigmoid(self.scaling_factor * inputs) 44 | 45 | def get_config(self): 46 | config = {'beta': self.get_weights()[0] if self.trainable else self.beta, 47 | 'trainable': self.trainable} 48 | base_config = super(Swish, self).get_config() 49 | return dict(list(base_config.items()) + list(config.items())) 50 | 51 | def compute_output_shape(self, input_shape): 52 | return input_shape 53 | -------------------------------------------------------------------------------- /keras_contrib/layers/convolutional/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/layers/convolutional/__init__.py -------------------------------------------------------------------------------- /keras_contrib/layers/convolutional/subpixelupscaling.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from __future__ import absolute_import 3 | 4 | from keras.layers import Layer 5 | 6 | from keras_contrib import backend as KC 7 | from keras_contrib.utils.conv_utils import normalize_data_format 8 | 9 | 10 | class SubPixelUpscaling(Layer): 11 | """ Sub-pixel convolutional upscaling layer. 12 | 13 | This layer requires a Convolution2D prior to it, 14 | having output filters computed according to 15 | the formula : 16 | 17 | filters = k * (scale_factor * scale_factor) 18 | where k = a user defined number of filters (generally larger than 32) 19 | scale_factor = the upscaling factor (generally 2) 20 | 21 | This layer performs the depth to space operation on 22 | the convolution filters, and returns a 23 | tensor with the size as defined below. 24 | 25 | # Example : 26 | ```python 27 | # A standard subpixel upscaling block 28 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(...) 29 | u = SubPixelUpscaling(scale_factor=2)(x) 30 | 31 | # Optional 32 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(u) 33 | ``` 34 | 35 | In practice, it is useful to have a second convolution layer after the 36 | SubPixelUpscaling layer to speed up the learning process. 37 | 38 | However, if you are stacking multiple 39 | SubPixelUpscaling blocks, it may increase 40 | the number of parameters greatly, so the 41 | Convolution layer after SubPixelUpscaling 42 | layer can be removed. 43 | 44 | # Arguments 45 | scale_factor: Upscaling factor. 46 | data_format: Can be None, 'channels_first' or 'channels_last'. 47 | 48 | # Input shape 49 | 4D tensor with shape: 50 | `(samples, k * (scale_factor * scale_factor) channels, rows, cols)` 51 | if data_format='channels_first' 52 | or 4D tensor with shape: 53 | `(samples, rows, cols, k * (scale_factor * scale_factor) channels)` 54 | if data_format='channels_last'. 55 | 56 | # Output shape 57 | 4D tensor with shape: 58 | `(samples, k channels, rows * scale_factor, cols * scale_factor))` 59 | if data_format='channels_first' 60 | or 4D tensor with shape: 61 | `(samples, rows * scale_factor, cols * scale_factor, k channels)` 62 | if data_format='channels_last'. 63 | 64 | # References 65 | - [Real-Time Single Image and Video Super-Resolution Using an 66 | Efficient Sub-Pixel Convolutional Neural Network]( 67 | https://arxiv.org/abs/1609.05158) 68 | """ 69 | 70 | def __init__(self, scale_factor=2, data_format=None, **kwargs): 71 | super(SubPixelUpscaling, self).__init__(**kwargs) 72 | 73 | self.scale_factor = scale_factor 74 | self.data_format = normalize_data_format(data_format) 75 | 76 | def build(self, input_shape): 77 | pass 78 | 79 | def call(self, x, mask=None): 80 | y = KC.depth_to_space(x, self.scale_factor, self.data_format) 81 | return y 82 | 83 | def compute_output_shape(self, input_shape): 84 | if self.data_format == 'channels_first': 85 | b, k, r, c = input_shape 86 | new_k = k // (self.scale_factor ** 2) 87 | new_r = r * self.scale_factor 88 | new_c = c * self.scale_factor 89 | return b, new_k, new_r, new_c 90 | else: 91 | b, r, c, k = input_shape 92 | new_r = r * self.scale_factor 93 | new_c = c * self.scale_factor 94 | new_k = k // (self.scale_factor ** 2) 95 | return b, new_r, new_c, new_k 96 | 97 | def get_config(self): 98 | config = {'scale_factor': self.scale_factor, 99 | 'data_format': self.data_format} 100 | base_config = super(SubPixelUpscaling, self).get_config() 101 | return dict(list(base_config.items()) + list(config.items())) 102 | -------------------------------------------------------------------------------- /keras_contrib/layers/normalization/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/layers/normalization/__init__.py -------------------------------------------------------------------------------- /keras_contrib/losses/__init__.py: -------------------------------------------------------------------------------- 1 | from .dssim import DSSIMObjective 2 | from .jaccard import jaccard_distance 3 | from .crf_losses import crf_loss, crf_nll 4 | -------------------------------------------------------------------------------- /keras_contrib/losses/crf_losses.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.losses import categorical_crossentropy 3 | from keras.losses import sparse_categorical_crossentropy 4 | 5 | 6 | def crf_nll(y_true, y_pred): 7 | """The negative log-likelihood for linear chain Conditional Random Field (CRF). 8 | 9 | This loss function is only used when the `layers.CRF` layer 10 | is trained in the "join" mode. 11 | 12 | # Arguments 13 | y_true: tensor with true targets. 14 | y_pred: tensor with predicted targets. 15 | 16 | # Returns 17 | A scalar representing corresponding to the negative log-likelihood. 18 | 19 | # Raises 20 | TypeError: If CRF is not the last layer. 21 | 22 | # About GitHub 23 | If you open an issue or a pull request about CRF, please 24 | add `cc @lzfelix` to notify Luiz Felix. 25 | """ 26 | 27 | crf, idx = y_pred._keras_history[:2] 28 | if crf._outbound_nodes: 29 | raise TypeError('When learn_model="join", CRF must be the last layer.') 30 | if crf.sparse_target: 31 | y_true = K.one_hot(K.cast(y_true[:, :, 0], 'int32'), crf.units) 32 | X = crf._inbound_nodes[idx].input_tensors[0] 33 | mask = crf._inbound_nodes[idx].input_masks[0] 34 | nloglik = crf.get_negative_log_likelihood(y_true, X, mask) 35 | return nloglik 36 | 37 | 38 | def crf_loss(y_true, y_pred): 39 | """General CRF loss function depending on the learning mode. 40 | 41 | # Arguments 42 | y_true: tensor with true targets. 43 | y_pred: tensor with predicted targets. 44 | 45 | # Returns 46 | If the CRF layer is being trained in the join mode, returns the negative 47 | log-likelihood. Otherwise returns the categorical crossentropy implemented 48 | by the underlying Keras backend. 49 | 50 | # About GitHub 51 | If you open an issue or a pull request about CRF, please 52 | add `cc @lzfelix` to notify Luiz Felix. 53 | """ 54 | crf, idx = y_pred._keras_history[:2] 55 | if crf.learn_mode == 'join': 56 | return crf_nll(y_true, y_pred) 57 | else: 58 | if crf.sparse_target: 59 | return sparse_categorical_crossentropy(y_true, y_pred) 60 | else: 61 | return categorical_crossentropy(y_true, y_pred) 62 | -------------------------------------------------------------------------------- /keras_contrib/losses/dssim.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import keras_contrib.backend as KC 3 | from keras import backend as K 4 | 5 | 6 | class DSSIMObjective: 7 | """Difference of Structural Similarity (DSSIM loss function). 8 | Clipped between 0 and 0.5 9 | 10 | Note : You should add a regularization term like a l2 loss in addition to this one. 11 | Note : In theano, the `kernel_size` must be a factor of the output size. So 3 could 12 | not be the `kernel_size` for an output of 32. 13 | 14 | # Arguments 15 | k1: Parameter of the SSIM (default 0.01) 16 | k2: Parameter of the SSIM (default 0.03) 17 | kernel_size: Size of the sliding window (default 3) 18 | max_value: Max value of the output (default 1.0) 19 | """ 20 | 21 | def __init__(self, k1=0.01, k2=0.03, kernel_size=3, max_value=1.0): 22 | self.__name__ = 'DSSIMObjective' 23 | self.kernel_size = kernel_size 24 | self.k1 = k1 25 | self.k2 = k2 26 | self.max_value = max_value 27 | self.c1 = (self.k1 * self.max_value) ** 2 28 | self.c2 = (self.k2 * self.max_value) ** 2 29 | self.dim_ordering = K.image_data_format() 30 | self.backend = K.backend() 31 | 32 | def __int_shape(self, x): 33 | return K.int_shape(x) if self.backend == 'tensorflow' else K.shape(x) 34 | 35 | def __call__(self, y_true, y_pred): 36 | # There are additional parameters for this function 37 | # Note: some of the 'modes' for edge behavior do not yet have a 38 | # gradient definition in the Theano tree 39 | # and cannot be used for learning 40 | 41 | kernel = [self.kernel_size, self.kernel_size] 42 | y_true = K.reshape(y_true, [-1] + list(self.__int_shape(y_pred)[1:])) 43 | y_pred = K.reshape(y_pred, [-1] + list(self.__int_shape(y_pred)[1:])) 44 | 45 | patches_pred = KC.extract_image_patches(y_pred, kernel, kernel, 'valid', 46 | self.dim_ordering) 47 | patches_true = KC.extract_image_patches(y_true, kernel, kernel, 'valid', 48 | self.dim_ordering) 49 | 50 | # Reshape to get the var in the cells 51 | bs, w, h, c1, c2, c3 = self.__int_shape(patches_pred) 52 | patches_pred = K.reshape(patches_pred, [-1, w, h, c1 * c2 * c3]) 53 | patches_true = K.reshape(patches_true, [-1, w, h, c1 * c2 * c3]) 54 | # Get mean 55 | u_true = K.mean(patches_true, axis=-1) 56 | u_pred = K.mean(patches_pred, axis=-1) 57 | # Get variance 58 | var_true = K.var(patches_true, axis=-1) 59 | var_pred = K.var(patches_pred, axis=-1) 60 | # Get std dev 61 | covar_true_pred = K.mean(patches_true * patches_pred, axis=-1) - u_true * u_pred 62 | 63 | ssim = (2 * u_true * u_pred + self.c1) * (2 * covar_true_pred + self.c2) 64 | denom = ((K.square(u_true) 65 | + K.square(u_pred) 66 | + self.c1) * (var_pred + var_true + self.c2)) 67 | ssim /= denom # no need for clipping, c1 and c2 make the denom non-zero 68 | return K.mean((1.0 - ssim) / 2.0) 69 | -------------------------------------------------------------------------------- /keras_contrib/losses/jaccard.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | 3 | 4 | def jaccard_distance(y_true, y_pred, smooth=100): 5 | """Jaccard distance for semantic segmentation. 6 | 7 | Also known as the intersection-over-union loss. 8 | 9 | This loss is useful when you have unbalanced numbers of pixels within an image 10 | because it gives all classes equal weight. However, it is not the defacto 11 | standard for image segmentation. 12 | 13 | For example, assume you are trying to predict if 14 | each pixel is cat, dog, or background. 15 | You have 80% background pixels, 10% dog, and 10% cat. 16 | If the model predicts 100% background 17 | should it be be 80% right (as with categorical cross entropy) 18 | or 30% (with this loss)? 19 | 20 | The loss has been modified to have a smooth gradient as it converges on zero. 21 | This has been shifted so it converges on 0 and is smoothed to avoid exploding 22 | or disappearing gradient. 23 | 24 | Jaccard = (|X & Y|)/ (|X|+ |Y| - |X & Y|) 25 | = sum(|A*B|)/(sum(|A|)+sum(|B|)-sum(|A*B|)) 26 | 27 | # Arguments 28 | y_true: The ground truth tensor. 29 | y_pred: The predicted tensor 30 | smooth: Smoothing factor. Default is 100. 31 | 32 | # Returns 33 | The Jaccard distance between the two tensors. 34 | 35 | # References 36 | - [What is a good evaluation measure for semantic segmentation?]( 37 | http://www.bmva.org/bmvc/2013/Papers/paper0032/paper0032.pdf) 38 | 39 | """ 40 | intersection = K.sum(K.abs(y_true * y_pred), axis=-1) 41 | sum_ = K.sum(K.abs(y_true) + K.abs(y_pred), axis=-1) 42 | jac = (intersection + smooth) / (sum_ - intersection + smooth) 43 | return (1 - jac) * smooth 44 | -------------------------------------------------------------------------------- /keras_contrib/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | from .crf_accuracies import crf_accuracy, crf_marginal_accuracy 2 | from .crf_accuracies import crf_viterbi_accuracy 3 | -------------------------------------------------------------------------------- /keras_contrib/metrics/crf_accuracies.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | 3 | 4 | def _get_accuracy(y_true, y_pred, mask, sparse_target=False): 5 | y_pred = K.argmax(y_pred, -1) 6 | if sparse_target: 7 | y_true = K.cast(y_true[:, :, 0], K.dtype(y_pred)) 8 | else: 9 | y_true = K.argmax(y_true, -1) 10 | judge = K.cast(K.equal(y_pred, y_true), K.floatx()) 11 | if mask is None: 12 | return K.mean(judge) 13 | else: 14 | mask = K.cast(mask, K.floatx()) 15 | return K.sum(judge * mask) / K.sum(mask) 16 | 17 | 18 | def crf_viterbi_accuracy(y_true, y_pred): 19 | '''Use Viterbi algorithm to get best path, and compute its accuracy. 20 | `y_pred` must be an output from CRF.''' 21 | crf, idx = y_pred._keras_history[:2] 22 | X = crf._inbound_nodes[idx].input_tensors[0] 23 | mask = crf._inbound_nodes[idx].input_masks[0] 24 | y_pred = crf.viterbi_decoding(X, mask) 25 | return _get_accuracy(y_true, y_pred, mask, crf.sparse_target) 26 | 27 | 28 | def crf_marginal_accuracy(y_true, y_pred): 29 | '''Use time-wise marginal argmax as prediction. 30 | `y_pred` must be an output from CRF with `learn_mode="marginal"`.''' 31 | crf, idx = y_pred._keras_history[:2] 32 | X = crf._inbound_nodes[idx].input_tensors[0] 33 | mask = crf._inbound_nodes[idx].input_masks[0] 34 | y_pred = crf.get_marginal_prob(X, mask) 35 | return _get_accuracy(y_true, y_pred, mask, crf.sparse_target) 36 | 37 | 38 | def crf_accuracy(y_true, y_pred): 39 | '''Ge default accuracy based on CRF `test_mode`.''' 40 | crf, idx = y_pred._keras_history[:2] 41 | if crf.test_mode == 'viterbi': 42 | return crf_viterbi_accuracy(y_true, y_pred) 43 | else: 44 | return crf_marginal_accuracy(y_true, y_pred) 45 | -------------------------------------------------------------------------------- /keras_contrib/optimizers/__init__.py: -------------------------------------------------------------------------------- 1 | from .ftml import FTML 2 | from .padam import Padam 3 | from .yogi import Yogi 4 | from .lars import LARS 5 | 6 | # aliases 7 | ftml = FTML 8 | lars = LARS 9 | -------------------------------------------------------------------------------- /keras_contrib/optimizers/ftml.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from keras.optimizers import Optimizer 3 | from keras import backend as K 4 | 5 | 6 | class FTML(Optimizer): 7 | """FTML optimizer. 8 | 9 | # Arguments 10 | lr: float >= 0. Learning rate. 11 | beta_1: float, 0 < beta < 1. Generally close to 0.5. 12 | beta_2: float, 0 < beta < 1. Generally close to 1. 13 | epsilon: float >= 0. Fuzz factor. 14 | decay: float >= 0. Learning rate decay over each update. 15 | 16 | # References 17 | - [FTML - Follow the Moving Leader in Deep Learning]( 18 | http://www.cse.ust.hk/~szhengac/papers/icml17.pdf) 19 | """ 20 | 21 | def __init__(self, lr=0.0025, beta_1=0.6, beta_2=0.999, 22 | epsilon=1e-8, decay=0., **kwargs): 23 | super(FTML, self).__init__(**kwargs) 24 | self.__dict__.update(locals()) 25 | self.iterations = K.variable(0) 26 | self.lr = K.variable(lr) 27 | self.beta_1 = K.variable(beta_1) 28 | self.beta_2 = K.variable(beta_2) 29 | self.decay = K.variable(decay) 30 | self.epsilon = epsilon 31 | self.inital_decay = decay 32 | 33 | def get_updates(self, loss, params): 34 | grads = self.get_gradients(loss, params) 35 | self.updates = [K.update_add(self.iterations, 1)] 36 | 37 | lr = self.lr 38 | if self.inital_decay > 0: 39 | lr *= (1. / (1. + self.decay * self.iterations)) 40 | 41 | t = self.iterations + 1 42 | 43 | lr_t = lr / (1. - K.pow(self.beta_1, t)) 44 | 45 | shapes = [K.int_shape(p) for p in params] 46 | zs = [K.zeros(shape) for shape in shapes] 47 | vs = [K.zeros(shape) for shape in shapes] 48 | ds = [K.zeros(shape) for shape in shapes] 49 | self.weights = [self.iterations] + zs + vs + ds 50 | 51 | for p, g, z, v, d in zip(params, grads, zs, vs, ds): 52 | v_t = self.beta_2 * v + (1. - self.beta_2) * K.square(g) 53 | d_t = (K.sqrt(v_t / (1. - K.pow(self.beta_2, t))) 54 | + self.epsilon) / lr_t 55 | sigma_t = d_t - self.beta_1 * d 56 | z_t = self.beta_1 * z + (1. - self.beta_1) * g - sigma_t * p 57 | 58 | p_t = - z_t / d_t 59 | 60 | self.updates.append(K.update(z, z_t)) 61 | self.updates.append(K.update(v, v_t)) 62 | self.updates.append(K.update(d, d_t)) 63 | 64 | new_p = p_t 65 | 66 | # Apply constraints. 67 | if getattr(p, 'constraint', None) is not None: 68 | new_p = p.constraint(new_p) 69 | 70 | self.updates.append(K.update(p, new_p)) 71 | return self.updates 72 | 73 | def get_config(self): 74 | config = {'lr': float(K.get_value(self.lr)), 75 | 'beta_1': float(K.get_value(self.beta_1)), 76 | 'beta_2': float(K.get_value(self.beta_2)), 77 | 'decay': float(K.get_value(self.decay)), 78 | 'epsilon': self.epsilon} 79 | base_config = super(FTML, self).get_config() 80 | return dict(list(base_config.items()) + list(config.items())) 81 | -------------------------------------------------------------------------------- /keras_contrib/optimizers/lars.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.optimizers import Optimizer 3 | 4 | 5 | class LARS(Optimizer): 6 | """Layer-wise Adaptive Rate Scaling for large batch training. 7 | Introduced by "Large Batch Training of Convolutional Networks" by Y. You, 8 | I. Gitman, and B. Ginsburg. (https://arxiv.org/abs/1708.03888) 9 | Implements the LARS learning rate scheme presented in the paper above. This 10 | optimizer is useful when scaling the batch size to up to 32K without 11 | significant performance degradation. It is recommended to use the optimizer 12 | in conjunction with: 13 | - Gradual learning rate warm-up 14 | - Linear learning rate scaling 15 | - Poly rule learning rate decay 16 | Note, LARS scaling is currently only enabled for dense tensors. 17 | 18 | Args: 19 | lr: A `Tensor` or floating point value. The base learning rate. 20 | momentum: A floating point value. Momentum hyperparameter. 21 | weight_decay: A floating point value. Weight decay hyperparameter. 22 | eeta: LARS coefficient as used in the paper. Dfault set to LARS 23 | coefficient from the paper. (eeta / weight_decay) determines the 24 | highest scaling factor in LARS. 25 | epsilon: Optional epsilon parameter to be set in models that have very 26 | small gradients. Default set to 0.0. 27 | nesterov: when set to True, nesterov momentum will be enabled 28 | """ 29 | 30 | def __init__(self, 31 | lr, 32 | momentum=0.9, 33 | weight_decay=0.0001, 34 | eeta=0.001, 35 | epsilon=0.0, 36 | nesterov=False, 37 | **kwargs): 38 | 39 | if momentum < 0.0: 40 | raise ValueError("momentum should be positive: %s" % momentum) 41 | if weight_decay < 0.0: 42 | raise ValueError("weight_decay is not positive: %s" % weight_decay) 43 | super(LARS, self).__init__(**kwargs) 44 | with K.name_scope(self.__class__.__name__): 45 | self.iterations = K.variable(0, dtype='int64', name='iterations') 46 | self.lr = K.variable(lr, name='lr') 47 | self.momentum = K.variable(momentum, name='momentum') 48 | self.weight_decay = K.variable(weight_decay, name='weight_decay') 49 | self.eeta = K.variable(eeta, name='eeta') 50 | self.epsilon = epsilon 51 | self.nesterov = nesterov 52 | 53 | def get_updates(self, loss, params): 54 | grads = self.get_gradients(loss, params) 55 | weights = self.get_weights() 56 | self.updates = [K.update_add(self.iterations, 1)] 57 | scaled_lr = self.lr 58 | w_norm = K.sqrt(K.sum([K.sum(K.square(weight)) 59 | for weight in weights])) 60 | g_norm = K.sqrt(K.sum([K.sum(K.square(grad)) 61 | for grad in grads])) 62 | scaled_lr = K.switch(K.greater(w_norm * g_norm, K.zeros([1])), 63 | K.expand_dims((self.eeta * w_norm / 64 | (g_norm + self.weight_decay * w_norm + 65 | self.epsilon)) * self.lr), 66 | K.ones([1]) * self.lr) 67 | if K.backend() == 'theano': 68 | scaled_lr = scaled_lr[0] # otherwise theano raise broadcasting error 69 | # momentum 70 | moments = [K.zeros(K.int_shape(param), dtype=K.dtype(param)) 71 | for param in params] 72 | self.weights = [self.iterations] + moments 73 | for param, grad, moment in zip(params, grads, moments): 74 | v0 = (moment * self.momentum) 75 | v1 = scaled_lr * grad # velocity 76 | veloc = v0 - v1 77 | self.updates.append(K.update(moment, veloc)) 78 | 79 | if self.nesterov: 80 | new_param = param + (veloc * self.momentum) - v1 81 | else: 82 | new_param = param + veloc 83 | 84 | # Apply constraints. 85 | if getattr(param, 'constraint', None) is not None: 86 | new_param = param.constraint(new_param) 87 | 88 | self.updates.append(K.update(param, new_param)) 89 | return self.updates 90 | 91 | def get_config(self): 92 | config = {'lr': float(K.get_value(self.lr)), 93 | 'momentum': float(K.get_value(self.momentum)), 94 | 'weight_decay': float(K.get_value(self.weight_decay)), 95 | 'epsilon': self.epsilon, 96 | 'eeta': float(K.get_value(self.eeta)), 97 | 'nesterov': self.nesterov} 98 | base_config = super(LARS, self).get_config() 99 | return dict(list(base_config.items()) + list(config.items())) 100 | -------------------------------------------------------------------------------- /keras_contrib/optimizers/padam.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.optimizers import Optimizer 3 | 4 | 5 | class Padam(Optimizer): 6 | """Partially adaptive momentum estimation optimizer. 7 | 8 | # Arguments 9 | lr: float >= 0. Learning rate. 10 | beta_1: float, 0 < beta < 1. Generally close to 1. 11 | beta_2: float, 0 < beta < 1. Generally close to 1. 12 | epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`. 13 | decay: float >= 0. Learning rate decay over each update. 14 | amsgrad: boolean. Whether to apply the AMSGrad variant of this 15 | algorithm from the paper "On the Convergence of Adam and 16 | Beyond". 17 | partial: float, 0 <= partial <= 0.5 . Parameter controlling partial 18 | momentum adaption. For `partial=0`, this optimizer behaves like SGD, 19 | for `partial=0.5` it behaves like AMSGrad. 20 | 21 | # References 22 | - [Closing the Generalization Gap of Adaptive Gradient Methods 23 | in Training Deep Neural Networks](https://arxiv.org/pdf/1806.06763.pdf) 24 | 25 | """ 26 | 27 | def __init__(self, lr=1e-1, beta_1=0.9, beta_2=0.999, 28 | epsilon=1e-8, decay=0., amsgrad=False, partial=1. / 8., **kwargs): 29 | if partial < 0 or partial > 0.5: 30 | raise ValueError( 31 | "Padam: 'partial' must be a positive float with a maximum " 32 | "value of `0.5`, since higher values will cause divergence " 33 | "during training." 34 | ) 35 | super(Padam, self).__init__(**kwargs) 36 | with K.name_scope(self.__class__.__name__): 37 | self.iterations = K.variable(0, dtype='int64', name='iterations') 38 | self.lr = K.variable(lr, name='lr') 39 | self.beta_1 = K.variable(beta_1, name='beta_1') 40 | self.beta_2 = K.variable(beta_2, name='beta_2') 41 | self.decay = K.variable(decay, name='decay') 42 | if epsilon is None: 43 | epsilon = K.epsilon() 44 | self.epsilon = epsilon 45 | self.partial = partial 46 | self.initial_decay = decay 47 | self.amsgrad = amsgrad 48 | 49 | def get_updates(self, loss, params): 50 | grads = self.get_gradients(loss, params) 51 | self.updates = [K.update_add(self.iterations, 1)] 52 | 53 | lr = self.lr 54 | if self.initial_decay > 0: 55 | lr = lr * (1. / (1. + self.decay * K.cast(self.iterations, 56 | K.dtype(self.decay)))) 57 | 58 | t = K.cast(self.iterations, K.floatx()) + 1 59 | lr_t = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) / 60 | (1. - K.pow(self.beta_1, t))) 61 | 62 | ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 63 | vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 64 | if self.amsgrad: 65 | vhats = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 66 | else: 67 | vhats = [K.zeros(1) for _ in params] 68 | self.weights = [self.iterations] + ms + vs + vhats 69 | 70 | for p, g, m, v, vhat in zip(params, grads, ms, vs, vhats): 71 | m_t = (self.beta_1 * m) + (1. - self.beta_1) * g 72 | v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g) 73 | if self.amsgrad: 74 | vhat_t = K.maximum(vhat, v_t) 75 | denom = (K.sqrt(vhat_t) + self.epsilon) 76 | self.updates.append(K.update(vhat, vhat_t)) 77 | else: 78 | denom = (K.sqrt(v_t) + self.epsilon) 79 | 80 | self.updates.append(K.update(m, m_t)) 81 | self.updates.append(K.update(v, v_t)) 82 | 83 | # Partial momentum adaption. 84 | new_p = p - (lr_t * (m_t / (denom ** (self.partial * 2)))) 85 | 86 | # Apply constraints. 87 | if getattr(p, 'constraint', None) is not None: 88 | new_p = p.constraint(new_p) 89 | 90 | self.updates.append(K.update(p, new_p)) 91 | return self.updates 92 | 93 | def get_config(self): 94 | config = {'lr': float(K.get_value(self.lr)), 95 | 'beta_1': float(K.get_value(self.beta_1)), 96 | 'beta_2': float(K.get_value(self.beta_2)), 97 | 'decay': float(K.get_value(self.decay)), 98 | 'epsilon': self.epsilon, 99 | 'amsgrad': self.amsgrad, 100 | 'partial': self.partial} 101 | base_config = super(Padam, self).get_config() 102 | return dict(list(base_config.items()) + list(config.items())) 103 | -------------------------------------------------------------------------------- /keras_contrib/optimizers/yogi.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras.optimizers import Optimizer 3 | 4 | 5 | class Yogi(Optimizer): 6 | """Yogi optimizer. 7 | Yogi is a variation of Adam that controls the increase in effective 8 | learning rate, which (according to the paper) leads to even better 9 | performance than Adam with similar theoretical guarantees on convergence. 10 | Default parameters follow those provided in the original paper, Tab.1 11 | # Arguments 12 | lr: float >= 0. Learning rate. 13 | beta_1: float, 0 < beta < 1. Generally close to 1. 14 | beta_2: float, 0 < beta < 1. Generally close to 1. 15 | epsilon: float >= 0. Fuzz factor. If `None`, defaults to `K.epsilon()`. 16 | decay: float >= 0. Learning rate decay over each update. 17 | # References 18 | - [Adaptive Methods for Nonconvex Optimization]( 19 | https://papers.nips.cc/paper/8186-adaptive-methods-for-nonconvex-optimization) 20 | 21 | If you open an issue or a pull request about the Yogi optimizer, 22 | please add 'cc @MarcoAndreaBuchmann' to notify him. 23 | """ 24 | 25 | def __init__(self, lr=0.01, beta_1=0.9, beta_2=0.999, 26 | epsilon=1e-3, decay=0., **kwargs): 27 | super(Yogi, self).__init__(**kwargs) 28 | if beta_1 <= 0 or beta_1 >= 1: 29 | raise ValueError("beta_1 has to be in ]0, 1[") 30 | if beta_2 <= 0 or beta_2 >= 1: 31 | raise ValueError("beta_2 has to be in ]0, 1[") 32 | 33 | with K.name_scope(self.__class__.__name__): 34 | self.iterations = K.variable(0, dtype='int64', name='iterations') 35 | self.lr = K.variable(lr, name='lr') 36 | self.beta_1 = K.variable(beta_1, name='beta_1') 37 | self.beta_2 = K.variable(beta_2, name='beta_2') 38 | self.decay = K.variable(decay, name='decay') 39 | if epsilon is None: 40 | epsilon = K.epsilon() 41 | if epsilon <= 0: 42 | raise ValueError("epsilon has to be larger than 0") 43 | self.epsilon = epsilon 44 | self.initial_decay = decay 45 | 46 | def get_updates(self, loss, params): 47 | grads = self.get_gradients(loss, params) 48 | self.updates = [K.update_add(self.iterations, 1)] 49 | 50 | lr = self.lr 51 | if self.initial_decay > 0: 52 | lr = lr * (1. / (1. + self.decay * K.cast(self.iterations, 53 | K.dtype(self.decay)))) 54 | 55 | t = K.cast(self.iterations, K.floatx()) + 1 56 | lr_t = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) / 57 | (1. - K.pow(self.beta_1, t))) 58 | 59 | ms = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 60 | vs = [K.zeros(K.int_shape(p), dtype=K.dtype(p)) for p in params] 61 | vhats = [K.zeros(1) for _ in params] 62 | self.weights = [self.iterations] + ms + vs + vhats 63 | 64 | for p, g, m, v, vhat in zip(params, grads, ms, vs, vhats): 65 | g2 = K.square(g) 66 | m_t = (self.beta_1 * m) + (1. - self.beta_1) * g 67 | v_t = v - (1. - self.beta_2) * K.sign(v - g2) * g2 68 | p_t = p - lr_t * m_t / (K.sqrt(v_t) + self.epsilon) 69 | 70 | self.updates.append(K.update(m, m_t)) 71 | self.updates.append(K.update(v, v_t)) 72 | new_p = p_t 73 | 74 | # Apply constraints. 75 | if getattr(p, 'constraint', None) is not None: 76 | new_p = p.constraint(new_p) 77 | 78 | self.updates.append(K.update(p, new_p)) 79 | return self.updates 80 | 81 | def get_config(self): 82 | config = {'lr': float(K.get_value(self.lr)), 83 | 'beta_1': float(K.get_value(self.beta_1)), 84 | 'beta_2': float(K.get_value(self.beta_2)), 85 | 'decay': float(K.get_value(self.decay)), 86 | 'epsilon': self.epsilon} 87 | base_config = super(Yogi, self).get_config() 88 | return dict(list(base_config.items()) + list(config.items())) 89 | -------------------------------------------------------------------------------- /keras_contrib/preprocessing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/preprocessing/__init__.py -------------------------------------------------------------------------------- /keras_contrib/regularizers/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import absolute_import 3 | -------------------------------------------------------------------------------- /keras_contrib/tests/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/tests/__init__.py -------------------------------------------------------------------------------- /keras_contrib/tests/activations.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from keras import backend as K 4 | 5 | 6 | def get_standard_values(): 7 | ''' 8 | These are just a set of floats used for testing the activation 9 | functions, and are useful in multiple tests. 10 | ''' 11 | return np.array([[0, 0.1, 0.5, 0.9, 1.0]], dtype=K.floatx()) 12 | 13 | 14 | def validate_activation(activation): 15 | activation(get_standard_values()) 16 | -------------------------------------------------------------------------------- /keras_contrib/tests/metrics.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from keras import backend as K 4 | 5 | all_metrics = [] 6 | all_sparse_metrics = [] 7 | 8 | 9 | def validate_metric(metric): 10 | y_a = K.variable(np.random.random((6, 7))) 11 | y_b = K.variable(np.random.random((6, 7))) 12 | output = metric(y_a, y_b) 13 | assert K.eval(output).shape == () 14 | -------------------------------------------------------------------------------- /keras_contrib/tests/optimizers.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy as np 3 | 4 | from keras_contrib.utils import test_utils 5 | from keras import optimizers 6 | from keras.models import Sequential 7 | from keras.layers import Dense, Activation 8 | from keras.utils import to_categorical 9 | 10 | 11 | def get_test_data(): 12 | np.random.seed(1337) 13 | (x_train, y_train), _ = test_utils.get_test_data(num_train=1000, 14 | num_test=200, 15 | input_shape=(10,), 16 | classification=True, 17 | num_classes=2) 18 | y_train = to_categorical(y_train) 19 | return x_train, y_train 20 | 21 | 22 | def get_model(input_dim, num_hidden, output_dim): 23 | model = Sequential() 24 | model.add(Dense(num_hidden, input_shape=(input_dim,))) 25 | model.add(Activation('relu')) 26 | model.add(Dense(output_dim)) 27 | model.add(Activation('softmax')) 28 | return model 29 | 30 | 31 | def _test_optimizer(optimizer, target=0.75): 32 | x_train, y_train = get_test_data() 33 | model = get_model(x_train.shape[1], 10, y_train.shape[1]) 34 | model.compile(loss='categorical_crossentropy', 35 | optimizer=optimizer, 36 | metrics=['accuracy']) 37 | history = model.fit(x_train, y_train, epochs=2, batch_size=16, verbose=0) 38 | assert history.history['acc'][-1] >= target 39 | config = optimizers.serialize(optimizer) 40 | custom_objects = {optimizer.__class__.__name__: optimizer.__class__} 41 | optim = optimizers.deserialize(config, custom_objects) 42 | new_config = optimizers.serialize(optim) 43 | assert config == new_config 44 | -------------------------------------------------------------------------------- /keras_contrib/tests/regularizers.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from keras.datasets import mnist 3 | from keras.layers import Activation 4 | from keras.layers import Dense 5 | from keras.models import Sequential 6 | from keras.utils import np_utils 7 | 8 | np.random.seed(1337) 9 | 10 | nb_classes = 10 11 | batch_size = 128 12 | nb_epoch = 5 13 | weighted_class = 9 14 | standard_weight = 1 15 | high_weight = 5 16 | max_train_samples = 5000 17 | max_test_samples = 1000 18 | 19 | 20 | def get_data(): 21 | # the data, shuffled and split between tran and test sets 22 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 23 | X_train = X_train.reshape(60000, 784)[:max_train_samples] 24 | X_test = X_test.reshape(10000, 784)[:max_test_samples] 25 | X_train = X_train.astype('float32') / 255 26 | X_test = X_test.astype('float32') / 255 27 | 28 | # convert class vectors to binary class matrices 29 | y_train = y_train[:max_train_samples] 30 | y_test = y_test[:max_test_samples] 31 | Y_train = np_utils.to_categorical(y_train, nb_classes) 32 | Y_test = np_utils.to_categorical(y_test, nb_classes) 33 | test_ids = np.where(y_test == np.array(weighted_class))[0] 34 | 35 | return (X_train, Y_train), (X_test, Y_test), test_ids 36 | 37 | 38 | def validate_regularizer(weight_reg=None, activity_reg=None): 39 | model = Sequential() 40 | model.add(Dense(50, input_shape=(784,))) 41 | model.add(Activation('relu')) 42 | model.add(Dense(10, W_regularizer=weight_reg, 43 | activity_regularizer=activity_reg)) 44 | model.add(Activation('softmax')) 45 | return model 46 | -------------------------------------------------------------------------------- /keras_contrib/utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/utils/__init__.py -------------------------------------------------------------------------------- /keras_contrib/utils/conv_utils.py: -------------------------------------------------------------------------------- 1 | import keras.backend as K 2 | 3 | 4 | def conv_output_length(input_length, filter_size, 5 | padding, stride, dilation=1): 6 | """Determines output length of a convolution given input length. 7 | 8 | Copy of the function of keras-team/keras because it's not in the public API 9 | So we can't use the function in keras-team/keras to test tf.keras 10 | 11 | # Arguments 12 | input_length: integer. 13 | filter_size: integer. 14 | padding: one of `"same"`, `"valid"`, `"full"`. 15 | stride: integer. 16 | dilation: dilation rate, integer. 17 | 18 | # Returns 19 | The output length (integer). 20 | """ 21 | if input_length is None: 22 | return None 23 | assert padding in {'same', 'valid', 'full', 'causal'} 24 | dilated_filter_size = filter_size + (filter_size - 1) * (dilation - 1) 25 | if padding == 'same': 26 | output_length = input_length 27 | elif padding == 'valid': 28 | output_length = input_length - dilated_filter_size + 1 29 | elif padding == 'causal': 30 | output_length = input_length 31 | elif padding == 'full': 32 | output_length = input_length + dilated_filter_size - 1 33 | return (output_length + stride - 1) // stride 34 | 35 | 36 | def normalize_data_format(value): 37 | """Checks that the value correspond to a valid data format. 38 | 39 | Copy of the function in keras-team/keras because it's not public API. 40 | 41 | # Arguments 42 | value: String or None. `'channels_first'` or `'channels_last'`. 43 | 44 | # Returns 45 | A string, either `'channels_first'` or `'channels_last'` 46 | 47 | # Example 48 | ```python 49 | >>> from keras import backend as K 50 | >>> K.normalize_data_format(None) 51 | 'channels_first' 52 | >>> K.normalize_data_format('channels_last') 53 | 'channels_last' 54 | ``` 55 | 56 | # Raises 57 | ValueError: if `value` or the global `data_format` invalid. 58 | """ 59 | if value is None: 60 | value = K.image_data_format() 61 | data_format = value.lower() 62 | if data_format not in {'channels_first', 'channels_last'}: 63 | raise ValueError('The `data_format` argument must be one of ' 64 | '"channels_first", "channels_last". Received: ' + 65 | str(value)) 66 | return data_format 67 | -------------------------------------------------------------------------------- /keras_contrib/utils/save_load_utils.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | 3 | import h5py 4 | import keras.backend as K 5 | from keras import optimizers 6 | from keras.engine import saving 7 | 8 | 9 | def save_all_weights(model, filepath, include_optimizer=True): 10 | """ 11 | Save model weights and optimizer weights but not configuration to a HDF5 file. 12 | Functionally between `save` and `save_weights`. 13 | 14 | The HDF5 file contains: 15 | - the model's weights 16 | - the model's optimizer's state (if any) 17 | If you have a complicated model or set of models that do not serialize 18 | to JSON correctly, use this method. 19 | # Arguments 20 | model: Keras model instance to be saved. 21 | filepath: String, path where to save the model. 22 | include_optimizer: If True, save optimizer's state together. 23 | # Raises 24 | ImportError: if h5py is not available. 25 | """ 26 | if h5py is None: 27 | raise ImportError('`save_all_weights` requires h5py.') 28 | 29 | with h5py.File(filepath, 'w') as f: 30 | model_weights_group = f.create_group('model_weights') 31 | model_layers = model.layers 32 | saving.save_weights_to_hdf5_group(model_weights_group, model_layers) 33 | 34 | if include_optimizer and hasattr(model, 'optimizer') and model.optimizer: 35 | if isinstance(model.optimizer, optimizers.TFOptimizer): 36 | warnings.warn( 37 | 'TensorFlow optimizers do not ' 38 | 'make it possible to access ' 39 | 'optimizer attributes or optimizer state ' 40 | 'after instantiation. ' 41 | 'As a result, we cannot save the optimizer ' 42 | 'as part of the model save file.' 43 | 'You will have to compile your model again after loading it. ' 44 | 'Prefer using a Keras optimizer instead ' 45 | '(see keras.io/optimizers).') 46 | else: 47 | # Save optimizer weights. 48 | symbolic_weights = getattr(model.optimizer, 'weights') 49 | if symbolic_weights: 50 | optimizer_weights_group = f.create_group('optimizer_weights') 51 | weight_values = K.batch_get_value(symbolic_weights) 52 | weight_names = [] 53 | for i, (w, val) in enumerate(zip(symbolic_weights, weight_values)): 54 | # Default values of symbolic_weights is /variable for theano 55 | if K.backend() == 'theano': 56 | if hasattr(w, 'name') and w.name != "/variable": 57 | name = str(w.name) 58 | else: 59 | name = 'param_' + str(i) 60 | else: 61 | if hasattr(w, 'name') and w.name: 62 | name = str(w.name) 63 | else: 64 | name = 'param_' + str(i) 65 | weight_names.append(name.encode('utf8')) 66 | optimizer_weights_group.attrs['weight_names'] = weight_names 67 | for name, val in zip(weight_names, weight_values): 68 | param_dset = optimizer_weights_group.create_dataset( 69 | name, 70 | val.shape, 71 | dtype=val.dtype) 72 | if not val.shape: 73 | # scalar 74 | param_dset[()] = val 75 | else: 76 | param_dset[:] = val 77 | 78 | 79 | def load_all_weights(model, filepath, include_optimizer=True): 80 | """Loads the weights of a model saved via `save_all_weights`. 81 | If model has been compiled, optionally load its optimizer's weights. 82 | # Arguments 83 | model: instantiated model with architecture matching the saved model. 84 | Compile the model beforehand if you want to load optimizer weights. 85 | filepath: String, path to the saved model. 86 | # Returns 87 | None. The model will have its weights updated. 88 | # Raises 89 | ImportError: if h5py is not available. 90 | ValueError: In case of an invalid savefile. 91 | """ 92 | if h5py is None: 93 | raise ImportError('`load_all_weights` requires h5py.') 94 | 95 | with h5py.File(filepath, mode='r') as f: 96 | # set weights 97 | saving.load_weights_from_hdf5_group(f['model_weights'], model.layers) 98 | # Set optimizer weights. 99 | if (include_optimizer 100 | and 'optimizer_weights' in f and hasattr(model, 'optimizer') 101 | and model.optimizer): 102 | optimizer_weights_group = f['optimizer_weights'] 103 | optimizer_weight_names = [n.decode('utf8') for n in 104 | optimizer_weights_group.attrs['weight_names']] 105 | optimizer_weight_values = [optimizer_weights_group[n] for n in 106 | optimizer_weight_names] 107 | model.optimizer.set_weights(optimizer_weight_values) 108 | -------------------------------------------------------------------------------- /keras_contrib/wrappers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/keras_contrib/wrappers/__init__.py -------------------------------------------------------------------------------- /pytest.ini: -------------------------------------------------------------------------------- 1 | # Configuration of py.test 2 | [pytest] 3 | addopts=-v 4 | -n 2 5 | --durations=10 6 | --cov-report term-missing 7 | 8 | # Do not run tests in the build folder 9 | norecursedirs= build 10 | 11 | # PEP-8 The following are ignored: 12 | # E402 module level import not at top of file - temporary measure to continue adding ros python packaged in sys.path 13 | # E731 do not assign a lambda expression, use a def 14 | 15 | pep8ignore=* E402 \ 16 | * E731 \ 17 | * W503 18 | 19 | pep8maxlinelength = 88 20 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | from setuptools import find_packages 3 | import os 4 | 5 | 6 | if os.environ.get('USE_TF_KERAS', None) == '1': 7 | name = 'tf_keras_contrib' 8 | install_requires = [] 9 | else: 10 | name = 'keras_contrib' 11 | install_requires = ['keras'] 12 | 13 | setup(name=name, 14 | version='2.0.8', 15 | description='Keras Deep Learning for Python, Community Contributions', 16 | author='Fariz Rahman', 17 | author_email='farizrahman4u@gmail.com', 18 | url='https://github.com/farizrahman4u/keras-contrib', 19 | license='MIT', 20 | install_requires=install_requires, 21 | extras_require={ 22 | 'h5py': ['h5py'], 23 | 'visualize': ['pydot>=1.2.0'], 24 | 'tests': ['pytest', 25 | 'pytest-pep8', 26 | 'pytest-xdist', 27 | 'pytest-cov'], 28 | }, 29 | classifiers=[ 30 | 'Development Status :: 3 - Alpha', 31 | 'Intended Audience :: Developers', 32 | 'Intended Audience :: Education', 33 | 'Intended Audience :: Science/Research', 34 | 'License :: OSI Approved :: MIT License', 35 | 'Programming Language :: Python :: 2', 36 | 'Programming Language :: Python :: 2.7', 37 | 'Programming Language :: Python :: 3', 38 | 'Programming Language :: Python :: 3.6', 39 | 'Topic :: Software Development :: Libraries', 40 | 'Topic :: Software Development :: Libraries :: Python Modules' 41 | ], 42 | packages=find_packages()) 43 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from keras import backend as K 3 | 4 | 5 | @pytest.fixture(autouse=True) 6 | def clear_session_after_test(): 7 | """Test wrapper to clean up after TensorFlow and CNTK tests. 8 | 9 | This wrapper runs for all the tests in the keras test suite. 10 | """ 11 | yield 12 | if K.backend() == 'tensorflow' or K.backend() == 'cntk': 13 | K.clear_session() 14 | -------------------------------------------------------------------------------- /tests/keras_contrib/activations/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/tests/keras_contrib/activations/.gitkeep -------------------------------------------------------------------------------- /tests/keras_contrib/activations/test_squash.py: -------------------------------------------------------------------------------- 1 | from keras_contrib import activations 2 | import keras.backend as K 3 | import numpy as np 4 | from numpy.testing import assert_allclose 5 | 6 | 7 | def get_standard_values(): 8 | """A set of floats used for testing squash. 9 | """ 10 | return np.array([[0, 0.1, 0.5, 0.9, 1.0]], dtype=K.floatx()) 11 | 12 | 13 | def test_squash_valid(): 14 | """Test using a reference implementation of squash. 15 | """ 16 | def squash(x, axis=-1): 17 | s_squared_norm = np.sum(np.square(x), axis) + 1e-7 18 | scale = np.sqrt(s_squared_norm) / (0.5 + s_squared_norm) 19 | return scale * x 20 | 21 | x = K.placeholder(ndim=2) 22 | f = K.function([x], [activations.squash(x)]) 23 | test_values = get_standard_values() 24 | 25 | result = f([test_values])[0] 26 | expected = squash(test_values) 27 | assert_allclose(result, expected, rtol=1e-05) 28 | 29 | 30 | test_squash_valid() 31 | -------------------------------------------------------------------------------- /tests/keras_contrib/callbacks/cyclical_learning_rate_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | from keras_contrib import callbacks 4 | from keras.models import Sequential 5 | from keras.layers import Dense 6 | from numpy.testing import assert_allclose 7 | 8 | 9 | def build_model(): 10 | model = Sequential([ 11 | Dense(2, activation='relu', input_shape=(2,)), 12 | Dense(1, activation='sigmoid') 13 | ]) 14 | return model 15 | 16 | 17 | def cycle(i): 18 | return np.floor(1 + i / (2 * 2000)) 19 | 20 | 21 | def x(i): 22 | return np.abs(i / 2000. - 2 * cycle(i) + 1) 23 | 24 | 25 | def test_cyclic_lr_triangular_1(): 26 | X = np.random.rand(4000, 2) 27 | y = np.random.rand(4000).reshape(-1, 1) 28 | 29 | clr = callbacks.CyclicLR() 30 | 31 | model = build_model() 32 | model.compile( 33 | optimizer='sgd', 34 | loss='binary_crossentropy', 35 | metrics=['accuracy'] 36 | ) 37 | model.fit(X, y, batch_size=1, epochs=1, verbose=0, callbacks=[clr]) 38 | 39 | r = np.concatenate([ 40 | np.linspace(0.001, 0.006, num=2001)[1:], 41 | np.linspace(0.006, 0.001, num=2001)[1:] 42 | ]) 43 | 44 | assert_allclose(clr.history['lr'], r) 45 | 46 | 47 | def test_cyclic_lr_triangular_2(): 48 | X = np.random.rand(4000, 2) 49 | y = np.random.rand(4000).reshape(-1, 1) 50 | 51 | clr = callbacks.CyclicLR(mode='triangular2') 52 | 53 | model = build_model() 54 | model.compile( 55 | optimizer='sgd', 56 | loss='binary_crossentropy', 57 | metrics=['accuracy'] 58 | ) 59 | model.fit(X, y, batch_size=1, epochs=2, verbose=0, callbacks=[clr]) 60 | 61 | r = np.concatenate([ 62 | np.linspace(0.001, 0.006, num=2001)[1:], 63 | np.linspace(0.006, 0.001, num=2001)[1:], 64 | np.linspace(0.001, 0.0035, num=2001)[1:], 65 | np.linspace(0.0035, 0.001, num=2001)[1:], 66 | ]) 67 | 68 | assert_allclose(clr.history['lr'], r) 69 | 70 | 71 | def test_cyclic_lr_exp_range(): 72 | X = np.random.rand(4000, 2) 73 | y = np.random.rand(4000).reshape(-1, 1) 74 | 75 | clr = callbacks.CyclicLR(mode='exp_range', gamma=0.9996) 76 | 77 | model = build_model() 78 | model.compile( 79 | optimizer='sgd', 80 | loss='binary_crossentropy', 81 | metrics=['accuracy'] 82 | ) 83 | model.fit(X, y, batch_size=1, epochs=2, verbose=0, callbacks=[clr]) 84 | 85 | exp_range = [] 86 | 87 | def scale_fn(i): 88 | return 0.001 + (0.006 - 0.001) * np.maximum(0, (1 - x(i))) * (0.9996 ** i) 89 | 90 | for i in range(8000): 91 | exp_range.append(scale_fn(i + 1)) 92 | 93 | assert_allclose(clr.history['lr'], np.array(exp_range)) 94 | 95 | 96 | def test_cyclic_lr_custom_fn_test(): 97 | X = np.random.rand(4000, 2) 98 | y = np.random.rand(4000).reshape(-1, 1) 99 | 100 | def clr_fn(x): 101 | return 1 / (5 ** (x * 0.0001)) 102 | 103 | clr = callbacks.CyclicLR(scale_fn=clr_fn, scale_mode='iterations') 104 | 105 | model = build_model() 106 | model.compile( 107 | optimizer='sgd', 108 | loss='binary_crossentropy', 109 | metrics=['accuracy'] 110 | ) 111 | model.fit(X, y, batch_size=1, epochs=2, verbose=0, callbacks=[clr]) 112 | 113 | custom_range = [] 114 | 115 | def scale_fn(i): 116 | c = 0.006 - 0.001 117 | return 0.001 + c * np.maximum(0, (1 - x(i))) * 1 / (5 ** (i * 0.0001)) 118 | 119 | for i in range(8000): 120 | custom_range.append(scale_fn(i + 1)) 121 | 122 | assert_allclose(clr.history['lr'], np.array(custom_range)) 123 | 124 | 125 | if __name__ == '__main__': 126 | pytest.main([__file__]) 127 | -------------------------------------------------------------------------------- /tests/keras_contrib/callbacks/tensorboard_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | import os 4 | import shutil 5 | from keras.utils import to_categorical 6 | from keras.layers import Layer, Input, Dense, Dropout, BatchNormalization 7 | from keras_contrib.utils.test_utils import to_list, unpack_singleton 8 | from keras_contrib.utils.test_utils import get_test_data 9 | from keras import Model 10 | from keras import backend as K 11 | from keras_contrib.callbacks import TensorBoardGrouped 12 | 13 | input_dim = 2 14 | num_hidden = 4 15 | num_classes = 2 16 | batch_size = 5 17 | train_samples = 20 18 | test_samples = 20 19 | 20 | 21 | def data_generator(x, y, batch_size): 22 | x = to_list(x) 23 | y = to_list(y) 24 | max_batch_index = len(x[0]) // batch_size 25 | i = 0 26 | while 1: 27 | x_batch = [array[i * batch_size: (i + 1) * batch_size] for array in x] 28 | x_batch = unpack_singleton(x_batch) 29 | 30 | y_batch = [array[i * batch_size: (i + 1) * batch_size] for array in y] 31 | y_batch = unpack_singleton(y_batch) 32 | yield x_batch, y_batch 33 | i += 1 34 | i = i % max_batch_index 35 | 36 | 37 | # Changing the default arguments of get_test_data. 38 | def get_data_callbacks(num_train=train_samples, 39 | num_test=test_samples, 40 | input_shape=(input_dim,), 41 | classification=True, 42 | num_classes=num_classes): 43 | return get_test_data(num_train=num_train, 44 | num_test=num_test, 45 | input_shape=input_shape, 46 | classification=classification, 47 | num_classes=num_classes) 48 | 49 | 50 | def test_TensorBoard(tmpdir): 51 | np.random.seed(np.random.randint(1, 1e7)) 52 | filepath = str(tmpdir / 'logs') 53 | 54 | (X_train, y_train), (X_test, y_test) = get_data_callbacks() 55 | y_test = to_categorical(y_test) 56 | y_train = to_categorical(y_train) 57 | 58 | class DummyStatefulMetric(Layer): 59 | 60 | def __init__(self, name='dummy_stateful_metric', **kwargs): 61 | super(DummyStatefulMetric, self).__init__(name=name, **kwargs) 62 | self.stateful = True 63 | self.state = K.variable(value=0, dtype='int32') 64 | 65 | def reset_states(self): 66 | pass 67 | 68 | def __call__(self, y_true, y_pred): 69 | return self.state 70 | 71 | inp = Input((input_dim,)) 72 | hidden = Dense(num_hidden, activation='relu')(inp) 73 | hidden = Dropout(0.1)(hidden) 74 | hidden = BatchNormalization()(hidden) 75 | output = Dense(num_classes, activation='softmax')(hidden) 76 | model = Model(inputs=inp, outputs=output) 77 | model.compile(loss='categorical_crossentropy', 78 | optimizer='sgd', 79 | metrics=['accuracy', DummyStatefulMetric()]) 80 | 81 | # we must generate new callbacks for each test, as they aren't stateless 82 | def callbacks_factory(histogram_freq): 83 | return [TensorBoardGrouped(log_dir=filepath, 84 | histogram_freq=histogram_freq, 85 | write_images=True, write_grads=True, 86 | batch_size=5)] 87 | 88 | # fit without validation data 89 | model.fit(X_train, y_train, batch_size=batch_size, 90 | callbacks=callbacks_factory(histogram_freq=0), 91 | epochs=3) 92 | 93 | # fit with validation data and accuracy 94 | model.fit(X_train, y_train, batch_size=batch_size, 95 | validation_data=(X_test, y_test), 96 | callbacks=callbacks_factory(histogram_freq=0), epochs=2) 97 | 98 | # fit generator without validation data 99 | train_generator = data_generator(X_train, y_train, batch_size) 100 | model.fit_generator(train_generator, len(X_train), epochs=2, 101 | callbacks=callbacks_factory(histogram_freq=0)) 102 | 103 | # fit generator with validation data and accuracy 104 | train_generator = data_generator(X_train, y_train, batch_size) 105 | model.fit_generator(train_generator, len(X_train), epochs=2, 106 | validation_data=(X_test, y_test), 107 | callbacks=callbacks_factory(histogram_freq=1)) 108 | 109 | assert os.path.isdir(filepath) 110 | shutil.rmtree(filepath) 111 | assert not tmpdir.listdir() 112 | 113 | 114 | if __name__ == '__main__': 115 | pytest.main([__file__]) 116 | -------------------------------------------------------------------------------- /tests/keras_contrib/constraints_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | 4 | from keras import backend as K 5 | from keras_contrib import constraints 6 | 7 | 8 | test_values = [0.1, 0.5, 3, 8, 1e-7] 9 | np.random.seed(3537) 10 | example_array = np.random.random((100, 100)) * 100. - 50. 11 | example_array[0, 0] = 0. # 0 could possibly cause trouble 12 | 13 | 14 | def test_clip(): 15 | clip_instance = constraints.clip() 16 | clipped = clip_instance(K.variable(example_array)) 17 | assert(np.max(np.abs(K.eval(clipped))) <= K.cast_to_floatx(0.01)) 18 | clip_instance = constraints.clip(0.1) 19 | clipped = clip_instance(K.variable(example_array)) 20 | assert(np.max(np.abs(K.eval(clipped))) <= K.cast_to_floatx(0.1)) 21 | 22 | if __name__ == '__main__': 23 | pytest.main([__file__]) 24 | -------------------------------------------------------------------------------- /tests/keras_contrib/datasets/test_datasets.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pytest 3 | import time 4 | import random 5 | from keras_contrib import datasets 6 | 7 | 8 | if __name__ == '__main__': 9 | pytest.main([__file__]) 10 | -------------------------------------------------------------------------------- /tests/keras_contrib/initializers_test.py: -------------------------------------------------------------------------------- 1 | from keras import backend as K 2 | from keras_contrib import backend as KC 3 | from keras_contrib import initializers 4 | import pytest 5 | import numpy as np 6 | 7 | 8 | # 2D tensor test fixture 9 | FC_SHAPE = (100, 100) 10 | 11 | # 4D convolution in th order. This shape has the same effective shape as 12 | # FC_SHAPE 13 | CONV_SHAPE = (25, 25, 2, 2) 14 | 15 | # The equivalent shape of both test fixtures 16 | SHAPE = (100, 100) 17 | 18 | 19 | def _runner(init, shape, target_mean=None, target_std=None, 20 | target_max=None, target_min=None, upper_bound=None, lower_bound=None): 21 | variable = init(shape) 22 | if not isinstance(variable, np.ndarray): 23 | output = K.get_value(variable) 24 | else: 25 | output = variable 26 | 27 | lim = 1e-2 28 | if target_std is not None: 29 | assert abs(output.std() - target_std) < lim 30 | if target_mean is not None: 31 | assert abs(output.mean() - target_mean) < lim 32 | if target_max is not None: 33 | assert abs(output.max() - target_max) < lim 34 | if target_min is not None: 35 | assert abs(output.min() - target_min) < lim 36 | if upper_bound is not None: 37 | assert output.max() < upper_bound 38 | if lower_bound is not None: 39 | assert output.min() > lower_bound 40 | 41 | 42 | ''' 43 | # Example : 44 | 45 | @pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV']) 46 | def test_uniform(tensor_shape): 47 | _runner(initializations.uniform, tensor_shape, target_mean=0., 48 | target_max=0.05, target_min=-0.05) 49 | 50 | ''' 51 | 52 | 53 | @pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV']) 54 | def test_cai(tensor_shape): 55 | # upper and lower bounds are proved in original paper 56 | _runner(initializers.ConvolutionAware(), tensor_shape, 57 | upper_bound=1, lower_bound=-1) 58 | 59 | if __name__ == '__main__': 60 | pytest.main([__file__]) 61 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/advanced_activations/test_pelu.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from keras_contrib.utils.test_utils import layer_test 3 | from keras_contrib.layers import PELU 4 | 5 | 6 | @pytest.mark.parametrize('kwargs', [{}, {'shared_axes': 1}]) 7 | def test_pelu(kwargs): 8 | layer_test(PELU, kwargs=kwargs, 9 | input_shape=(2, 3, 4)) 10 | 11 | 12 | if __name__ == '__main__': 13 | pytest.main([__file__]) 14 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/advanced_activations/test_sinerelu.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from keras_contrib.utils.test_utils import layer_test 3 | from keras_contrib.layers import SineReLU 4 | 5 | 6 | @pytest.mark.parametrize('epsilon', [0.0025, 0.0035, 0.0045]) 7 | def test_sine_relu(epsilon): 8 | layer_test(SineReLU, kwargs={'epsilon': epsilon}, input_shape=(2, 3, 4)) 9 | 10 | 11 | if __name__ == '__main__': 12 | pytest.main([__file__]) 13 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/advanced_activations/test_srelu.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from keras_contrib.utils.test_utils import layer_test 3 | from keras_contrib.layers import SReLU 4 | 5 | 6 | @pytest.mark.parametrize('kwargs', [{}, {'shared_axes': 1}]) 7 | def test_srelu(kwargs): 8 | layer_test(SReLU, kwargs=kwargs, input_shape=(2, 3, 4)) 9 | 10 | 11 | if __name__ == '__main__': 12 | pytest.main([__file__]) 13 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/advanced_activations/test_swish.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from keras_contrib.utils.test_utils import layer_test 3 | from keras_contrib.layers import Swish 4 | 5 | 6 | @pytest.mark.parametrize('trainable', [False, True]) 7 | def test_swish(trainable): 8 | layer_test(Swish, kwargs={'beta': 1.0, 'trainable': trainable}, 9 | input_shape=(2, 3, 4)) 10 | 11 | 12 | if __name__ == '__main__': 13 | pytest.main([__file__]) 14 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/convolutional/test_cosineconvolution2d.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from keras import backend as K 4 | from keras.models import Sequential 5 | from numpy.testing import assert_allclose 6 | 7 | from keras_contrib.utils.test_utils import layer_test 8 | from keras_contrib.layers import CosineConvolution2D 9 | 10 | # TensorFlow does not support full convolution. 11 | if K.backend() == 'theano': 12 | _convolution_border_modes = ['valid', 'same'] 13 | data_format = 'channels_first' 14 | else: 15 | _convolution_border_modes = ['valid', 'same'] 16 | data_format = 'channels_last' 17 | 18 | 19 | @pytest.mark.parametrize('border_mode', _convolution_border_modes) 20 | @pytest.mark.parametrize('subsample', [(1, 1), (2, 2)]) 21 | @pytest.mark.parametrize('use_bias_mode', [True, False]) 22 | @pytest.mark.parametrize('use_regularizer', [True, False]) 23 | def test_cosineconvolution_2d(border_mode, 24 | subsample, 25 | use_bias_mode, 26 | use_regularizer): 27 | num_samples = 2 28 | num_filter = 2 29 | stack_size = 3 30 | num_row = 10 31 | num_col = 6 32 | 33 | if border_mode == 'same' and subsample != (1, 1): 34 | return 35 | 36 | kwargs = {'filters': num_filter, 37 | 'kernel_size': (3, 3), 38 | 'padding': border_mode, 39 | 'strides': subsample, 40 | 'use_bias': use_bias_mode, 41 | 'data_format': data_format} 42 | if use_regularizer: 43 | kwargs.update({'kernel_regularizer': 'l2', 44 | 'bias_regularizer': 'l2', 45 | 'activity_regularizer': 'l2'}) 46 | 47 | layer_test(CosineConvolution2D, 48 | kwargs=kwargs, 49 | input_shape=(num_samples, num_row, num_col, stack_size)) 50 | 51 | 52 | def test_cosineconvolution_2d_correctness(): 53 | if data_format == 'channels_first': 54 | X = np.random.randn(1, 3, 5, 5) 55 | input_dim = (3, 5, 5) 56 | W0 = X[:, :, ::-1, ::-1] 57 | elif data_format == 'channels_last': 58 | X = np.random.randn(1, 5, 5, 3) 59 | input_dim = (5, 5, 3) 60 | W0 = X[0, :, :, :, None] 61 | 62 | model = Sequential() 63 | model.add(CosineConvolution2D(1, (5, 5), use_bias=True, 64 | input_shape=input_dim, 65 | data_format=data_format)) 66 | model.compile(loss='mse', optimizer='rmsprop') 67 | W = model.get_weights() 68 | W[0] = W0 69 | W[1] = np.asarray([1.]) 70 | model.set_weights(W) 71 | out = model.predict(X) 72 | assert_allclose(out, np.ones((1, 1, 1, 1), dtype=K.floatx()), atol=1e-5) 73 | 74 | model = Sequential() 75 | model.add(CosineConvolution2D(1, (5, 5), 76 | use_bias=False, 77 | input_shape=input_dim, 78 | data_format=data_format)) 79 | model.compile(loss='mse', optimizer='rmsprop') 80 | W = model.get_weights() 81 | W[0] = -2 * W0 82 | model.set_weights(W) 83 | out = model.predict(X) 84 | assert_allclose(out, -np.ones((1, 1, 1, 1), dtype=K.floatx()), atol=1e-5) 85 | 86 | 87 | if __name__ == '__main__': 88 | pytest.main([__file__]) 89 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/convolutional/test_subpixelupscaling.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from keras import backend as K 4 | 5 | from keras_contrib import backend as KC 6 | from keras_contrib.layers import SubPixelUpscaling 7 | from keras_contrib.utils.test_utils import layer_test 8 | 9 | # TensorFlow does not support full convolution. 10 | if K.backend() == 'theano': 11 | _convolution_border_modes = ['valid', 'same'] 12 | data_format = 'channels_first' 13 | else: 14 | _convolution_border_modes = ['valid', 'same'] 15 | data_format = 'channels_last' 16 | 17 | 18 | @pytest.mark.parametrize('scale_factor', [2, 3, 4]) 19 | def test_sub_pixel_upscaling(scale_factor): 20 | num_samples = 2 21 | num_row = 16 22 | num_col = 16 23 | input_dtype = K.floatx() 24 | 25 | nb_channels = 4 * (scale_factor ** 2) 26 | input_data = np.random.random((num_samples, nb_channels, num_row, num_col)) 27 | input_data = input_data.astype(input_dtype) 28 | 29 | if K.image_data_format() == 'channels_last': 30 | input_data = input_data.transpose((0, 2, 3, 1)) 31 | 32 | input_tensor = K.variable(input_data) 33 | expected_output = K.eval(KC.depth_to_space(input_tensor, 34 | scale=scale_factor)) 35 | 36 | layer_test(SubPixelUpscaling, 37 | kwargs={'scale_factor': scale_factor}, 38 | input_data=input_data, 39 | expected_output=expected_output, 40 | expected_output_dtype=K.floatx()) 41 | 42 | 43 | if __name__ == '__main__': 44 | pytest.main([__file__]) 45 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/test_capsule.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | from numpy.testing import assert_allclose 4 | 5 | from keras_contrib.utils.test_utils import layer_test 6 | from keras_contrib.utils.test_utils import is_tf_keras 7 | from keras import backend as K 8 | from keras_contrib.layers import capsule 9 | from keras.models import Sequential 10 | 11 | 12 | @pytest.mark.parametrize('num_capsule', [10, 20]) 13 | @pytest.mark.parametrize('dim_capsule', [10, 20]) 14 | @pytest.mark.parametrize('routings', [3, 4]) 15 | @pytest.mark.parametrize('share_weights', [True, False]) 16 | @pytest.mark.parametrize('activation', ['sigmoid', 'relu']) 17 | def test_capsule(num_capsule, 18 | dim_capsule, 19 | routings, 20 | share_weights, 21 | activation): 22 | 23 | # TODO: removed this once the issue #25546 in the Tensorflow repo is fixed. 24 | if is_tf_keras and not share_weights: 25 | return 26 | 27 | num_samples = 100 28 | num_rows = 256 29 | num_cols = 256 30 | 31 | kwargs = {'num_capsule': num_capsule, 32 | 'dim_capsule': dim_capsule, 33 | 'routings': routings, 34 | 'share_weights': share_weights, 35 | 'activation': activation} 36 | 37 | layer_test(capsule.Capsule, 38 | kwargs=kwargs, 39 | input_shape=(num_samples, num_rows, num_cols)) 40 | 41 | 42 | def test_capsule_correctness(): 43 | X = np.random.random((1, 1, 1)) 44 | 45 | model = Sequential() 46 | model.add(capsule.Capsule(1, 1, 1, True, activation='sigmoid')) 47 | 48 | model.compile(loss='mse', optimizer='rmsprop') 49 | init_out = model.predict(X) # mock predict call to initialize weights 50 | model.set_weights([np.zeros((1, 1, 1))]) 51 | out = model.predict(X) 52 | assert_allclose(out, np.zeros((1, 1, 1), dtype=K.floatx()) + 0.5, atol=1e-5) 53 | 54 | 55 | if __name__ == '__main__': 56 | pytest.main([__file__]) 57 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/test_core.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | 4 | from keras import regularizers 5 | from keras import constraints 6 | from keras.models import Sequential 7 | from keras import backend as K 8 | from keras_contrib.layers import core 9 | from keras_contrib.utils.test_utils import layer_test 10 | from numpy.testing import assert_allclose 11 | 12 | 13 | @pytest.mark.parametrize('input_shape', [(3, 2), 14 | (3, 4, 2), 15 | (None, None, 2), 16 | (3, 4, 5, 2)]) 17 | def test_cosinedense(input_shape): 18 | 19 | layer_test(core.CosineDense, 20 | kwargs={'units': 3}, 21 | input_shape=input_shape) 22 | 23 | 24 | def test_cosinedense_reg_constraint(): 25 | layer_test(core.CosineDense, 26 | kwargs={'units': 3, 27 | 'kernel_regularizer': regularizers.l2(0.01), 28 | 'bias_regularizer': regularizers.l1(0.01), 29 | 'activity_regularizer': regularizers.l2(0.01), 30 | 'kernel_constraint': constraints.MaxNorm(1), 31 | 'bias_constraint': constraints.MaxNorm(1)}, 32 | input_shape=(3, 2)) 33 | 34 | 35 | def test_cosinedense_correctness(): 36 | X = np.random.randn(1, 20) 37 | model = Sequential() 38 | model.add(core.CosineDense(1, use_bias=True, input_shape=(20,))) 39 | model.compile(loss='mse', optimizer='rmsprop') 40 | W = model.get_weights() 41 | W[0] = X.T 42 | W[1] = np.asarray([1.]) 43 | model.set_weights(W) 44 | out = model.predict(X) 45 | assert_allclose(out, np.ones((1, 1), dtype=K.floatx()), atol=1e-5) 46 | 47 | X = np.random.randn(1, 20) 48 | model = Sequential() 49 | model.add(core.CosineDense(1, use_bias=False, input_shape=(20,))) 50 | model.compile(loss='mse', optimizer='rmsprop') 51 | W = model.get_weights() 52 | W[0] = -2 * X.T 53 | model.set_weights(W) 54 | out = model.predict(X) 55 | assert_allclose(out, -np.ones((1, 1), dtype=K.floatx()), atol=1e-5) 56 | 57 | 58 | if __name__ == '__main__': 59 | pytest.main([__file__]) 60 | -------------------------------------------------------------------------------- /tests/keras_contrib/layers/test_crf.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | import os 4 | from numpy.testing import assert_allclose 5 | 6 | from keras.layers import Embedding 7 | from keras.models import Sequential 8 | from keras.models import load_model 9 | from keras_contrib.losses import crf_loss 10 | from keras_contrib.metrics import crf_accuracy 11 | from keras_contrib.metrics import crf_marginal_accuracy 12 | from keras_contrib.metrics import crf_viterbi_accuracy 13 | from keras_contrib.layers import CRF 14 | from keras_contrib.utils.test_utils import is_tf_keras 15 | 16 | nb_samples, timesteps, embedding_dim, output_dim = 2, 10, 4, 5 17 | embedding_num = 12 18 | 19 | MODEL_PERSISTENCE_PATH = './test_saving_crf_model.h5' 20 | 21 | 22 | @pytest.mark.xfail(is_tf_keras, 23 | reason='TODO: fix it. Using K.tf which is bad.', 24 | strict=True) 25 | def test_CRF(): 26 | # data 27 | x = np.random.randint(1, embedding_num, nb_samples * timesteps) 28 | x = x.reshape((nb_samples, timesteps)) 29 | x[0, -4:] = 0 # right padding 30 | x[1, :5] = 0 # left padding 31 | y = np.random.randint(0, output_dim, nb_samples * timesteps) 32 | y = y.reshape((nb_samples, timesteps)) 33 | y_onehot = np.eye(output_dim)[y] 34 | y = np.expand_dims(y, 2) # .astype('float32') 35 | 36 | # test with no masking, onehot, fix length 37 | model = Sequential() 38 | model.add(Embedding(embedding_num, embedding_dim, input_length=timesteps)) 39 | crf = CRF(output_dim) 40 | model.add(crf) 41 | model.compile(optimizer='rmsprop', loss=crf_loss) 42 | model.fit(x, y_onehot, epochs=1, batch_size=10) 43 | model.save(MODEL_PERSISTENCE_PATH) 44 | load_model(MODEL_PERSISTENCE_PATH, 45 | custom_objects={'CRF': CRF, 46 | 'crf_loss': crf_loss, 47 | 'crf_viterbi_accuracy': crf_viterbi_accuracy}) 48 | 49 | # test with masking, sparse target, dynamic length; 50 | # test crf_viterbi_accuracy, crf_marginal_accuracy 51 | 52 | model = Sequential() 53 | model.add(Embedding(embedding_num, embedding_dim, mask_zero=True)) 54 | crf = CRF(output_dim, sparse_target=True) 55 | model.add(crf) 56 | model.compile(optimizer='rmsprop', loss=crf_loss, 57 | metrics=[crf_viterbi_accuracy, crf_marginal_accuracy]) 58 | model.fit(x, y, epochs=1, batch_size=10) 59 | 60 | # check mask 61 | y_pred = model.predict(x).argmax(-1) 62 | assert (y_pred[0, -4:] == 0).all() # right padding 63 | assert (y_pred[1, :5] == 0).all() # left padding 64 | 65 | # test viterbi_acc 66 | _, v_acc, _ = model.evaluate(x, y) 67 | np_acc = (y_pred[x > 0] == y[:, :, 0][x > 0]).astype('float32').mean() 68 | print(v_acc, np_acc) 69 | assert np.abs(v_acc - np_acc) < 1e-4 70 | 71 | # test config 72 | model.get_config() 73 | 74 | # test marginal learn mode, fix length 75 | 76 | model = Sequential() 77 | model.add(Embedding(embedding_num, embedding_dim, input_length=timesteps, 78 | mask_zero=True)) 79 | crf = CRF(output_dim, learn_mode='marginal', unroll=True) 80 | model.add(crf) 81 | model.compile(optimizer='rmsprop', loss=crf_loss) 82 | model.fit(x, y_onehot, epochs=1, batch_size=10) 83 | 84 | # check mask (marginal output) 85 | y_pred = model.predict(x) 86 | assert_allclose(y_pred[0, -4:], 1. / output_dim, atol=1e-6) 87 | assert_allclose(y_pred[1, :5], 1. / output_dim, atol=1e-6) 88 | 89 | # test marginal learn mode, but with Viterbi test_mode 90 | model = Sequential() 91 | model.add(Embedding(embedding_num, embedding_dim, input_length=timesteps, 92 | mask_zero=True)) 93 | crf = CRF(output_dim, learn_mode='marginal', test_mode='viterbi') 94 | model.add(crf) 95 | model.compile(optimizer='rmsprop', loss=crf_loss, metrics=[crf_accuracy]) 96 | model.fit(x, y_onehot, epochs=1, batch_size=10) 97 | 98 | y_pred = model.predict(x) 99 | 100 | # check y_pred is onehot vector (output from 'viterbi' test mode) 101 | assert_allclose(np.eye(output_dim)[y_pred.argmax(-1)], y_pred, atol=1e-6) 102 | 103 | try: 104 | os.remove(MODEL_PERSISTENCE_PATH) 105 | except OSError: 106 | pass 107 | 108 | 109 | if __name__ == '__main__': 110 | pytest.main([__file__]) 111 | -------------------------------------------------------------------------------- /tests/keras_contrib/losses/dssim_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import numpy as np 3 | from keras_contrib.utils.test_utils import is_tf_keras 4 | from numpy.testing import assert_allclose 5 | from keras.layers import Conv2D 6 | from keras.models import Sequential 7 | from keras.optimizers import Adam 8 | 9 | from keras.losses import sparse_categorical_crossentropy 10 | from keras import backend as K 11 | from keras_contrib.losses import DSSIMObjective 12 | 13 | allobj = [] 14 | 15 | 16 | def test_objective_shapes_3d(): 17 | y_a = K.variable(np.random.random((5, 6, 7))) 18 | y_b = K.variable(np.random.random((5, 6, 7))) 19 | for obj in allobj: 20 | objective_output = obj(y_a, y_b) 21 | assert K.eval(objective_output).shape == (5, 6) 22 | 23 | 24 | def test_objective_shapes_2d(): 25 | y_a = K.variable(np.random.random((6, 7))) 26 | y_b = K.variable(np.random.random((6, 7))) 27 | for obj in allobj: 28 | objective_output = obj(y_a, y_b) 29 | assert K.eval(objective_output).shape == (6,) 30 | 31 | 32 | def test_cce_one_hot(): 33 | y_a = K.variable(np.random.randint(0, 7, (5, 6))) 34 | y_b = K.variable(np.random.random((5, 6, 7))) 35 | objective_output = sparse_categorical_crossentropy(y_a, y_b) 36 | assert K.eval(objective_output).shape == (5, 6) 37 | 38 | y_a = K.variable(np.random.randint(0, 7, (6,))) 39 | y_b = K.variable(np.random.random((6, 7))) 40 | assert K.eval(sparse_categorical_crossentropy(y_a, y_b)).shape == (6,) 41 | 42 | 43 | def test_DSSIM_channels_last(): 44 | prev_data = K.image_data_format() 45 | K.set_image_data_format('channels_last') 46 | for input_dim, kernel_size in zip([32, 33], [2, 3]): 47 | input_shape = [input_dim, input_dim, 3] 48 | X = np.random.random_sample(4 * input_dim * input_dim * 3) 49 | X = X.reshape([4] + input_shape) 50 | y = np.random.random_sample(4 * input_dim * input_dim * 3) 51 | y = y.reshape([4] + input_shape) 52 | 53 | model = Sequential() 54 | model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape, 55 | activation='relu')) 56 | model.add(Conv2D(3, (3, 3), padding='same', input_shape=input_shape, 57 | activation='relu')) 58 | adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8) 59 | model.compile(loss=DSSIMObjective(kernel_size=kernel_size), 60 | metrics=['mse'], 61 | optimizer=adam) 62 | model.fit(X, y, batch_size=2, epochs=1, shuffle='batch') 63 | 64 | # Test same 65 | x1 = K.constant(X, 'float32') 66 | x2 = K.constant(X, 'float32') 67 | dssim = DSSIMObjective(kernel_size=kernel_size) 68 | assert_allclose(0.0, K.eval(dssim(x1, x2)), atol=1e-4) 69 | 70 | # Test opposite 71 | x1 = K.zeros([4] + input_shape) 72 | x2 = K.ones([4] + input_shape) 73 | dssim = DSSIMObjective(kernel_size=kernel_size) 74 | assert_allclose(0.5, K.eval(dssim(x1, x2)), atol=1e-4) 75 | 76 | K.set_image_data_format(prev_data) 77 | 78 | 79 | @pytest.mark.xfail(is_tf_keras, 80 | reason='TODO fix this.', 81 | strict=True) 82 | def test_DSSIM_channels_first(): 83 | prev_data = K.image_data_format() 84 | K.set_image_data_format('channels_first') 85 | for input_dim, kernel_size in zip([32, 33], [2, 3]): 86 | input_shape = [3, input_dim, input_dim] 87 | X = np.random.random_sample(4 * input_dim * input_dim * 3) 88 | X = X.reshape([4] + input_shape) 89 | y = np.random.random_sample(4 * input_dim * input_dim * 3) 90 | y = y.reshape([4] + input_shape) 91 | 92 | model = Sequential() 93 | model.add(Conv2D(32, (3, 3), padding='same', input_shape=input_shape, 94 | activation='relu')) 95 | model.add(Conv2D(3, (3, 3), padding='same', input_shape=input_shape, 96 | activation='relu')) 97 | adam = Adam(lr=0.001, beta_1=0.9, beta_2=0.999, epsilon=1e-8) 98 | model.compile(loss=DSSIMObjective(kernel_size=kernel_size), metrics=['mse'], 99 | optimizer=adam) 100 | model.fit(X, y, batch_size=2, epochs=1, shuffle='batch') 101 | 102 | # Test same 103 | x1 = K.constant(X, 'float32') 104 | x2 = K.constant(X, 'float32') 105 | dssim = DSSIMObjective(kernel_size=kernel_size) 106 | assert_allclose(0.0, K.eval(dssim(x1, x2)), atol=1e-4) 107 | 108 | # Test opposite 109 | x1 = K.zeros([4] + input_shape) 110 | x2 = K.ones([4] + input_shape) 111 | dssim = DSSIMObjective(kernel_size=kernel_size) 112 | assert_allclose(0.5, K.eval(dssim(x1, x2)), atol=1e-4) 113 | 114 | K.set_image_data_format(prev_data) 115 | 116 | 117 | if __name__ == '__main__': 118 | pytest.main([__file__]) 119 | -------------------------------------------------------------------------------- /tests/keras_contrib/losses/jaccard_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from keras_contrib.losses import jaccard_distance 4 | from keras_contrib.utils.test_utils import is_tf_keras 5 | from keras import backend as K 6 | import numpy as np 7 | 8 | 9 | @pytest.mark.xfail(is_tf_keras, 10 | reason='TODO fix this.', 11 | strict=True) 12 | def test_jaccard_distance(): 13 | # all_right, almost_right, half_right, all_wrong 14 | y_true = np.array([[0, 0, 1, 0], [0, 0, 1, 0], [0, 0, 1, 0], 15 | [0, 0, 1., 0.]]) 16 | y_pred = np.array([[0, 0, 1, 0], [0, 0, 0.9, 0], [0, 0, 0.1, 0], 17 | [1, 1, 0.1, 1.]]) 18 | 19 | r = jaccard_distance( 20 | K.variable(y_true), 21 | K.variable(y_pred), ) 22 | if K.is_keras_tensor(r): 23 | assert K.int_shape(r) == (4, ) 24 | 25 | all_right, almost_right, half_right, all_wrong = K.eval(r) 26 | assert all_right == 0, 'should converge on zero' 27 | assert all_right < almost_right 28 | assert almost_right < half_right 29 | assert half_right < all_wrong 30 | 31 | 32 | def test_jaccard_distance_shapes_3d(): 33 | y_a = K.variable(np.random.random((5, 6, 7))) 34 | y_b = K.variable(np.random.random((5, 6, 7))) 35 | objective_output = jaccard_distance(y_a, y_b) 36 | assert K.eval(objective_output).shape == (5, 6) 37 | 38 | 39 | def test_jaccard_distance_shapes_2d(): 40 | y_a = K.variable(np.random.random((6, 7))) 41 | y_b = K.variable(np.random.random((6, 7))) 42 | objective_output = jaccard_distance(y_a, y_b) 43 | assert K.eval(objective_output).shape == (6, ) 44 | -------------------------------------------------------------------------------- /tests/keras_contrib/metrics/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/tests/keras_contrib/metrics/.gitkeep -------------------------------------------------------------------------------- /tests/keras_contrib/optimizers/ftml_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pytest 3 | from keras_contrib.utils.test_utils import is_tf_keras 4 | from keras_contrib.tests import optimizers 5 | from keras_contrib.optimizers import ftml 6 | 7 | 8 | @pytest.mark.xfail(is_tf_keras, 9 | reason='TODO fix this.', 10 | strict=True) 11 | def test_ftml(): 12 | optimizers._test_optimizer(ftml()) 13 | optimizers._test_optimizer(ftml(lr=0.003, beta_1=0.8, 14 | beta_2=0.9, epsilon=1e-5, 15 | decay=1e-3)) 16 | -------------------------------------------------------------------------------- /tests/keras_contrib/optimizers/lars_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import numpy as np 3 | from keras_contrib.tests import optimizers 4 | from keras_contrib.optimizers import lars 5 | from keras.models import Sequential 6 | from keras.layers import Dense 7 | 8 | 9 | def test_base_lars(): 10 | optimizers._test_optimizer(lars(0.01)) 11 | 12 | 13 | def test_nesterov_lars(): 14 | optimizers._test_optimizer(lars(0.01, nesterov=True)) 15 | -------------------------------------------------------------------------------- /tests/keras_contrib/optimizers/padam_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from keras_contrib.tests import optimizers 3 | from keras_contrib.optimizers import Padam 4 | 5 | 6 | def test_padam(): 7 | optimizers._test_optimizer(Padam()) 8 | optimizers._test_optimizer(Padam(decay=1e-3)) 9 | -------------------------------------------------------------------------------- /tests/keras_contrib/optimizers/yogi_test.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | import pytest 3 | from keras_contrib.tests import optimizers 4 | from keras_contrib.optimizers import Yogi 5 | from keras_contrib.utils.test_utils import is_tf_keras 6 | 7 | 8 | def test_yogi(): 9 | optimizers._test_optimizer(Yogi()) 10 | optimizers._test_optimizer(Yogi(beta_1=0.9, beta_2=0.9)) 11 | optimizers._test_optimizer(Yogi(beta_1=0.9, beta_2=0.99)) 12 | optimizers._test_optimizer(Yogi(beta_1=0.9, beta_2=0.999)) 13 | 14 | 15 | @pytest.mark.skipif(is_tf_keras, 16 | reason='Sometimes fail. It is random.', 17 | strict=True) 18 | def test_yogi_change_lr(): 19 | optimizers._test_optimizer(Yogi(beta_1=0.9, beta_2=0.999, lr=0.001)) 20 | -------------------------------------------------------------------------------- /tests/keras_contrib/preprocessing/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/tests/keras_contrib/preprocessing/.gitkeep -------------------------------------------------------------------------------- /tests/keras_contrib/regularizers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/tests/keras_contrib/regularizers/.gitkeep -------------------------------------------------------------------------------- /tests/keras_contrib/utils/save_load_utils_test.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | from keras import backend as K 4 | from keras.layers import Input, Dense 5 | from keras.models import Model 6 | from numpy.testing import assert_allclose 7 | 8 | from keras_contrib.utils.save_load_utils import save_all_weights, load_all_weights 9 | 10 | 11 | @pytest.mark.skipif(K.backend() != 'tensorflow', 12 | reason='save_all_weights and load_all_weights only ' 13 | 'supported on TensorFlow') 14 | def test_save_and_load_all_weights(): 15 | ''' 16 | Test save_all_weights and load_all_weights. 17 | Save and load optimizer and model weights but not configuration. 18 | ''' 19 | 20 | def make_model(): 21 | _x = Input((10,)) 22 | _y = Dense(10)(_x) 23 | _m = Model(_x, _y) 24 | _m.compile('adam', 'mean_squared_error') 25 | _m._make_train_function() 26 | return _m 27 | 28 | # make a model 29 | m1 = make_model() 30 | # set weights 31 | w1 = m1.layers[1].kernel # dense layer 32 | w1value = K.get_value(w1) 33 | w1value[0, 0:4] = [1, 3, 3, 7] 34 | K.set_value(w1, w1value) 35 | # set optimizer weights 36 | ow1 = m1.optimizer.weights[3] # momentum weights 37 | ow1value = K.get_value(ow1) 38 | ow1value[0, 0:3] = [4, 2, 0] 39 | K.set_value(ow1, ow1value) 40 | # save all weights 41 | save_all_weights(m1, 'model.h5') 42 | # new model 43 | m2 = make_model() 44 | # load all weights 45 | load_all_weights(m2, 'model.h5') 46 | # check weights 47 | assert_allclose(K.get_value(m2.layers[1].kernel)[0, 0:4], [1, 3, 3, 7]) 48 | # check optimizer weights 49 | assert_allclose(K.get_value(m2.optimizer.weights[3])[0, 0:3], [4, 2, 0]) 50 | os.remove('model.h5') 51 | 52 | 53 | if __name__ == '__main__': 54 | pytest.main([__file__]) 55 | -------------------------------------------------------------------------------- /tests/keras_contrib/wrappers/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/keras-team/keras-contrib/3fc5ef709e061416f4bc8a92ca3750c824b5d2b0/tests/keras_contrib/wrappers/.gitkeep -------------------------------------------------------------------------------- /tests/tooling/test_codeowners.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pytest 3 | from github import Github 4 | try: 5 | import pathlib 6 | except ImportError: 7 | import pathlib2 as pathlib 8 | 9 | path_to_keras_contrib = pathlib.Path(__file__).resolve().parents[2] 10 | path_to_codeowners = path_to_keras_contrib / 'CODEOWNERS' 11 | 12 | authenticated = True 13 | try: 14 | github_client = Github(os.environ['GITHUB_TOKEN']) 15 | except KeyError: 16 | try: 17 | github_client = Github(os.environ['GITHUB_USER'], 18 | os.environ['GITHUB_PASSWORD']) 19 | except KeyError: 20 | authenticated = False 21 | 22 | 23 | def parse_codeowners(): 24 | map_path_owner = [] 25 | for line in open(path_to_codeowners, 'r'): 26 | line = line.strip() 27 | if line.startswith('#') or line == '': 28 | continue 29 | x = line.split(' ') 30 | path = path_to_keras_contrib / x[0] 31 | owner = x[-1] 32 | map_path_owner.append((path, owner)) 33 | return map_path_owner 34 | 35 | 36 | def test_codeowners_file_exist(): 37 | for path, _ in parse_codeowners(): 38 | assert path.exists() 39 | 40 | 41 | @pytest.mark.skipif(not authenticated, 42 | reason='It should be possible to run the test without' 43 | 'authentication, but we might get our request refused' 44 | 'by github. To be deterministic, we\'ll disable it.') 45 | def test_codeowners_user_exist(): 46 | for _, user in parse_codeowners(): 47 | assert user[0] == '@' 48 | assert github_client.get_user(user[1:]) 49 | 50 | 51 | directories_to_test = [ 52 | 'examples', 53 | 'keras_contrib/activations', 54 | 'keras_contrib/applications', 55 | 'keras_contrib/callbacks', 56 | 'keras_contrib/constraints', 57 | 'keras_contrib/datasets', 58 | 'keras_contrib/initializers', 59 | 'keras_contrib/layers', 60 | 'keras_contrib/losses', 61 | 'keras_contrib/metrics', 62 | 'keras_contrib/optimizers', 63 | 'keras_contrib/preprocessing', 64 | 'keras_contrib/regularizers', 65 | 'keras_contrib/wrappers' 66 | ] 67 | directories_to_test = [path_to_keras_contrib / x for x in directories_to_test] 68 | 69 | # TODO: remove those files or find them owners. 70 | exclude = [ 71 | 'examples/cifar10_clr.py', 72 | 'examples/cifar10_densenet.py', 73 | 'examples/cifar10_nasnet.py', 74 | 'examples/cifar10_resnet.py', 75 | 'examples/cifar10_ror.py', 76 | 'examples/cifar10_wide_resnet.py', 77 | 'examples/conll2000_chunking_crf.py', 78 | 'examples/improved_wgan.py', 79 | 'examples/jaccard_loss.py', 80 | 'keras_contrib/callbacks/cyclical_learning_rate.py', 81 | 'keras_contrib/callbacks/dead_relu_detector.py', 82 | 'keras_contrib/applications/resnet.py', 83 | 'keras_contrib/constraints/clip.py', 84 | 'keras_contrib/datasets/coco.py', 85 | 'keras_contrib/datasets/conll2000.py', 86 | 'keras_contrib/datasets/pascal_voc.py', 87 | 'keras_contrib/initializers/convaware.py', 88 | 'keras_contrib/losses/crf_losses.py', 89 | 'keras_contrib/losses/dssim.py', 90 | 'keras_contrib/losses/jaccard.py', 91 | 'keras_contrib/layers/advanced_activations/pelu.py', 92 | 'keras_contrib/layers/advanced_activations/srelu.py', 93 | 'keras_contrib/layers/convolutional/cosineconvolution2d.py', 94 | 'keras_contrib/layers/core.py', 95 | 'keras_contrib/layers/crf.py', 96 | 'keras_contrib/layers/normalization/instancenormalization.py', 97 | 'keras_contrib/optimizers/ftml.py', 98 | 'keras_contrib/optimizers/lars.py', 99 | 'keras_contrib/metrics/crf_accuracies.py', 100 | ] 101 | exclude = [path_to_keras_contrib / x for x in exclude] 102 | 103 | 104 | @pytest.mark.parametrize('directory', directories_to_test) 105 | def test_all_files_have_owners(directory): 106 | files_with_owners = [x[0] for x in parse_codeowners()] 107 | for root, dirs, files in os.walk(directory): 108 | for name in files: 109 | file_path = pathlib.Path(root) / name 110 | if file_path.suffix != '.py': 111 | continue 112 | if file_path.name == '__init__.py': 113 | continue 114 | if file_path in exclude: 115 | continue 116 | assert file_path in files_with_owners 117 | 118 | 119 | if __name__ == '__main__': 120 | pytest.main([__file__]) 121 | -------------------------------------------------------------------------------- /tests/tooling/test_documentation.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | import inspect 3 | import re 4 | import sys 5 | from itertools import compress 6 | 7 | import pytest 8 | 9 | modules = ['keras_contrib.layers', 10 | 'keras_contrib', 11 | 'keras_contrib.backend.tensorflow_backend', 12 | 'keras_contrib.wrappers', 13 | 'keras_contrib.utils', 14 | 'keras_contrib.callbacks', 15 | 'keras_contrib.activations', 16 | 'keras_contrib.losses', 17 | 'keras_contrib.optimizers'] 18 | accepted_name = ['from_config'] 19 | accepted_module = [] 20 | 21 | # Functions or classes with less than 'MIN_CODE_SIZE' lines can be ignored 22 | MIN_CODE_SIZE = 10 23 | 24 | 25 | def handle_class(name, member): 26 | if is_accepted(name, member): 27 | return 28 | 29 | if member.__doc__ is None and not member_too_small(member): 30 | raise ValueError("{} class doesn't have any documentation".format(name), 31 | member.__module__, inspect.getmodule(member).__file__) 32 | for n, met in inspect.getmembers(member): 33 | if inspect.ismethod(met): 34 | handle_method(n, met) 35 | 36 | 37 | def handle_function(name, member): 38 | if is_accepted(name, member) or member_too_small(member): 39 | # We don't need to check this one. 40 | return 41 | doc = member.__doc__ 42 | if doc is None: 43 | raise ValueError("{} function doesn't have any documentation".format(name), 44 | member.__module__, inspect.getmodule(member).__file__) 45 | 46 | args = list(inspect.signature(member).parameters.keys()) 47 | assert_args_presence(args, doc, member, name) 48 | assert_function_style(name, member, doc, args) 49 | assert_doc_style(name, member, doc) 50 | 51 | 52 | def assert_doc_style(name, member, doc): 53 | lines = doc.split("\n") 54 | first_line = lines[0] 55 | if len(first_line.strip()) == 0: 56 | raise ValueError( 57 | "{} the documentation should be on the first line.".format(name), 58 | member.__module__) 59 | if first_line.strip()[-1] != '.': 60 | raise ValueError("{} first line should end with a '.'".format(name), 61 | member.__module__) 62 | 63 | 64 | def assert_function_style(name, member, doc, args): 65 | code = inspect.getsource(member) 66 | has_return = re.findall(r"\s*return \S+", code, re.MULTILINE) 67 | if has_return and "# Returns" not in doc: 68 | innerfunction = [inspect.getsource(x) for x in member.__code__.co_consts if 69 | inspect.iscode(x)] 70 | return_in_sub = [ret for code_inner in innerfunction for ret in 71 | re.findall(r"\s*return \S+", code_inner, re.MULTILINE)] 72 | if len(return_in_sub) < len(has_return): 73 | raise ValueError("{} needs a '# Returns' section".format(name), 74 | member.__module__) 75 | 76 | has_raise = re.findall(r"^\s*raise \S+", code, re.MULTILINE) 77 | if has_raise and "# Raises" not in doc: 78 | innerfunction = [inspect.getsource(x) for x in member.__code__.co_consts if 79 | inspect.iscode(x)] 80 | raise_in_sub = [ret for code_inner in innerfunction for ret in 81 | re.findall(r"\s*raise \S+", code_inner, re.MULTILINE)] 82 | if len(raise_in_sub) < len(has_raise): 83 | raise ValueError("{} needs a '# Raises' section".format(name), 84 | member.__module__) 85 | 86 | if len(args) > 0 and "# Arguments" not in doc: 87 | raise ValueError("{} needs a '# Arguments' section".format(name), 88 | member.__module__) 89 | 90 | assert_blank_before(name, member, doc, ['# Arguments', '# Raises', '# Returns']) 91 | 92 | 93 | def assert_blank_before(name, member, doc, keywords): 94 | doc_lines = [x.strip() for x in doc.split('\n')] 95 | for keyword in keywords: 96 | if keyword in doc_lines: 97 | index = doc_lines.index(keyword) 98 | if doc_lines[index - 1] != '': 99 | raise ValueError( 100 | "{} '{}' should have a blank line above.".format(name, keyword), 101 | member.__module__) 102 | 103 | 104 | def is_accepted(name, member): 105 | if 'keras' not in str(member.__module__): 106 | return True 107 | return name in accepted_name or member.__module__ in accepted_module 108 | 109 | 110 | def member_too_small(member): 111 | code = inspect.getsource(member).split('\n') 112 | return len(code) < MIN_CODE_SIZE 113 | 114 | 115 | def assert_args_presence(args, doc, member, name): 116 | args_not_in_doc = [arg not in doc for arg in args] 117 | if any(args_not_in_doc): 118 | raise ValueError( 119 | "{} {} arguments are not present in documentation ".format(name, list( 120 | compress(args, args_not_in_doc))), member.__module__) 121 | words = doc.replace('*', '').split() 122 | # Check arguments styling 123 | styles = [arg + ":" not in words for arg in args] 124 | if any(styles): 125 | raise ValueError( 126 | "{} {} are not style properly 'argument': documentation".format( 127 | name, 128 | list(compress(args, styles))), 129 | member.__module__) 130 | 131 | # Check arguments order 132 | indexes = [words.index(arg + ":") for arg in args] 133 | if indexes != sorted(indexes): 134 | raise ValueError( 135 | "{} arguments order is different from the documentation".format(name), 136 | member.__module__) 137 | 138 | 139 | def handle_method(name, member): 140 | if name in accepted_name or member.__module__ in accepted_module: 141 | return 142 | handle_function(name, member) 143 | 144 | 145 | def handle_module(mod): 146 | for name, mem in inspect.getmembers(mod): 147 | if inspect.isclass(mem): 148 | handle_class(name, mem) 149 | elif inspect.isfunction(mem): 150 | handle_function(name, mem) 151 | elif 'keras' in name and inspect.ismodule(mem): 152 | # Only test keras' modules 153 | handle_module(mem) 154 | 155 | 156 | @pytest.mark.skipif(sys.version_info < (3, 3), reason="requires python3.3") 157 | @pytest.mark.parametrize('module', modules) 158 | def test_doc(module): 159 | mod = importlib.import_module(module) 160 | handle_module(mod) 161 | 162 | 163 | if __name__ == '__main__': 164 | pytest.main([__file__]) 165 | --------------------------------------------------------------------------------