Comparar commits

..

102 Commits

Autor SHA1 Mensagem Data
Francois Chollet afbd5d34a3 merge 2017-05-24 14:57:32 -07:00
Francois Chollet 99e4e481c5 merge master 2017-05-22 15:30:24 -07:00
Francois Chollet 2061f41987 style fixes 2017-05-22 13:25:04 -07:00
Francois Chollet 457b0c1d3e Merge branch 'master' into tf-keras 2017-04-07 14:15:00 -07:00
Francois Chollet bf5735b577 Merge branch 'master' into tf-keras 2017-04-07 14:03:45 -07:00
Francois Chollet 1f82b19349 add changes to inception_v3 2017-04-07 13:46:10 -07:00
Francois Chollet b8b2fc4e6c merge. 2017-04-07 13:43:32 -07:00
Francois Chollet b5411f10a1 Merge branch 'master' into tf-keras 2017-04-05 11:57:42 -07:00
Francois Chollet fce18b245c merge 2017-04-05 10:46:20 -07:00
Francois Chollet e872da85e4 exception json decoding error 2017-04-04 11:46:23 -07:00
Francois Chollet a2a2e49457 merge 2017-04-03 17:18:56 -07:00
Francois Chollet 032abdb666 Merge branch 'tf-keras' of github.com:fchollet/keras into tf-keras 2017-04-03 15:29:06 -07:00
Francois Chollet 8100ac79c1 Make config file saving conditional on permissions. 2017-04-03 15:28:51 -07:00
Francois Chollet 16db6db6ae style fix 2017-04-02 13:23:13 -07:00
Francois Chollet 4026f89bd1 merge master. 2017-04-02 13:22:06 -07:00
Francois Chollet 5436b4fb00 Merge branch 'master' into tf-keras 2017-04-02 12:56:20 -07:00
Francois Chollet 6c199c41dd Style fix. 2017-04-02 12:54:50 -07:00
Francois Chollet 1a7e51cfc8 Backend fixes. 2017-04-02 12:50:18 -07:00
Francois Chollet df14349c2a Merge branch 'tf-keras' of github.com:fchollet/keras into tf-keras 2017-04-02 12:46:57 -07:00
Francois Chollet 855e8dccde backport py3 fix in backend 2017-04-02 12:46:37 -07:00
Francois Chollet 850d92516c Merge branch 'master' into tf-keras 2017-04-02 12:45:16 -07:00
Francois Chollet 96909acd1e Merge branch 'tf-keras' of github.com:fchollet/keras into tf-keras 2017-04-02 11:49:55 -07:00
Francois Chollet 9479666083 Adapt merge tests. 2017-04-02 11:49:41 -07:00
Francois Chollet c0e972f3b4 Merge branch 'master' into tf-keras 2017-04-02 11:42:28 -07:00
Francois Chollet a517bc69fb rm legacy interface tests 2017-04-02 11:39:32 -07:00
Francois Chollet 57d7fce61d Remove backend tests 2017-04-02 11:29:43 -07:00
Francois Chollet 4a5a3dd685 merge master. 2017-04-02 11:21:03 -07:00
Francois Chollet 819f3e2ba5 style fix 2017-03-15 15:55:09 -07:00
Francois Chollet 6ef5bb2ddc style fixes 2017-03-15 12:47:08 -07:00
Francois Chollet 01081d4899 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-15 12:46:22 -07:00
Francois Chollet f37c7d4fd9 rm objectives 2017-03-15 12:46:00 -07:00
Francois Chollet 4a2ff8d019 Remove common.py 2017-03-15 12:45:23 -07:00
Francois Chollet 59b1e2a25c Merge branch 'master' into tf-keras
# Conflicts:
#	keras/backend/__init__.py
#	keras/backend/common.py
#	keras/backend/theano_backend.py
2017-03-15 12:44:24 -07:00
Francois Chollet 240eda535d Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-14 09:11:09 -07:00
Francois Chollet 9d62df3f21 Merge branch 'master' into tf-keras 2017-03-14 09:10:19 -07:00
Francois Chollet 776a15aad9 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 17:44:26 -07:00
Francois Chollet 4b79df99b9 Make Keras dir creation safer in multithreaded envs. 2017-03-13 17:44:15 -07:00
Francois Chollet 3acd5b2e86 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 14:16:37 -07:00
Francois Chollet 5952ea52aa Merge branch 'keras-2' into tf-keras 2017-03-13 14:16:06 -07:00
Francois Chollet 50eb3bfa1b Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 12:18:53 -07:00
Francois Chollet b6b5343af3 Fixes. 2017-03-13 12:18:43 -07:00
Francois Chollet ff7209cc16 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 12:08:14 -07:00
Francois Chollet 4736730e22 Add docstring. 2017-03-13 12:07:52 -07:00
Francois Chollet 38cdc03cc4 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 12:02:07 -07:00
Francois Chollet c00a73a65e Merge 2017-03-13 12:01:54 -07:00
Francois Chollet 6a835faf79 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-13 11:59:16 -07:00
Francois Chollet 3f9379ec3e Add mandatory imports 2017-03-13 11:59:12 -07:00
Francois Chollet c11bbd807c merge. 2017-03-13 11:58:27 -07:00
Francois Chollet ba3ea75307 Merge branch 'tf-keras' of github.com:fchollet/keras into tf-keras 2017-03-10 20:40:27 -08:00
Francois Chollet 4b975c113c merge. 2017-03-10 20:40:14 -08:00
Francois Chollet 50ee2f9602 merge. 2017-03-10 10:22:03 -08:00
Francois Chollet 565d1d5116 Fix TF imports 2017-03-10 10:21:02 -08:00
Francois Chollet 4794363fae merge 2017-03-10 10:19:13 -08:00
Francois Chollet c2cc739938 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-03-10 09:51:37 -08:00
Francois Chollet 6790c0d247 add mandatory imports 2017-03-10 09:51:30 -08:00
Francois Chollet a92026d719 Remove internal docs links from docstrings. 2017-03-10 09:47:23 -08:00
Francois Chollet d14df154e5 merge 2017-03-10 09:39:28 -08:00
Francois Chollet 1b6e14e944 Use int_shape where appropriate. 2017-03-06 19:02:10 -08:00
Francois Chollet 27329b8400 merge 2017-03-06 18:47:56 -08:00
Francois Chollet 28f3eaedd1 Merge. 2017-03-05 17:44:00 -08:00
Francois Chollet 2abdcdfb8e Update. 2017-03-05 17:42:59 -08:00
Francois Chollet 4b7122ef9c Add module level imports 2017-03-05 16:11:10 -08:00
Francois Chollet 9840b5ad24 fix backend imports. 2017-03-05 14:02:11 -08:00
Francois Chollet 4adb619518 merge 2017-03-05 13:57:49 -08:00
Francois Chollet cff822c9df Merge branch 'keras-2' into tf-keras 2017-03-04 17:59:19 -08:00
Francois Chollet f9ede2ba1b Merge branch 'keras-2' into tf-keras 2017-03-03 11:52:09 -08:00
Francois Chollet 71b5c2d05b Add comment. 2017-03-03 11:51:11 -08:00
Francois Chollet d69432cd0a Add short aliases for global pooling layers. 2017-03-03 10:44:15 -08:00
Francois Chollet 8a99aaf604 Merge. 2017-03-01 18:23:31 -08:00
Francois Chollet aabe81e82b Merge. 2017-03-01 18:22:44 -08:00
Francois Chollet 94545cea9b Linter fixes. 2017-03-01 18:21:28 -08:00
Francois Chollet c25a319463 Fix circular imports issue. 2017-02-28 15:27:26 -08:00
Francois Chollet 1847036cfd Reallow causal padding. 2017-02-28 15:27:17 -08:00
Francois Chollet 3865b589e1 merge. 2017-02-28 14:46:38 -08:00
Francois Chollet 2832c740aa Reallow causal padding. 2017-02-26 16:45:27 -08:00
Francois Chollet 9ee8425072 Linter fixes. 2017-02-26 16:32:01 -08:00
Francois Chollet 1db4438ac9 merge. 2017-02-26 15:21:58 -08:00
Francois Chollet 1bd4fac1a7 merge 2017-02-26 15:02:04 -08:00
Francois Chollet a58fb1d917 merge. 2017-02-26 14:34:43 -08:00
Francois Chollet 5ae17cd983 Linter fixes. 2017-02-26 14:31:41 -08:00
Francois Chollet 9b0ff98ead merge. 2017-02-26 13:53:12 -08:00
Francois Chollet 27e943eda2 Linter fixes. 2017-02-26 13:51:27 -08:00
Francois Chollet 71b74d6b89 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-02-26 13:22:38 -08:00
Francois Chollet afd9d8087d Linter fixes. 2017-02-26 13:22:30 -08:00
Francois Chollet dc66ca402a Merge branch 'keras-2' into tf-keras 2017-02-26 13:20:52 -08:00
Francois Chollet 7b231e2819 Merge branch 'tf-keras' of https://github.com/fchollet/keras into tf-keras 2017-02-26 12:47:57 -08:00
Francois Chollet 369bfcb1bf lint fixes 2017-02-26 12:47:53 -08:00
Francois Chollet 2ca7908f59 merge 2017-02-26 12:46:35 -08:00
Francois Chollet d684124d89 Fixes. 2017-02-26 12:44:02 -08:00
Francois Chollet d2a609e459 Add names in optimizer variables. 2017-02-26 11:17:57 -08:00
Francois Chollet bd4d40e514 Fix typo. 2017-02-25 15:13:53 -08:00
Francois Chollet 5abbd05245 Docstring fixes. 2017-02-25 14:24:15 -08:00
Francois Chollet 265464141e Style fixes. 2017-02-25 14:21:07 -08:00
Francois Chollet 6feb1d9e27 Update setup.py. 2017-02-25 13:55:49 -08:00
Francois Chollet 7936401a87 Remove backend tests. 2017-02-25 13:54:18 -08:00
Francois Chollet 672fe90dd9 Atomize TF imports in backend. 2017-02-25 13:50:38 -08:00
Francois Chollet d5a384ed61 Atomize TF imports (except for backend). 2017-02-25 13:50:28 -08:00
Francois Chollet 22b943e935 Merge branch 'keras-2' into tf-keras 2017-02-25 11:29:28 -08:00
Francois Chollet 94268267c4 Make compute_output_shape private. 2017-02-25 11:06:08 -08:00
Francois Chollet 350da1a3c3 Merge keras-2. 2017-02-25 10:54:48 -08:00
Francois Chollet 3fc74cfc0b Second pass over TF conversion (nearly done). 2017-02-24 16:45:35 -08:00
Francois Chollet c6e6acdebf First pass over TF conversion. 2017-02-24 13:35:00 -08:00
122 arquivos alterados com 3239 adições e 13487 exclusões
-1
Ver Arquivo
@@ -19,4 +19,3 @@ examples/img/*
# developer environments
.idea
.vscode
+3 -23
Ver Arquivo
@@ -14,13 +14,9 @@ matrix:
- python: 3.5
env: KERAS_BACKEND=tensorflow
- python: 2.7
env: KERAS_BACKEND=theano THEANO_FLAGS=optimizer=fast_compile
env: KERAS_BACKEND=theano
- python: 3.5
env: KERAS_BACKEND=theano THEANO_FLAGS=optimizer=fast_compile
- python: 2.7
env: KERAS_BACKEND=cntk
- python: 3.5
env: KERAS_BACKEND=cntk
env: KERAS_BACKEND=theano
install:
# code below is taken from http://conda.pydata.org/docs/travis.html
# We do this conditionally because it saves us some downloading if the
@@ -53,22 +49,6 @@ install:
# install TensorFlow (CPU version).
- pip install tensorflow
# install cntk
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.0-cp27-cp27mu-linux_x86_64.whl;
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.5" ]]; then
pip install https://cntk.ai/PythonWheel/CPU-Only/cntk-2.0-cp35-cp35m-linux_x86_64.whl;
fi
#install open mpi
- rm -rf ~/mpi
- mkdir ~/mpi
- pushd ~/mpi
- wget http://cntk.ai/PythonWheel/ForKeras/depends/openmpi_1.10-3.zip
- unzip ./openmpi_1.10-3.zip
- sudo dpkg -i openmpi_1.10-3.deb
- popd
# command to run tests
script:
@@ -86,5 +66,5 @@ script:
elif [[ "$TEST_MODE" == "DOC" ]]; then
PYTHONPATH=$PWD:$PYTHONPATH py.test tests/test_documentation.py;
else
PYTHONPATH=$PWD:$PYTHONPATH py.test tests/ --ignore=tests/integration_tests --ignore=tests/test_documentation.py --cov=keras tests/ --cov-fail-under 80 --cov-report term-missing;
PYTHONPATH=$PWD:$PYTHONPATH py.test tests/ --ignore=tests/integration_tests --ignore=tests/test_documentation.py --cov=keras tests/ --cov-fail-under 78 --cov-report term-missing;
fi
+9 -22
Ver Arquivo
@@ -19,7 +19,6 @@ To easily update Theano: `pip install git+git://github.com/Theano/Theano.git --u
The more information you provide, the easier it is for us to validate that there is a bug and the faster we'll be able to take action. If you want your issue to be resolved quickly, following the steps above is crucial.
---
## Requesting a Feature
@@ -32,50 +31,39 @@ You can also use Github issues to request features you would like to see in Kera
3. After discussing the feature you may choose to attempt a Pull Request. If you're at all able, start writing some code. We always have more work to do than time to do it. If you can write some code then that will speed the process along.
---
## Requests for Contributions
[This is the board](https://github.com/fchollet/keras/projects/1) where we list current outstanding issues and features to be added. If you want to start contributing to Keras, this is the place to start.
---
## Pull Requests
**Where should I submit my pull request?**
1. **Keras improvements and bugfixes** go to the [Keras `master` branch](https://github.com/fchollet/keras/tree/master).
2. **Experimental new features** such as layers and datasets go to [keras-contrib](https://github.com/farizrahman4u/keras-contrib). Unless it is a new feature listed in [Requests for Contributions](https://github.com/fchollet/keras/projects/1), in which case it belongs in core Keras. If you think your feature belongs in core Keras, you can submit a design doc to explain your feature and argue for it (see explainations below).
2. **New features** such as layers and datasets go to [keras-contrib](https://github.com/farizrahman4u/keras-contrib). Unless it is a new feature listed in [Requests for Contributions](https://github.com/fchollet/keras/projects/1), in which case it belongs in core Keras.
Here's a quick guide to submitting your improvements:
1. If your PR introduces a change in functionality, make sure you start by writing a design doc and sending it to the Keras mailing list to discuss whether the change should be made, and how to handle it. This will save you from having your PR closed down the road! Of course, if your PR is a simple bug fix, you don't need to do that. The process for writing and submitting design docs is as follow:
- Start from [this Google Doc template](https://docs.google.com/document/d/1ZXNfce77LDW9tFAj6U5ctaJmI5mT7CQXOFMEAZo-mAA/edit#), and copy it to new Google doc.
- Fill in the content. Note that you will need to insert code examples. To insert code, use a Google Doc extension such as [CodePretty](https://chrome.google.com/webstore/detail/code-pretty/igjbncgfgnfpbnifnnlcmjfbnidkndnh?hl=en) (there are several such extensions available).
- Set sharing settings to "everyone with the link is allowed to comment"
- Send the document to `keras-users@googlegroups.com` with a subject that starts with `[API DESIGN REVIEW]` (all caps) so that we notice it.
- Wait for comments, and answer them as they come. Edit the proposal as necessary.
- The proposal will finally be approved or rejected. Once approved, you can send out Pull Requests or ask others to write Pull Requests.
1. If your PR introduces a change in functionality, make sure you start by opening an issue to discuss whether the change should be made, and how to handle it. This will save you from having your PR closed down the road! Of course, if your PR is a simple bug fix, you don't need to do that.
2. Write the code (or get others to write it). This is the hard part!
2. Write the code. This is the hard part!
3. Make sure any new function or class you introduce has proper docstrings. Make sure any code you touch still has up-to-date docstrings and documentation. **Docstring style should be respected.** In particular, they should be formatted in MarkDown, and there should be sections for `Arguments`, `Returns`, `Raises` (if applicable). Look at other docstrings in the codebase for examples.
4. Write tests. Your code should have full unit test coverage. If you want to see your PR merged promptly, this is crucial.
5. Run our test suite locally. It's easy: from the Keras folder, simply run: `py.test tests/`.
- You will need to install the test requirements as well: `pip install -e .[tests]`.
- You will need to install the test requirements as well: `pip install -e .[tests]`.
6. Make sure all tests are passing:
- with the Theano backend, on Python 2.7 and Python 3.5. Make sure you have the development version of Theano.
- with the TensorFlow backend, on Python 2.7 and Python 3.5. Make sure you have the development version of TensorFlow.
- with the Theano backend, on Python 2.7 and Python 3.5. Make sure you have the development version of Theano.
- with the TensorFlow backend, on Python 2.7 and Python 3.5. Make sure you have the development version of TensorFlow.
7. We use PEP8 syntax conventions, but we aren't dogmatic when it comes to line length. Make sure your lines stay reasonably sized, though. To make your life easier, we recommend running a PEP8 linter:
- Install PEP8 packages: `pip install pep8 pytest-pep8 autopep8`
- Run a standalone PEP8 check: `py.test --pep8 -m pep8`
- You can automatically fix some PEP8 error by running: `autopep8 -i --select <errors> <FILENAME>` for example: `autopep8 -i --select E128 tests/keras/backend/test_backends.py`
- Install PEP8 packages: `pip install pep8 pytest-pep8 autopep8`
- Run a standalone PEP8 check: `py.test --pep8 -m pep8`
- You can automatically fix some PEP8 error by running: `autopep8 -i --select <errors> <FILENAME>` for example: `autopep8 -i --select E128 tests/keras/backend/test_backends.py`
8. When committing, use appropriate, descriptive commit messages.
@@ -83,7 +71,6 @@ Here's a quick guide to submitting your improvements:
10. Submit your PR. If your changes have been approved in a previous discussion, and if you have complete (and passing) unit tests as well as proper docstrings/documentation, your PR is likely to be merged promptly. Otherwise, well...
---
## Adding new examples
+1 -5
Ver Arquivo
@@ -8,12 +8,8 @@ All contributions by Google:
Copyright (c) 2015, Google, Inc.
All rights reserved.
All contributions by Microsoft:
Copyright (c) 2017, Microsoft, Inc.
All rights reserved.
All other contributions:
Copyright (c) 2015 - 2017, the respective contributors.
Copyright (c) 2015, the respective contributors.
All rights reserved.
Each contributor holds copyright over their respective contributions.
+3 -8
Ver Arquivo
@@ -1,11 +1,11 @@
# Keras: Deep Learning for Python
# Keras: Deep Learning library for TensorFlow and Theano
[![Build Status](https://travis-ci.org/fchollet/keras.svg?branch=master)](https://travis-ci.org/fchollet/keras)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/fchollet/keras/blob/master/LICENSE)
## You have just found Keras.
Keras is a high-level neural networks API, written in Python and capable of running on top of [TensorFlow](https://github.com/tensorflow/tensorflow), [CNTK](https://github.com/Microsoft/cntk), or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Keras is a high-level neural networks API, written in Python and capable of running on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Use Keras if you need a deep learning library that:
@@ -125,11 +125,6 @@ Keras uses the following dependencies:
- TensorFlow
- [See installation instructions](https://www.tensorflow.org/install/).
*When using the CNTK backend:*
- CNTK
- [See installation instructions](https://docs.microsoft.com/en-us/cognitive-toolkit/setup-cntk-on-your-machine).
*When using the Theano backend:*
- Theano
@@ -148,7 +143,7 @@ sudo pip install keras
------------------
## Switching from TensorFlow to CNTK or Theano
## Switching from TensorFlow to Theano
By default, Keras will use TensorFlow as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
+3 -6
Ver Arquivo
@@ -286,8 +286,7 @@ PAGES = [
'page': 'utils.md',
'all_module_functions': [utils],
'classes': [utils.CustomObjectScope,
utils.HDF5Matrix,
utils.Sequence]
utils.HDF5Matrix]
},
]
@@ -321,11 +320,9 @@ def get_classes_ancestors(classes):
def get_function_signature(function, method=True):
wrapped = getattr(function, '_original_function', None)
if wrapped is None:
signature = getattr(function, '_legacy_support_signature', None)
if signature is None:
signature = inspect.getargspec(function)
else:
signature = inspect.getargspec(wrapped)
defaults = signature.defaults
if method:
args = signature.args[1:]
+3 -3
Ver Arquivo
@@ -130,10 +130,10 @@ for i, layer in enumerate(base_model.layers):
print(i, layer.name)
# we chose to train the top 2 inception blocks, i.e. we will freeze
# the first 249 layers and unfreeze the rest:
for layer in model.layers[:249]:
# the first 172 layers and unfreeze the rest:
for layer in model.layers[:172]:
layer.trainable = False
for layer in model.layers[249:]:
for layer in model.layers[172:]:
layer.trainable = True
# we need to recompile the model for these modifications to take effect
+4 -5
Ver Arquivo
@@ -4,13 +4,12 @@
Keras is a model-level library, providing high-level building blocks for developing deep learning models. It does not handle itself low-level operations such as tensor products, convolutions and so on. Instead, it relies on a specialized, well-optimized tensor manipulation library to do so, serving as the "backend engine" of Keras. Rather than picking one single tensor library and making the implementation of Keras tied to that library, Keras handles the problem in a modular way, and several different backend engines can be plugged seamlessly into Keras.
At this time, Keras has three backend implementations available: the **TensorFlow** backend, the **Theano** backend, and the **CNTK** backend.
At this time, Keras has two backend implementations available: the **TensorFlow** backend and the **Theano** backend.
- [TensorFlow](http://www.tensorflow.org/) is an open-source symbolic tensor manipulation framework developed by Google, Inc.
- [Theano](http://deeplearning.net/software/theano/) is an open-source symbolic tensor manipulation framework developed by LISA/MILA Lab at Université de Montréal.
- [CNTK](https://www.microsoft.com/en-us/cognitive-toolkit/) is an open-source, commercial-grade toolkit for deep learning developed by Microsoft.
In the future, we are likely to add more backend options.
In the future, we are likely to add more backend options. Go ask Microsoft about how their CNTK backend project is doing.
----
@@ -35,7 +34,7 @@ The default configuration file looks like this:
}
```
Simply change the field `backend` to `"theano"`, `"tensorflow"`, or `"cntk"`, and Keras will use the new configuration next time you run any Keras code.
Simply change the field `backend` to either `"theano"` or `"tensorflow"`, and Keras will use the new configuration next time you run any Keras code.
You can also define the environment variable ``KERAS_BACKEND`` and this will
override what is defined in your config file :
@@ -66,7 +65,7 @@ You can change these settings by editing `$HOME/.keras/keras.json`.
- For 3D data, `"channels_last"` assumes `(conv_dim1, conv_dim2, conv_dim3, channels)` while `"channels_first"` assumes `(channels, conv_dim1, conv_dim2, conv_dim3)`.
* `epsilon`: float, a numeric fuzzing constant used to avoid dividing by zero in some operations.
* `floatx`: string, `"float16"`, `"float32"`, or `"float64"`. Default float precision.
* `backend`: string, `"tensorflow"`, `"theano"`, or `"cntk"`.
* `backend`: string, `"tensorflow"` or `"theano"`.
----
+3 -4
Ver Arquivo
@@ -17,7 +17,6 @@ model.add(Dense(64, kernel_constraint=max_norm(2.)))
## Available constraints
- __max_norm(max_value=2, axis=0)__: maximum-norm constraint
- __non_neg()__: non-negativity constraint
- __unit_norm(axis=0)__: unit-norm constraint
- __min_max_norm(min_value=0.0, max_value=1.0, rate=1.0, axis=0)__: minimum/maximum-norm constraint
- __max_norm__(max_value=2, axis=0): maximum-norm constraint
- __non_neg__(): non-negativity constraint
- __unit_norm__(): unit-norm constraint, enforces the matrix to have unit norm along the last axis
+3 -3
Ver Arquivo
@@ -16,7 +16,7 @@
- [How can I remove a layer from a Sequential model?](#how-can-i-remove-a-layer-from-a-sequential-model)
- [How can I use pre-trained models in Keras?](#how-can-i-use-pre-trained-models-in-keras)
- [How can I use HDF5 inputs with Keras?](#how-can-i-use-hdf5-inputs-with-keras)
- [Where is the Keras configuration file stored?](#where-is-the-keras-configuration-file-stored)
- [Where is the Keras configuration filed stored?](#where-is-the-keras-configuration-filed-stored)
---
@@ -38,7 +38,7 @@ Please cite Keras in your publications if it helps your research. Here is an exa
### How can I run Keras on GPU?
If you are running on the TensorFlow or CNTK backends, your code will automatically run on GPU if any available GPU is detected.
If you are running on the TensorFlow backend, your code will automatically run on GPU if any available GPU is detected.
If you are running on the Theano backend, you can use one of the following methods:
@@ -424,7 +424,7 @@ with h5py.File('input/file.hdf5', 'r') as f:
---
### Where is the Keras configuration file stored?
### Where is the Keras configuration filed stored?
The default directory where all Keras data is stored is:
+1 -1
Ver Arquivo
@@ -361,7 +361,7 @@ from keras.models import Model, Sequential
# First, let's define a vision model using a Sequential model.
# This model will encode an image into a vector.
vision_model = Sequential()
vision_model.add(Conv2D(64, (3, 3), activation='relu', padding='same', input_shape=(3, 224, 224)))
vision_model.add(Conv2D(64, (3, 3) activation='relu', padding='same', input_shape=(3, 224, 224)))
vision_model.add(Conv2D(64, (3, 3), activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Conv2D(128, (3, 3), activation='relu', padding='same'))
+1 -1
Ver Arquivo
@@ -1,3 +1,3 @@
# Keras: The Python Deep Learning library
# Keras: Deep Learning library for Theano and TensorFlow
{{autogenerated}}
+1 -2
Ver Arquivo
@@ -21,8 +21,7 @@ class MyLayer(Layer):
def build(self, input_shape):
# Create a trainable weight variable for this layer.
self.kernel = self.add_weight(name='kernel',
shape=(input_shape[1], self.output_dim),
self.kernel = self.add_weight(shape=(input_shape[1], self.output_dim),
initializer='uniform',
trainable=True)
super(MyLayer, self).build(input_shape) # Be sure to call this somewhere!
+9 -56
Ver Arquivo
@@ -2,10 +2,8 @@
## text_to_word_sequence
```python
keras.preprocessing.text.text_to_word_sequence(text,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=" ")
keras.preprocessing.text.text_to_word_sequence(text,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, split=" ")
```
Split a sentence into a list of words.
@@ -14,74 +12,29 @@ Split a sentence into a list of words.
- __Arguments__:
- __text__: str.
- __filters__: list (or concatenation) of characters to filter out, such as
punctuation. Default: '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n' , includes
basic punctuation, tabs, and newlines.
- __filters__: list (or concatenation) of characters to filter out, such as punctuation. Default: '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n' , includes basic punctuation, tabs, and newlines.
- __lower__: boolean. Whether to set the text to lowercase.
- __split__: str. Separator for word splitting.
## one_hot
```python
keras.preprocessing.text.one_hot(text,
n,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=" ")
keras.preprocessing.text.one_hot(text, n,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n', lower=True, split=" ")
```
One-hot encodes a text into a list of word indexes in a vocabulary of size n.
This is a wrapper to the `hashing_trick` function using `hash` as the hashing function.
One-hot encode a text into a list of word indexes in a vocabulary of size n.
- __Return__: List of integers in [1, n]. Each integer encodes a word (unicity non-guaranteed).
- __Arguments__:
- __text__: str.
- __Arguments__: Same as `text_to_word_sequence` above.
- __n__: int. Size of vocabulary.
- __filters__: list (or concatenation) of characters to filter out, such as
punctuation. Default: '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n' , includes
basic punctuation, tabs, and newlines.
- __lower__: boolean. Whether to set the text to lowercase.
- __split__: str. Separator for word splitting.
## hashing_trick
```python
keras.preprocessing.text.hashing_trick(text,
n,
hash_function=None,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=' ')
```
Converts a text to a sequence of indices in a fixed-size hashing space
- __Return__:
A list of integer word indices (unicity non-guaranteed).
- __Arguments__:
- __text__: str.
- __n__: Dimension of the hashing space.
- __hash_function__: defaults to python `hash` function, can be 'md5' or
any function that takes in input a string and returns a int.
Note that 'hash' is not a stable hashing function, so
it is not consistent across different runs, while 'md5'
is a stable hashing function.
- __filters__: list (or concatenation) of characters to filter out, such as
punctuation. Default: '!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n' , includes
basic punctuation, tabs, and newlines.
- __lower__: boolean. Whether to set the text to lowercase.
- __split__: str. Separator for word splitting.
## Tokenizer
```python
keras.preprocessing.text.Tokenizer(num_words=None,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=" ",
char_level=False)
keras.preprocessing.text.Tokenizer(num_words=None, filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True, split=" ", char_level=False)
```
Class for vectorizing texts, or/and turning texts into sequences (=list of word indexes, where the word of rank i in the dataset (starting at 1) has index i).
+2 -2
Ver Arquivo
@@ -136,8 +136,8 @@ def shuffle_mats_or_lists(matrix_list, stop_ind=None):
elif isinstance(mat, list):
ret.append([mat[i] for i in a])
else:
raise TypeError('`shuffle_mats_or_lists` only supports '
'numpy.array and list objects.')
raise TypeError('shuffle_mats_or_lists only supports '
'numpy.array and list objects')
return ret
+1 -1
Ver Arquivo
@@ -24,7 +24,7 @@ print('Loading data...')
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')
print('Pad sequences (samples x time)')
print("Pad sequences (samples x time)")
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
print('x_train shape:', x_train.shape)
+1 -1
Ver Arquivo
@@ -37,7 +37,7 @@ print('Loading data...')
X_train = sequence.pad_sequences(X_train, max_length)
X_test = sequence.pad_sequences(X_test, max_length)
# Compile and train different models while measuring performance.
# Compile and train different models while meauring performance.
results = []
for mode in modes:
print('Testing mode: implementation={}'.format(mode))
+8 -5
Ver Arquivo
@@ -57,7 +57,7 @@ from scipy.optimize import fmin_l_bfgs_b
import time
import argparse
from keras.applications import vgg19
from keras.applications import vgg16
from keras import backend as K
parser = argparse.ArgumentParser(description='Neural style transfer with Keras.')
@@ -99,7 +99,7 @@ def preprocess_image(image_path):
img = load_img(image_path, target_size=(img_nrows, img_ncols))
img = img_to_array(img)
img = np.expand_dims(img, axis=0)
img = vgg19.preprocess_input(img)
img = vgg16.preprocess_input(img)
return img
# util function to convert a tensor into a valid image
@@ -137,7 +137,7 @@ input_tensor = K.concatenate([base_image,
# build the VGG16 network with our 3 images as input
# the model will be loaded with pre-trained ImageNet weights
model = vgg19.VGG19(input_tensor=input_tensor,
model = vgg16.VGG16(input_tensor=input_tensor,
weights='imagenet', include_top=False)
print('Model loaded.')
@@ -199,7 +199,7 @@ def total_variation_loss(x):
# combine these loss functions into a single scalar
loss = K.variable(0.)
layer_features = outputs_dict['block5_conv2']
layer_features = outputs_dict['block4_conv2']
base_image_features = layer_features[0, :, :, :]
combination_features = layer_features[2, :, :, :]
loss += content_weight * content_loss(base_image_features,
@@ -273,7 +273,10 @@ evaluator = Evaluator()
# run scipy-based optimization (L-BFGS) over the pixels of the generated image
# so as to minimize the neural style loss
x = preprocess_image(base_image_path)
if K.image_data_format() == 'channels_first':
x = np.random.uniform(0, 255, (1, 3, img_nrows, img_ncols)) - 128.
else:
x = np.random.uniform(0, 255, (1, img_nrows, img_ncols, 3)) - 128.
for i in range(iterations):
print('Start of iteration', i)
-174
Ver Arquivo
@@ -1,174 +0,0 @@
'''Compares self-normalizing MLPs with regular MLPs.
Compares the performance of a simple MLP using two
different activation functions: RELU and SELU
on the Reuters newswire topic classification task.
# Reference:
Klambauer, G., Unterthiner, T., Mayr, A., & Hochreiter, S. (2017).
Self-Normalizing Neural Networks. arXiv preprint arXiv:1706.02515.
https://arxiv.org/abs/1706.02515
'''
from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
import keras
from keras.datasets import reuters
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.layers.noise import AlphaDropout
from keras.preprocessing.text import Tokenizer
max_words = 1000
batch_size = 16
epochs = 40
plot = True
def create_network(n_dense=6,
dense_units=16,
activation='selu',
dropout=AlphaDropout,
dropout_rate=0.1,
kernel_initializer='lecun_normal',
optimizer='adam',
num_classes=1,
max_words=max_words):
"""Generic function to create a fully-connected neural network.
# Arguments
n_dense: int > 0. Number of dense layers.
dense_units: int > 0. Number of dense units per layer.
dropout: keras.layers.Layer. A dropout layer to apply.
dropout_rate: 0 <= float <= 1. The rate of dropout.
kernel_initializer: str. The initializer for the weights.
optimizer: str/keras.optimizers.Optimizer. The optimizer to use.
num_classes: int > 0. The number of classes to predict.
max_words: int > 0. The maximum number of words per data point.
# Returns
A Keras model instance (compiled).
"""
model = Sequential()
model.add(Dense(dense_units, input_shape=(max_words,),
kernel_initializer=kernel_initializer))
model.add(Activation(activation))
model.add(dropout(dropout_rate))
for i in range(n_dense - 1):
model.add(Dense(dense_units, kernel_initializer=kernel_initializer))
model.add(Activation(activation))
model.add(dropout(dropout_rate))
model.add(Dense(num_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
return model
network1 = {
'n_dense': 6,
'dense_units': 16,
'activation': 'relu',
'dropout': Dropout,
'dropout_rate': 0.5,
'kernel_initializer': 'glorot_uniform',
'optimizer': 'sgd'
}
network2 = {
'n_dense': 6,
'dense_units': 16,
'activation': 'selu',
'dropout': AlphaDropout,
'dropout_rate': 0.1,
'kernel_initializer': 'lecun_normal',
'optimizer': 'sgd'
}
print('Loading data...')
(x_train, y_train), (x_test, y_test) = reuters.load_data(num_words=max_words,
test_split=0.2)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')
num_classes = np.max(y_train) + 1
print(num_classes, 'classes')
print('Vectorizing sequence data...')
tokenizer = Tokenizer(num_words=max_words)
x_train = tokenizer.sequences_to_matrix(x_train, mode='binary')
x_test = tokenizer.sequences_to_matrix(x_test, mode='binary')
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)
print('Convert class vector to binary class matrix '
'(for use with categorical_crossentropy)')
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
print('y_train shape:', y_train.shape)
print('y_test shape:', y_test.shape)
print('\nBuilding network 1...')
model1 = create_network(num_classes=num_classes, **network1)
history_model1 = model1.fit(x_train,
y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_split=0.1)
score_model1 = model1.evaluate(x_test,
y_test,
batch_size=batch_size,
verbose=1)
print('\nBuilding network 2...')
model2 = create_network(num_classes=num_classes, **network2)
history_model2 = model2.fit(x_train,
y_train,
batch_size=batch_size,
epochs=epochs,
verbose=1,
validation_split=0.1)
score_model2 = model2.evaluate(x_test,
y_test,
batch_size=batch_size,
verbose=1)
print('\nNetwork 1 results')
print('Hyperparameters:', network1)
print('Test score:', score_model1[0])
print('Test accuracy:', score_model1[1])
print('Network 2 results')
print('Hyperparameters:', network2)
print('Test score:', score_model2[0])
print('Test accuracy:', score_model2[1])
plt.plot(range(epochs),
history_model1.history['val_loss'],
'g-',
label='Network 1 Val Loss')
plt.plot(range(epochs),
history_model2.history['val_loss'],
'r-',
label='Network 2 Val Loss')
plt.plot(range(epochs),
history_model1.history['loss'],
'g--',
label='Network 1 Loss')
plt.plot(range(epochs),
history_model2.history['loss'],
'r--',
label='Network 2 Loss')
plt.xlabel('Epochs')
plt.ylabel('Loss')
plt.legend()
plt.savefig('comparison_of_networks.png')
+1 -2
Ver Arquivo
@@ -79,8 +79,7 @@ decoder_deconv_1 = Conv2DTranspose(filters,
padding='same',
strides=1,
activation='relu')
decoder_deconv_2 = Conv2DTranspose(filters,
kernel_size=num_conv,
decoder_deconv_2 = Conv2DTranspose(filters, num_conv,
padding='same',
strides=1,
activation='relu')
+13 -8
Ver Arquivo
@@ -1,23 +1,28 @@
"""The Keras API.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from . import utils
from . import activations
from . import applications
from . import backend
from . import datasets
from . import engine
from . import layers
from . import preprocessing
from . import wrappers
from . import callbacks
from . import constraints
from . import datasets
from . import engine
from . import initializers
from . import layers
from . import losses
from . import metrics
from . import models
from . import losses
from . import optimizers
from . import preprocessing
from . import regularizers
from . import utils
from . import wrappers
# Importable from root because it's technically not a layer
from .layers import Input
__version__ = '2.0.5'
__version__ = '2.0.4-tf'
+6 -15
Ver Arquivo
@@ -1,7 +1,12 @@
"""Keras built-in activation functions.
"""
from __future__ import absolute_import
import six
from __future__ import division
from __future__ import print_function
import warnings
from . import backend as K
import six
from .utils.generic_utils import deserialize_keras_object
from .engine import Layer
@@ -34,20 +39,6 @@ def elu(x, alpha=1.0):
return K.elu(x, alpha)
def selu(x):
"""Scaled Exponential Linear Unit. (Klambauer et al., 2017)
# Arguments
x: A tensor or variable to compute the activation function for.
# References
- [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515)
"""
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
return scale * K.elu(x, alpha)
def softplus(x):
return K.softplus(x)
+8 -3
Ver Arquivo
@@ -1,6 +1,11 @@
"""Keras Applications: models with automatic loading of pre-trained weights.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .inception_v3 import InceptionV3
from .resnet50 import ResNet50
from .vgg16 import VGG16
from .vgg19 import VGG19
from .resnet50 import ResNet50
from .inception_v3 import InceptionV3
from .xception import Xception
from .mobilenet import MobileNet
+7 -1
Ver Arquivo
@@ -1,7 +1,13 @@
"""Utilities used by models pre-trained on ImageNet.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import json
from ..utils.data_utils import get_file
from .. import backend as K
from ..utils.data_utils import get_file
CLASS_INDEX = None
CLASS_INDEX_PATH = 'https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json'
+13 -14
Ver Arquivo
@@ -10,27 +10,29 @@ and that the input preprocessing function is also different (same as Xception).
- [Rethinking the Inception Architecture for Computer Vision](http://arxiv.org/abs/1512.00567)
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
from ..models import Model
from .. import backend as K
from .. import layers
from ..engine.topology import get_source_inputs
from .imagenet_utils import _obtain_input_shape
from .imagenet_utils import decode_predictions # pylint: disable=unused-import
from ..layers import AveragePooling2D
from ..layers import Activation
from ..layers import Dense
from ..layers import Input
from ..layers import BatchNormalization
from ..layers import Conv2D
from ..layers import MaxPooling2D
from ..layers import AveragePooling2D
from ..layers import Dense
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..engine.topology import get_source_inputs
from ..layers import Input
from ..layers import MaxPooling2D
from ..models import Model
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
from .imagenet_utils import _obtain_input_shape
from ..utils.layer_utils import convert_all_kernels_in_model
WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.5/inception_v3_weights_tf_dim_ordering_tf_kernels.h5'
@@ -156,10 +158,7 @@ def InceptionV3(include_top=True,
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
img_input = Input(tensor=input_tensor, shape=input_shape)
if K.image_data_format() == 'channels_first':
channel_axis = 1
-641
Ver Arquivo
@@ -1,641 +0,0 @@
"""MobileNet v1 models for Keras.
MobileNet is a general architecture and can be used for multiple use cases.
Depending on the use case, it can use different input layer size and
different width factors. This allows different width models to reduce
the number of multiply-adds and thereby
reduce inference cost on mobile devices.
MobileNets support any input size greater than 32 x 32, with larger image sizes
offering better performance.
The number of parameters and number of multiply-adds
can be modified by using the `alpha` parameter,
which increases/decreases the number of filters in each layer.
By altering the image size and `alpha` parameter,
all 16 models from the paper can be built, with ImageNet weights provided.
The paper demonstrates the performance of MobileNets using `alpha` values of
1.0 (also called 100 % MobileNet), 0.75, 0.5 and 0.25.
For each of these `alpha` values, weights for 4 different input image sizes
are provided (224, 192, 160, 128).
The following table describes the size and accuracy of the 100% MobileNet
on size 224 x 224:
----------------------------------------------------------------------------
Width Multiplier (alpha) | ImageNet Acc | Multiply-Adds (M) | Params (M)
----------------------------------------------------------------------------
| 1.0 MobileNet-224 | 70.6 % | 529 | 4.2 |
| 0.75 MobileNet-224 | 68.4 % | 325 | 2.6 |
| 0.50 MobileNet-224 | 63.7 % | 149 | 1.3 |
| 0.25 MobileNet-224 | 50.6 % | 41 | 0.5 |
----------------------------------------------------------------------------
The following table describes the performance of
the 100 % MobileNet on various input sizes:
------------------------------------------------------------------------
Resolution | ImageNet Acc | Multiply-Adds (M) | Params (M)
------------------------------------------------------------------------
| 1.0 MobileNet-224 | 70.6 % | 529 | 4.2 |
| 1.0 MobileNet-192 | 69.1 % | 529 | 4.2 |
| 1.0 MobileNet-160 | 67.2 % | 529 | 4.2 |
| 1.0 MobileNet-128 | 64.4 % | 529 | 4.2 |
------------------------------------------------------------------------
The weights for all 16 models are obtained and translated
from Tensorflow checkpoints found at
https://github.com/tensorflow/models/blob/master/slim/nets/mobilenet_v1.md
# Reference
- [MobileNets: Efficient Convolutional Neural Networks for
Mobile Vision Applications](https://arxiv.org/pdf/1704.04861.pdf))
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
import warnings
from ..models import Model
from ..layers import Input
from ..layers import Activation
from ..layers import Dropout
from ..layers import Reshape
from ..layers import BatchNormalization
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..layers import Conv2D
from .. import initializers
from .. import regularizers
from .. import constraints
from ..utils import conv_utils
from ..utils.data_utils import get_file
from ..engine.topology import get_source_inputs
from ..engine import InputSpec
from ..applications.imagenet_utils import _obtain_input_shape
from ..applications.imagenet_utils import decode_predictions
from .. import backend as K
BASE_WEIGHT_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.6/'
def relu6(x):
return K.relu(x, max_value=6)
def preprocess_input(x):
x /= 255.
x -= 0.5
x *= 2.
return x
class DepthwiseConv2D(Conv2D):
"""Depthwise separable 2D convolution.
Depthwise Separable convolutions consists in performing
just the first step in a depthwise spatial convolution
(which acts on each input channel separately).
The `depth_multiplier` argument controls how many
output channels are generated per input channel in the depthwise step.
# Arguments
kernel_size: An integer or tuple/list of 2 integers, specifying the
width and height of the 2D convolution window.
Can be a single integer to specify the same value for
all spatial dimensions.
strides: An integer or tuple/list of 2 integers,
specifying the strides of the convolution along the width and height.
Can be a single integer to specify the same value for
all spatial dimensions.
Specifying any stride value != 1 is incompatible with specifying
any `dilation_rate` value != 1.
padding: one of `"valid"` or `"same"` (case-insensitive).
depth_multiplier: The number of depthwise convolution output channels
for each input channel.
The total number of depthwise convolution output
channels will be equal to `filters_in * depth_multiplier`.
data_format: A string,
one of `channels_last` (default) or `channels_first`.
The ordering of the dimensions in the inputs.
`channels_last` corresponds to inputs with shape
`(batch, height, width, channels)` while `channels_first`
corresponds to inputs with shape
`(batch, channels, height, width)`.
It defaults to the `image_data_format` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "channels_last".
activation: Activation function to use
(see [activations](../activations.md)).
If you don't specify anything, no activation is applied
(ie. "linear" activation: `a(x) = x`).
use_bias: Boolean, whether the layer uses a bias vector.
depthwise_initializer: Initializer for the depthwise kernel matrix
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
depthwise_regularizer: Regularizer function applied to
the depthwise kernel matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
depthwise_constraint: Constraint function applied to
the depthwise kernel matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
# Input shape
4D tensor with shape:
`[batch, channels, rows, cols]` if data_format='channels_first'
or 4D tensor with shape:
`[batch, rows, cols, channels]` if data_format='channels_last'.
# Output shape
4D tensor with shape:
`[batch, filters, new_rows, new_cols]` if data_format='channels_first'
or 4D tensor with shape:
`[batch, new_rows, new_cols, filters]` if data_format='channels_last'.
`rows` and `cols` values might have changed due to padding.
"""
def __init__(self,
kernel_size,
strides=(1, 1),
padding='valid',
depth_multiplier=1,
data_format=None,
activation=None,
use_bias=True,
depthwise_initializer='glorot_uniform',
bias_initializer='zeros',
depthwise_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
depthwise_constraint=None,
bias_constraint=None,
**kwargs):
super(DepthwiseConv2D, self).__init__(
filters=None,
kernel_size=kernel_size,
strides=strides,
padding=padding,
data_format=data_format,
activation=activation,
use_bias=use_bias,
bias_regularizer=bias_regularizer,
activity_regularizer=activity_regularizer,
bias_constraint=bias_constraint,
**kwargs)
self.depth_multiplier = depth_multiplier
self.depthwise_initializer = initializers.get(depthwise_initializer)
self.depthwise_regularizer = regularizers.get(depthwise_regularizer)
self.depthwise_constraint = constraints.get(depthwise_constraint)
self.bias_initializer = initializers.get(bias_initializer)
def build(self, input_shape):
if len(input_shape) < 4:
raise ValueError('Inputs to `DepthwiseConv2D` should have rank 4. '
'Received input shape:', str(input_shape))
if self.data_format == 'channels_first':
channel_axis = 1
else:
channel_axis = 3
if input_shape[channel_axis] is None:
raise ValueError('The channel dimension of the inputs to '
'`DepthwiseConv2D` '
'should be defined. Found `None`.')
input_dim = int(input_shape[channel_axis])
depthwise_kernel_shape = (self.kernel_size[0],
self.kernel_size[1],
input_dim,
self.depth_multiplier)
self.depthwise_kernel = self.add_weight(
shape=depthwise_kernel_shape,
initializer=self.depthwise_initializer,
name='depthwise_kernel',
regularizer=self.depthwise_regularizer,
constraint=self.depthwise_constraint)
if self.use_bias:
self.bias = self.add_weight(shape=(input_dim * self.depth_multiplier,),
initializer=self.bias_initializer,
name='bias',
regularizer=self.bias_regularizer,
constraint=self.bias_constraint)
else:
self.bias = None
# Set input spec.
self.input_spec = InputSpec(ndim=4, axes={channel_axis: input_dim})
self.built = True
def call(self, inputs, training=None):
outputs = K.depthwise_conv2d(
inputs,
self.depthwise_kernel,
strides=self.strides,
padding=self.padding,
dilation_rate=self.dilation_rate,
data_format=self.data_format)
if self.bias:
outputs = K.bias_add(
outputs,
self.bias,
data_format=self.data_format)
if self.activation is not None:
return self.activation(outputs)
return outputs
def compute_output_shape(self, input_shape):
if self.data_format == 'channels_first':
rows = input_shape[2]
cols = input_shape[3]
out_filters = input_shape[1] * self.depth_multiplier
elif self.data_format == 'channels_last':
rows = input_shape[1]
cols = input_shape[2]
out_filters = input_shape[3] * self.depth_multiplier
rows = conv_utils.conv_output_length(rows, self.kernel_size[0],
self.padding,
self.strides[0])
cols = conv_utils.conv_output_length(cols, self.kernel_size[1],
self.padding,
self.strides[1])
if self.data_format == 'channels_first':
return (input_shape[0], out_filters, rows, cols)
elif self.data_format == 'channels_last':
return (input_shape[0], rows, cols, out_filters)
def get_config(self):
config = super(DepthwiseConv2D, self).get_config()
config.pop('filters')
config.pop('kernel_initializer')
config.pop('kernel_regularizer')
config.pop('kernel_constraint')
config['depth_multiplier'] = self.depth_multiplier
config['depthwise_initializer'] = initializers.serialize(self.depthwise_initializer)
config['depthwise_regularizer'] = regularizers.serialize(self.depthwise_regularizer)
config['depthwise_constraint'] = constraints.serialize(self.depthwise_constraint)
return config
def MobileNet(input_shape=None,
alpha=1.0,
depth_multiplier=1,
dropout=1e-3,
include_top=True,
weights='imagenet',
input_tensor=None,
pooling=None,
classes=1000):
"""Instantiates the MobileNet architecture.
Note that only TensorFlow is supported for now,
therefore it only works with the data format
`image_data_format='channels_last'` in your Keras config
at `~/.keras/keras.json`.
To load a MobileNet model via `load_model`, import the custom
objects `relu6` and `DepthwiseConv2D` and pass them to the
`custom_objects` parameter.
E.g.
model = load_model('mobilenet.h5', custom_objects={
'relu6': mobilenet.relu6,
'DepthwiseConv2D': mobilenet.DepthwiseConv2D})
# Arguments
input_shape: optional shape tuple, only to be specified
if `include_top` is False (otherwise the input shape
has to be `(224, 224, 3)` (with `channels_last` data format)
or (3, 224, 224) (with `channels_first` data format).
It should have exactly 3 inputs channels,
and width and height should be no smaller than 32.
E.g. `(200, 200, 3)` would be one valid value.
alpha: controls the width of the network.
- If `alpha` < 1.0, proportionally decreases the number
of filters in each layer.
- If `alpha` > 1.0, proportionally increases the number
of filters in each layer.
- If `alpha` = 1, default number of filters from the paper
are used at each layer.
depth_multiplier: depth multiplier for depthwise convolution
(also called the resolution multiplier)
dropout: dropout rate
include_top: whether to include the fully-connected
layer at the top of the network.
weights: `None` (random initialization) or
`imagenet` (ImageNet weights)
input_tensor: optional Keras tensor (i.e. output of
`layers.Input()`)
to use as image input for the model.
pooling: Optional pooling mode for feature extraction
when `include_top` is `False`.
- `None` means that the output of the model
will be the 4D tensor output of the
last convolutional layer.
- `avg` means that global average pooling
will be applied to the output of the
last convolutional layer, and thus
the output of the model will be a
2D tensor.
- `max` means that global max pooling will
be applied.
classes: optional number of classes to classify images
into, only to be specified if `include_top` is True, and
if no `weights` argument is specified.
# Returns
A Keras model instance.
# Raises
ValueError: in case of invalid argument for `weights`,
or invalid input shape.
RuntimeError: If attempting to run this model with a
backend that does not support separable convolutions.
"""
if K.backend() != 'tensorflow':
raise RuntimeError('Only Tensorflow backend is currently supported, '
'as other backends do not support '
'depthwise convolution.')
if weights not in {'imagenet', None}:
raise ValueError('The `weights` argument should be either '
'`None` (random initialization) or `imagenet` '
'(pre-training on ImageNet).')
if weights == 'imagenet' and include_top and classes != 1000:
raise ValueError('If using `weights` as ImageNet with `include_top` '
'as true, `classes` should be 1000')
# Determine proper input shape.
input_shape = _obtain_input_shape(input_shape,
default_size=224,
min_size=32,
data_format=K.image_data_format(),
include_top=include_top or weights)
if K.image_data_format() == 'channels_last':
row_axis, col_axis = (0, 1)
else:
row_axis, col_axis = (1, 2)
rows = input_shape[row_axis]
cols = input_shape[col_axis]
if weights == 'imagenet':
if depth_multiplier != 1:
raise ValueError('If imagenet weights are being loaded, '
'depth multiplier must be 1')
if alpha not in [0.25, 0.50, 0.75, 1.0]:
raise ValueError('If imagenet weights are being loaded, '
'alpha can be one of'
'`0.25`, `0.50`, `0.75` or `1.0` only.')
if rows != cols or rows not in [128, 160, 192, 224]:
raise ValueError('If imagenet weights are being loaded, '
'input must have a static square shape (one of '
'(128,128), (160,160), (192,192), or (224, 224)).'
' Input shape provided = %s' % (input_shape,))
if K.image_data_format() != 'channels_last':
warnings.warn('The MobileNet family of models is only available '
'for the input data format "channels_last" '
'(width, height, channels). '
'However your settings specify the default '
'data format "channels_first" (channels, width, height).'
' You should set `image_data_format="channels_last"` '
'in your Keras config located at ~/.keras/keras.json. '
'The model being returned right now will expect inputs '
'to follow the "channels_last" data format.')
K.set_image_data_format('channels_last')
old_data_format = 'channels_first'
else:
old_data_format = None
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
x = _conv_block(img_input, 32, alpha, strides=(2, 2))
x = _depthwise_conv_block(x, 64, alpha, depth_multiplier, block_id=1)
x = _depthwise_conv_block(x, 128, alpha, depth_multiplier,
strides=(2, 2), block_id=2)
x = _depthwise_conv_block(x, 128, alpha, depth_multiplier, block_id=3)
x = _depthwise_conv_block(x, 256, alpha, depth_multiplier,
strides=(2, 2), block_id=4)
x = _depthwise_conv_block(x, 256, alpha, depth_multiplier, block_id=5)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier,
strides=(2, 2), block_id=6)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=7)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=8)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=9)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=10)
x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=11)
x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier,
strides=(2, 2), block_id=12)
x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier, block_id=13)
if include_top:
if K.image_data_format() == 'channels_first':
shape = (int(1024 * alpha), 1, 1)
else:
shape = (1, 1, int(1024 * alpha))
x = GlobalAveragePooling2D()(x)
x = Reshape(shape, name='reshape_1')(x)
x = Dropout(dropout, name='dropout')(x)
x = Conv2D(classes, (1, 1),
padding='same', name='conv_preds')(x)
x = Activation('softmax', name='act_softmax')(x)
x = Reshape((classes,), name='reshape_2')(x)
else:
if pooling == 'avg':
x = GlobalAveragePooling2D()(x)
elif pooling == 'max':
x = GlobalMaxPooling2D()(x)
# Ensure that the model takes into account
# any potential predecessors of `input_tensor`.
if input_tensor is not None:
inputs = get_source_inputs(input_tensor)
else:
inputs = img_input
# Create model.
model = Model(inputs, x, name='mobilenet_%0.2f_%s' % (alpha, rows))
# load weights
if weights == 'imagenet':
if K.image_data_format() == 'channels_first':
raise ValueError('Weights for "channels_last" format '
'are not available.')
if alpha == 1.0:
alpha_text = '1_0'
elif alpha == 0.75:
alpha_text = '7_5'
elif alpha == 0.50:
alpha_text = '5_0'
else:
alpha_text = '2_5'
if include_top:
model_name = 'mobilenet_%s_%d_tf.h5' % (alpha_text, rows)
weigh_path = BASE_WEIGHT_PATH + model_name
weights_path = get_file(model_name,
weigh_path,
cache_subdir='models')
else:
model_name = 'mobilenet_%s_%d_tf_no_top.h5' % (alpha_text, rows)
weigh_path = BASE_WEIGHT_PATH + model_name
weights_path = get_file(model_name,
weigh_path,
cache_subdir='models')
model.load_weights(weights_path)
if old_data_format:
K.set_image_data_format(old_data_format)
return model
def _conv_block(inputs, filters, alpha, kernel=(3, 3), strides=(1, 1)):
"""Adds an initial convolution layer (with batch normalization and relu6).
# Arguments
inputs: Input tensor of shape `(rows, cols, 3)`
(with `channels_last` data format) or
(3, rows, cols) (with `channels_first` data format).
It should have exactly 3 inputs channels,
and width and height should be no smaller than 32.
E.g. `(224, 224, 3)` would be one valid value.
filters: Integer, the dimensionality of the output space
(i.e. the number output of filters in the convolution).
alpha: controls the width of the network.
- If `alpha` < 1.0, proportionally decreases the number
of filters in each layer.
- If `alpha` > 1.0, proportionally increases the number
of filters in each layer.
- If `alpha` = 1, default number of filters from the paper
are used at each layer.
kernel: An integer or tuple/list of 2 integers, specifying the
width and height of the 2D convolution window.
Can be a single integer to specify the same value for
all spatial dimensions.
strides: An integer or tuple/list of 2 integers,
specifying the strides of the convolution along the width and height.
Can be a single integer to specify the same value for
all spatial dimensions.
Specifying any stride value != 1 is incompatible with specifying
any `dilation_rate` value != 1.
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if data_format='channels_first'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if data_format='channels_last'.
# Output shape
4D tensor with shape:
`(samples, filters, new_rows, new_cols)` if data_format='channels_first'
or 4D tensor with shape:
`(samples, new_rows, new_cols, filters)` if data_format='channels_last'.
`rows` and `cols` values might have changed due to stride.
# Returns
Output tensor of block.
"""
channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
filters = int(filters * alpha)
x = Conv2D(filters, kernel,
padding='same',
use_bias=False,
strides=strides,
name='conv1')(inputs)
x = BatchNormalization(axis=channel_axis, name='conv1_bn')(x)
return Activation(relu6, name='conv1_relu')(x)
def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha,
depth_multiplier=1, strides=(1, 1), block_id=1):
"""Adds a depthwise convolution block.
A depthwise convolution block consists of a depthwise conv,
batch normalization, relu6, pointwise convolution,
batch normalization and relu6 activation.
# Arguments
inputs: Input tensor of shape `(rows, cols, channels)`
(with `channels_last` data format) or
(channels, rows, cols) (with `channels_first` data format).
pointwise_conv_filters: Integer, the dimensionality of the output space
(i.e. the number output of filters in the pointwise convolution).
alpha: controls the width of the network.
- If `alpha` < 1.0, proportionally decreases the number
of filters in each layer.
- If `alpha` > 1.0, proportionally increases the number
of filters in each layer.
- If `alpha` = 1, default number of filters from the paper
are used at each layer.
depth_multiplier: The number of depthwise convolution output channels
for each input channel.
The total number of depthwise convolution output
channels will be equal to `filters_in * depth_multiplier`.
strides: An integer or tuple/list of 2 integers,
specifying the strides of the convolution along the width and height.
Can be a single integer to specify the same value for
all spatial dimensions.
Specifying any stride value != 1 is incompatible with specifying
any `dilation_rate` value != 1.
block_id: Integer, a unique identification designating the block number.
# Input shape
4D tensor with shape:
`(batch, channels, rows, cols)` if data_format='channels_first'
or 4D tensor with shape:
`(batch, rows, cols, channels)` if data_format='channels_last'.
# Output shape
4D tensor with shape:
`(batch, filters, new_rows, new_cols)` if data_format='channels_first'
or 4D tensor with shape:
`(batch, new_rows, new_cols, filters)` if data_format='channels_last'.
`rows` and `cols` values might have changed due to stride.
# Returns
Output tensor of block.
"""
channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
pointwise_conv_filters = int(pointwise_conv_filters * alpha)
x = DepthwiseConv2D((3, 3),
padding='same',
depth_multiplier=depth_multiplier,
strides=strides,
use_bias=False,
name='conv_dw_%d' % block_id)(inputs)
x = BatchNormalization(axis=channel_axis, name='conv_dw_%d_bn' % block_id)(x)
x = Activation(relu6, name='conv_dw_%d_relu' % block_id)(x)
x = Conv2D(pointwise_conv_filters, (1, 1),
padding='same',
use_bias=False,
strides=(1, 1),
name='conv_pw_%d' % block_id)(x)
x = BatchNormalization(axis=channel_axis, name='conv_pw_%d_bn' % block_id)(x)
return Activation(relu6, name='conv_pw_%d_relu' % block_id)(x)
+20 -20
Ver Arquivo
@@ -7,31 +7,32 @@
Adapted from code contributed by BigMoyan.
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
from ..layers import Input
from .. import backend as K
from .. import layers
from ..layers import Dense
from ..engine.topology import get_source_inputs
from .imagenet_utils import _obtain_input_shape
from .imagenet_utils import decode_predictions # pylint: disable=unused-import
from .imagenet_utils import preprocess_input # pylint: disable=unused-import
from ..layers import Activation
from ..layers import Flatten
from ..layers import Conv2D
from ..layers import MaxPooling2D
from ..layers import ZeroPadding2D
from ..layers import AveragePooling2D
from ..layers import BatchNormalization
from ..layers import Conv2D
from ..layers import Dense
from ..layers import Flatten
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..layers import BatchNormalization
from ..layers import Input
from ..layers import MaxPooling2D
from ..layers import ZeroPadding2D
from ..models import Model
from .. import backend as K
from ..engine.topology import get_source_inputs
from ..utils import layer_utils
from ..utils.data_utils import get_file
from .imagenet_utils import decode_predictions
from .imagenet_utils import preprocess_input
from .imagenet_utils import _obtain_input_shape
WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5'
@@ -43,7 +44,7 @@ def identity_block(input_tensor, kernel_size, filters, stage, block):
# Arguments
input_tensor: input tensor
kernel_size: default 3, the kernel size of middle conv layer at main path
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the filterss of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
@@ -77,14 +78,15 @@ def identity_block(input_tensor, kernel_size, filters, stage, block):
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
"""A block that has a conv layer at shortcut.
"""conv_block is the block that has a conv layer at shortcut.
# Arguments
input_tensor: input tensor
kernel_size: default 3, the kernel size of middle conv layer at main path
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the filterss of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
strides: Tuple of integers.
# Returns
Output tensor for the block.
@@ -194,10 +196,8 @@ def ResNet50(include_top=True, weights='imagenet',
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
img_input = Input(tensor=input_tensor, shape=input_shape)
if K.image_data_format() == 'channels_last':
bn_axis = 3
else:
+14 -15
Ver Arquivo
@@ -6,26 +6,27 @@
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556)
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
from ..models import Model
from ..layers import Flatten
from ..layers import Dense
from ..layers import Input
from .. import backend as K
from ..engine.topology import get_source_inputs
from .imagenet_utils import _obtain_input_shape
from .imagenet_utils import decode_predictions # pylint: disable=unused-import
from .imagenet_utils import preprocess_input # pylint: disable=unused-import
from ..layers import Conv2D
from ..layers import MaxPooling2D
from ..layers import Dense
from ..layers import Flatten
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..engine.topology import get_source_inputs
from ..layers import Input
from ..layers import MaxPooling2D
from ..models import Model
from ..utils import layer_utils
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
from .imagenet_utils import preprocess_input
from .imagenet_utils import _obtain_input_shape
WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
@@ -103,10 +104,8 @@ def VGG16(include_top=True, weights='imagenet',
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
img_input = Input(tensor=input_tensor, shape=input_shape)
# Block 1
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
+14 -15
Ver Arquivo
@@ -6,26 +6,27 @@
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556)
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
from ..models import Model
from ..layers import Flatten
from ..layers import Dense
from ..layers import Input
from .. import backend as K
from ..engine.topology import get_source_inputs
from .imagenet_utils import _obtain_input_shape
from .imagenet_utils import decode_predictions # pylint: disable=unused-import
from .imagenet_utils import preprocess_input # pylint: disable=unused-import
from ..layers import Conv2D
from ..layers import MaxPooling2D
from ..layers import Dense
from ..layers import Flatten
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..engine.topology import get_source_inputs
from ..layers import Input
from ..layers import MaxPooling2D
from ..models import Model
from ..utils import layer_utils
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
from .imagenet_utils import preprocess_input
from .imagenet_utils import _obtain_input_shape
WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels.h5'
@@ -103,10 +104,8 @@ def VGG19(include_top=True, weights='imagenet',
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
img_input = Input(tensor=input_tensor, shape=input_shape)
# Block 1
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
+13 -15
Ver Arquivo
@@ -17,27 +17,28 @@ due to its reliance on `SeparableConvolution` layers.
- [Xception: Deep Learning with Depthwise Separable Convolutions](https://arxiv.org/abs/1610.02357)
"""
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
from ..models import Model
from .. import backend as K
from .. import layers
from ..layers import Dense
from ..layers import Input
from ..layers import BatchNormalization
from ..engine.topology import get_source_inputs
from .imagenet_utils import _obtain_input_shape
from .imagenet_utils import decode_predictions # pylint: disable=unused-import
from ..layers import Activation
from ..layers import BatchNormalization
from ..layers import Conv2D
from ..layers import SeparableConv2D
from ..layers import MaxPooling2D
from ..layers import Dense
from ..layers import GlobalAveragePooling2D
from ..layers import GlobalMaxPooling2D
from ..engine.topology import get_source_inputs
from ..layers import Input
from ..layers import MaxPooling2D
from ..layers import SeparableConv2D
from ..models import Model
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
from .imagenet_utils import _obtain_input_shape
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.4/xception_weights_tf_dim_ordering_tf_kernels.h5'
@@ -133,10 +134,7 @@ def Xception(include_top=True, weights='imagenet',
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
img_input = Input(tensor=input_tensor, shape=input_shape)
x = Conv2D(32, (3, 3), strides=(2, 2), use_bias=False, name='block1_conv1')(img_input)
x = BatchNormalization(name='block1_conv1_bn')(x)
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
-101
Ver Arquivo
@@ -1,101 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
import os
import json
import sys
from .common import epsilon
from .common import floatx
from .common import set_epsilon
from .common import set_floatx
from .common import cast_to_floatx
from .common import image_data_format
from .common import set_image_data_format
# Obtain Keras base dir path: either ~/.keras or /tmp.
_keras_base_dir = os.path.expanduser('~')
if not os.access(_keras_base_dir, os.W_OK):
_keras_base_dir = '/tmp'
_keras_dir = os.path.join(_keras_base_dir, '.keras')
# Default backend: TensorFlow.
_BACKEND = 'tensorflow'
# Attempt to read Keras config file.
_config_path = os.path.expanduser(os.path.join(_keras_dir, 'keras.json'))
if os.path.exists(_config_path):
try:
_config = json.load(open(_config_path))
except ValueError:
_config = {}
_floatx = _config.get('floatx', floatx())
assert _floatx in {'float16', 'float32', 'float64'}
_epsilon = _config.get('epsilon', epsilon())
assert isinstance(_epsilon, float)
_backend = _config.get('backend', _BACKEND)
assert _backend in {'theano', 'tensorflow', 'cntk'}
_image_data_format = _config.get('image_data_format',
image_data_format())
assert _image_data_format in {'channels_last', 'channels_first'}
set_floatx(_floatx)
set_epsilon(_epsilon)
set_image_data_format(_image_data_format)
_BACKEND = _backend
# Save config file, if possible.
if not os.path.exists(_keras_dir):
try:
os.makedirs(_keras_dir)
except OSError:
# Except permission denied and potential race conditions
# in multi-threaded environments.
pass
if not os.path.exists(_config_path):
_config = {
'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND,
'image_data_format': image_data_format()
}
try:
with open(_config_path, 'w') as f:
f.write(json.dumps(_config, indent=4))
except IOError:
# Except permission denied.
pass
# Set backend based on KERAS_BACKEND flag, if applicable.
if 'KERAS_BACKEND' in os.environ:
_backend = os.environ['KERAS_BACKEND']
assert _backend in {'theano', 'tensorflow', 'cntk'}
_BACKEND = _backend
# Import backend functions.
if _BACKEND == 'cntk':
sys.stderr.write('Using CNTK backend\n')
from .cntk_backend import *
elif _BACKEND == 'theano':
sys.stderr.write('Using Theano backend.\n')
from .theano_backend import *
elif _BACKEND == 'tensorflow':
sys.stderr.write('Using TensorFlow backend.\n')
from .tensorflow_backend import *
else:
raise ValueError('Unknown backend: ' + str(_BACKEND))
def backend():
"""Publicly accessible method
for determining the current backend.
# Returns
String, the name of the backend Keras is currently using.
# Example
```python
>>> keras.backend.backend()
'tensorflow'
```
"""
return _BACKEND
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
-188
Ver Arquivo
@@ -1,188 +0,0 @@
import numpy as np
# the type of float to use throughout the session.
_FLOATX = 'float32'
_EPSILON = 10e-8
_IMAGE_DATA_FORMAT = 'channels_last'
def epsilon():
"""Returns the value of the fuzz
factor used in numeric expressions.
# Returns
A float.
# Example
```python
>>> keras.backend.epsilon()
1e-08
```
"""
return _EPSILON
def set_epsilon(e):
"""Sets the value of the fuzz
factor used in numeric expressions.
# Arguments
e: float. New value of epsilon.
# Example
```python
>>> from keras import backend as K
>>> K.epsilon()
1e-08
>>> K.set_epsilon(1e-05)
>>> K.epsilon()
1e-05
```
"""
global _EPSILON
_EPSILON = e
def floatx():
"""Returns the default float type, as a string.
(e.g. 'float16', 'float32', 'float64').
# Returns
String, the current default float type.
# Example
```python
>>> keras.backend.floatx()
'float32'
```
"""
return _FLOATX
def set_floatx(floatx):
"""Sets the default float type.
# Arguments
floatx: String, 'float16', 'float32', or 'float64'.
# Example
```python
>>> from keras import backend as K
>>> K.floatx()
'float32'
>>> K.set_floatx('float16')
>>> K.floatx()
'float16'
```
"""
global _FLOATX
if floatx not in {'float16', 'float32', 'float64'}:
raise ValueError('Unknown floatx type: ' + str(floatx))
_FLOATX = str(floatx)
def cast_to_floatx(x):
"""Cast a Numpy array to the default Keras float type.
# Arguments
x: Numpy array.
# Returns
The same Numpy array, cast to its new type.
# Example
```python
>>> from keras import backend as K
>>> K.floatx()
'float32'
>>> arr = numpy.array([1.0, 2.0], dtype='float64')
>>> arr.dtype
dtype('float64')
>>> new_arr = K.cast_to_floatx(arr)
>>> new_arr
array([ 1., 2.], dtype=float32)
>>> new_arr.dtype
dtype('float32')
```
"""
return np.asarray(x, dtype=_FLOATX)
def image_data_format():
"""Returns the default image data format convention ('channels_first' or 'channels_last').
# Returns
A string, either `'channels_first'` or `'channels_last'`
# Example
```python
>>> keras.backend.image_data_format()
'channels_first'
```
"""
return _IMAGE_DATA_FORMAT
def set_image_data_format(data_format):
"""Sets the value of the data format convention.
# Arguments
data_format: string. `'channels_first'` or `'channels_last'`.
# Example
```python
>>> from keras import backend as K
>>> K.image_data_format()
'channels_first'
>>> K.set_image_data_format('channels_last')
>>> K.image_data_format()
'channels_last'
```
"""
global _IMAGE_DATA_FORMAT
if data_format not in {'channels_last', 'channels_first'}:
raise ValueError('Unknown data_format:', data_format)
_IMAGE_DATA_FORMAT = str(data_format)
# Legacy methods
def set_image_dim_ordering(dim_ordering):
"""Legacy setter for `image_data_format`.
# Arguments
dim_ordering: string. `tf` or `th`.
# Example
```python
>>> from keras import backend as K
>>> K.image_data_format()
'channels_first'
>>> K.set_image_data_format('channels_last')
>>> K.image_data_format()
'channels_last'
```
# Raises
ValueError: if `dim_ordering` is invalid.
"""
global _IMAGE_DATA_FORMAT
if dim_ordering not in {'tf', 'th'}:
raise ValueError('Unknown dim_ordering:', dim_ordering)
if dim_ordering == 'th':
data_format = 'channels_first'
else:
data_format = 'channels_last'
_IMAGE_DATA_FORMAT = data_format
def image_dim_ordering():
"""Legacy getter for `image_data_format`.
# Returns
string, one of `'th'`, `'tf'`
"""
if _IMAGE_DATA_FORMAT == 'channels_first':
return 'th'
else:
return 'tf'
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+59 -67
Ver Arquivo
@@ -1,29 +1,33 @@
"""Keras callbacks: utilities called at certain points during model training.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
from collections import deque
from collections import Iterable
from collections import OrderedDict
import csv
import six
import numpy as np
import time
import json
import os
import time
import warnings
from collections import deque
from collections import OrderedDict
from collections import Iterable
from .utils.generic_utils import Progbar
from . import backend as K
import numpy as np
from tensorflow.python.summary import summary as tf_summary
from tensorflow.contrib.tensorboard.plugins import projector
from tensorflow.python.training import saver as saver_lib
from tensorflow.python.ops import array_ops
from .utils.generic_utils import Progbar
# pylint: disable=g-import-not-at-top
try:
import requests
except ImportError:
requests = None
if K.backend() == 'tensorflow':
import tensorflow as tf
from tensorflow.contrib.tensorboard.plugins import projector
# pylint: enable=g-import-not-at-top
class CallbackList(object):
@@ -490,11 +494,8 @@ class EarlyStopping(Callback):
def on_epoch_end(self, epoch, logs=None):
current = logs.get(self.monitor)
if current is None:
warnings.warn(
'Early stopping conditioned on metric `%s` '
'which is not available. Available metrics are: %s' %
(self.monitor, ','.join(list(logs.keys()))), RuntimeWarning
)
warnings.warn('Early stopping requires %s available!' %
(self.monitor), RuntimeWarning)
if self.monitor_op(current - self.min_delta, self.best):
self.best = current
@@ -523,6 +524,8 @@ class RemoteMonitor(Callback):
path: String; path relative to `root` to which the events will be sent.
field: String; JSON field under which the data will be stored.
headers: Dictionary; optional custom HTTP headers.
Defaults to:
`{'Accept': 'application/json', 'Content-Type': 'application/json'}`
"""
def __init__(self,
@@ -531,7 +534,9 @@ class RemoteMonitor(Callback):
field='data',
headers=None):
super(RemoteMonitor, self).__init__()
if headers is None:
headers = {'Accept': 'application/json',
'Content-Type': 'application/json'}
self.root = root
self.path = path
self.field = field
@@ -579,21 +584,23 @@ class LearningRateScheduler(Callback):
class TensorBoard(Callback):
# pylint: disable=line-too-long
"""Tensorboard basic visualizations.
[TensorBoard](https://www.tensorflow.org/get_started/summaries_and_tensorboard)
is a visualization tool provided with TensorFlow.
This callback writes a log for TensorBoard, which allows
you to visualize dynamic graphs of your training and test
metrics, as well as activation histograms for the different
layers in your model.
TensorBoard is a visualization tool provided with TensorFlow.
If you have installed TensorFlow with pip, you should be able
to launch TensorBoard from the command line:
```
tensorboard --logdir=/full_path_to_your_logs
```
You can find more information about TensorBoard
[here](https://www.tensorflow.org/get_started/summaries_and_tensorboard).
# Arguments
log_dir: the path of the directory where to save the log
@@ -621,6 +628,7 @@ class TensorBoard(Callback):
about metadata files format. In case if the same metadata file is
used for all embedding layers, string can be passed.
"""
# pylint: enable=line-too-long
def __init__(self, log_dir='./logs',
histogram_freq=0,
@@ -632,9 +640,6 @@ class TensorBoard(Callback):
embeddings_layer_names=None,
embeddings_metadata=None):
super(TensorBoard, self).__init__()
if K.backend() != 'tensorflow':
raise RuntimeError('TensorBoard callback only works '
'with the TensorFlow backend.')
self.log_dir = log_dir
self.histogram_freq = histogram_freq
self.merged = None
@@ -651,58 +656,52 @@ class TensorBoard(Callback):
self.sess = K.get_session()
if self.histogram_freq and self.merged is None:
for layer in self.model.layers:
for weight in layer.weights:
mapped_weight_name = weight.name.replace(':', '_')
tf.summary.histogram(mapped_weight_name, weight)
tf_summary.histogram(weight.name, weight)
if self.write_grads:
grads = model.optimizer.get_gradients(model.total_loss,
weight)
tf.summary.histogram('{}_grad'.format(mapped_weight_name), grads)
tf_summary.histogram('{}_grad'.format(weight.name), grads)
if self.write_images:
w_img = tf.squeeze(weight)
w_img = array_ops.squeeze(weight)
shape = K.int_shape(w_img)
if len(shape) == 2: # dense layer kernel case
if shape[0] > shape[1]:
w_img = tf.transpose(w_img)
w_img = array_ops.transpose(w_img)
shape = K.int_shape(w_img)
w_img = tf.reshape(w_img, [1,
shape[0],
shape[1],
1])
w_img = array_ops.reshape(w_img, [1,
shape[0],
shape[1],
1])
elif len(shape) == 3: # convnet case
if K.image_data_format() == 'channels_last':
# switch to channels_first to display
# every kernel as a separate image
w_img = tf.transpose(w_img, perm=[2, 0, 1])
w_img = array_ops.transpose(w_img, perm=[2, 0, 1])
shape = K.int_shape(w_img)
w_img = tf.reshape(w_img, [shape[0],
shape[1],
shape[2],
1])
w_img = array_ops.reshape(
w_img, [shape[0], shape[1], shape[2], 1])
elif len(shape) == 1: # bias case
w_img = tf.reshape(w_img, [1,
shape[0],
1,
1])
w_img = array_ops.reshape(
w_img, [1, shape[0], 1, 1])
else:
# not possible to handle 3D convnets etc.
continue
shape = K.int_shape(w_img)
assert len(shape) == 4 and shape[-1] in [1, 3, 4]
tf.summary.image(mapped_weight_name, w_img)
tf_summary.image(weight.name, w_img)
if hasattr(layer, 'output'):
tf.summary.histogram('{}_out'.format(layer.name),
tf_summary.histogram('{}_out'.format(layer.name),
layer.output)
self.merged = tf.summary.merge_all()
self.merged = tf_summary.merge_all()
if self.write_graph:
self.writer = tf.summary.FileWriter(self.log_dir,
self.writer = tf_summary.FileWriter(self.log_dir,
self.sess.graph)
else:
self.writer = tf.summary.FileWriter(self.log_dir)
self.writer = tf_summary.FileWriter(self.log_dir)
if self.embeddings_freq:
embeddings_layer_names = self.embeddings_layer_names
@@ -715,7 +714,7 @@ class TensorBoard(Callback):
for layer in self.model.layers
if layer.name in embeddings_layer_names}
self.saver = tf.train.Saver(list(embeddings.values()))
self.saver = saver_lib.Saver(list(embeddings.values()))
embeddings_metadata = {}
@@ -778,7 +777,7 @@ class TensorBoard(Callback):
for name, value in logs.items():
if name in ['batch', 'size']:
continue
summary = tf.Summary()
summary = tf_summary.Summary()
summary_value = summary.value.add()
summary_value.simple_value = value.item()
summary_value.tag = name
@@ -873,12 +872,8 @@ class ReduceLROnPlateau(Callback):
logs['lr'] = K.get_value(self.model.optimizer.lr)
current = logs.get(self.monitor)
if current is None:
warnings.warn(
'Reduce LR on plateau conditioned on metric `%s` '
'which is not available. Available metrics are: %s' %
(self.monitor, ','.join(list(logs.keys()))), RuntimeWarning
)
warnings.warn('Learning Rate Plateau Reducing requires %s available!' %
self.monitor, RuntimeWarning)
else:
if self.in_cooldown():
self.cooldown_counter -= 1
@@ -976,7 +971,7 @@ class CSVLogger(Callback):
class LambdaCallback(Callback):
r"""Callback for creating simple, custom callbacks on-the-fly.
"""Callback for creating simple, custom callbacks on-the-fly.
This callback is constructed with anonymous functions that will be called
at the appropriate time. Note that the callbacks expects positional
@@ -1003,15 +998,12 @@ class LambdaCallback(Callback):
batch_print_callback = LambdaCallback(
on_batch_begin=lambda batch,logs: print(batch))
# Stream the epoch loss to a file in JSON format. The file content
# is not well-formed JSON but rather has a JSON object per line.
import json
json_log = open('loss_log.json', mode='wt', buffering=1)
json_logging_callback = LambdaCallback(
on_epoch_end=lambda epoch, logs: json_log.write(
json.dumps({'epoch': epoch, 'loss': logs['loss']}) + '\n'),
on_train_end=lambda logs: json_log.close()
)
# Plot the loss after every epoch.
import numpy as np
import matplotlib.pyplot as plt
plot_loss_callback = LambdaCallback(
on_epoch_end=lambda epoch, logs: plt.plot(np.arange(epoch),
logs['loss']))
# Terminate some processes after having finished model training.
processes = ...
@@ -1021,7 +1013,7 @@ class LambdaCallback(Callback):
model.fit(...,
callbacks=[batch_print_callback,
json_logging_callback,
plot_loss_callback,
cleanup_callback])
```
"""
+13 -12
Ver Arquivo
@@ -1,8 +1,13 @@
"""Constraints: functions that impose constraints on weights values.
"""
from __future__ import absolute_import
import six
from __future__ import division
from __future__ import print_function
from . import backend as K
from .utils.generic_utils import serialize_keras_object
import six
from .utils.generic_utils import deserialize_keras_object
from .utils.generic_utils import serialize_keras_object
class Constraint(object):
@@ -27,7 +32,7 @@ class MaxNorm(Constraint):
has shape `(input_dim, output_dim)`,
set `axis` to `0` to constrain each weight vector
of length `(input_dim,)`.
In a `Conv2D` layer with `data_format="channels_last"`,
In a `Convolution2D` layer with `data_format="channels_last"`,
the weight tensor has shape
`(rows, cols, input_depth, output_depth)`,
set `axis` to `[0, 1, 2]`
@@ -58,7 +63,7 @@ class NonNeg(Constraint):
"""
def __call__(self, w):
w *= K.cast(K.greater_equal(w, 0.), K.floatx())
w *= K.cast(w >= 0., K.floatx())
return w
@@ -71,7 +76,7 @@ class UnitNorm(Constraint):
has shape `(input_dim, output_dim)`,
set `axis` to `0` to constrain each weight vector
of length `(input_dim,)`.
In a `Conv2D` layer with `data_format="channels_last"`,
In a `Convolution2D` layer with `data_format="channels_last"`,
the weight tensor has shape
`(rows, cols, input_depth, output_depth)`,
set `axis` to `[0, 1, 2]`
@@ -112,7 +117,7 @@ class MinMaxNorm(Constraint):
has shape `(input_dim, output_dim)`,
set `axis` to `0` to constrain each weight vector
of length `(input_dim,)`.
In a `Conv2D` layer with `data_format="channels_last"`,
In a `Convolution2D` layer with `dim_ordering="tf"`,
the weight tensor has shape
`(rows, cols, input_depth, output_depth)`,
set `axis` to `[0, 1, 2]`
@@ -142,16 +147,12 @@ class MinMaxNorm(Constraint):
# Aliases.
# pylint: disable=invalid-name
max_norm = MaxNorm
non_neg = NonNeg
unit_norm = UnitNorm
min_max_norm = MinMaxNorm
# Legacy aliases.
maxnorm = max_norm
nonneg = non_neg
unitnorm = unit_norm
# pylint: enable=invalid-name
def serialize(constraint):
+9 -4
Ver Arquivo
@@ -1,8 +1,13 @@
"""Keras datasets: utilities for downloading and pre-processing common datasets.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from . import mnist
from . import imdb
from . import reuters
from . import boston_housing
from . import cifar10
from . import cifar100
from . import boston_housing
from . import imdb
from . import mnist
from . import reuters
+8 -4
Ver Arquivo
@@ -1,5 +1,11 @@
from ..utils.data_utils import get_file
"""Boston housing price regression dataset.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
from ..utils.data_utils import get_file
def load_data(path='boston_housing.npz', seed=113, test_split=0.2):
@@ -16,9 +22,7 @@ def load_data(path='boston_housing.npz', seed=113, test_split=0.2):
Tuple of Numpy arrays: `(x_train, y_train), (x_test, y_test)`.
"""
assert 0 <= test_split < 1
path = get_file(path,
origin='https://s3.amazonaws.com/keras-datasets/boston_housing.npz',
file_hash='f553886a1f8d56431e820c5b82552d9d95cfcb96d1e678153f8839538947dff5')
path = get_file(path, origin='https://s3.amazonaws.com/keras-datasets/boston_housing.npz')
f = np.load(path)
x = f['x']
y = f['y']
+5
Ver Arquivo
@@ -1,5 +1,10 @@
"""Utilities used by the CIFAR10 and CIFAR100 datasets.
"""
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import sys
from six.moves import cPickle
+10 -4
Ver Arquivo
@@ -1,10 +1,16 @@
"""CIFAR10 small image classification dataset.
"""
from __future__ import absolute_import
from .cifar import load_batch
from ..utils.data_utils import get_file
from .. import backend as K
import numpy as np
from __future__ import division
from __future__ import print_function
import os
from .. import backend as K
from .cifar import load_batch
import numpy as np
from ..utils.data_utils import get_file
def load_data():
"""Loads CIFAR10 dataset.
+11 -5
Ver Arquivo
@@ -1,10 +1,16 @@
"""CIFAR100 small image classification dataset.
"""
from __future__ import absolute_import
from .cifar import load_batch
from ..utils.data_utils import get_file
from .. import backend as K
import numpy as np
from __future__ import division
from __future__ import print_function
import os
from .. import backend as K
from .cifar import load_batch
import numpy as np
from ..utils.data_utils import get_file
def load_data(label_mode='fine'):
"""Loads CIFAR100 dataset.
@@ -19,7 +25,7 @@ def load_data(label_mode='fine'):
ValueError: in case of invalid `label_mode`.
"""
if label_mode not in ['fine', 'coarse']:
raise ValueError('`label_mode` must be one of `"fine"`, `"coarse"`.')
raise ValueError('label_mode must be one of "fine" "coarse".')
dirname = 'cifar-100-python'
origin = 'http://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz'
+41 -25
Ver Arquivo
@@ -1,15 +1,19 @@
"""IMDB movie review sentiment classification dataset.
"""
from __future__ import absolute_import
from ..utils.data_utils import get_file
from ..preprocessing.sequence import _remove_long_seq
from six.moves import zip
import numpy as np
from __future__ import division
from __future__ import print_function
import json
import warnings
import numpy as np
from six.moves import zip
from ..utils.data_utils import get_file
def load_data(path='imdb.npz', num_words=None, skip_top=0,
maxlen=None, seed=113,
start_char=1, oov_char=2, index_from=3, **kwargs):
start_char=1, oov_char=2, index_from=3):
"""Loads the IMDB dataset.
# Arguments
@@ -17,7 +21,7 @@ def load_data(path='imdb.npz', num_words=None, skip_top=0,
num_words: max number of words to include. Words are ranked
by how often they occur (in the training set) and only
the most frequent words are kept
skip_top: skip the top N most frequently occurring words
skip_top: skip the top N most frequently occuring words
(which may not be informative).
maxlen: truncate sequences after this length.
seed: random seed for sample shuffling.
@@ -40,18 +44,14 @@ def load_data(path='imdb.npz', num_words=None, skip_top=0,
Words that were not seen in the training set but are in the test set
have simply been skipped.
"""
# Legacy support
if 'nb_words' in kwargs:
warnings.warn('The `nb_words` argument in `load_data` '
'has been renamed `num_words`.')
num_words = kwargs.pop('nb_words')
if kwargs:
raise TypeError('Unrecognized keyword arguments: ' + str(kwargs))
path = get_file(path, origin='https://s3.amazonaws.com/text-datasets/imdb.npz')
with np.load(path) as f:
x_train, labels_train = f['x_train'], f['y_train']
x_test, labels_test = f['x_test'], f['y_test']
path = get_file(path,
origin='https://s3.amazonaws.com/text-datasets/imdb.npz')
f = np.load(path)
x_train = f['x_train']
labels_train = f['y_train']
x_test = f['x_test']
labels_test = f['y_test']
f.close()
np.random.seed(seed)
np.random.shuffle(x_train)
@@ -72,7 +72,14 @@ def load_data(path='imdb.npz', num_words=None, skip_top=0,
xs = [[w + index_from for w in x] for x in xs]
if maxlen:
xs, labels = _remove_long_seq(maxlen, xs, labels)
new_xs = []
new_labels = []
for x, y in zip(xs, labels):
if len(x) < maxlen:
new_xs.append(x)
new_labels.append(y)
xs = new_xs
labels = new_labels
if not xs:
raise ValueError('After filtering for sequences shorter than maxlen=' +
str(maxlen) + ', no sequence was kept. '
@@ -84,13 +91,22 @@ def load_data(path='imdb.npz', num_words=None, skip_top=0,
# reserve 'index_from' (=3 by default) characters:
# 0 (padding), 1 (start), 2 (OOV)
if oov_char is not None:
xs = [[w if (skip_top <= w < num_words) else oov_char for w in x] for x in xs]
xs = [[oov_char if (w >= num_words or w < skip_top) else w for w in x] for x in xs]
else:
xs = [[w for w in x if (skip_top <= w < num_words)] for x in xs]
new_xs = []
for x in xs:
nx = []
for w in x:
if skip_top <= w < num_words:
nx.append(w)
new_xs.append(nx)
xs = new_xs
idx = len(x_train)
x_train, y_train = np.array(xs[:idx]), np.array(labels[:idx])
x_test, y_test = np.array(xs[idx:]), np.array(labels[idx:])
x_train = np.array(xs[:len(x_train)])
y_train = np.array(labels[:len(x_train)])
x_test = np.array(xs[len(x_train):])
y_test = np.array(labels[len(x_train):])
return (x_train, y_train), (x_test, y_test)
+11 -3
Ver Arquivo
@@ -1,5 +1,11 @@
from ..utils.data_utils import get_file
"""MNIST handwritten digits classification dataset.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
from ..utils.data_utils import get_file
def load_data(path='mnist.npz'):
@@ -14,7 +20,9 @@ def load_data(path='mnist.npz'):
"""
path = get_file(path, origin='https://s3.amazonaws.com/img-datasets/mnist.npz')
f = np.load(path)
x_train, y_train = f['x_train'], f['y_train']
x_test, y_test = f['x_test'], f['y_test']
x_train = f['x_train']
y_train = f['y_train']
x_test = f['x_test']
y_test = f['y_test']
f.close()
return (x_train, y_train), (x_test, y_test)
+37 -23
Ver Arquivo
@@ -1,16 +1,20 @@
"""Reuters newswire topic classification dataset.
"""
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from ..utils.data_utils import get_file
from ..preprocessing.sequence import _remove_long_seq
from six.moves import zip
import numpy as np
from __future__ import division
from __future__ import print_function
import json
import warnings
import numpy as np
from six.moves import zip
from ..utils.data_utils import get_file
def load_data(path='reuters.npz', num_words=None, skip_top=0,
maxlen=None, test_split=0.2, seed=113,
start_char=1, oov_char=2, index_from=3, **kwargs):
start_char=1, oov_char=2, index_from=3):
"""Loads the Reuters newswire classification dataset.
# Arguments
@@ -18,7 +22,7 @@ def load_data(path='reuters.npz', num_words=None, skip_top=0,
num_words: max number of words to include. Words are ranked
by how often they occur (in the training set) and only
the most frequent words are kept
skip_top: skip the top N most frequently occurring words
skip_top: skip the top N most frequently occuring words
(which may not be informative).
maxlen: truncate sequences after this length.
test_split: Fraction of the dataset to be used as test data.
@@ -38,17 +42,11 @@ def load_data(path='reuters.npz', num_words=None, skip_top=0,
Words that were not seen in the training set but are in the test set
have simply been skipped.
"""
# Legacy support
if 'nb_words' in kwargs:
warnings.warn('The `nb_words` argument in `load_data` '
'has been renamed `num_words`.')
num_words = kwargs.pop('nb_words')
if kwargs:
raise TypeError('Unrecognized keyword arguments: ' + str(kwargs))
path = get_file(path, origin='https://s3.amazonaws.com/text-datasets/reuters.npz')
with np.load(path) as f:
xs, labels = f['x'], f['y']
npzfile = np.load(path)
xs = npzfile['x']
labels = npzfile['y']
npzfile.close()
np.random.seed(seed)
np.random.shuffle(xs)
@@ -61,7 +59,14 @@ def load_data(path='reuters.npz', num_words=None, skip_top=0,
xs = [[w + index_from for w in x] for x in xs]
if maxlen:
xs, labels = _remove_long_seq(maxlen, xs, labels)
new_xs = []
new_labels = []
for x, y in zip(xs, labels):
if len(x) < maxlen:
new_xs.append(x)
new_labels.append(y)
xs = new_xs
labels = new_labels
if not num_words:
num_words = max([max(x) for x in xs])
@@ -70,13 +75,22 @@ def load_data(path='reuters.npz', num_words=None, skip_top=0,
# reserve 'index_from' (=3 by default) characters:
# 0 (padding), 1 (start), 2 (OOV)
if oov_char is not None:
xs = [[w if (skip_top <= w < num_words) else oov_char for w in x] for x in xs]
xs = [[oov_char if (w >= num_words or w < skip_top) else w for w in x] for x in xs]
else:
xs = [[w for w in x if (skip_top <= w < num_words)] for x in xs]
new_xs = []
for x in xs:
nx = []
for w in x:
if skip_top <= w < num_words:
nx.append(w)
new_xs.append(nx)
xs = new_xs
idx = int(len(xs) * (1 - test_split))
x_train, y_train = np.array(xs[:idx]), np.array(labels[:idx])
x_test, y_test = np.array(xs[idx:]), np.array(labels[idx:])
x_train = np.array(xs[:int(len(xs) * (1 - test_split))])
y_train = np.array(labels[:int(len(xs) * (1 - test_split))])
x_test = np.array(xs[int(len(xs) * (1 - test_split)):])
y_test = np.array(labels[int(len(xs) * (1 - test_split)):])
return (x_train, y_train), (x_test, y_test)
+9 -3
Ver Arquivo
@@ -1,8 +1,14 @@
# note: topology.Node is an internal class,
"""The Keras Engine: graph topology and training loop functionality.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
# Note: topology.Node is an internal class,
# it isn't meant to be used by Keras users.
from .topology import InputSpec
from .topology import get_source_inputs
from .topology import Input
from .topology import InputLayer
from .topology import InputSpec
from .topology import Layer
from .topology import get_source_inputs
from .training import Model
+129 -204
Ver Arquivo
@@ -1,30 +1,38 @@
# -*- coding: utf-8 -*-
from __future__ import print_function
"""Base layer code and base model (Container) code.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import json
import yaml
import warnings
import copy
import inspect
import json
import os
import re
from six.moves import zip
import warnings
from .. import backend as K
from .. import initializers
import numpy as np
from six.moves import zip
from tensorflow.python.framework import tensor_shape
from ..utils.io_utils import ask_to_proceed_with_overwrite
from ..utils.layer_utils import print_summary as print_layer_summary
from ..utils.generic_utils import has_arg
from ..utils import conv_utils
from ..legacy import interfaces
# pylint: disable=g-import-not-at-top
try:
import h5py
except ImportError:
h5py = None
try:
import yaml
except ImportError:
yaml = None
# pylint: enable=g-import-not-at-top
class InputSpec(object):
"""Specifies the ndim, dtype and shape of every input to a layer.
@@ -93,15 +101,11 @@ class Node(object):
output_tensors: list of output tensors.
input_masks: list of input masks (a mask can be a tensor, or None).
output_masks: list of output masks (a mask can be a tensor, or None).
input_shapes: list of input shape tuples.
output_shapes: list of output shape tuples.
arguments: dictionary of keyword arguments that were passed to the
`call` method of the layer at the call that created the node.
`node_indices` and `tensor_indices` are basically fine-grained coordinates
describing the origin of the `input_tensors`, verifying the following:
`input_tensors[i] == inbound_layers[i].inbound_nodes[node_indices[i]].output_tensors[tensor_indices[i]]`
describing the origin of the `input_tensors`.
A node from layer A to layer B is added to:
A.outbound_nodes
@@ -112,7 +116,6 @@ class Node(object):
inbound_layers, node_indices, tensor_indices,
input_tensors, output_tensors,
input_masks, output_masks,
input_shapes, output_shapes,
arguments=None):
# Layer instance (NOT a list).
# this is the layer that takes a list of input tensors
@@ -150,9 +153,9 @@ class Node(object):
# Following 2 properties: input and output shapes.
# List of shape tuples, shapes of input_tensors.
self.input_shapes = input_shapes
self.input_shapes = [K.int_shape(x) for x in input_tensors]
# List of shape tuples, shapes of output_tensors.
self.output_shapes = output_shapes
self.output_shapes = [K.int_shape(x) for x in output_tensors]
# Optional keyword arguments to layer's `call`.
self.arguments = arguments
@@ -221,12 +224,12 @@ class Layer(object):
`self._add_inbound_node(last_layer)`
- Add layer to tensor history
If layer is not built:
- Build from x._keras_shape
- Build from inputs shape
get_weights()
set_weights(weights)
get_config()
count_params()
compute_output_shape(input_shape)
_compute_output_shape(input_shape)
compute_mask(x, mask)
get_input_at(node_index)
get_output_at(node_index)
@@ -360,7 +363,6 @@ class Layer(object):
def non_trainable_weights(self, weights):
self._non_trainable_weights = weights
@interfaces.legacy_add_weight_support
def add_weight(self,
name,
shape,
@@ -385,6 +387,7 @@ class Layer(object):
# Returns
The created weight variable.
"""
shape = tuple(tensor_shape.TensorShape(shape).as_list())
initializer = initializers.get(initializer)
if dtype is None:
dtype = K.floatx()
@@ -415,9 +418,7 @@ class Layer(object):
"""
inputs = _to_list(inputs)
for x in inputs:
try:
K.is_keras_tensor(x)
except ValueError:
if not isinstance(x, K.tensor_types()):
raise ValueError('Layer ' + self.name + ' was called with '
'an input that isn\'t a symbolic tensor. '
'Received type: ' +
@@ -481,6 +482,8 @@ class Layer(object):
x_shape = None
if x_shape is not None:
for axis, value in spec.axes.items():
if hasattr(value, 'value'):
value = value.value
if value is not None and x_shape[int(axis)] not in {value, None}:
raise ValueError('Input ' + str(input_index) +
' is incompatible with layer ' +
@@ -496,6 +499,8 @@ class Layer(object):
x_shape = None
if x_shape is not None:
for spec_dim, dim in zip(spec.shape, x_shape):
if hasattr(spec_dim, 'value'):
spec_dim = spec_dim.value
if spec_dim is not None and dim is not None:
if spec_dim != dim:
raise ValueError(
@@ -505,7 +510,7 @@ class Layer(object):
str(spec.shape) + ', found shape=' +
str(x_shape))
def call(self, inputs, **kwargs):
def call(self, inputs, **kwargs): # pylint: disable=unused-argument
"""This is where the layer's logic lives.
# Arguments
@@ -523,10 +528,7 @@ class Layer(object):
If a Keras tensor is passed:
- We call self._add_inbound_node().
- If necessary, we `build` the layer to match
the _keras_shape of the input(s).
- We update the _keras_shape of every input tensor with
its new shape (obtained via self.compute_output_shape).
This is done as part of _add_inbound_node().
the shape of the input(s).
- We update the _keras_history of the output tensor(s)
with the current layer.
This is done as part of _add_inbound_node().
@@ -554,17 +556,7 @@ class Layer(object):
# Collect input shapes to build layer.
input_shapes = []
for x_elem in _to_list(inputs):
if hasattr(x_elem, '_keras_shape'):
input_shapes.append(x_elem._keras_shape)
elif hasattr(K, 'int_shape'):
input_shapes.append(K.int_shape(x_elem))
else:
raise ValueError('You tried to call layer "' + self.name +
'". This layer has no information'
' about its expected input shape, '
'and thus cannot be built. '
'You can build it manually via: '
'`layer.build(batch_input_shape)`')
input_shapes.append(K.int_shape(x_elem))
if len(input_shapes) == 1:
self.build(input_shapes[0])
else:
@@ -584,13 +576,11 @@ class Layer(object):
user_kwargs = copy.copy(kwargs)
if not _is_all_none(previous_mask):
# The previous layer generated a mask.
if has_arg(self.call, 'mask'):
if 'mask' in inspect.getargspec(self.call).args:
if 'mask' not in kwargs:
# If mask is explicitly passed to __call__,
# we should override the default mask.
kwargs['mask'] = previous_mask
# Handle automatic shape inference (only useful for Theano).
input_shape = _collect_input_shape(inputs)
# Actually call the layer, collecting output(s), mask(s), and shape(s).
output = self.call(inputs, **kwargs)
@@ -610,15 +600,6 @@ class Layer(object):
else:
output = output_ls_copy
# Infering the output shape is only relevant for Theano.
if all([s is not None for s in _to_list(input_shape)]):
output_shape = self.compute_output_shape(input_shape)
else:
if isinstance(input_shape, list):
output_shape = [None for _ in input_shape]
else:
output_shape = None
# Add an inbound node to the layer, so that it keeps track
# of the call and of all new variables created during the call.
# This also updates the layer history of the output tensor(s).
@@ -626,7 +607,6 @@ class Layer(object):
# this does nothing.
self._add_inbound_node(input_tensors=inputs, output_tensors=output,
input_masks=previous_mask, output_masks=output_mask,
input_shapes=input_shape, output_shapes=output_shape,
arguments=user_kwargs)
# Apply activity regularizer if any:
@@ -637,7 +617,7 @@ class Layer(object):
def _add_inbound_node(self, input_tensors, output_tensors,
input_masks, output_masks,
input_shapes, output_shapes, arguments=None):
arguments=None):
"""Internal method to create an inbound node for the layer.
# Arguments
@@ -645,8 +625,6 @@ class Layer(object):
output_tensors: list of output tensors.
input_masks: list of input masks (a mask can be a tensor, or None).
output_masks: list of output masks (a mask can be a tensor, or None).
input_shapes: list of input shape tuples.
output_shapes: list of output shape tuples.
arguments: dictionary of keyword arguments that were passed to the
`call` method of the layer at the call that created the node.
"""
@@ -654,8 +632,6 @@ class Layer(object):
output_tensors = _to_list(output_tensors)
input_masks = _to_list(input_masks)
output_masks = _to_list(output_masks)
input_shapes = _to_list(input_shapes)
output_shapes = _to_list(output_shapes)
# Collect input tensor(s) coordinates.
inbound_layers = []
@@ -682,14 +658,11 @@ class Layer(object):
output_tensors=output_tensors,
input_masks=input_masks,
output_masks=output_masks,
input_shapes=input_shapes,
output_shapes=output_shapes,
arguments=arguments
)
# Update tensor history, _keras_shape and _uses_learning_phase.
# Update tensor history and `_uses_learning_phase`.
for i in range(len(output_tensors)):
output_tensors[i]._keras_shape = output_shapes[i]
uses_lp = any([getattr(x, '_uses_learning_phase', False) for x in input_tensors])
uses_lp = getattr(self, 'uses_learning_phase', False) or uses_lp
output_tensors[i]._uses_learning_phase = getattr(output_tensors[i], '_uses_learning_phase', False) or uses_lp
@@ -697,7 +670,7 @@ class Layer(object):
len(self.inbound_nodes) - 1,
i)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
"""Computes the output shape of the layer.
Assumes that the layer will be built
@@ -712,13 +685,12 @@ class Layer(object):
# Returns
An input shape tuple.
"""
if hasattr(self, 'get_output_shape_for'):
msg = "Class `{}.{}` defines `get_output_shape_for` but does not override `compute_output_shape`. " + \
"If this is a Keras 1 layer, please implement `compute_output_shape` to support Keras 2."
warnings.warn(msg.format(type(self).__module__, type(self).__name__), stacklevel=2)
return input_shape
if isinstance(input_shape, list):
return [tensor_shape.TensorShape(shape) for shape in input_shape]
else:
return tensor_shape.TensorShape(input_shape)
def compute_mask(self, inputs, mask=None):
def compute_mask(self, inputs, mask=None): # pylint: disable=unused-argument
"""Computes an output mask tensor.
# Arguments
@@ -744,11 +716,11 @@ class Layer(object):
str(mask))
# masking not explicitly supported: return None as mask
return None
# if masking is explicitly supported, by default
# if masking is explictly supported, by default
# carry over the input mask
return mask
def build(self, input_shape):
def build(self, input_shape): # pylint: disable=unused-argument
"""Creates the layer weights.
Must be implemented on all layers that have weights.
@@ -1020,9 +992,9 @@ class Layer(object):
if len(all_input_shapes) == 1:
input_shapes = self.inbound_nodes[0].input_shapes
if len(input_shapes) == 1:
return input_shapes[0]
return tuple(tensor_shape.TensorShape(input_shapes[0]).as_list())
else:
return input_shapes
return [tuple(tensor_shape.TensorShape(shape).as_list()) for shape in input_shapes]
else:
raise AttributeError('The layer "' + str(self.name) +
' has multiple inbound nodes, '
@@ -1054,9 +1026,9 @@ class Layer(object):
if len(all_output_shapes) == 1:
output_shapes = self.inbound_nodes[0].output_shapes
if len(output_shapes) == 1:
return output_shapes[0]
return tuple(tensor_shape.TensorShape(output_shapes[0]).as_list())
else:
return output_shapes
return [tuple(tensor_shape.TensorShape(shape).as_list()) for shape in output_shapes]
else:
raise AttributeError('The layer "' + str(self.name) +
' has multiple inbound nodes, '
@@ -1081,14 +1053,14 @@ class Layer(object):
(e.g. L2 weight regularization, which only depends
on the layer's weights variables, not on any inputs tensors).
"""
if losses is None or losses == []:
if losses is None or losses == []: # pylint: disable=g-explicit-bool-comparison
return
# Update self.losses
losses = _to_list(losses)
if hasattr(self, '_losses'):
self._losses += losses
# Update self._per_input_updates
if isinstance(input, list) and inputs == []:
if inputs == []: # pylint: disable=g-explicit-bool-comparison
inputs = None
if inputs is not None:
inputs_hash = _object_list_uid(inputs)
@@ -1113,14 +1085,14 @@ class Layer(object):
the updates as conditional on these inputs.
If None is passed, the updates are assumed unconditional.
"""
if updates is None or updates == []:
if updates is None or updates == []: # pylint: disable=g-explicit-bool-comparison
return
# Update self.updates
updates = _to_list(updates)
if hasattr(self, '_updates'):
self._updates += updates
# Update self._per_input_updates
if isinstance(inputs, list) and inputs == []:
if inputs == []: # pylint: disable=g-explicit-bool-comparison
inputs = None
if inputs is not None:
inputs_hash = _object_list_uid(inputs)
@@ -1253,7 +1225,7 @@ class Layer(object):
"""
if not self.built:
if self.__class__.__name__ == 'Sequential':
self.build()
self.build() # pylint: disable=no-value-for-parameter
else:
raise RuntimeError('You tried to call `count_params` on ' +
self.name + ', but the layer isn\'t built. '
@@ -1281,7 +1253,6 @@ class InputLayer(Layer):
name: Name of the layer (string).
"""
@interfaces.legacy_input_support
def __init__(self, input_shape=None, batch_size=None,
batch_input_shape=None,
dtype=None, input_tensor=None, sparse=False, name=None):
@@ -1298,8 +1269,7 @@ class InputLayer(Layer):
raise ValueError('Only provide the input_shape OR '
'batch_input_shape argument to '
'InputLayer, not both at the same time.')
if input_tensor is not None and batch_input_shape is None:
# If input_tensor is set, and batch_input_shape is not set:
if input_tensor is not None:
# Attempt automatic input shape inference.
try:
batch_input_shape = K.int_shape(input_tensor)
@@ -1337,7 +1307,6 @@ class InputLayer(Layer):
name=self.name)
else:
self.is_placeholder = False
input_tensor._keras_shape = batch_input_shape
# Create an input node to add to self.outbound_node
# and set output_tensors' _keras_history.
input_tensor._uses_learning_phase = False
@@ -1349,9 +1318,7 @@ class InputLayer(Layer):
input_tensors=[input_tensor],
output_tensors=[input_tensor],
input_masks=[None],
output_masks=[None],
input_shapes=[batch_input_shape],
output_shapes=[batch_input_shape])
output_masks=[None])
def get_config(self):
config = {'batch_input_shape': self.batch_input_shape,
@@ -1361,9 +1328,13 @@ class InputLayer(Layer):
return config
def Input(shape=None, batch_shape=None,
name=None, dtype=K.floatx(), sparse=False,
tensor=None):
def Input( # pylint: disable=invalid-name
shape=None,
batch_shape=None,
name=None,
dtype=K.floatx(),
sparse=False,
tensor=None):
"""`Input()` is used to instantiate a Keras tensor.
A Keras tensor is a tensor object from the underlying backend
@@ -1375,10 +1346,8 @@ def Input(shape=None, batch_shape=None,
it becomes possible to do:
`model = Model(input=[a, b], output=c)`
The added Keras attributes are:
._keras_shape: Integer shape tuple propagated
via Keras-side shape inference.
._keras_history: Last layer applied to the tensor.
The added Keras attribute is:
`_keras_history`: Last layer applied to the tensor.
the entire layer graph is retrievable from that layer,
recursively.
@@ -1424,7 +1393,7 @@ def Input(shape=None, batch_shape=None,
name=name, dtype=dtype,
sparse=sparse,
input_tensor=tensor)
# Return tensor including _keras_shape and _keras_history.
# Return tensor including `_keras_history`.
# Note that in this case train_output and test_output are the same pointer.
outputs = input_layer.inbound_nodes[0].output_tensors
if len(outputs) == 1:
@@ -1468,13 +1437,9 @@ class Container(Layer):
# Class Methods
from_config
# Raises
TypeError: if input tensors are not Keras tensors from InputLayer objects
"""
@interfaces.legacy_model_constructor_support
def __init__(self, inputs, outputs, name=None):
def __init__(self, inputs, outputs, name=None): # pylint: disable=super-init-not-called
# Handle `name` argument.
if not name:
prefix = self.__class__.__name__.lower()
@@ -1497,19 +1462,13 @@ class Container(Layer):
self.outputs = [outputs]
# Check for redundancy in inputs.
if len(set(self.inputs)) != len(self.inputs):
inputs_set = set(self.inputs)
if len(inputs_set) != len(self.inputs):
raise ValueError('The list of inputs passed to the model '
'is redundant. '
'All inputs should only appear once.'
' Found: ' + str(self.inputs))
# Check for redundancy in outputs.
if len(set(self.outputs)) != len(self.outputs):
warnings.warn('The list of outputs passed to the model '
'is redundant. '
'All outputs should only appear once.'
' Found: ' + str(self.outputs))
# List of initial layers (1 to 1 mapping with self.inputs,
# hence the same layer might appear twice)
self.input_layers = []
@@ -1529,7 +1488,7 @@ class Container(Layer):
# every time the Container is called on a set on input tensors,
# we compute the output tensors,
# output masks and output shapes in one pass,
# then cache them here. When one of these output is queried later,
# then cache them here. When of of these output is queried later,
# we retrieve it from there instead of recomputing it.
self._output_mask_cache = {}
self._output_tensor_cache = {}
@@ -1611,25 +1570,16 @@ class Container(Layer):
self._feed_inputs = []
self._feed_input_shapes = []
for i, layer in enumerate(self.input_layers):
# Check that layer is an InputLayer.
if not isinstance(layer, InputLayer):
raise TypeError(
'Input layers to a `Model` must be `InputLayer` objects. '
'Received inputs: {}. '
'Input {} (0-based) originates '
'from layer type `{}`.'.format(inputs,
i,
layer.__class__.__name__))
self.input_names.append(layer.name)
if layer.is_placeholder:
self._feed_input_names.append(layer.name)
self._feed_inputs.append(layer.input)
self._feed_input_shapes.append(self.inputs[i]._keras_shape)
self._feed_input_shapes.append(K.int_shape(self.inputs[i]))
for layer in self.output_layers:
self.output_names.append(layer.name)
self.internal_input_shapes = [x._keras_shape for x in self.inputs]
self.internal_output_shapes = [x._keras_shape for x in self.outputs]
self.internal_input_shapes = [K.int_shape(x) for x in self.inputs]
self.internal_output_shapes = [K.int_shape(x) for x in self.outputs]
# Container_nodes: set of nodes included in the graph
# (not all nodes included in the layers
@@ -1812,9 +1762,7 @@ class Container(Layer):
output_tensors=self.outputs,
# No container-level masking for now.
input_masks=[None for _ in self.inputs],
output_masks=[None for _ in self.outputs],
input_shapes=[x._keras_shape for x in self.inputs],
output_shapes=[x._keras_shape for x in self.outputs])
output_masks=[None for _ in self.outputs])
self.built = True
# The following are implemented as property functions:
@@ -2075,8 +2023,20 @@ class Container(Layer):
_, output_masks, _ = self.run_internal_graph(inputs, masks)
return output_masks
def compute_output_shape(self, input_shape):
input_shapes = _to_list(input_shape)
def _compute_output_shape(self, input_shape):
if isinstance(input_shape, list):
input_shapes = []
for shape in input_shape:
if shape is not None:
input_shapes.append(tuple(tensor_shape.TensorShape(shape).as_list()))
else:
input_shapes.append(None)
else:
if input_shape is not None:
input_shapes = [tuple(tensor_shape.TensorShape(input_shape).as_list())]
else:
input_shapes = [None]
if len(input_shapes) != len(self.input_layers):
raise ValueError('Invalid input_shape argument ' +
str(input_shape) + ': model has ' +
@@ -2085,9 +2045,13 @@ class Container(Layer):
cache_key = ','.join([str(x) for x in input_shapes])
if cache_key in self._output_shape_cache:
output_shapes = self._output_shape_cache[cache_key]
if isinstance(output_shapes, list) and len(output_shapes) == 1:
return output_shapes[0]
return output_shapes
if isinstance(output_shapes, list):
if len(output_shapes) == 1:
return tensor_shape.TensorShape(output_shapes[0])
else:
return [tensor_shape.TensorShape(shape) for shape in output_shapes]
else:
return tensor_shape.TensorShape(output_shapes)
else:
# Bad luck, we have to run the graph manually.
layers_to_output_shapes = {}
@@ -2124,11 +2088,14 @@ class Container(Layer):
input_shapes.append(input_shape)
if len(input_shapes) == 1:
output_shape = layer.compute_output_shape(input_shapes[0])
output_shape = layer._compute_output_shape(input_shapes[0])
else:
output_shape = layer.compute_output_shape(input_shapes)
output_shape = layer._compute_output_shape(input_shapes)
if isinstance(output_shape, list):
output_shapes = [tuple(tensor_shape.TensorShape(shape).as_list()) for shape in output_shape]
else:
output_shapes = [tuple(tensor_shape.TensorShape(output_shape).as_list())]
output_shapes = _to_list(output_shape)
node_index = layer.inbound_nodes.index(node)
for j in range(len(output_shapes)):
shape_key = layer.name + '_%s_%s' % (node_index, j)
@@ -2149,9 +2116,13 @@ class Container(Layer):
output_shapes.append(layers_to_output_shapes[key])
# Store in cache.
self._output_shape_cache[cache_key] = output_shapes
if isinstance(output_shapes, list) and len(output_shapes) == 1:
return output_shapes[0]
return output_shapes
if isinstance(output_shapes, list):
if len(output_shapes) == 1:
return tensor_shape.TensorShape(output_shapes[0])
else:
return [tensor_shape.TensorShape(shape) for shape in output_shapes]
else:
return tensor_shape.TensorShape(output_shapes)
def run_internal_graph(self, inputs, masks=None):
"""Computes output tensors for new inputs.
@@ -2206,7 +2177,7 @@ class Container(Layer):
kwargs = {}
if len(computed_data) == 1:
computed_tensor, computed_mask = computed_data[0]
if has_arg(layer.call, 'mask'):
if 'mask' in inspect.getargspec(layer.call).args:
if 'mask' not in kwargs:
kwargs['mask'] = computed_mask
output_tensors = _to_list(layer.call(computed_tensor, **kwargs))
@@ -2217,7 +2188,7 @@ class Container(Layer):
else:
computed_tensors = [x[0] for x in computed_data]
computed_masks = [x[1] for x in computed_data]
if has_arg(layer.call, 'mask'):
if 'mask' in inspect.getargspec(layer.call).args:
if 'mask' not in kwargs:
kwargs['mask'] = computed_masks
output_tensors = _to_list(layer.call(computed_tensors, **kwargs))
@@ -2242,17 +2213,13 @@ class Container(Layer):
# (e.g. weight regularizers).
self.add_loss(layer.get_losses_for(None), None)
# Update _keras_shape.
if all([hasattr(x, '_keras_shape') for x in computed_tensors]):
if len(computed_tensors) == 1:
shapes = _to_list(layer.compute_output_shape(computed_tensors[0]._keras_shape))
uses_learning_phase = computed_tensors[0]._uses_learning_phase
else:
shapes = _to_list(layer.compute_output_shape([x._keras_shape for x in computed_tensors]))
uses_learning_phase = any([x._uses_learning_phase for x in computed_tensors])
for x, s in zip(output_tensors, shapes):
x._keras_shape = s
x._uses_learning_phase = getattr(x, '_uses_learning_phase', False) or uses_learning_phase
# Update `_uses_learning_phase`.
if len(computed_tensors) == 1:
uses_learning_phase = getattr(computed_tensors[0], '_uses_learning_phase', False)
else:
uses_learning_phase = any([getattr(x, '_uses_learning_phase', False) for x in computed_tensors])
for x in output_tensors:
x._uses_learning_phase = getattr(x, '_uses_learning_phase', False) or uses_learning_phase
# Update tensor_map.
for x, y, mask in zip(reference_output_tensors, output_tensors, output_masks):
@@ -2264,11 +2231,7 @@ class Container(Layer):
for x in self.outputs:
assert str(id(x)) in tensor_map, 'Could not compute output ' + str(x)
tensor, mask = tensor_map[str(id(x))]
if hasattr(tensor, '_keras_shape') and output_shapes is not None:
shape = tensor._keras_shape
output_shapes.append(shape)
else:
output_shapes = None
output_shapes.append(K.int_shape(x))
output_tensors.append(tensor)
output_masks.append(mask)
@@ -2290,7 +2253,7 @@ class Container(Layer):
self._output_mask_cache[cache_key] = output_masks
if output_shapes is not None:
input_shapes = [x._keras_shape for x in inputs]
input_shapes = [K.int_shape(x) for x in inputs]
cache_key = ','.join([str(x) for x in input_shapes])
if len(output_shapes) == 1:
output_shapes = output_shapes[0]
@@ -2414,7 +2377,7 @@ class Container(Layer):
layer_name = layer_data['name']
# Instantiate layer.
from ..layers import deserialize as deserialize_layer
from ..layers import deserialize as deserialize_layer # pylint: disable=g-import-not-at-top
layer = deserialize_layer(layer_data,
custom_objects=custom_objects)
created_layers[layer_name] = layer
@@ -2502,7 +2465,7 @@ class Container(Layer):
model = load_model('my_model.h5')
```
"""
from ..models import save_model
from ..models import save_model # pylint: disable=g-import-not-at-top
save_model(self, filepath, overwrite, include_optimizer)
def save_weights(self, filepath, overwrite=True):
@@ -2580,7 +2543,7 @@ class Container(Layer):
# Returns
Model config with Keras version information added.
"""
from .. import __version__ as keras_version
from .. import __version__ as keras_version # pylint: disable=g-import-not-at-top
config = self.get_config()
model_config = {
@@ -2634,28 +2597,18 @@ class Container(Layer):
# Returns
A YAML string.
# Raises
ImportError: if yaml module is not found.
"""
if yaml is None:
raise ImportError('Requires yaml module installed.')
return yaml.dump(self._updated_config(), **kwargs)
def summary(self, line_length=None, positions=None, print_fn=print):
"""Prints a string summary of the network.
# Arguments
line_length: Total length of printed lines
(e.g. set this to adapt the display to different
terminal window sizes).
positions: Relative or absolute positions of log elements
in each line. If not provided,
defaults to `[.33, .55, .67, 1.]`.
print_fn: Print function to use.
It will be called on each line of the summary.
You can set it to a custom function
in order to capture the string summary.
"""
return print_layer_summary(self,
line_length=line_length,
positions=positions,
print_fn=print_fn)
def summary(self, line_length=None, positions=None):
print_layer_summary(self,
line_length=line_length,
positions=positions)
def get_source_inputs(tensor, layer=None, node_index=None):
@@ -2780,17 +2733,14 @@ def _collect_input_shape(input_tensors):
input_tensors = _to_list(input_tensors)
shapes = []
for x in input_tensors:
try:
shapes.append(K.int_shape(x))
except TypeError:
shapes.append(None)
shapes.append(K.int_shape(x))
if len(shapes) == 1:
return shapes[0]
return shapes
def save_weights_to_hdf5_group(f, layers):
from .. import __version__ as keras_version
from .. import __version__ as keras_version # pylint: disable=g-import-not-at-top
f.attrs['layer_names'] = [layer.name.encode('utf8') for layer in layers]
f.attrs['backend'] = K.backend().encode('utf8')
@@ -2938,31 +2888,6 @@ def preprocess_weights_for_loading(layer, weights,
(2, 3, 1, 0))
weights = [kernel, recurrent_kernel, bias]
if layer.__class__.__name__ in ['Model', 'Sequential']:
new_weights = []
# trainable weights
for sublayer in layer.layers:
num_weights = len(sublayer.trainable_weights)
if num_weights > 0:
new_weights.extend(preprocess_weights_for_loading(
layer=sublayer,
weights=weights[:num_weights],
original_keras_version=original_keras_version,
original_backend=original_backend))
weights = weights[num_weights:]
# non-trainable weights
for sublayer in layer.layers:
num_weights = len([l for l in sublayer.weights if l not in sublayer.trainable_weights])
if num_weights > 0:
new_weights.extend(preprocess_weights_for_loading(
layer=sublayer,
weights=weights[:num_weights],
original_keras_version=original_keras_version,
original_backend=original_backend))
weights = weights[num_weights:]
weights = new_weights
conv_layers = ['Conv1D',
'Conv2D',
'Conv3D',
+212 -180
Ver Arquivo
@@ -1,29 +1,32 @@
"""Keras training and evaluation routines.
"""
# -*- coding: utf-8 -*-
from __future__ import print_function
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
import copy
import multiprocessing
import threading
import time
import warnings
from .. import backend as K
from .. import callbacks as cbks
from .. import losses
from .. import metrics as metrics_module
from .. import optimizers
import numpy as np
import six
from .topology import Container
from ..utils.generic_utils import Progbar
from keras.utils import Sequence
from keras.utils import GeneratorEnqueuer
from keras.utils import OrderedEnqueuer
# pylint: disable=g-import-not-at-top
try:
import queue
except ImportError:
import Queue as queue
from .topology import Container
from .. import backend as K
from .. import optimizers
from .. import losses
from .. import metrics as metrics_module
from ..utils.generic_utils import Progbar
from .. import callbacks as cbks
from ..legacy import interfaces
# pylint: enable=g-import-not-at-top
def _standardize_input_data(data, names, shapes=None,
@@ -101,7 +104,7 @@ def _standardize_input_data(data, names, shapes=None,
if len(names) > 1:
# Case: model expects multiple inputs but only received
# a single Numpy array.
raise ValueError('The model expects ' + str(len(names)) + ' ' +
raise ValueError('The model expects ' + str(len(names)) +
exception_prefix +
' arrays, but only received one array. '
'Found: array with shape ' + str(data.shape))
@@ -156,7 +159,7 @@ def _standardize_sample_or_class_weights(x_weight, output_names, weight_type):
# Raises
ValueError: In case of invalid user-provided argument.
"""
if x_weight is None or len(x_weight) == 0:
if x_weight is None or len(x_weight) == 0: # pylint: disable=g-explicit-length-test
return [None for _ in output_names]
if len(output_names) == 1:
if isinstance(x_weight, list) and len(x_weight) == 1:
@@ -200,7 +203,7 @@ def _standardize_sample_weights(sample_weight, output_names):
'sample_weight')
def _check_array_lengths(inputs, targets, weights=None):
def _check_array_lengths(inputs, targets, weights):
"""Does user input validation for numpy arrays.
# Arguments
@@ -211,34 +214,29 @@ def _check_array_lengths(inputs, targets, weights=None):
# Raises
ValueError: in case of incorrectly formatted data.
"""
def set_of_lengths(x):
# return a set with the variation between
# different shapes, with None => 0
if x is None:
return {0}
else:
return set([0 if y is None else y.shape[0] for y in x])
set_x = set_of_lengths(inputs)
set_y = set_of_lengths(targets)
set_w = set_of_lengths(weights)
x_lengths = [x.shape[0] for x in inputs]
y_lengths = [y.shape[0] for y in targets]
w_lengths = [w.shape[0] for w in weights]
set_x = set(x_lengths)
if len(set_x) > 1:
raise ValueError('All input arrays (x) should have '
'the same number of samples. Got array shapes: ' +
str([x.shape for x in inputs]))
set_y = set(y_lengths)
if len(set_y) > 1:
raise ValueError('All target arrays (y) should have '
'the same number of samples. Got array shapes: ' +
str([y.shape for y in targets]))
set_w = set(w_lengths)
if len(set_w) > 1:
raise ValueError('All sample_weight arrays should have '
'the same number of samples. Got array shapes: ' +
str([w.shape for w in weights]))
if set_x and set_y and list(set_x)[0] != list(set_y)[0]:
raise ValueError('Input arrays should have '
'the same number of samples as target arrays. '
'Found ' + str(list(set_x)[0]) + ' input samples '
'and ' + str(list(set_y)[0]) + ' target samples.')
if len(set_w) > 1:
raise ValueError('All sample_weight arrays should have '
'the same number of samples. Got array shapes: ' +
str([w.shape for w in weights]))
if set_y and set_w and list(set_y)[0] != list(set_w)[0]:
raise ValueError('Sample_weight arrays should have '
'the same number of samples as target arrays. Got ' +
@@ -247,7 +245,7 @@ def _check_array_lengths(inputs, targets, weights=None):
def _check_loss_and_target_compatibility(targets, loss_fns, output_shapes):
"""Does validation on the compatibility of targets and loss functions.
"""Does validation on the compatiblity of targets and loss functions.
This helps prevent users from using loss functions incorrectly.
@@ -260,7 +258,7 @@ def _check_loss_and_target_compatibility(targets, loss_fns, output_shapes):
ValueError: if a loss function or target array
is incompatible with an output.
"""
key_losses = {'mean_squared_error',
key_losses = {'mean_square_error',
'binary_crossentropy',
'categorical_crossentropy'}
for y, loss, shape in zip(targets, loss_fns, output_shapes):
@@ -392,25 +390,21 @@ def _slice_arrays(arrays, start=None, stop=None):
# Returns
A slice of the array(s).
"""
if arrays is None:
return [None]
elif isinstance(arrays, list):
if isinstance(arrays, list):
if hasattr(start, '__len__'):
# hdf5 datasets only support list objects as indices
if hasattr(start, 'shape'):
start = start.tolist()
return [None if x is None else x[start] for x in arrays]
return [x[start] for x in arrays]
else:
return [None if x is None else x[start:stop] for x in arrays]
return [x[start:stop] for x in arrays]
else:
if hasattr(start, '__len__'):
if hasattr(start, 'shape'):
start = start.tolist()
return arrays[start]
elif hasattr(start, '__getitem__'):
return arrays[start:stop]
else:
return [None]
return arrays[start:stop]
def _weighted_masked_objective(fn):
@@ -445,7 +439,6 @@ def _weighted_masked_objective(fn):
# score_array has ndim >= 2
score_array = fn(y_true, y_pred)
if mask is not None:
# Cast the mask to floatX to avoid float64 upcasting in theano
mask = K.cast(mask, K.floatx())
# mask should have the same shape as score_array
score_array *= mask
@@ -453,12 +446,13 @@ def _weighted_masked_objective(fn):
# to the number of unmasked samples.
score_array /= K.mean(mask)
# reduce score_array to same ndim as weight array
ndim = K.ndim(score_array)
weight_ndim = K.ndim(weights)
score_array = K.mean(score_array, axis=list(range(weight_ndim, ndim)))
# apply sample weighting
if weights is not None:
# reduce score_array to same ndim as weight array
ndim = K.ndim(score_array)
weight_ndim = K.ndim(weights)
score_array = K.mean(score_array, axis=list(range(weight_ndim, ndim)))
score_array *= weights
score_array /= K.mean(K.cast(K.not_equal(weights, 0), K.floatx()))
return K.mean(score_array)
@@ -493,7 +487,6 @@ def _masked_objective(fn):
# score_array has ndim >= 2
score_array = fn(y_true, y_pred)
if mask is not None:
# Cast the mask to floatX to avoid float64 upcasting in theano
mask = K.cast(mask, K.floatx())
# mask should have the same shape as score_array
score_array *= mask
@@ -571,7 +564,7 @@ def _standardize_weights(y, sample_weight=None, class_weight=None,
return sample_weight
elif isinstance(class_weight, dict):
if len(y.shape) > 2:
raise ValueError('`class_weight` not supported for '
raise ValueError('class_weight not supported for '
'3+ dimensional targets.')
if y.shape[1] > 1:
y_classes = y.argmax(axis=1)
@@ -588,6 +581,97 @@ def _standardize_weights(y, sample_weight=None, class_weight=None,
return np.ones((y.shape[0], y.shape[1]), dtype=K.floatx())
class GeneratorEnqueuer(object):
"""Builds a queue out of a data generator.
Used in `fit_generator`, `evaluate_generator`, `predict_generator`.
# Arguments
generator: a generator function which endlessly yields data
pickle_safe: use multiprocessing if True, otherwise threading
"""
def __init__(self, generator, pickle_safe=False):
self._generator = generator
self._pickle_safe = pickle_safe
self._threads = []
self._stop_event = None
self.queue = None
def start(self, workers=1, max_q_size=10, wait_time=0.05):
"""Kicks off threads which add data from the generator into the queue.
# Arguments
workers: number of worker threads
max_q_size: queue size (when full, threads could block on put())
wait_time: time to sleep in-between calls to put()
"""
def data_generator_task():
while not self._stop_event.is_set():
try:
if self._pickle_safe or self.queue.qsize() < max_q_size:
generator_output = next(self._generator)
self.queue.put(generator_output)
else:
time.sleep(wait_time)
except Exception:
self._stop_event.set()
raise
try:
if self._pickle_safe:
self.queue = multiprocessing.Queue(maxsize=max_q_size)
self._stop_event = multiprocessing.Event()
else:
self.queue = queue.Queue()
self._stop_event = threading.Event()
for _ in range(workers):
if self._pickle_safe:
# Reset random seed else all children processes
# share the same seed
np.random.seed()
thread = multiprocessing.Process(target=data_generator_task)
thread.daemon = True
else:
thread = threading.Thread(target=data_generator_task)
self._threads.append(thread)
thread.start()
except:
self.stop()
raise
def is_running(self):
return self._stop_event is not None and not self._stop_event.is_set()
def stop(self, timeout=None):
"""Stop running threads and wait for them to exit, if necessary.
Should be called by the same thread which called start().
# Arguments
timeout: maximum time to wait on thread.join()
"""
if self.is_running():
self._stop_event.set()
for thread in self._threads:
if thread.is_alive():
if self._pickle_safe:
thread.terminate()
else:
thread.join(timeout)
if self._pickle_safe:
if self.queue is not None:
self.queue.close()
self._threads = []
self._stop_event = None
self.queue = None
class Model(Container):
"""The `Model` class adds training & evaluation routines to a `Container`.
"""
@@ -626,13 +710,12 @@ class Model(Container):
If the model has multiple outputs, you can use a different
`sample_weight_mode` on each output by passing a
dictionary or a list of modes.
**kwargs: when using the Theano backend, these arguments
are passed into K.function. When using the Tensorflow backend,
these arguments are passed into `tf.Session.run`.
**kwargs: Additional arguments passed to `tf.Session.run`.
# Raises
ValueError: In case of invalid arguments for
`optimizer`, `loss`, `metrics` or `sample_weight_mode`.
RuntimeError: If the model has no loss to optimize.
"""
loss = loss or {}
self.optimizer = optimizers.get(optimizer)
@@ -902,21 +985,25 @@ class Model(Container):
# Functions for train, test and predict will
# be compiled lazily when required.
# This saves time when the user is not using all functions.
self._function_kwargs = kwargs
self.train_function = None
self.test_function = None
self.predict_function = None
self._function_kwargs = kwargs
# Collected trainable weights, sorted in topological order.
# Collected trainable weights and sort them deterministically.
trainable_weights = self.trainable_weights
# Sort weights by name.
if trainable_weights:
trainable_weights.sort(key=lambda x: x.name)
self._collected_trainable_weights = trainable_weights
def _make_train_function(self):
if not hasattr(self, 'train_function'):
raise RuntimeError('You must compile your model before using it.')
if self.train_function is None:
inputs = self._feed_inputs + self._feed_targets + self._feed_sample_weights
inputs = (self._feed_inputs +
self._feed_targets +
self._feed_sample_weights)
if self.uses_learning_phase and not isinstance(K.learning_phase(), int):
inputs += [K.learning_phase()]
@@ -936,7 +1023,9 @@ class Model(Container):
if not hasattr(self, 'test_function'):
raise RuntimeError('You must compile your model before using it.')
if self.test_function is None:
inputs = self._feed_inputs + self._feed_targets + self._feed_sample_weights
inputs = (self._feed_inputs +
self._feed_targets +
self._feed_sample_weights)
if self.uses_learning_phase and not isinstance(K.learning_phase(), int):
inputs += [K.learning_phase()]
# Return loss and metrics, no gradient updates.
@@ -950,6 +1039,7 @@ class Model(Container):
def _make_predict_function(self):
if not hasattr(self, 'predict_function'):
self.predict_function = None
self._function_kwargs = {}
if self.predict_function is None:
if self.uses_learning_phase and not isinstance(K.learning_phase(), int):
inputs = self._feed_inputs + [K.learning_phase()]
@@ -957,12 +1047,11 @@ class Model(Container):
inputs = self._feed_inputs
# Gets network outputs. Does not update weights.
# Does update the network states.
kwargs = getattr(self, '_function_kwargs', {})
self.predict_function = K.function(inputs,
self.outputs,
updates=self.state_updates,
name='predict_function',
**kwargs)
**self._function_kwargs)
def _fit_loop(self, f, ins, out_labels=None, batch_size=32,
epochs=100, verbose=1, callbacks=None,
@@ -1270,8 +1359,7 @@ class Model(Container):
shuffle=True,
class_weight=None,
sample_weight=None,
initial_epoch=0,
**kwargs):
initial_epoch=0):
"""Trains the model for a fixed number of epochs (iterations on a dataset).
# Arguments
@@ -1330,14 +1418,6 @@ class Model(Container):
ValueError: In case of mismatch between the provided input data
and what the model expects.
"""
# Legacy support
if 'nb_epoch' in kwargs:
warnings.warn('The `nb_epoch` argument in `fit` '
'has been renamed `epochs`.', stacklevel=2)
epochs = kwargs.pop('nb_epoch')
if kwargs:
raise TypeError('Unrecognized keyword arguments: ' + str(kwargs))
# Validate user data.
x, y, sample_weights = self._standardize_user_data(
x, y,
@@ -1349,10 +1429,10 @@ class Model(Container):
if validation_data:
do_validation = True
if len(validation_data) == 2:
val_x, val_y = validation_data
val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence
val_sample_weight = None
elif len(validation_data) == 3:
val_x, val_y, val_sample_weight = validation_data
val_x, val_y, val_sample_weight = validation_data # pylint: disable=unpacking-non-sequence
else:
raise ValueError('When passing validation_data, '
'it must contain 2 (x_val, y_val) '
@@ -1374,10 +1454,7 @@ class Model(Container):
elif validation_split and 0. < validation_split < 1.:
do_validation = True
if hasattr(x[0], 'shape'):
split_at = int(x[0].shape[0] * (1. - validation_split))
else:
split_at = int(len(x[0]) * (1. - validation_split))
split_at = int(len(x[0]) * (1. - validation_split))
x, val_x = (_slice_arrays(x, 0, split_at), _slice_arrays(x, split_at))
y, val_y = (_slice_arrays(y, 0, split_at), _slice_arrays(y, split_at))
sample_weights, val_sample_weights = (
@@ -1619,7 +1696,6 @@ class Model(Container):
return outputs[0]
return outputs
@interfaces.legacy_generator_methods_support
def fit_generator(self, generator,
steps_per_epoch,
epochs=1,
@@ -1628,9 +1704,9 @@ class Model(Container):
validation_data=None,
validation_steps=None,
class_weight=None,
max_queue_size=10,
max_q_size=10,
workers=1,
use_multiprocessing=False,
pickle_safe=False,
initial_epoch=0):
"""Fits the model on data yielded batch-by-batch by a Python generator.
@@ -1638,14 +1714,8 @@ class Model(Container):
For instance, this allows you to do real-time data augmentation
on images on CPU in parallel to training your model on GPU.
The use of `keras.utils.Sequence` guarantees the ordering
and guarantees the single use of every input per epoch when
using `use_multiprocessing=True`.
# Arguments
generator: a generator or an instance of Sequence (keras.utils.Sequence)
object in order to avoid duplicate data
when using multiprocessing.
generator: a generator.
The output of the generator must be either
- a tuple (inputs, targets)
- a tuple (inputs, targets, sample_weights).
@@ -1670,10 +1740,10 @@ class Model(Container):
to yield from `generator` before stopping.
class_weight: dictionary mapping class indices to a weight
for the class.
max_queue_size: maximum size for the generator queue
max_q_size: maximum size for the generator queue
workers: maximum number of processes to spin up
when using process based threading
use_multiprocessing: if True, use process based threading.
pickle_safe: if True, use process based threading.
Note that because
this implementation relies on multiprocessing,
you should not pass
@@ -1718,8 +1788,7 @@ class Model(Container):
# python 2 has 'next', 3 has '__next__'
# avoid any explicit version checks
val_gen = (hasattr(validation_data, 'next') or
hasattr(validation_data, '__next__') or
isinstance(validation_data, Sequence))
hasattr(validation_data, '__next__'))
if val_gen and not validation_steps:
raise ValueError('When using a generator for validation data, '
'you must specify a value for '
@@ -1753,12 +1822,12 @@ class Model(Container):
if do_validation and not val_gen:
if len(validation_data) == 2:
val_x, val_y = validation_data
val_x, val_y = validation_data # pylint: disable=unpacking-non-sequence
val_sample_weight = None
elif len(validation_data) == 3:
val_x, val_y, val_sample_weight = validation_data
val_x, val_y, val_sample_weight = validation_data # pylint: disable=unpacking-non-sequence
else:
raise ValueError('`validation_data` should be a tuple '
raise ValueError('validation_data should be a tuple '
'`(val_x, val_y, val_sample_weight)` '
'or `(val_x, val_y)`. Found: ' +
str(validation_data))
@@ -1769,25 +1838,11 @@ class Model(Container):
val_data += [0.]
for cbk in callbacks:
cbk.validation_data = val_data
is_sequence = isinstance(generator, Sequence)
if not is_sequence and use_multiprocessing and workers > 1:
warnings.warn(
UserWarning('Using a generator with `use_multiprocessing=True`'
' and multiple workers may duplicate your data.'
' Please consider using the`keras.utils.Sequence'
' class.'))
enqueuer = None
try:
if is_sequence:
enqueuer = OrderedEnqueuer(generator,
use_multiprocessing=use_multiprocessing)
else:
enqueuer = GeneratorEnqueuer(generator,
use_multiprocessing=use_multiprocessing,
wait_time=wait_time)
enqueuer.start(workers=workers, max_queue_size=max_queue_size)
output_generator = enqueuer.get()
enqueuer = GeneratorEnqueuer(generator, pickle_safe=pickle_safe)
enqueuer.start(max_q_size=max_q_size, workers=workers)
callback_model.stop_training = False
while epoch < epochs:
@@ -1795,20 +1850,26 @@ class Model(Container):
steps_done = 0
batch_index = 0
while steps_done < steps_per_epoch:
generator_output = next(output_generator)
generator_output = None
while enqueuer.is_running():
if not enqueuer.queue.empty():
generator_output = enqueuer.queue.get()
break
else:
time.sleep(wait_time)
if not hasattr(generator_output, '__len__'):
raise ValueError('Output of generator should be '
raise ValueError('output of generator should be '
'a tuple `(x, y, sample_weight)` '
'or `(x, y)`. Found: ' +
str(generator_output))
if len(generator_output) == 2:
x, y = generator_output
x, y = generator_output # pylint: disable=unpacking-non-sequence
sample_weight = None
elif len(generator_output) == 3:
x, y, sample_weight = generator_output
x, y, sample_weight = generator_output # pylint: disable=unpacking-non-sequence
else:
raise ValueError('Output of generator should be '
raise ValueError('output of generator should be '
'a tuple `(x, y, sample_weight)` '
'or `(x, y)`. Found: ' +
str(generator_output))
@@ -1846,9 +1907,9 @@ class Model(Container):
val_outs = self.evaluate_generator(
validation_data,
validation_steps,
max_queue_size=max_queue_size,
max_q_size=max_q_size,
workers=workers,
use_multiprocessing=use_multiprocessing)
pickle_safe=pickle_safe)
else:
# No need for try/except because
# data has already been validated.
@@ -1875,11 +1936,8 @@ class Model(Container):
callbacks.on_train_end()
return self.history
@interfaces.legacy_generator_methods_support
def evaluate_generator(self, generator, steps,
max_queue_size=10,
workers=1,
use_multiprocessing=False):
max_q_size=10, workers=1, pickle_safe=False):
"""Evaluates the model on a data generator.
The generator should return the same kind of data
@@ -1888,15 +1946,12 @@ class Model(Container):
# Arguments
generator: Generator yielding tuples (inputs, targets)
or (inputs, targets, sample_weights)
or an instance of Sequence (keras.utils.Sequence)
object in order to avoid duplicate data
when using multiprocessing.
steps: Total number of steps (batches of samples)
to yield from `generator` before stopping.
max_queue_size: maximum size for the generator queue
max_q_size: maximum size for the generator queue
workers: maximum number of processes to spin up
when using process based threading
use_multiprocessing: if True, use process based threading.
pickle_safe: if True, use process based threading.
Note that because
this implementation relies on multiprocessing,
you should not pass
@@ -1920,40 +1975,33 @@ class Model(Container):
wait_time = 0.01
all_outs = []
batch_sizes = []
is_sequence = isinstance(generator, Sequence)
if not is_sequence and use_multiprocessing and workers > 1:
warnings.warn(
UserWarning('Using a generator with `use_multiprocessing=True`'
' and multiple workers may duplicate your data.'
' Please consider using the`keras.utils.Sequence'
' class.'))
enqueuer = None
try:
if is_sequence:
enqueuer = OrderedEnqueuer(generator,
use_multiprocessing=use_multiprocessing)
else:
enqueuer = GeneratorEnqueuer(generator,
use_multiprocessing=use_multiprocessing,
wait_time=wait_time)
enqueuer.start(workers=workers, max_queue_size=max_queue_size)
output_generator = enqueuer.get()
enqueuer = GeneratorEnqueuer(generator, pickle_safe=pickle_safe)
enqueuer.start(workers=workers, max_q_size=max_q_size)
while steps_done < steps:
generator_output = next(output_generator)
generator_output = None
while enqueuer.is_running():
if not enqueuer.queue.empty():
generator_output = enqueuer.queue.get()
break
else:
time.sleep(wait_time)
if not hasattr(generator_output, '__len__'):
raise ValueError('Output of generator should be a tuple '
raise ValueError('output of generator should be a tuple '
'(x, y, sample_weight) '
'or (x, y). Found: ' +
str(generator_output))
if len(generator_output) == 2:
x, y = generator_output
x, y = generator_output # pylint: disable=unpacking-non-sequence
sample_weight = None
elif len(generator_output) == 3:
x, y, sample_weight = generator_output
x, y, sample_weight = generator_output # pylint: disable=unpacking-non-sequence
else:
raise ValueError('Output of generator should be a tuple '
raise ValueError('output of generator should be a tuple '
'(x, y, sample_weight) '
'or (x, y). Found: ' +
str(generator_output))
@@ -1965,9 +2013,6 @@ class Model(Container):
batch_size = len(list(x.values())[0])
else:
batch_size = len(x)
if batch_size == 0:
raise ValueError('Received an empty batch. '
'Batches should at least contain one item.')
all_outs.append(outs)
steps_done += 1
@@ -1987,28 +2032,22 @@ class Model(Container):
weights=batch_sizes))
return averages
@interfaces.legacy_generator_methods_support
def predict_generator(self, generator, steps,
max_queue_size=10,
workers=1,
use_multiprocessing=False,
verbose=0):
max_q_size=10, workers=1,
pickle_safe=False, verbose=0):
"""Generates predictions for the input samples from a data generator.
The generator should return the same kind of data as accepted by
`predict_on_batch`.
# Arguments
generator: Generator yielding batches of input samples
or an instance of Sequence (keras.utils.Sequence)
object in order to avoid duplicate data
when using multiprocessing.
generator: Generator yielding batches of input samples.
steps: Total number of steps (batches of samples)
to yield from `generator` before stopping.
max_queue_size: Maximum size for the generator queue.
max_q_size: Maximum size for the generator queue.
workers: Maximum number of processes to spin up
when using process based threading
use_multiprocessing: If `True`, use process based threading.
pickle_safe: If `True`, use process based threading.
Note that because
this implementation relies on multiprocessing,
you should not pass
@@ -2029,40 +2068,33 @@ class Model(Container):
steps_done = 0
wait_time = 0.01
all_outs = []
is_sequence = isinstance(generator, Sequence)
if not is_sequence and use_multiprocessing and workers > 1:
warnings.warn(
UserWarning('Using a generator with `use_multiprocessing=True`'
' and multiple workers may duplicate your data.'
' Please consider using the`keras.utils.Sequence'
' class.'))
enqueuer = None
try:
if is_sequence:
enqueuer = OrderedEnqueuer(generator,
use_multiprocessing=use_multiprocessing)
else:
enqueuer = GeneratorEnqueuer(generator,
use_multiprocessing=use_multiprocessing,
wait_time=wait_time)
enqueuer.start(workers=workers, max_queue_size=max_queue_size)
output_generator = enqueuer.get()
enqueuer = GeneratorEnqueuer(generator, pickle_safe=pickle_safe)
enqueuer.start(workers=workers, max_q_size=max_q_size)
if verbose == 1:
progbar = Progbar(target=steps)
while steps_done < steps:
generator_output = next(output_generator)
generator_output = None
while enqueuer.is_running():
if not enqueuer.queue.empty():
generator_output = enqueuer.queue.get()
break
else:
time.sleep(wait_time)
if isinstance(generator_output, tuple):
# Compatibility with the generators
# used for training.
if len(generator_output) == 2:
x, _ = generator_output
x, _ = generator_output # pylint: disable=unpacking-non-sequence
elif len(generator_output) == 3:
x, _, _ = generator_output
x, _, _ = generator_output # pylint: disable=unpacking-non-sequence
else:
raise ValueError('Output of generator should be '
raise ValueError('output of generator should be '
'a tuple `(x, y, sample_weight)` '
'or `(x, y)`. Found: ' +
str(generator_output))
+17 -29
Ver Arquivo
@@ -1,9 +1,17 @@
"""Keras initializer classes (soon to be replaced with core TF initializers).
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import math
from . import backend as K
import numpy as np
import six
from . import backend as K
from .utils.generic_utils import serialize_keras_object
from tensorflow.python.framework import tensor_shape
from .utils.generic_utils import deserialize_keras_object
from .utils.generic_utils import serialize_keras_object
class Initializer(object):
@@ -199,11 +207,11 @@ class VarianceScaling(Initializer):
else:
scale /= max(1., float(fan_in + fan_out) / 2)
if self.distribution == 'normal':
stddev = np.sqrt(scale)
stddev = math.sqrt(scale)
return K.truncated_normal(shape, 0., stddev,
dtype=dtype, seed=self.seed)
else:
limit = np.sqrt(3. * scale)
limit = math.sqrt(3. * scale)
return K.random_uniform(shape, -limit, limit,
dtype=dtype, seed=self.seed)
@@ -371,29 +379,6 @@ def he_normal(seed=None):
seed=seed)
def lecun_normal(seed=None):
"""LeCun normal initializer.
It draws samples from a truncated normal distribution centered on 0
with `stddev = sqrt(1 / fan_in)`
where `fan_in` is the number of input units in the weight tensor.
# Arguments
seed: A Python integer. Used to seed the random generator.
# Returns
An initializer.
# References
- [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515)
- [Efficient Backprop](http://yann.lecun.com/exdb/publis/pdf/lecun-98b.pdf)
"""
return VarianceScaling(scale=1.,
mode='fan_in',
distribution='normal',
seed=seed)
def he_uniform(seed=None):
"""He uniform variance scaling initializer.
@@ -418,6 +403,7 @@ def he_uniform(seed=None):
# Compatibility aliases
# pylint: disable=invalid-name
zero = zeros = Zeros
one = ones = Ones
constant = Constant
@@ -426,6 +412,7 @@ normal = random_normal = RandomNormal
truncated_normal = TruncatedNormal
identity = Identity
orthogonal = Orthogonal
# pylint: enable=invalid-name
# Utility functions
@@ -446,6 +433,7 @@ def _compute_fans(shape, data_format='channels_last'):
# Raises
ValueError: in case of invalid `data_format` argument.
"""
shape = tensor_shape.TensorShape(shape).as_list()
if len(shape) == 2:
fan_in = shape[0]
fan_out = shape[1]
@@ -465,8 +453,8 @@ def _compute_fans(shape, data_format='channels_last'):
raise ValueError('Invalid data_format: ' + data_format)
else:
# No specific assumptions.
fan_in = np.sqrt(np.prod(shape))
fan_out = np.sqrt(np.prod(shape))
fan_in = math.sqrt(np.prod(shape))
fan_out = math.sqrt(np.prod(shape))
return fan_in, fan_out
+17 -45
Ver Arquivo
@@ -1,54 +1,26 @@
"""Keras layers module.
"""
# pylint: disable=wildcard-import
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from ..utils.generic_utils import deserialize_keras_object
from ..engine import Layer
from .advanced_activations import *
from .convolutional import *
from .convolutional_recurrent import *
from .core import *
from .embeddings import *
from ..engine import Input
from ..engine import InputLayer
from ..engine import InputSpec
from .merge import *
from .core import *
from .convolutional import *
from .pooling import *
from ..engine import Layer
from .local import *
from .recurrent import *
from .normalization import *
from .embeddings import *
from .merge import *
from .noise import *
from .advanced_activations import *
from .normalization import *
from .pooling import *
from .recurrent import *
from .serialization import deserialize
from .serialization import serialize
from .wrappers import *
from .convolutional_recurrent import *
from ..legacy.layers import *
def serialize(layer):
"""Serialize a layer.
# Arguments
layer: a Layer object.
# Returns
dictionary with config.
"""
return {'class_name': layer.__class__.__name__,
'config': layer.get_config()}
def deserialize(config, custom_objects=None):
"""Instantiate a layer from a config dictionary.
# Arguments
config: dict of the form {'class_name': str, 'config': dict}
custom_objects: dict mapping class names (or function names)
of custom (non-Keras) objects to class/functions
# Returns
Layer instance (may be Model, Sequential, Layer...)
"""
from .. import models
globs = globals() # All layers.
globs['Model'] = models.Model
globs['Sequential'] = models.Sequential
return deserialize_keras_object(config,
module_objects=globs,
custom_objects=custom_objects,
printable_module_name='layer')
+12 -16
Ver Arquivo
@@ -1,13 +1,17 @@
"""Layers that act as activation functions.
"""
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from ..engine import Layer
from ..engine import InputSpec
from .. import backend as K
from ..legacy import interfaces
from ..engine import Layer
from tensorflow.python.framework import tensor_shape
class LeakyReLU(Layer):
@@ -28,8 +32,6 @@ class LeakyReLU(Layer):
# Arguments
alpha: float >= 0. Negative slope coefficient.
# References
- [Rectifier Nonlinearities Improve Neural Network Acoustic Models](https://web.stanford.edu/~awni/papers/relu_hybrid_icml2013_final.pdf)
"""
def __init__(self, alpha=0.3, **kwargs):
@@ -41,7 +43,7 @@ class LeakyReLU(Layer):
return K.relu(inputs, alpha=self.alpha)
def get_config(self):
config = {'alpha': float(self.alpha)}
config = {'alpha': self.alpha}
base_config = super(LeakyReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -75,11 +77,8 @@ class PReLU(Layer):
so that each filter only has one set of parameters,
set `shared_axes=[1, 2]`.
# References
- [Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](https://arxiv.org/abs/1502.01852)
"""
@interfaces.legacy_prelu_support
def __init__(self, alpha_initializer='zeros',
alpha_regularizer=None,
alpha_constraint=None,
@@ -98,7 +97,8 @@ class PReLU(Layer):
self.shared_axes = list(shared_axes)
def build(self, input_shape):
param_shape = list(input_shape[1:])
input_shape = tensor_shape.TensorShape(input_shape).as_list()
param_shape = input_shape[1:]
self.param_broadcast = [False] * len(param_shape)
if self.shared_axes is not None:
for i in self.shared_axes:
@@ -156,8 +156,6 @@ class ELU(Layer):
# Arguments
alpha: scale for the negative factor.
# References
- [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)](https://arxiv.org/abs/1511.07289v1)
"""
def __init__(self, alpha=1.0, **kwargs):
@@ -192,8 +190,6 @@ class ThresholdedReLU(Layer):
# Arguments
theta: float >= 0. Threshold location of activation.
# References
- [Zero-Bias Autoencoders and the Benefits of Co-Adapting Features](http://arxiv.org/abs/1402.3337)
"""
def __init__(self, theta=1.0, **kwargs):
@@ -202,7 +198,7 @@ class ThresholdedReLU(Layer):
self.theta = K.cast_to_floatx(theta)
def call(self, inputs, mask=None):
return inputs * K.cast(K.greater(inputs, self.theta), K.floatx())
return inputs * K.cast(inputs > self.theta, K.floatx())
def get_config(self):
config = {'theta': float(self.theta)}
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+48 -42
Ver Arquivo
@@ -1,17 +1,20 @@
# -*- coding: utf-8 -*-
"""Convolutional-recurrent layers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from .. import activations
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from .recurrent import Recurrent
import numpy as np
from ..engine import InputSpec
import numpy as np
from .recurrent import Recurrent
from tensorflow.python.framework import tensor_shape
from ..utils import conv_utils
from ..legacy import interfaces
class ConvRecurrent2D(Recurrent):
@@ -62,7 +65,7 @@ class ConvRecurrent2D(Recurrent):
# Masking
This layer supports masking for input data with a variable number
of timesteps. To introduce masks to your data,
use an [Embedding](embeddings.md) layer with the `mask_zero` parameter
use an `Embedding` layer with the `mask_zero` parameter
set to `True`.
**Note:** for the time being, masking is only supported with Theano.
@@ -108,9 +111,10 @@ class ConvRecurrent2D(Recurrent):
self.input_spec = [InputSpec(ndim=5)]
self.state_spec = None
def compute_output_shape(self, input_shape):
if isinstance(input_shape, list):
def _compute_output_shape(self, input_shape):
if type(input_shape) is list:
input_shape = input_shape[0]
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_first':
rows = input_shape[3]
cols = input_shape[4]
@@ -129,16 +133,28 @@ class ConvRecurrent2D(Recurrent):
dilation=self.dilation_rate[1])
if self.return_sequences:
if self.data_format == 'channels_first':
return (input_shape[0], input_shape[1],
self.filters, rows, cols)
return tensor_shape.TensorShape([input_shape[0],
input_shape[1],
self.filters,
rows,
cols])
elif self.data_format == 'channels_last':
return (input_shape[0], input_shape[1],
rows, cols, self.filters)
return tensor_shape.TensorShape([input_shape[0],
input_shape[1],
rows,
cols,
self.filters])
else:
if self.data_format == 'channels_first':
return (input_shape[0], self.filters, rows, cols)
return tensor_shape.TensorShape([input_shape[0],
self.filters,
rows,
cols])
elif self.data_format == 'channels_last':
return (input_shape[0], rows, cols, self.filters)
return tensor_shape.TensorShape([input_shape[0],
rows,
cols,
self.filters])
def get_config(self):
config = {'filters': self.filters,
@@ -184,46 +200,34 @@ class ConvLSTM2D(ConvRecurrent2D):
the dilation rate to use for dilated convolution.
Currently, specifying any `dilation_rate` value != 1 is
incompatible with specifying any `strides` value != 1.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you don't specify anything, no activation is applied
(ie. "linear" activation: `a(x) = x`).
recurrent_activation: Activation function to use
for the recurrent step
(see [activations](../activations.md)).
for the recurrent step.
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix,
used for the linear transformation of the inputs.
(see [initializers](../initializers.md)).
used for the linear transformation of the inputs..
recurrent_initializer: Initializer for the `recurrent_kernel`
weights matrix,
used for the linear transformation of the recurrent state.
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
used for the linear transformation of the recurrent state..
bias_initializer: Initializer for the bias vector.
unit_forget_bias: Boolean.
If True, add 1 to the bias of the forget gate at initialization.
Use in combination with `bias_initializer="zeros"`.
This is recommended in [Jozefowicz et al.](http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
recurrent_regularizer: Regularizer function applied to
the `recurrent_kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `recurrent_kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to
the `kernel` weights matrix
(see [constraints](../constraints.md)).
the `kernel` weights matrix.
recurrent_constraint: Constraint function applied to
the `recurrent_kernel` weights matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the `recurrent_kernel` weights matrix.
bias_constraint: Constraint function applied to the bias vector.
return_sequences: Boolean. Whether to return the last output
in the output sequence, or the full sequence.
go_backwards: Boolean (default False).
@@ -274,7 +278,6 @@ class ConvLSTM2D(ConvRecurrent2D):
cells output
"""
@interfaces.legacy_convlstm2d_support
def __init__(self, filters,
kernel_size,
strides=(1, 1),
@@ -336,8 +339,10 @@ class ConvLSTM2D(ConvRecurrent2D):
def build(self, input_shape):
if isinstance(input_shape, list):
input_shape = input_shape[0]
input_shape = tuple(tensor_shape.TensorShape(input_shape).as_list())
batch_size = input_shape[0] if self.stateful else None
self.input_spec[0] = InputSpec(shape=(batch_size, None) + input_shape[2:])
if self.stateful:
self.reset_states()
else:
@@ -423,7 +428,8 @@ class ConvLSTM2D(ConvRecurrent2D):
if not self.stateful:
raise RuntimeError('Layer must be stateful.')
input_shape = self.input_spec[0].shape
output_shape = self.compute_output_shape(input_shape)
output_shape = self._compute_output_shape(input_shape)
if not input_shape[0]:
raise ValueError('If a RNN is stateful, a complete '
'input_shape must be provided '
@@ -474,7 +480,7 @@ class ConvLSTM2D(ConvRecurrent2D):
padding=self.padding)
ones += 1.
def dropped_inputs():
def dropped_inputs(): # pylint: disable=function-redefined
return K.dropout(ones, self.recurrent_dropout)
rec_dp_mask = [K.in_train_phase(dropped_inputs,
ones,
+76 -179
Ver Arquivo
@@ -1,25 +1,26 @@
# -*- coding: utf-8 -*-
"""Core Keras layers.
"""
from __future__ import absolute_import
from __future__ import division
import numpy as np
from __future__ import print_function
import copy
import inspect
import types as python_types
import warnings
from .. import backend as K
from .. import activations
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from ..engine import InputSpec
from ..engine import Layer
import numpy as np
from tensorflow.python.framework import tensor_shape
from ..utils.generic_utils import deserialize_keras_object
from ..utils.generic_utils import func_dump
from ..utils.generic_utils import func_load
from ..utils.generic_utils import deserialize_keras_object
from ..utils.generic_utils import has_arg
from ..legacy import interfaces
class Masking(Layer):
@@ -85,11 +86,8 @@ class Dropout(Layer):
you want the dropout mask to be the same for all timesteps,
you can use `noise_shape=(batch_size, 1, features)`.
seed: A Python integer to use as random seed.
# References
- [Dropout: A Simple Way to Prevent Neural Networks from Overfitting](http://www.cs.toronto.edu/~rsalakhu/papers/srivastava14a.pdf)
"""
@interfaces.legacy_dropout_support
def __init__(self, rate, noise_shape=None, seed=None, **kwargs):
super(Dropout, self).__init__(**kwargs)
self.rate = min(1., max(0., rate))
@@ -142,7 +140,6 @@ class SpatialDropout1D(Dropout):
- [Efficient Object Localization Using Convolutional Networks](https://arxiv.org/abs/1411.4280)
"""
@interfaces.legacy_spatialdropout1d_support
def __init__(self, rate, **kwargs):
super(SpatialDropout1D, self).__init__(rate, **kwargs)
self.input_spec = InputSpec(ndim=3)
@@ -187,14 +184,13 @@ class SpatialDropout2D(Dropout):
- [Efficient Object Localization Using Convolutional Networks](https://arxiv.org/abs/1411.4280)
"""
@interfaces.legacy_spatialdropoutNd_support
def __init__(self, rate, data_format=None, **kwargs):
super(SpatialDropout2D, self).__init__(rate, **kwargs)
if data_format is None:
data_format = K.image_data_format()
if data_format not in {'channels_last', 'channels_first'}:
raise ValueError('`data_format` must be in '
'{`"channels_last"`, `"channels_first"`}')
raise ValueError('data_format must be in '
'{"channels_last", "channels_first"}')
self.data_format = data_format
self.input_spec = InputSpec(ndim=4)
@@ -202,8 +198,10 @@ class SpatialDropout2D(Dropout):
input_shape = K.shape(inputs)
if self.data_format == 'channels_first':
noise_shape = (input_shape[0], input_shape[1], 1, 1)
else:
elif self.data_format == 'channels_last':
noise_shape = (input_shape[0], 1, 1, input_shape[3])
else:
raise ValueError('Invalid data_format:', self.data_format)
return noise_shape
@@ -240,14 +238,13 @@ class SpatialDropout3D(Dropout):
- [Efficient Object Localization Using Convolutional Networks](https://arxiv.org/abs/1411.4280)
"""
@interfaces.legacy_spatialdropoutNd_support
def __init__(self, rate, data_format=None, **kwargs):
super(SpatialDropout3D, self).__init__(rate, **kwargs)
if data_format is None:
data_format = K.image_data_format()
if data_format not in {'channels_last', 'channels_first'}:
raise ValueError('`data_format` must be in '
'{`"channels_last"`, `"channels_first"`}')
raise ValueError('data_format must be in '
'{"channels_last", "channels_first"}')
self.data_format = data_format
self.input_spec = InputSpec(ndim=5)
@@ -255,8 +252,10 @@ class SpatialDropout3D(Dropout):
input_shape = K.shape(inputs)
if self.data_format == 'channels_first':
noise_shape = (input_shape[0], input_shape[1], 1, 1, 1)
else:
elif self.data_format == 'channels_last':
noise_shape = (input_shape[0], 1, 1, 1, input_shape[4])
else:
raise ValueError('Invalid data_format:', self.data_format)
return noise_shape
@@ -265,7 +264,6 @@ class Activation(Layer):
# Arguments
activation: name of activation function to use
(see: [activations](../activations.md)),
or alternatively, a Theano or TensorFlow operation.
# Input shape
@@ -295,13 +293,13 @@ class Reshape(Layer):
"""Reshapes an output to a certain shape.
# Arguments
target_shape: target shape. Tuple of integers.
Does not include the batch axis.
target_shape: target shape. Tuple of integers,
does not include the samples dimension (batch size).
# Input shape
Arbitrary, although all dimensions in the input shaped must be fixed.
Use the keyword argument `input_shape`
(tuple of integers, does not include the batch axis)
(tuple of integers, does not include the samples axis)
when using this layer as the first layer in a model.
# Output shape
@@ -331,22 +329,27 @@ class Reshape(Layer):
self.target_shape = tuple(target_shape)
def _fix_unknown_dimension(self, input_shape, output_shape):
"""Finds and replaces a missing dimension in an output shape.
"""Find and replace a missing dimension in an output shape.
This is a near direct port of the internal Numpy function
`_fix_unknown_dimension` in `numpy/core/src/multiarray/shape.c`
# Arguments
input_shape: original shape of array being reshaped
output_shape: target shape of the array, with at most
input_shape: shape of array being reshaped
output_shape: desired shape of the array with at most
a single -1 which indicates a dimension that should be
derived from the input shape.
# Returns
The new output shape with a `-1` replaced with its computed value.
The new output shape with a -1 replaced with its computed value.
Raises a ValueError if the total array size of the output_shape is
different then the input_shape, or more then one unknown dimension
is specified.
# Raises
ValueError: if `input_shape` and `output_shape` do not match.
ValueError: in case of invalid values
for `input_shape` or `input_shape`.
"""
output_shape = list(output_shape)
msg = 'total size of new array must be unchanged'
@@ -368,28 +371,24 @@ class Reshape(Layer):
output_shape[unknown] = original // known
elif original != known:
raise ValueError(msg)
return output_shape
return tuple(output_shape)
def compute_output_shape(self, input_shape):
return (input_shape[0],) + self._fix_unknown_dimension(
input_shape[1:], self.target_shape)
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
output_shape = [input_shape[0]]
output_shape += self._fix_unknown_dimension(input_shape[1:],
self.target_shape)
return tensor_shape.TensorShape(output_shape)
def call(self, inputs):
# In case the target shape is not fully defined,
# we need access to the shape of `inputs`.
# solution: rely on `K.int_shape`.
# we need access to the shape of x.
target_shape = self.target_shape
if -1 in target_shape:
# Target shape not fully defined.
input_shape = None
try:
input_shape = K.int_shape(inputs)
except TypeError:
pass
if input_shape is not None:
target_shape = self.compute_output_shape(input_shape)[1:]
return K.reshape(inputs, (-1,) + target_shape)
# target shape not fully defined
target_shape = self._compute_output_shape(inputs.get_shape())
target_shape = target_shape.as_list()[1:]
return K.reshape(inputs, (-1,) + tuple(target_shape))
def get_config(self):
config = {'target_shape': self.target_shape}
@@ -432,13 +431,13 @@ class Permute(Layer):
self.dims = tuple(dims)
self.input_spec = InputSpec(ndim=len(self.dims) + 1)
def compute_output_shape(self, input_shape):
input_shape = list(input_shape)
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
output_shape = copy.copy(input_shape)
for i, dim in enumerate(self.dims):
target_dim = input_shape[dim]
output_shape[i + 1] = target_dim
return tuple(output_shape)
return tensor_shape.TensorShape(output_shape)
def call(self, inputs):
return K.permute_dimensions(inputs, (0,) + self.dims)
@@ -456,7 +455,7 @@ class Flatten(Layer):
```python
model = Sequential()
model.add(Conv2D(64, 3, 3,
model.add(Convolution2D(64, 3, 3,
border_mode='same',
input_shape=(3, 32, 32)))
# now: model.output_shape == (None, 64, 32, 32)
@@ -470,7 +469,8 @@ class Flatten(Layer):
super(Flatten, self).__init__(**kwargs)
self.input_spec = InputSpec(min_ndim=3)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if not all(input_shape[1:]):
raise ValueError('The shape of the input to "Flatten" '
'is not fully defined '
@@ -478,10 +478,12 @@ class Flatten(Layer):
'Make sure to pass a complete "input_shape" '
'or "batch_input_shape" argument to the first '
'layer in your model.')
return (input_shape[0], np.prod(input_shape[1:]))
return tensor_shape.TensorShape([input_shape[0], np.prod(input_shape[1:])])
def call(self, inputs):
return K.batch_flatten(inputs)
outputs = K.batch_flatten(inputs)
outputs.set_shape(self._compute_output_shape(inputs.get_shape()))
return outputs
class RepeatVector(Layer):
@@ -514,8 +516,9 @@ class RepeatVector(Layer):
self.n = n
self.input_spec = InputSpec(ndim=2)
def compute_output_shape(self, input_shape):
return (input_shape[0], self.n, input_shape[1])
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
return tensor_shape.TensorShape([input_shape[0], self.n, input_shape[1]])
def call(self, inputs):
return K.repeat(inputs, self.n)
@@ -547,30 +550,12 @@ class Lambda(Layer):
neg = K.relu(-x)
return K.concatenate([pos, neg], axis=1)
def antirectifier_output_shape(input_shape):
shape = list(input_shape)
assert len(shape) == 2 # only valid for 2D tensors
shape[-1] *= 2
return tuple(shape)
model.add(Lambda(antirectifier,
output_shape=antirectifier_output_shape))
model.add(Lambda(antirectifier))
```
# Arguments
function: The function to be evaluated.
Takes input tensor as first argument.
output_shape: Expected output shape from function.
Only relevant when using Theano.
Can be a tuple or function.
If a tuple, it only specifies the first dimension onward;
sample dimension is assumed either the same as the input:
`output_shape = (input_shape[0], ) + output_shape`
or, the input is `None` and
the sample dimension is also `None`:
`output_shape = (None, ) + output_shape`
If a function, it specifies the entire shape as a function of the
input shape: `output_shape = f(input_shape)`
arguments: optional dictionary of keyword arguments to be passed
to the function.
@@ -584,9 +569,10 @@ class Lambda(Layer):
(or auto-inferred when using TensorFlow).
"""
@interfaces.legacy_lambda_support
def __init__(self, function, output_shape=None,
mask=None, arguments=None, **kwargs):
def __init__(self, function,
mask=None,
arguments=None,
**kwargs):
super(Lambda, self).__init__(**kwargs)
self.function = function
self.arguments = arguments if arguments else {}
@@ -594,55 +580,10 @@ class Lambda(Layer):
self.supports_masking = True
self.mask = mask
if output_shape is None:
self._output_shape = None
elif isinstance(output_shape, (tuple, list)):
self._output_shape = tuple(output_shape)
else:
if not callable(output_shape):
raise TypeError('In Lambda, `output_shape` '
'must be a list, a tuple, or a function.')
self._output_shape = output_shape
def compute_output_shape(self, input_shape):
if self._output_shape is None:
# With TensorFlow, we can infer the output shape directly:
if K.backend() == 'tensorflow':
if isinstance(input_shape, list):
xs = [K.placeholder(shape=shape) for shape in input_shape]
x = self.call(xs)
else:
x = K.placeholder(shape=input_shape)
x = self.call(x)
if isinstance(x, list):
return [K.int_shape(x_elem) for x_elem in x]
else:
return K.int_shape(x)
# Otherwise, we default to the input shape.
warnings.warn('`output_shape` argument not specified for layer {} '
'and cannot be automatically inferred '
'with the Theano backend. '
'Defaulting to output shape `{}` '
'(same as input shape). '
'If the expected output shape is different, '
'specify it via the `output_shape` argument.'
.format(self.name, input_shape))
return input_shape
elif isinstance(self._output_shape, (tuple, list)):
if isinstance(input_shape, list):
num_samples = input_shape[0][0]
else:
num_samples = input_shape[0] if input_shape else None
return (num_samples,) + tuple(self._output_shape)
else:
shape = self._output_shape(input_shape)
if not isinstance(shape, (list, tuple)):
raise ValueError('`output_shape` function must return a tuple.')
return tuple(shape)
def call(self, inputs, mask=None):
arguments = self.arguments
if has_arg(self.function, 'mask'):
arg_spec = inspect.getargspec(self.function)
if 'mask' in arg_spec.args:
arguments['mask'] = mask
return self.function(inputs, **arguments)
@@ -659,20 +600,8 @@ class Lambda(Layer):
function = self.function.__name__
function_type = 'function'
if isinstance(self._output_shape, python_types.LambdaType):
output_shape = func_dump(self._output_shape)
output_shape_type = 'lambda'
elif callable(self._output_shape):
output_shape = self._output_shape.__name__
output_shape_type = 'function'
else:
output_shape = self._output_shape
output_shape_type = 'raw'
config = {'function': function,
'function_type': function_type,
'output_shape': output_shape,
'output_shape_type': output_shape_type,
'arguments': self.arguments}
base_config = super(Lambda, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -695,31 +624,7 @@ class Lambda(Layer):
else:
raise TypeError('Unknown function type:', function_type)
output_shape_type = config.pop('output_shape_type')
if output_shape_type == 'function':
# Simple lookup in custom objects
output_shape = deserialize_keras_object(
config['output_shape'],
custom_objects=custom_objects,
printable_module_name='output_shape function in Lambda layer')
elif output_shape_type == 'lambda':
# Unsafe deserialization from bytecode
output_shape = func_load(config['output_shape'], globs=globs)
else:
output_shape = config['output_shape']
# If arguments were numpy array, they have been saved as
# list. We need to recover the ndarray
if 'arguments' in config:
for key in config['arguments']:
if isinstance(config['arguments'][key], dict):
arg_dict = config['arguments'][key]
if 'type' in arg_dict and arg_dict['type'] == 'ndarray':
# Overwrite the argument with its numpy translation
config['arguments'][key] = np.array(arg_dict['value'])
config['function'] = function
config['output_shape'] = output_shape
return cls(**config)
@@ -752,28 +657,20 @@ class Dense(Layer):
# Arguments
units: Positive integer, dimensionality of the output space.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you don't specify anything, no activation is applied
(ie. "linear" activation: `a(x) = x`).
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
kernel_initializer: Initializer for the `kernel` weights matrix.
bias_initializer: Initializer for the bias vector.
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to
the `kernel` weights matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the `kernel` weights matrix.
bias_constraint: Constraint function applied to the bias vector.
# Input shape
nD tensor with shape: `(batch_size, ..., input_dim)`.
@@ -786,7 +683,6 @@ class Dense(Layer):
the output would have shape `(batch_size, units)`.
"""
@interfaces.legacy_dense_support
def __init__(self, units,
activation=None,
use_bias=True,
@@ -842,12 +738,13 @@ class Dense(Layer):
output = self.activation(output)
return output
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
assert input_shape and len(input_shape) >= 2
assert input_shape[-1]
output_shape = list(input_shape)
output_shape[-1] = self.units
return tuple(output_shape)
return tensor_shape.TensorShape(output_shape)
def get_config(self):
config = {
+22 -32
Ver Arquivo
@@ -1,11 +1,15 @@
"""Embedding layer.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from ..engine import Layer
from ..legacy import interfaces
from tensorflow.python.framework import tensor_shape
class Embedding(Layer):
@@ -34,18 +38,15 @@ class Embedding(Layer):
input_dim: int > 0. Size of the vocabulary,
i.e. maximum integer index + 1.
output_dim: int >= 0. Dimension of the dense embedding.
embeddings_initializer: Initializer for the `embeddings` matrix
(see [initializers](../initializers.md)).
embeddings_initializer: Initializer for the `embeddings` matrix.
embeddings_regularizer: Regularizer function applied to
the `embeddings` matrix
(see [regularizer](../regularizers.md)).
the `embeddings` matrix.
embeddings_constraint: Constraint function applied to
the `embeddings` matrix
(see [constraints](../constraints.md)).
the `embeddings` matrix.
mask_zero: Whether or not the input value 0 is a special "padding"
value that should be masked out.
This is useful when using [recurrent layers](recurrent.md)
which may take variable length input.
This is useful when using recurrent layers,
which may take variable length inputs.
If this is `True` then all subsequent layers
in the model need to support masking or an exception will be raised.
If mask_zero is set to True, as a consequence, index 0 cannot be
@@ -66,7 +67,6 @@ class Embedding(Layer):
- [A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)
"""
@interfaces.legacy_embedding_support
def __init__(self, input_dim, output_dim,
embeddings_initializer='uniform',
embeddings_regularizer=None,
@@ -75,6 +75,7 @@ class Embedding(Layer):
mask_zero=False,
input_length=None,
**kwargs):
kwargs['dtype'] = 'int32'
if 'input_shape' not in kwargs:
if input_length:
kwargs['input_shape'] = (input_length,)
@@ -92,13 +93,13 @@ class Embedding(Layer):
self.input_length = input_length
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
self.embeddings = self.add_weight(
shape=(self.input_dim, self.output_dim),
initializer=self.embeddings_initializer,
name='embeddings',
regularizer=self.embeddings_regularizer,
constraint=self.embeddings_constraint,
dtype=self.dtype)
constraint=self.embeddings_constraint)
self.built = True
def compute_mask(self, inputs, mask=None):
@@ -107,26 +108,15 @@ class Embedding(Layer):
else:
return K.not_equal(inputs, 0)
def compute_output_shape(self, input_shape):
if self.input_length is None:
return input_shape + (self.output_dim,)
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if not self.input_length:
input_length = input_shape[1]
else:
# input_length can be tuple if input is 3D or higher
if isinstance(self.input_length, (list, tuple)):
in_lens = list(self.input_length)
else:
in_lens = [self.input_length]
if len(in_lens) != len(input_shape) - 1:
ValueError('"input_length" is %s, but received input has shape %s' %
(str(self.input_length), str(input_shape)))
else:
for i, (s1, s2) in enumerate(zip(in_lens, input_shape[1:])):
if s1 is not None and s2 is not None and s1 != s2:
ValueError('"input_length" is %s, but received input has shape %s' %
(str(self.input_length), str(input_shape)))
elif s1 is None:
in_lens[i] = s2
return (input_shape[0],) + tuple(in_lens) + (self.output_dim,)
input_length = self.input_length
return tensor_shape.TensorShape([input_shape[0],
input_length,
self.output_dim])
def call(self, inputs):
if K.dtype(inputs) != 'int32':
+101 -57
Ver Arquivo
@@ -1,15 +1,19 @@
"""Locally-connected layers.
"""
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from .. import activations
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from ..engine import Layer
from ..engine import InputSpec
from ..engine import Layer
from tensorflow.python.framework import tensor_shape
from ..utils import conv_utils
from ..legacy import interfaces
class LocallyConnected1D(Layer):
@@ -43,27 +47,19 @@ class LocallyConnected1D(Layer):
any `dilation_rate` value != 1.
padding: Currently only supports `"valid"` (case-insensitive).
`"same"` may be supported in the future.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you don't specify anything, no activation is applied
(ie. "linear" activation: `a(x) = x`).
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
kernel_initializer: Initializer for the `kernel` weights matrix.
bias_initializer: Initializer for the bias vector.
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
kernel_constraint: Constraint function applied to the kernel matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to the kernel matrix.
bias_constraint: Constraint function applied to the bias vector.
# Input shape
3D tensor with shape: `(batch_size, steps, input_dim)`
@@ -73,7 +69,6 @@ class LocallyConnected1D(Layer):
`steps` value might have changed due to padding or strides.
"""
@interfaces.legacy_conv1d_support
def __init__(self, filters,
kernel_size,
strides=1,
@@ -110,6 +105,7 @@ class LocallyConnected1D(Layer):
self.input_spec = InputSpec(ndim=3)
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
input_dim = input_shape[2]
if input_dim is None:
raise ValueError('Axis 2 of input should be fully-defined. '
@@ -139,19 +135,31 @@ class LocallyConnected1D(Layer):
self.input_spec = InputSpec(ndim=3, axes={2: input_dim})
self.built = True
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
length = conv_utils.conv_output_length(input_shape[1],
self.kernel_size[0],
self.padding,
self.strides[0])
return (input_shape[0], length, self.filters)
return tensor_shape.TensorShape([input_shape[0], length, self.filters])
def call(self, inputs):
output_length, _, filters = self.kernel_shape
stride = self.strides[0]
output_length, feature_dim, filters = self.kernel_shape
xs = []
for i in range(output_length):
slice_length = slice(i * stride,
i * stride + self.kernel_size[0])
xs.append(K.reshape(inputs[:, slice_length, :],
(1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
# Shape: `(output_length, batch_size, filters)`.
output = K.batch_dot(x_aggregate, self.kernel)
output = K.permute_dimensions(output, (1, 0, 2))
output = K.local_conv1d(inputs, self.kernel, self.kernel_size, self.strides)
if self.use_bias:
output = K.bias_add(output, self.bias)
output += K.reshape(self.bias, (1, output_length, filters))
if self.activation is not None:
output = self.activation(output)
return output
@@ -221,27 +229,19 @@ class LocallyConnected2D(Layer):
It defaults to the `image_data_format` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "channels_last".
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you don't specify anything, no activation is applied
(ie. "linear" activation: `a(x) = x`).
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
kernel_initializer: Initializer for the `kernel` weights matrix.
bias_initializer: Initializer for the bias vector.
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
kernel_constraint: Constraint function applied to the kernel matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to the kernel matrix.
bias_constraint: Constraint function applied to the bias vector.
# Input shape
4D tensor with shape:
@@ -257,7 +257,6 @@ class LocallyConnected2D(Layer):
`rows` and `cols` values might have changed due to padding.
"""
@interfaces.legacy_conv2d_support
def __init__(self, filters,
kernel_size,
strides=(1, 1),
@@ -294,6 +293,7 @@ class LocallyConnected2D(Layer):
self.input_spec = InputSpec(ndim=4)
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_last':
input_row, input_col = input_shape[1:-1]
input_filter = input_shape[3]
@@ -305,6 +305,7 @@ class LocallyConnected2D(Layer):
' a LocallyConnected2D layer '
'should be fully-defined, but layer received '
'the inputs shape ' + str(input_shape))
output_row = conv_utils.conv_output_length(input_row, self.kernel_size[0],
self.padding, self.strides[0])
output_col = conv_utils.conv_output_length(input_col, self.kernel_size[1],
@@ -333,38 +334,81 @@ class LocallyConnected2D(Layer):
self.input_spec = InputSpec(ndim=4, axes={-1: input_filter})
self.built = True
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_first':
rows = input_shape[2]
cols = input_shape[3]
elif self.data_format == 'channels_last':
rows = input_shape[1]
cols = input_shape[2]
rows = conv_utils.conv_output_length(rows, self.kernel_size[0],
self.padding, self.strides[0])
cols = conv_utils.conv_output_length(cols, self.kernel_size[1],
self.padding, self.strides[1])
if self.data_format == 'channels_first':
return (input_shape[0], self.filters, rows, cols)
return tensor_shape.TensorShape([input_shape[0], self.filters, rows, cols])
elif self.data_format == 'channels_last':
return (input_shape[0], rows, cols, self.filters)
return tensor_shape.TensorShape([input_shape[0], rows, cols, self.filters])
def call(self, inputs):
_, _, filters = self.kernel_shape
stride_row, stride_col = self.strides
_, feature_dim, filters = self.kernel_shape
output = K.local_conv2d(inputs,
self.kernel,
self.kernel_size,
self.strides,
(self.output_row, self.output_col),
self.data_format)
if self.data_format == 'channels_first':
if K.backend() == 'theano':
output = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.kernel_size[0])
slice_col = slice(j * stride_col,
j * stride_col + self.kernel_size[1])
x_flatten = K.reshape(inputs[:, :, slice_row, slice_col],
(1, -1, feature_dim))
output.append(K.dot(x_flatten,
self.kernel[i * self.output_col + j, :, :]))
output = K.concatenate(output, axis=0)
else:
xs = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.kernel_size[0])
slice_col = slice(j * stride_col,
j * stride_col + self.kernel_size[1])
xs.append(K.reshape(inputs[:, :, slice_row, slice_col],
(1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
output = K.batch_dot(x_aggregate, self.kernel)
output = K.reshape(output,
(self.output_row, self.output_col, -1, filters))
output = K.permute_dimensions(output, (2, 3, 0, 1))
elif self.data_format == 'channels_last':
xs = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.kernel_size[0])
slice_col = slice(j * stride_col,
j * stride_col + self.kernel_size[1])
xs.append(K.reshape(inputs[:, slice_row, slice_col, :],
(1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
output = K.batch_dot(x_aggregate, self.kernel)
output = K.reshape(output,
(self.output_row, self.output_col, -1, filters))
output = K.permute_dimensions(output, (2, 0, 1, 3))
if self.use_bias:
if self.data_format == 'channels_first' or self.data_format == 'channels_last':
output = K.bias_add(output, self.bias, data_format=self.data_format)
if self.data_format == 'channels_first':
output += K.reshape(self.bias,
(1, filters, self.output_row, self.output_col))
elif self.data_format == 'channels_last':
output += K.reshape(self.bias,
(1, self.output_row, self.output_col, filters))
output = self.activation(output)
return output
+20 -12
Ver Arquivo
@@ -1,5 +1,12 @@
from ..engine.topology import Layer
"""Layers can merge several input tensors into a single output tensor.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from ..engine.topology import Layer
from tensorflow.python.framework import tensor_shape
class _Merge(Layer):
@@ -38,7 +45,7 @@ class _Merge(Layer):
return None
elif len(shape1) < len(shape2):
return self._compute_elemwise_op_output_shape(shape2, shape1)
elif len(shape2) == 0:
elif not shape2:
return shape1
output_shape = list(shape1[:-len(shape2)])
for i, j in zip(shape1[-len(shape2):], shape2):
@@ -265,7 +272,7 @@ class Concatenate(_Merge):
'on a list of inputs')
if all([shape is None for shape in input_shape]):
return
reduced_inputs_shapes = [list(shape) for shape in input_shape]
reduced_inputs_shapes = [tensor_shape.TensorShape(shape).as_list() for shape in input_shape]
shape_set = set()
for i in range(len(reduced_inputs_shapes)):
del reduced_inputs_shapes[i][self.axis]
@@ -282,18 +289,19 @@ class Concatenate(_Merge):
'on a list of inputs.')
return K.concatenate(inputs, axis=self.axis)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
if not isinstance(input_shape, list):
raise ValueError('A `Concatenate` layer should be called '
'on a list of inputs.')
input_shapes = input_shape
output_shape = list(input_shapes[0])
output_shape = tensor_shape.TensorShape(input_shapes[0]).as_list()
for shape in input_shapes[1:]:
shape = tensor_shape.TensorShape(shape).as_list()
if output_shape[self.axis] is None or shape[self.axis] is None:
output_shape[self.axis] = None
break
output_shape[self.axis] += shape[self.axis]
return tuple(output_shape)
return tensor_shape.TensorShape(output_shape)
def compute_mask(self, inputs, mask=None):
if mask is None:
@@ -371,8 +379,8 @@ class Dot(_Merge):
if not isinstance(input_shape, list) or len(input_shape) != 2:
raise ValueError('A `Dot` layer should be called '
'on a list of 2 inputs.')
shape1 = input_shape[0]
shape2 = input_shape[1]
shape1 = tensor_shape.TensorShape(input_shape[0]).as_list()
shape2 = tensor_shape.TensorShape(input_shape[1]).as_list()
if shape1 is None or shape2 is None:
return
if isinstance(self.axes, int):
@@ -409,12 +417,12 @@ class Dot(_Merge):
output = K.batch_dot(x1, x2, axes)
return output
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
if not isinstance(input_shape, list) or len(input_shape) != 2:
raise ValueError('A `Dot` layer should be called '
'on a list of 2 inputs.')
shape1 = list(input_shape[0])
shape2 = list(input_shape[1])
shape1 = tensor_shape.TensorShape(input_shape[0]).as_list()
shape2 = tensor_shape.TensorShape(input_shape[1]).as_list()
if isinstance(self.axes, int):
if self.axes < 0:
axes = [self.axes % len(shape1), self.axes % len(shape2)]
@@ -428,7 +436,7 @@ class Dot(_Merge):
output_shape = shape1 + shape2
if len(output_shape) == 1:
output_shape += [1]
return tuple(output_shape)
return tensor_shape.TensorShape(output_shape)
def compute_mask(self, inputs, mask=None):
return None
+5 -72
Ver Arquivo
@@ -1,11 +1,13 @@
# -*- coding: utf-8 -*-
"""Layers for regularization models via the addition of noise.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from ..engine import Layer
from .. import backend as K
from ..engine import Layer
import numpy as np
from ..legacy import interfaces
from ..engine import InputSpec
class GaussianNoise(Layer):
@@ -30,7 +32,6 @@ class GaussianNoise(Layer):
Same shape as input.
"""
@interfaces.legacy_gaussiannoise_support
def __init__(self, stddev, **kwargs):
super(GaussianNoise, self).__init__(**kwargs)
self.supports_masking = True
@@ -71,7 +72,6 @@ class GaussianDropout(Layer):
- [Dropout: A Simple Way to Prevent Neural Networks from Overfitting Srivastava, Hinton, et al. 2014](http://www.cs.toronto.edu/~rsalakhu/papers/srivastava14a.pdf)
"""
@interfaces.legacy_gaussiandropout_support
def __init__(self, rate, **kwargs):
super(GaussianDropout, self).__init__(**kwargs)
self.supports_masking = True
@@ -91,70 +91,3 @@ class GaussianDropout(Layer):
config = {'rate': self.rate}
base_config = super(GaussianDropout, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class AlphaDropout(Layer):
"""Applies Alpha Dropout to the input.
Alpha Dropout is a `Dropout` that keeps mean and variance of inputs
to their original values, in order to ensure the self-normalizing property
even after this dropout.
Alpha Dropout fits well to Scaled Exponential Linear Units
by randomly setting activations to the negative saturation value.
# Arguments
rate: float, drop probability (as with `Dropout`).
The multiplicative noise will have
standard deviation `sqrt(rate / (1 - rate))`.
seed: A Python integer to use as random seed.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
(tuple of integers, does not include the samples axis)
when using this layer as the first layer in a model.
# Output shape
Same shape as input.
# References
- [Self-Normalizing Neural Networks](https://arxiv.org/abs/1706.02515)
"""
def __init__(self, rate, noise_shape=None, seed=None, **kwargs):
super(AlphaDropout, self).__init__(**kwargs)
self.rate = rate
self.noise_shape = noise_shape
self.seed = seed
self.supports_masking = True
def _get_noise_shape(self, inputs):
return self.noise_shape if self.noise_shape else K.shape(inputs)
def call(self, inputs, training=None):
if 0. < self.rate < 1.:
noise_shape = self._get_noise_shape(inputs)
def dropped_inputs(inputs=inputs, rate=self.rate, seed=self.seed):
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
alpha_p = -alpha * scale
kept_idx = K.greater_equal(K.random_uniform(noise_shape, seed=seed), rate)
kept_idx = K.cast(kept_idx, K.floatx())
# Get affine transformation params
a = ((1 - rate) * (1 + rate * alpha_p ** 2)) ** -0.5
b = -a * alpha_p * rate
# Apply mask
x = inputs * kept_idx + alpha_p * (1 - kept_idx)
# Do affine transformation
return a * x + b
return K.in_train_phase(dropped_inputs, inputs, training=training)
return inputs
def get_config(self):
config = {'rate': self.rate}
base_config = super(AlphaDropout, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+12 -7
Ver Arquivo
@@ -1,12 +1,17 @@
# -*- coding: utf-8 -*-
"""Normalization layers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from ..engine import Layer, InputSpec
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from .. import backend as K
from ..legacy import interfaces
from ..engine import InputSpec
from ..engine import Layer
from tensorflow.python.framework import tensor_shape
class BatchNormalization(Layer):
@@ -52,7 +57,6 @@ class BatchNormalization(Layer):
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](https://arxiv.org/abs/1502.03167)
"""
@interfaces.legacy_batchnorm_support
def __init__(self,
axis=-1,
momentum=0.99,
@@ -85,6 +89,7 @@ class BatchNormalization(Layer):
self.gamma_constraint = constraints.get(gamma_constraint)
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
dim = input_shape[self.axis]
if dim is None:
raise ValueError('Axis ' + str(self.axis) + ' of '
@@ -124,7 +129,7 @@ class BatchNormalization(Layer):
self.built = True
def call(self, inputs, training=None):
input_shape = K.int_shape(inputs)
input_shape = inputs.get_shape().as_list()
# Prepare broadcasting shape.
ndim = len(input_shape)
reduction_axes = list(range(len(input_shape)))
@@ -137,7 +142,7 @@ class BatchNormalization(Layer):
def normalize_inference():
if needs_broadcasting:
# In this case we must explicitly broadcast all parameters.
# In this case we must explictly broadcast all parameters.
broadcast_moving_mean = K.reshape(self.moving_mean,
broadcast_shape)
broadcast_moving_variance = K.reshape(self.moving_variance,
+40 -34
Ver Arquivo
@@ -1,11 +1,15 @@
# -*- coding: utf-8 -*-
"""Pooling layers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
from ..engine import Layer
from ..engine import InputSpec
from ..engine import Layer
from tensorflow.python.framework import tensor_shape
from ..utils import conv_utils
from ..legacy import interfaces
class _Pooling1D(Layer):
@@ -22,12 +26,13 @@ class _Pooling1D(Layer):
self.padding = conv_utils.normalize_padding(padding)
self.input_spec = InputSpec(ndim=3)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
length = conv_utils.conv_output_length(input_shape[1],
self.pool_size[0],
self.padding,
self.strides[0])
return (input_shape[0], length, input_shape[2])
return tensor_shape.TensorShape([input_shape[0], length, input_shape[2]])
def _pooling_function(self, inputs, pool_size, strides,
padding, data_format):
@@ -67,7 +72,6 @@ class MaxPooling1D(_Pooling1D):
3D tensor with shape: `(batch_size, downsampled_steps, features)`.
"""
@interfaces.legacy_pooling1d_support
def __init__(self, pool_size=2, strides=None,
padding='valid', **kwargs):
super(MaxPooling1D, self).__init__(pool_size, strides,
@@ -97,7 +101,6 @@ class AveragePooling1D(_Pooling1D):
3D tensor with shape: `(batch_size, downsampled_steps, features)`.
"""
@interfaces.legacy_pooling1d_support
def __init__(self, pool_size=2, strides=None,
padding='valid', **kwargs):
super(AveragePooling1D, self).__init__(pool_size, strides,
@@ -126,11 +129,12 @@ class _Pooling2D(Layer):
self.data_format = conv_utils.normalize_data_format(data_format)
self.input_spec = InputSpec(ndim=4)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_first':
rows = input_shape[2]
cols = input_shape[3]
elif self.data_format == 'channels_last':
else:
rows = input_shape[1]
cols = input_shape[2]
rows = conv_utils.conv_output_length(rows, self.pool_size[0],
@@ -138,9 +142,9 @@ class _Pooling2D(Layer):
cols = conv_utils.conv_output_length(cols, self.pool_size[1],
self.padding, self.strides[1])
if self.data_format == 'channels_first':
return (input_shape[0], input_shape[1], rows, cols)
elif self.data_format == 'channels_last':
return (input_shape[0], rows, cols, input_shape[3])
return tensor_shape.TensorShape([input_shape[0], input_shape[1], rows, cols])
else:
return tensor_shape.TensorShape([input_shape[0], rows, cols, input_shape[3]])
def _pooling_function(self, inputs, pool_size, strides,
padding, data_format):
@@ -204,7 +208,6 @@ class MaxPooling2D(_Pooling2D):
`(batch_size, channels, pooled_rows, pooled_cols)`
"""
@interfaces.legacy_pooling2d_support
def __init__(self, pool_size=(2, 2), strides=None, padding='valid',
data_format=None, **kwargs):
super(MaxPooling2D, self).__init__(pool_size, strides, padding,
@@ -259,7 +262,6 @@ class AveragePooling2D(_Pooling2D):
`(batch_size, channels, pooled_rows, pooled_cols)`
"""
@interfaces.legacy_pooling2d_support
def __init__(self, pool_size=(2, 2), strides=None, padding='valid',
data_format=None, **kwargs):
super(AveragePooling2D, self).__init__(pool_size, strides, padding,
@@ -287,12 +289,13 @@ class _Pooling3D(Layer):
self.data_format = conv_utils.normalize_data_format(data_format)
self.input_spec = InputSpec(ndim=5)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_first':
len_dim1 = input_shape[2]
len_dim2 = input_shape[3]
len_dim3 = input_shape[4]
elif self.data_format == 'channels_last':
else:
len_dim1 = input_shape[1]
len_dim2 = input_shape[2]
len_dim3 = input_shape[3]
@@ -303,13 +306,17 @@ class _Pooling3D(Layer):
len_dim3 = conv_utils.conv_output_length(len_dim3, self.pool_size[2],
self.padding, self.strides[2])
if self.data_format == 'channels_first':
return (input_shape[0],
input_shape[1],
len_dim1, len_dim2, len_dim3)
elif self.data_format == 'channels_last':
return (input_shape[0],
len_dim1, len_dim2, len_dim3,
input_shape[4])
return tensor_shape.TensorShape([input_shape[0],
input_shape[1],
len_dim1,
len_dim2,
len_dim3])
else:
return tensor_shape.TensorShape([input_shape[0],
len_dim1,
len_dim2,
len_dim3,
input_shape[4]])
def _pooling_function(self, inputs, pool_size, strides,
padding, data_format):
@@ -369,7 +376,6 @@ class MaxPooling3D(_Pooling3D):
`(batch_size, channels, pooled_dim1, pooled_dim2, pooled_dim3)`
"""
@interfaces.legacy_pooling3d_support
def __init__(self, pool_size=(2, 2, 2), strides=None, padding='valid',
data_format=None, **kwargs):
super(MaxPooling3D, self).__init__(pool_size, strides, padding,
@@ -419,7 +425,6 @@ class AveragePooling3D(_Pooling3D):
`(batch_size, channels, pooled_dim1, pooled_dim2, pooled_dim3)`
"""
@interfaces.legacy_pooling3d_support
def __init__(self, pool_size=(2, 2, 2), strides=None, padding='valid',
data_format=None, **kwargs):
super(AveragePooling3D, self).__init__(pool_size, strides, padding,
@@ -441,8 +446,9 @@ class _GlobalPooling1D(Layer):
super(_GlobalPooling1D, self).__init__(**kwargs)
self.input_spec = InputSpec(ndim=3)
def compute_output_shape(self, input_shape):
return (input_shape[0], input_shape[2])
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
return tensor_shape.TensorShape([input_shape[0], input_shape[2]])
def call(self, inputs):
raise NotImplementedError
@@ -482,17 +488,17 @@ class _GlobalPooling2D(Layer):
"""Abstract class for different global pooling 2D layers.
"""
@interfaces.legacy_global_pooling_support
def __init__(self, data_format=None, **kwargs):
super(_GlobalPooling2D, self).__init__(**kwargs)
self.data_format = conv_utils.normalize_data_format(data_format)
self.input_spec = InputSpec(ndim=4)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_last':
return (input_shape[0], input_shape[3])
return tensor_shape.TensorShape([input_shape[0], input_shape[3]])
else:
return (input_shape[0], input_shape[1])
return tensor_shape.TensorShape([input_shape[0], input_shape[1]])
def call(self, inputs):
raise NotImplementedError
@@ -577,17 +583,17 @@ class _GlobalPooling3D(Layer):
"""Abstract class for different global pooling 3D layers.
"""
@interfaces.legacy_global_pooling_support
def __init__(self, data_format=None, **kwargs):
super(_GlobalPooling3D, self).__init__(**kwargs)
self.data_format = conv_utils.normalize_data_format(data_format)
self.input_spec = InputSpec(ndim=5)
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.data_format == 'channels_last':
return (input_shape[0], input_shape[4])
return tensor_shape.TensorShape([input_shape[0], input_shape[4]])
else:
return (input_shape[0], input_shape[1])
return tensor_shape.TensorShape([input_shape[0], input_shape[1]])
def call(self, inputs):
raise NotImplementedError
+70 -131
Ver Arquivo
@@ -1,16 +1,20 @@
# -*- coding: utf-8 -*-
"""Recurrent layers.
"""
from __future__ import absolute_import
import numpy as np
from __future__ import division
from __future__ import print_function
from .. import backend as K
from .. import activations
from .. import backend as K
from .. import constraints
from .. import initializers
from .. import regularizers
from .. import constraints
from ..engine import Layer
from ..engine import InputSpec
from ..legacy import interfaces
from ..engine import Layer
import numpy as np
from tensorflow.python.framework import tensor_shape
# pylint: disable=access-member-before-definition
def _time_distributed_dense(x, w, b=None, dropout=None,
input_dim=None, output_dim=None,
@@ -96,8 +100,6 @@ class Recurrent(Layer):
`[(input_dim, output_dim), (output_dim, output_dim), (output_dim,)]`.
return_sequences: Boolean. Whether to return the last output
in the output sequence, or the full sequence.
return_state: Boolean. Whether to return the last state
in addition to the output.
go_backwards: Boolean (default False).
If True, process the input sequence backwards and return the
reversed sequence.
@@ -141,9 +143,6 @@ class Recurrent(Layer):
(Optional) 2D tensors with shape `(batch_size, output_dim)`.
# Output shape
- if `return_state`: a list of tensors. The first tensor is
the output. The remaining tensors are the last states,
each with shape `(batch_size, units)`.
- if `return_sequences`: 3D tensor with shape
`(batch_size, timesteps, units)`.
- else, 2D tensor with shape `(batch_size, units)`.
@@ -151,7 +150,7 @@ class Recurrent(Layer):
# Masking
This layer supports masking for input data with a variable number
of timesteps. To introduce masks to your data,
use an [Embedding](embeddings.md) layer with the `mask_zero` parameter
use an `Embedding` layer with the `mask_zero` parameter
set to `True`.
# Note on using statefulness in RNNs
@@ -188,7 +187,6 @@ class Recurrent(Layer):
"""
def __init__(self, return_sequences=False,
return_state=False,
go_backwards=False,
stateful=False,
unroll=False,
@@ -196,11 +194,7 @@ class Recurrent(Layer):
**kwargs):
super(Recurrent, self).__init__(**kwargs)
self.return_sequences = return_sequences
self.return_state = return_state
self.go_backwards = go_backwards
if K.backend() == 'cntk' and stateful:
raise ValueError('Stateful RNN is not currently supported with CNTK.')
self.stateful = stateful
self.unroll = unroll
self.implementation = implementation
@@ -210,30 +204,22 @@ class Recurrent(Layer):
self.dropout = 0
self.recurrent_dropout = 0
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
if isinstance(input_shape, list):
input_shape = input_shape[0]
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.return_sequences:
output_shape = (input_shape[0], input_shape[1], self.units)
return tensor_shape.TensorShape([input_shape[0], input_shape[1], self.units])
else:
output_shape = (input_shape[0], self.units)
if self.return_state:
state_shape = [(input_shape[0], self.units) for _ in self.states]
return [output_shape] + state_shape
else:
return output_shape
return tensor_shape.TensorShape([input_shape[0], self.units])
def compute_mask(self, inputs, mask):
if isinstance(mask, list):
mask = mask[0]
output_mask = mask if self.return_sequences else None
if self.return_state:
state_mask = [None for _ in self.states]
return [output_mask] + state_mask
if self.return_sequences:
if isinstance(mask, list):
return mask[0]
return mask
else:
return output_mask
return None
def step(self, inputs, states):
raise NotImplementedError
@@ -337,8 +323,7 @@ class Recurrent(Layer):
go_backwards=self.go_backwards,
mask=mask,
constants=constants,
unroll=self.unroll,
input_length=input_shape[1])
unroll=self.unroll)
if self.stateful:
updates = []
for i in range(len(states)):
@@ -351,18 +336,9 @@ class Recurrent(Layer):
outputs._uses_learning_phase = True
if self.return_sequences:
output = outputs
return outputs
else:
output = last_output
if self.return_state:
if not isinstance(states, (list, tuple)):
states = [states]
else:
states = list(states)
return [output] + states
else:
return output
return last_output
def reset_states(self, states=None):
if not self.stateful:
@@ -406,7 +382,6 @@ class Recurrent(Layer):
def get_config(self):
config = {'return_sequences': self.return_sequences,
'return_state': self.return_state,
'go_backwards': self.go_backwards,
'stateful': self.stateful,
'unroll': self.unroll,
@@ -420,39 +395,29 @@ class SimpleRNN(Recurrent):
# Arguments
units: Positive integer, dimensionality of the output space.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you don't specify anything, no activation is applied
If you pass None, no activation is applied
(ie. "linear" activation: `a(x) = x`).
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix,
used for the linear transformation of the inputs.
(see [initializers](../initializers.md)).
used for the linear transformation of the inputs..
recurrent_initializer: Initializer for the `recurrent_kernel`
weights matrix,
used for the linear transformation of the recurrent state.
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
used for the linear transformation of the recurrent state..
bias_initializer: Initializer for the bias vector.
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
recurrent_regularizer: Regularizer function applied to
the `recurrent_kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `recurrent_kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to
the `kernel` weights matrix
(see [constraints](../constraints.md)).
the `kernel` weights matrix.
recurrent_constraint: Constraint function applied to
the `recurrent_kernel` weights matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the `recurrent_kernel` weights matrix.
bias_constraint: Constraint function applied to the bias vector.
dropout: Float between 0 and 1.
Fraction of the units to drop for
the linear transformation of the inputs.
@@ -464,7 +429,6 @@ class SimpleRNN(Recurrent):
- [A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)
"""
@interfaces.legacy_recurrent_support
def __init__(self, units,
activation='tanh',
use_bias=True,
@@ -506,6 +470,7 @@ class SimpleRNN(Recurrent):
def build(self, input_shape):
if isinstance(input_shape, list):
input_shape = input_shape[0]
input_shape = tensor_shape.TensorShape(input_shape).as_list()
batch_size = input_shape[0] if self.stateful else None
self.input_dim = input_shape[2]
@@ -540,7 +505,7 @@ class SimpleRNN(Recurrent):
if self.implementation > 0:
return inputs
else:
input_shape = K.int_shape(inputs)
input_shape = inputs.get_shape().as_list()
input_dim = input_shape[2]
timesteps = input_shape[1]
return _time_distributed_dense(inputs,
@@ -597,7 +562,7 @@ class SimpleRNN(Recurrent):
ones = K.ones_like(K.reshape(inputs[:, 0, 0], (-1, 1)))
ones = K.tile(ones, (1, self.units))
def dropped_inputs():
def dropped_inputs(): # pylint: disable=function-redefined
return K.dropout(ones, self.recurrent_dropout)
rec_dp_mask = K.in_train_phase(dropped_inputs,
ones,
@@ -632,42 +597,30 @@ class GRU(Recurrent):
# Arguments
units: Positive integer, dimensionality of the output space.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you pass None, no activation is applied
(ie. "linear" activation: `a(x) = x`).
recurrent_activation: Activation function to use
for the recurrent step
(see [activations](../activations.md)).
for the recurrent step.
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix,
used for the linear transformation of the inputs.
(see [initializers](../initializers.md)).
used for the linear transformation of the inputs..
recurrent_initializer: Initializer for the `recurrent_kernel`
weights matrix,
used for the linear transformation of the recurrent state.
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
used for the linear transformation of the recurrent state..
bias_initializer: Initializer for the bias vector.
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
recurrent_regularizer: Regularizer function applied to
the `recurrent_kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `recurrent_kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to
the `kernel` weights matrix
(see [constraints](../constraints.md)).
the `kernel` weights matrix.
recurrent_constraint: Constraint function applied to
the `recurrent_kernel` weights matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the `recurrent_kernel` weights matrix.
bias_constraint: Constraint function applied to the bias vector.
dropout: Float between 0 and 1.
Fraction of the units to drop for
the linear transformation of the inputs.
@@ -681,7 +634,6 @@ class GRU(Recurrent):
- [A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)
"""
@interfaces.legacy_recurrent_support
def __init__(self, units,
activation='tanh',
recurrent_activation='hard_sigmoid',
@@ -725,7 +677,7 @@ class GRU(Recurrent):
def build(self, input_shape):
if isinstance(input_shape, list):
input_shape = input_shape[0]
input_shape = tensor_shape.TensorShape(input_shape).as_list()
batch_size = input_shape[0] if self.stateful else None
self.input_dim = input_shape[2]
self.input_spec[0] = InputSpec(shape=(batch_size, None, self.input_dim))
@@ -776,7 +728,7 @@ class GRU(Recurrent):
def preprocess_input(self, inputs, training=None):
if self.implementation == 0:
input_shape = K.int_shape(inputs)
input_shape = inputs.get_shape().as_list()
input_dim = input_shape[2]
timesteps = input_shape[1]
@@ -815,7 +767,7 @@ class GRU(Recurrent):
ones = K.ones_like(K.reshape(inputs[:, 0, 0], (-1, 1)))
ones = K.tile(ones, (1, self.units))
def dropped_inputs():
def dropped_inputs(): # pylint: disable=function-redefined
return K.dropout(ones, self.recurrent_dropout)
rec_dp_mask = [K.in_train_phase(dropped_inputs,
ones,
@@ -905,46 +857,34 @@ class LSTM(Recurrent):
# Arguments
units: Positive integer, dimensionality of the output space.
activation: Activation function to use
(see [activations](../activations.md)).
activation: Activation function to use.
If you pass None, no activation is applied
(ie. "linear" activation: `a(x) = x`).
recurrent_activation: Activation function to use
for the recurrent step
(see [activations](../activations.md)).
for the recurrent step.
use_bias: Boolean, whether the layer uses a bias vector.
kernel_initializer: Initializer for the `kernel` weights matrix,
used for the linear transformation of the inputs.
(see [initializers](../initializers.md)).
used for the linear transformation of the inputs..
recurrent_initializer: Initializer for the `recurrent_kernel`
weights matrix,
used for the linear transformation of the recurrent state.
(see [initializers](../initializers.md)).
bias_initializer: Initializer for the bias vector
(see [initializers](../initializers.md)).
used for the linear transformation of the recurrent state..
bias_initializer: Initializer for the bias vector.
unit_forget_bias: Boolean.
If True, add 1 to the bias of the forget gate at initialization.
Setting it to true will also force `bias_initializer="zeros"`.
This is recommended in [Jozefowicz et al.](http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)
kernel_regularizer: Regularizer function applied to
the `kernel` weights matrix
(see [regularizer](../regularizers.md)).
the `kernel` weights matrix.
recurrent_regularizer: Regularizer function applied to
the `recurrent_kernel` weights matrix
(see [regularizer](../regularizers.md)).
bias_regularizer: Regularizer function applied to the bias vector
(see [regularizer](../regularizers.md)).
the `recurrent_kernel` weights matrix.
bias_regularizer: Regularizer function applied to the bias vector.
activity_regularizer: Regularizer function applied to
the output of the layer (its "activation").
(see [regularizer](../regularizers.md)).
the output of the layer (its "activation")..
kernel_constraint: Constraint function applied to
the `kernel` weights matrix
(see [constraints](../constraints.md)).
the `kernel` weights matrix.
recurrent_constraint: Constraint function applied to
the `recurrent_kernel` weights matrix
(see [constraints](../constraints.md)).
bias_constraint: Constraint function applied to the bias vector
(see [constraints](../constraints.md)).
the `recurrent_kernel` weights matrix.
bias_constraint: Constraint function applied to the bias vector.
dropout: Float between 0 and 1.
Fraction of the units to drop for
the linear transformation of the inputs.
@@ -953,12 +893,11 @@ class LSTM(Recurrent):
the linear transformation of the recurrent state.
# References
- [Long short-term memory](http://www.bioinf.jku.at/publications/older/2604.pdf) (original 1997 paper)
- [Learning to forget: Continual prediction with LSTM](http://www.mitpressjournals.org/doi/pdf/10.1162/089976600300015015)
- [Long short-term memory](http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf) (original 1997 paper)
- [Supervised sequence labeling with recurrent neural networks](http://www.cs.toronto.edu/~graves/preprint.pdf)
- [A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)
"""
@interfaces.legacy_recurrent_support
def __init__(self, units,
activation='tanh',
recurrent_activation='hard_sigmoid',
@@ -1005,7 +944,7 @@ class LSTM(Recurrent):
def build(self, input_shape):
if isinstance(input_shape, list):
input_shape = input_shape[0]
input_shape = tensor_shape.TensorShape(input_shape).as_list()
batch_size = input_shape[0] if self.stateful else None
self.input_dim = input_shape[2]
self.input_spec[0] = InputSpec(shape=(batch_size, None, self.input_dim))
@@ -1068,7 +1007,7 @@ class LSTM(Recurrent):
def preprocess_input(self, inputs, training=None):
if self.implementation == 0:
input_shape = K.int_shape(inputs)
input_shape = inputs.get_shape().as_list()
input_dim = input_shape[2]
timesteps = input_shape[1]
@@ -1110,7 +1049,7 @@ class LSTM(Recurrent):
ones = K.ones_like(K.reshape(inputs[:, 0, 0], (-1, 1)))
ones = K.tile(ones, (1, self.units))
def dropped_inputs():
def dropped_inputs(): # pylint: disable=function-redefined
return K.dropout(ones, self.recurrent_dropout)
rec_dp_mask = [K.in_train_phase(dropped_inputs,
ones,
+49
Ver Arquivo
@@ -0,0 +1,49 @@
"""Layer serialization/deserialization functions.
"""
# pylint: disable=wildcard-import
# pylint: disable=unused-import
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .advanced_activations import *
from .convolutional import *
from .convolutional_recurrent import *
from .core import *
from .embeddings import *
from ..engine import Input
from ..engine import InputLayer
from .local import *
from .merge import *
from .noise import *
from .normalization import *
from .pooling import *
from .recurrent import *
from ..utils.generic_utils import deserialize_keras_object
from .wrappers import *
def serialize(layer):
return {'class_name': layer.__class__.__name__,
'config': layer.get_config()}
def deserialize(config, custom_objects=None):
"""Instantiates a layer from a config dictionary.
# Arguments
config: dict of the form {'class_name': str, 'config': dict}
custom_objects: dict mapping class names (or function names)
of custom (non-Keras) objects to class/functions
# Returns
Layer instance (may be Model, Sequential, Layer...)
"""
from .. import models # pylint: disable=g-import-not-at-top
globs = globals() # All layers.
globs['Model'] = models.Model
globs['Sequential'] = models.Sequential
return deserialize_keras_object(config,
module_objects=globs,
custom_objects=custom_objects,
printable_module_name='layer')
+34 -38
Ver Arquivo
@@ -1,11 +1,16 @@
# -*- coding: utf-8 -*-
"""Wrapper layers: layers that augment the functionality of another layer.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import copy
import inspect
from ..engine import Layer
from ..engine import InputSpec
from ..utils.generic_utils import has_arg
from .. import backend as K
from tensorflow.python.framework import tensor_shape
class Wrapper(Layer):
@@ -83,14 +88,14 @@ class Wrapper(Layer):
@classmethod
def from_config(cls, config, custom_objects=None):
from . import deserialize as deserialize_layer
from . import deserialize as deserialize_layer # pylint: disable=g-import-not-at-top
layer = deserialize_layer(config.pop('layer'),
custom_objects=custom_objects)
return cls(layer, **config)
class TimeDistributed(Wrapper):
"""This wrapper applies a layer to every temporal slice of an input.
"""This wrapper allows to apply a layer to every temporal slice of an input.
The input should be at least 3D, and the dimension of index one
will be considered to be the temporal dimension.
@@ -139,40 +144,35 @@ class TimeDistributed(Wrapper):
self.supports_masking = True
def build(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
assert len(input_shape) >= 3
self.input_spec = InputSpec(shape=input_shape)
child_input_shape = (input_shape[0],) + input_shape[2:]
child_input_shape = [input_shape[0]] + input_shape[2:]
if not self.layer.built:
self.layer.build(child_input_shape)
self.layer.built = True
super(TimeDistributed, self).build()
def compute_output_shape(self, input_shape):
child_input_shape = (input_shape[0],) + input_shape[2:]
child_output_shape = self.layer.compute_output_shape(child_input_shape)
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
child_input_shape = tensor_shape.TensorShape(
[input_shape[0]] + input_shape[2:])
child_output_shape = self.layer._compute_output_shape( # pylint: disable=protected-access
child_input_shape).as_list()
timesteps = input_shape[1]
return (child_output_shape[0], timesteps) + child_output_shape[1:]
def call(self, inputs, training=None, mask=None):
kwargs = {}
if has_arg(self.layer.call, 'training'):
kwargs['training'] = training
uses_learning_phase = False
return tensor_shape.TensorShape(
[child_output_shape[0], timesteps] + child_output_shape[1:])
def call(self, inputs, mask=None):
input_shape = K.int_shape(inputs)
if input_shape[0]:
# batch size matters, use rnn-based implementation
def step(x, _):
global uses_learning_phase
output = self.layer.call(x, **kwargs)
if hasattr(output, '_uses_learning_phase'):
uses_learning_phase = (output._uses_learning_phase or
uses_learning_phase)
output = self.layer.call(x)
return output, []
_, outputs, _ = K.rnn(step, inputs,
initial_states=[],
input_length=input_shape[1],
unroll=False)
y = outputs
else:
@@ -184,22 +184,16 @@ class TimeDistributed(Wrapper):
input_length = K.shape(inputs)[1]
# Shape: (num_samples * timesteps, ...)
inputs = K.reshape(inputs, (-1,) + input_shape[2:])
# (num_samples * timesteps, ...)
y = self.layer.call(inputs, **kwargs)
if hasattr(y, '_uses_learning_phase'):
uses_learning_phase = y._uses_learning_phase
y = self.layer.call(inputs) # (num_samples * timesteps, ...)
# Shape: (num_samples, timesteps, ...)
output_shape = self.compute_output_shape(input_shape)
y = K.reshape(y, (-1, input_length) + output_shape[2:])
output_shape = self._compute_output_shape(input_shape).as_list() # pylint: disable=protected-access
y = K.reshape(y, [-1, input_length] + output_shape[2:])
# Apply activity regularizer if any:
if (hasattr(self.layer, 'activity_regularizer') and
self.layer.activity_regularizer is not None):
regularization_loss = self.layer.activity_regularizer(y)
self.add_loss(regularization_loss, inputs)
if uses_learning_phase:
y._uses_learning_phase = True
return y
@@ -221,8 +215,7 @@ class Bidirectional(Wrapper):
```python
model = Sequential()
model.add(Bidirectional(LSTM(10, return_sequences=True),
input_shape=(5, 10)))
model.add(Bidirectional(LSTM(10, return_sequences=True), input_shape=(5, 10)))
model.add(Bidirectional(LSTM(10)))
model.add(Dense(5))
model.add(Activation('softmax'))
@@ -259,21 +252,24 @@ class Bidirectional(Wrapper):
self.forward_layer.set_weights(weights[:nw // 2])
self.backward_layer.set_weights(weights[nw // 2:])
def compute_output_shape(self, input_shape):
def _compute_output_shape(self, input_shape):
input_shape = tensor_shape.TensorShape(input_shape).as_list()
if self.merge_mode in ['sum', 'ave', 'mul']:
return self.forward_layer.compute_output_shape(input_shape)
return self.forward_layer._compute_output_shape(input_shape) # pylint: disable=protected-access
elif self.merge_mode == 'concat':
shape = list(self.forward_layer.compute_output_shape(input_shape))
shape = self.forward_layer._compute_output_shape(input_shape).as_list() # pylint: disable=protected-access
shape[-1] *= 2
return tuple(shape)
return tensor_shape.TensorShape(shape)
elif self.merge_mode is None:
return [self.forward_layer.compute_output_shape(input_shape)] * 2
shape = self.forward_layer._compute_output_shape(input_shape) # pylint: disable=protected-access
return [shape, copy.copy(shape)]
def call(self, inputs, training=None, mask=None):
kwargs = {}
if has_arg(self.layer.call, 'training'):
func_args = inspect.getargspec(self.layer.call).args
if 'training' in func_args:
kwargs['training'] = training
if has_arg(self.layer.call, 'mask'):
if 'mask' in func_args:
kwargs['mask'] = mask
y = self.forward_layer.call(inputs, **kwargs)
Ver Arquivo
+11 -19
Ver Arquivo
@@ -3,6 +3,7 @@
import six
import warnings
import functools
import inspect
import numpy as np
@@ -85,7 +86,7 @@ def generate_legacy_interface(allowed_positional_args=None,
warnings.warn('Update your `' + object_name +
'` call to the Keras 2 API: ' + signature, stacklevel=2)
return func(*args, **kwargs)
wrapper._original_function = func
wrapper._legacy_support_signature = inspect.getargspec(func)
return wrapper
return legacy_support
@@ -160,7 +161,7 @@ def recurrent_args_preprocessor(args, kwargs):
kwargs.pop('forget_bias_init')
warnings.warn('The `forget_bias_init` argument '
'has been ignored. Use `unit_forget_bias=True` '
'instead to initialize with ones.', stacklevel=3)
'instead to intialize with ones.', stacklevel=3)
if 'input_dim' in kwargs:
input_length = kwargs.pop('input_length', None)
input_dim = kwargs.pop('input_dim')
@@ -460,7 +461,7 @@ def convlstm2d_args_preprocessor(args, kwargs):
else:
warnings.warn('The `forget_bias_init` argument '
'has been ignored. Use `unit_forget_bias=True` '
'instead to initialize with ones.', stacklevel=3)
'instead to intialize with ones.', stacklevel=3)
args, kwargs, _converted = conv2d_args_preprocessor(args, kwargs)
return args, kwargs, converted + _converted
@@ -576,21 +577,14 @@ def generator_methods_args_preprocessor(args, kwargs):
if hasattr(generator, 'batch_size'):
kwargs['steps_per_epoch'] = samples_per_epoch // generator.batch_size
else:
warnings.warn('The semantics of the Keras 2 argument '
' `steps_per_epoch` is not the same as the '
'Keras 1 argument `samples_per_epoch`. '
'`steps_per_epoch` is the number of batches '
'to draw from the generator at each epoch. '
'Update your method calls accordingly.', stacklevel=3)
kwargs['steps_per_epoch'] = samples_per_epoch
converted.append(('samples_per_epoch', 'steps_per_epoch'))
keras1_args = {'samples_per_epoch', 'val_samples', 'nb_epoch', 'nb_val_samples', 'nb_worker'}
if keras1_args.intersection(kwargs.keys()):
warnings.warn('The semantics of the Keras 2 argument '
'`steps_per_epoch` is not the same as the '
'Keras 1 argument `samples_per_epoch`. '
'`steps_per_epoch` is the number of batches '
'to draw from the generator at each epoch. '
'Basically steps_per_epoch = samples_per_epoch/batch_size. '
'Similarly `nb_val_samples`->`validation_steps` and '
'`val_samples`->`steps` arguments have changed. '
'Update your method calls accordingly.', stacklevel=3)
return args, kwargs, converted
@@ -600,9 +594,7 @@ legacy_generator_methods_support = generate_legacy_method_interface(
('val_samples', 'steps'),
('nb_epoch', 'epochs'),
('nb_val_samples', 'validation_steps'),
('nb_worker', 'workers'),
('pickle_safe', 'use_multiprocessing'),
('max_q_size', 'max_queue_size')],
('nb_worker', 'workers')],
preprocessor=generator_methods_args_preprocessor)
+4 -2
Ver Arquivo
@@ -1,9 +1,10 @@
import inspect
import types as python_types
import warnings
from ..engine.topology import Layer, InputSpec
from .. import backend as K
from ..utils.generic_utils import func_dump, func_load, has_arg
from ..utils.generic_utils import func_dump, func_load
from .. import regularizers
from .. import constraints
from .. import activations
@@ -196,7 +197,8 @@ class Merge(Layer):
# Case: "mode" is a lambda or function.
if callable(self.mode):
arguments = self.arguments
if has_arg(self.mode, 'mask'):
arg_spec = inspect.getargspec(self.mode)
if 'mask' in arg_spec.args:
arguments['mask'] = mask
return self.mode(inputs, **arguments)
-27
Ver Arquivo
@@ -1,27 +0,0 @@
from .layers import Merge
def needs_legacy_support(model):
return isinstance(model.layers[0], Merge)
def legacy_sequential_layers(model):
layers = []
if model.layers:
if isinstance(model.layers[0], Merge):
merge = model.layers[0]
for layer in merge.layers:
if hasattr(layer, 'layers'):
for sublayer in layer.layers:
if sublayer not in layers:
layers.append(sublayer)
else:
if layer not in layers:
layers.append(layer)
else:
if model.layers[0] not in layers:
layers.append(model.layers[0])
for layer in model.layers[1:]:
if layer not in layers:
layers.append(layer)
return layers
+12 -6
Ver Arquivo
@@ -1,6 +1,11 @@
"""Built-in Keras loss functions.
"""
from __future__ import absolute_import
import six
from __future__ import division
from __future__ import print_function
from . import backend as K
import six
from .utils.generic_utils import deserialize_keras_object
@@ -13,6 +18,7 @@ def mean_absolute_error(y_true, y_pred):
def mean_absolute_percentage_error(y_true, y_pred):
# Equivalent to MAE, but sometimes easier to interpret.
diff = K.abs((y_true - y_pred) / K.clip(K.abs(y_true),
K.epsilon(),
None))
@@ -35,8 +41,8 @@ def hinge(y_true, y_pred):
def categorical_hinge(y_true, y_pred):
pos = K.sum(y_true * y_pred, axis=-1)
neg = K.max((1. - y_true) * y_pred, axis=-1)
return K.maximum(0., neg - pos + 1.)
neg = K.max((1.0 - y_true) * y_pred, axis=-1)
return K.mean(K.maximum(0.0, neg - pos + 1), axis=-1)
def logcosh(y_true, y_pred):
@@ -46,15 +52,15 @@ def logcosh(y_true, y_pred):
def categorical_crossentropy(y_true, y_pred):
return K.categorical_crossentropy(y_true, y_pred)
return K.categorical_crossentropy(y_pred, y_true)
def sparse_categorical_crossentropy(y_true, y_pred):
return K.sparse_categorical_crossentropy(y_true, y_pred)
return K.sparse_categorical_crossentropy(y_pred, y_true)
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
def kullback_leibler_divergence(y_true, y_pred):
+16 -14
Ver Arquivo
@@ -1,19 +1,26 @@
"""Built-in Keras metrics functions.
"""
from __future__ import absolute_import
import six
from __future__ import division
from __future__ import print_function
from . import backend as K
from .losses import mean_squared_error
# pylint: disable=unused-import
from .losses import binary_crossentropy
from .losses import categorical_crossentropy
from .losses import cosine_proximity
from .losses import hinge
from .losses import kullback_leibler_divergence
from .losses import mean_absolute_error
from .losses import mean_absolute_percentage_error
from .losses import mean_squared_error
from .losses import mean_squared_logarithmic_error
from .losses import hinge
from .losses import logcosh
from .losses import squared_hinge
from .losses import categorical_crossentropy
from .losses import sparse_categorical_crossentropy
from .losses import binary_crossentropy
from .losses import kullback_leibler_divergence
from .losses import poisson
from .losses import cosine_proximity
from .losses import sparse_categorical_crossentropy
from .losses import squared_hinge
# pylint: disable=unused-import
import six
from .utils.generic_utils import deserialize_keras_object
@@ -36,11 +43,6 @@ def sparse_categorical_accuracy(y_true, y_pred):
def top_k_categorical_accuracy(y_true, y_pred, k=5):
return K.mean(K.in_top_k(y_pred, K.argmax(y_true, axis=-1), k), axis=-1)
def sparse_top_k_categorical_accuracy(y_true, y_pred, k=5):
return K.mean(K.in_top_k(y_pred, K.cast(K.max(y_true, axis=-1), 'int32'), k), axis=-1)
# Aliases
mse = MSE = mean_squared_error
+117 -257
Ver Arquivo
@@ -1,31 +1,37 @@
"""Home of the Sequential model, and the `save_model`/`load_model` functions.
"""
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import warnings
import copy
import json
import os
import yaml
import numpy as np
import warnings
from . import backend as K
from . import optimizers
from . import layers as layer_module
from .utils.io_utils import ask_to_proceed_with_overwrite
from .engine.training import Model
from . import optimizers
from .engine import topology
from .engine.topology import Layer
from .engine.topology import Input
from .legacy import layers as legacy_layers
from .legacy import models as legacy_models
from .legacy import interfaces
from .engine.topology import Layer
from .engine.training import Model
import numpy as np
from .utils.io_utils import ask_to_proceed_with_overwrite
# pylint: disable=g-import-not-at-top
try:
import h5py
except ImportError:
h5py = None
try:
import yaml
except ImportError:
yaml = None
# pylint: enable=g-import-not-at-top
def save_model(model, filepath, overwrite=True, include_optimizer=True):
"""Save a model to a HDF5 file.
@@ -74,11 +80,7 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True):
# if obj is any numpy type
if type(obj).__module__ == np.__name__:
if isinstance(obj, np.ndarray):
return {'type': type(obj),
'value': obj.tolist()}
else:
return obj.item()
return obj.item()
# misc functions (e.g. loss function)
if callable(obj):
@@ -90,7 +92,7 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True):
raise TypeError('Not JSON Serializable:', obj)
from . import __version__ as keras_version
from . import __version__ as keras_version # pylint: disable=g-import-not-at-top
# If file exists and should not be overwritten.
if not overwrite and os.path.isfile(filepath):
@@ -107,10 +109,7 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True):
}, default=get_json_type).encode('utf8')
model_weights_group = f.create_group('model_weights')
if legacy_models.needs_legacy_support(model):
model_layers = legacy_models.legacy_sequential_layers(model)
else:
model_layers = model.layers
model_layers = model.layers
topology.save_weights_to_hdf5_group(model_weights_group, model_layers)
if include_optimizer and hasattr(model, 'optimizer'):
@@ -144,8 +143,8 @@ def save_model(model, filepath, overwrite=True, include_optimizer=True):
weight_values = K.batch_get_value(symbolic_weights)
weight_names = []
for i, (w, val) in enumerate(zip(symbolic_weights, weight_values)):
# Default values of symbolic_weights is /variable for theano and cntk
if K.backend() == 'theano' or K.backend() == 'cntk':
# Default values of symbolic_weights is /variable for theano
if K.backend() == 'theano':
if hasattr(w, 'name') and w.name != "/variable":
name = str(w.name)
else:
@@ -207,81 +206,91 @@ def load_model(filepath, custom_objects=None, compile=True):
obj: object, dict, or list.
# Returns
The same structure, where occurrences
The same structure, where occurences
of a custom object name have been replaced
with the custom object.
"""
if isinstance(obj, list):
deserialized = []
for value in obj:
deserialized.append(convert_custom_objects(value))
if value in custom_objects:
deserialized.append(custom_objects[value])
else:
deserialized.append(value)
return deserialized
if isinstance(obj, dict):
deserialized = {}
for key, value in obj.items():
deserialized[key] = convert_custom_objects(value)
deserialized[key] = []
if isinstance(value, list):
for element in value:
if element in custom_objects:
deserialized[key].append(custom_objects[element])
else:
deserialized[key].append(element)
elif value in custom_objects:
deserialized[key] = custom_objects[value]
else:
deserialized[key] = value
return deserialized
if obj in custom_objects:
return custom_objects[obj]
return obj
with h5py.File(filepath, mode='r') as f:
# instantiate model
model_config = f.attrs.get('model_config')
if model_config is None:
raise ValueError('No model found in config file.')
model_config = json.loads(model_config.decode('utf-8'))
model = model_from_config(model_config, custom_objects=custom_objects)
# set weights
topology.load_weights_from_hdf5_group(f['model_weights'], model.layers)
f = h5py.File(filepath, mode='r')
# Early return if compilation is not required.
if not compile:
return model
# instantiate model
model_config = f.attrs.get('model_config')
if model_config is None:
raise ValueError('No model found in config file.')
model_config = json.loads(model_config.decode('utf-8'))
model = model_from_config(model_config, custom_objects=custom_objects)
# instantiate optimizer
training_config = f.attrs.get('training_config')
if training_config is None:
warnings.warn('No training configuration found in save file: '
'the model was *not* compiled. Compile it manually.')
return model
training_config = json.loads(training_config.decode('utf-8'))
optimizer_config = training_config['optimizer_config']
optimizer = optimizers.deserialize(optimizer_config,
custom_objects=custom_objects)
# set weights
topology.load_weights_from_hdf5_group(f['model_weights'], model.layers)
# Recover loss functions and metrics.
loss = convert_custom_objects(training_config['loss'])
metrics = convert_custom_objects(training_config['metrics'])
sample_weight_mode = training_config['sample_weight_mode']
loss_weights = training_config['loss_weights']
# Early return if compilation is not required.
if not compile:
f.close()
return model
# Compile model.
model.compile(optimizer=optimizer,
loss=loss,
metrics=metrics,
loss_weights=loss_weights,
sample_weight_mode=sample_weight_mode)
# instantiate optimizer
training_config = f.attrs.get('training_config')
if training_config is None:
warnings.warn('No training configuration found in save file: '
'the model was *not* compiled. Compile it manually.')
f.close()
return model
training_config = json.loads(training_config.decode('utf-8'))
optimizer_config = training_config['optimizer_config']
optimizer = optimizers.deserialize(optimizer_config,
custom_objects=custom_objects)
# Set optimizer weights.
if 'optimizer_weights' in f:
# Build train function (to get weight updates).
if isinstance(model, Sequential):
model.model._make_train_function()
else:
model._make_train_function()
optimizer_weights_group = f['optimizer_weights']
optimizer_weight_names = [n.decode('utf8') for n in
optimizer_weights_group.attrs['weight_names']]
optimizer_weight_values = [optimizer_weights_group[n] for n in
optimizer_weight_names]
try:
model.optimizer.set_weights(optimizer_weight_values)
except ValueError:
warnings.warn('Error in loading the saved optimizer '
'state. As a result, your model is '
'starting with a freshly initialized '
'optimizer.')
# Recover loss functions and metrics.
loss = convert_custom_objects(training_config['loss'])
metrics = convert_custom_objects(training_config['metrics'])
sample_weight_mode = training_config['sample_weight_mode']
loss_weights = training_config['loss_weights']
# Compile model.
model.compile(optimizer=optimizer,
loss=loss,
metrics=metrics,
loss_weights=loss_weights,
sample_weight_mode=sample_weight_mode)
# Set optimizer weights.
if 'optimizer_weights' in f:
# Build train function (to get weight updates).
if isinstance(model, Sequential):
model.model._make_train_function()
else:
model._make_train_function()
optimizer_weights_group = f['optimizer_weights']
optimizer_weight_names = [n.decode('utf8') for n in optimizer_weights_group.attrs['weight_names']]
optimizer_weight_values = [optimizer_weights_group[n] for n in optimizer_weight_names]
model.optimizer.set_weights(optimizer_weight_values)
f.close()
return model
@@ -298,7 +307,7 @@ def model_from_config(config, custom_objects=None):
A Keras model instance (uncompiled).
# Raises
TypeError: if `config` is not a dictionary.
TypeError if `config` is not a dictionary
"""
if isinstance(config, list):
raise TypeError('`model_from_config` expects a dictionary, not a list. '
@@ -318,7 +327,12 @@ def model_from_yaml(yaml_string, custom_objects=None):
# Returns
A Keras model instance (uncompiled).
# Raises
ImportError: if yaml module is not found.
"""
if yaml is None:
raise ImportError('Requires yaml module installed.')
config = yaml.load(yaml_string)
return layer_module.deserialize(config, custom_objects=custom_objects)
@@ -462,9 +476,7 @@ class Sequential(Model):
output_tensors=self.outputs,
# no model-level masking for now
input_masks=[None for _ in self.inputs],
output_masks=[None],
input_shapes=[x._keras_shape for x in self.inputs],
output_shapes=[self.outputs[0]._keras_shape])
output_masks=[None])
else:
output_tensor = layer(self.outputs[0])
if isinstance(output_tensor, list):
@@ -475,7 +487,7 @@ class Sequential(Model):
self.outputs = [output_tensor]
# update self.inbound_nodes
self.inbound_nodes[0].output_tensors = self.outputs
self.inbound_nodes[0].output_shapes = [self.outputs[0]._keras_shape]
self.inbound_nodes[0].output_shapes = [K.int_shape(self.outputs[0])]
self.layers.append(layer)
self.built = False
@@ -499,7 +511,7 @@ class Sequential(Model):
self.outputs = [self.layers[-1].output]
# update self.inbound_nodes
self.inbound_nodes[0].output_tensors = self.outputs
self.inbound_nodes[0].output_shapes = [self.outputs[0]._keras_shape]
self.inbound_nodes[0].output_shapes = [K.int_shape(self.outputs[0])]
self.built = False
def get_layer(self, name=None, index=None):
@@ -564,36 +576,9 @@ class Sequential(Model):
self.build()
return self.model.uses_learning_phase
@property
def _flattened_layers(self):
layers = []
if self.layers:
# Support for legacy models
if isinstance(self.layers[0], legacy_layers.Merge):
merge = self.layers[0]
for layer in merge.layers:
if hasattr(layer, '_flattened_layers'):
for sublayer in layer._flattened_layers:
if sublayer not in layers:
layers.append(sublayer)
elif hasattr(layer, 'layers'):
for sublayer in layer.layers:
if sublayer not in layers:
layers.append(sublayer)
else:
if layer not in layers:
layers.append(layer)
else:
if self.layers[0] not in layers:
layers.append(self.layers[0])
for layer in self.layers[1:]:
if layer not in layers:
layers.append(layer)
return layers
def _gather_list_attr(self, attr):
all_attrs = []
for layer in self._flattened_layers:
for layer in self.layers:
all_attrs += getattr(layer, attr, [])
return all_attrs
@@ -611,12 +596,10 @@ class Sequential(Model):
def trainable_weights(self):
if not self.trainable:
return []
# Support for legacy behavior
return self._gather_list_attr('trainable_weights')
@property
def non_trainable_weights(self):
# Support for legacy behavior
weights = self._gather_list_attr('non_trainable_weights')
if not self.trainable:
trainable_weights = self._gather_list_attr('trainable_weights')
@@ -670,14 +653,6 @@ class Sequential(Model):
A flat list of Numpy arrays
(one array per model weight).
"""
# Legacy support
if legacy_models.needs_legacy_support(self):
layers = legacy_models.legacy_sequential_layers(self)
weights = []
for layer in layers:
weights.append(layer.get_weights())
return weights
if self.model is None:
self.build()
return self.model.get_weights()
@@ -690,14 +665,6 @@ class Sequential(Model):
of Numpy arrays with shapes and types matching
the output of `model.get_weights()`.
"""
# Legacy support
if legacy_models.needs_legacy_support(self):
layers = legacy_models.legacy_sequential_layers(self)
for layer in layers:
nb_param = len(layer.weights)
layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
if self.model is None:
self.build()
self.model.set_weights(weights)
@@ -708,12 +675,7 @@ class Sequential(Model):
f = h5py.File(filepath, mode='r')
if 'layer_names' not in f.attrs and 'model_weights' in f:
f = f['model_weights']
# Legacy support
if legacy_models.needs_legacy_support(self):
layers = legacy_models.legacy_sequential_layers(self)
else:
layers = self.layers
layers = self.layers
if by_name:
topology.load_weights_from_hdf5_group_by_name(f, layers)
else:
@@ -729,12 +691,7 @@ class Sequential(Model):
proceed = ask_to_proceed_with_overwrite(filepath)
if not proceed:
return
# Legacy support
if legacy_models.needs_legacy_support(self):
layers = legacy_models.legacy_sequential_layers(self)
else:
layers = self.layers
layers = self.layers
f = h5py.File(filepath, 'w')
topology.save_weights_to_hdf5_group(f, layers)
f.flush()
@@ -792,7 +749,7 @@ class Sequential(Model):
def fit(self, x, y, batch_size=32, epochs=10, verbose=1, callbacks=None,
validation_split=0., validation_data=None, shuffle=True,
class_weight=None, sample_weight=None, initial_epoch=0, **kwargs):
class_weight=None, sample_weight=None, initial_epoch=0):
"""Trains the model for a fixed number of epochs.
# Arguments
@@ -839,14 +796,6 @@ class Sequential(Model):
# Raises
RuntimeError: if the model was never compiled.
"""
# Legacy support
if 'nb_epoch' in kwargs:
warnings.warn('The `nb_epoch` argument in `fit` '
'has been renamed `epochs`.')
epochs = kwargs.pop('nb_epoch')
if kwargs:
raise TypeError('Unrecognized keyword arguments: ' + str(kwargs))
if self.model is None:
raise RuntimeError('The model needs to be compiled '
'before being used.')
@@ -1017,7 +966,6 @@ class Sequential(Model):
else:
return (proba > 0.5).astype('int32')
@interfaces.legacy_generator_methods_support
def fit_generator(self, generator,
steps_per_epoch,
epochs=1,
@@ -1026,9 +974,9 @@ class Sequential(Model):
validation_data=None,
validation_steps=None,
class_weight=None,
max_queue_size=10,
max_q_size=10,
workers=1,
use_multiprocessing=False,
pickle_safe=False,
initial_epoch=0):
"""Fits the model on data generated batch-by-batch by a Python generator.
@@ -1065,9 +1013,9 @@ class Sequential(Model):
validation dataset divided by the batch size.
class_weight: Dictionary mapping class indices to a weight
for the class.
max_queue_size: Maximum size for the generator queue
max_q_size: Maximum size for the generator queue
workers: Maximum number of processes to spin up
use_multiprocessing: if True, use process based threading.
pickle_safe: Ff True, use process based threading.
Note that because
this implementation relies on multiprocessing,
you should not pass
@@ -1111,15 +1059,14 @@ class Sequential(Model):
validation_data=validation_data,
validation_steps=validation_steps,
class_weight=class_weight,
max_queue_size=max_queue_size,
max_q_size=max_q_size,
workers=workers,
use_multiprocessing=use_multiprocessing,
pickle_safe=pickle_safe,
initial_epoch=initial_epoch)
@interfaces.legacy_generator_methods_support
def evaluate_generator(self, generator, steps,
max_queue_size=10, workers=1,
use_multiprocessing=False):
max_q_size=10, workers=1,
pickle_safe=False):
"""Evaluates the model on a data generator.
The generator should return the same kind of data
@@ -1130,9 +1077,9 @@ class Sequential(Model):
or (inputs, targets, sample_weights)
steps: Total number of steps (batches of samples)
to yield from `generator` before stopping.
max_queue_size: maximum size for the generator queue
max_q_size: maximum size for the generator queue
workers: maximum number of processes to spin up
use_multiprocessing: if True, use process based threading.
pickle_safe: if True, use process based threading.
Note that because this implementation
relies on multiprocessing, you should not pass
non picklable arguments to the generator
@@ -1152,14 +1099,13 @@ class Sequential(Model):
'before being used.')
return self.model.evaluate_generator(generator,
steps,
max_queue_size=max_queue_size,
max_q_size=max_q_size,
workers=workers,
use_multiprocessing=use_multiprocessing)
pickle_safe=pickle_safe)
@interfaces.legacy_generator_methods_support
def predict_generator(self, generator, steps,
max_queue_size=10, workers=1,
use_multiprocessing=False, verbose=0):
max_q_size=10, workers=1,
pickle_safe=False, verbose=0):
"""Generates predictions for the input samples from a data generator.
The generator should return the same kind of data as accepted by
@@ -1169,9 +1115,9 @@ class Sequential(Model):
generator: generator yielding batches of input samples.
steps: Total number of steps (batches of samples)
to yield from `generator` before stopping.
max_queue_size: maximum size for the generator queue
max_q_size: maximum size for the generator queue
workers: maximum number of processes to spin up
use_multiprocessing: if True, use process based threading.
pickle_safe: if True, use process based threading.
Note that because this implementation
relies on multiprocessing, you should not pass
non picklable arguments to the generator
@@ -1184,15 +1130,12 @@ class Sequential(Model):
if self.model is None:
self.build()
return self.model.predict_generator(generator, steps,
max_queue_size=max_queue_size,
max_q_size=max_q_size,
workers=workers,
use_multiprocessing=use_multiprocessing,
pickle_safe=pickle_safe,
verbose=verbose)
def get_config(self):
if isinstance(self.layers[0], legacy_layers.Merge):
return self.legacy_get_config()
config = []
for layer in self.layers:
config.append({'class_name': layer.__class__.__name__,
@@ -1201,91 +1144,8 @@ class Sequential(Model):
@classmethod
def from_config(cls, config, custom_objects=None):
if 'class_name' not in config[0] or config[0]['class_name'] == 'Merge':
return cls.legacy_from_config(config)
model = cls()
for conf in config:
layer = layer_module.deserialize(conf, custom_objects=custom_objects)
model.add(layer)
return model
def legacy_get_config(self):
"""Retrieves the model configuration as a Python list.
# Returns
A list of dicts (each dict is a layer config).
"""
config = []
if isinstance(self.layers[0], legacy_layers.Merge):
assert hasattr(self.layers[0], 'layers')
layers = []
for layer in self.layers[0].layers:
layer_config = {'class_name': layer.__class__.__name__,
'config': layer.get_config()}
layers.append(layer_config)
merge_config = self.layers[0].get_config()
merge_config['layers'] = layers
config.append({'class_name': 'Merge', 'config': merge_config})
else:
config.append({'class_name': self.layers[0].__class__.__name__,
'config': self.layers[0].get_config()})
for layer in self.layers[1:]:
config.append({'class_name': layer.__class__.__name__,
'config': layer.get_config()})
return copy.deepcopy(config)
@classmethod
def legacy_from_config(cls, config, layer_cache=None):
"""Load a model from a legacy configuration.
# Arguments
config: dictionary with configuration.
layer_cache: cache to draw pre-existing layer.
# Returns
The loaded Model.
"""
if not layer_cache:
layer_cache = {}
def normalize_legacy_config(conf):
if 'class_name' not in conf:
class_name = conf['name']
name = conf.get('custom_name')
conf['name'] = name
return {'class_name': class_name,
'config': conf}
return conf
# the model we will return
model = cls()
def get_or_create_layer(layer_data):
name = layer_data['config'].get('name')
if name in layer_cache:
return layer_cache[name]
layer = layer_module.deserialize(layer_data)
layer_cache[name] = layer
return layer
first_layer = config[0]
first_layer = normalize_legacy_config(first_layer)
if first_layer['class_name'] == 'Merge':
merge_inputs = []
first_layer_config = first_layer['config']
for merge_input_config in first_layer_config.pop('layers'):
merge_input = layer_module.deserialize(merge_input_config)
merge_inputs.append(merge_input)
first_layer_config['layers'] = merge_inputs
merge = legacy_layers.Merge.from_config(first_layer_config)
model.add(merge)
else:
layer = get_or_create_layer(first_layer)
model.add(layer)
for conf in config[1:]:
conf = normalize_legacy_config(conf)
layer = get_or_create_layer(conf)
model.add(layer)
return model
-6
Ver Arquivo
@@ -1,6 +0,0 @@
"""Legacy objectives module.
Only kept for backwards API compatibility.
"""
from __future__ import absolute_import
from .losses import *
+38 -45
Ver Arquivo
@@ -1,42 +1,20 @@
"""Keras optimizer classes (will eventually be replaced with core optimizers).
"""
from __future__ import absolute_import
import six
import copy
from six.moves import zip
from __future__ import division
from __future__ import print_function
from . import backend as K
from .utils.generic_utils import serialize_keras_object
import six
from six.moves import zip
from tensorflow.python.training import optimizer as tf_optimizer_module
from .utils.generic_utils import deserialize_keras_object
if K.backend() == 'tensorflow':
import tensorflow as tf
from .utils.generic_utils import serialize_keras_object
def clip_norm(g, c, n):
if c <= 0: # if clipnorm == 0 no need to add ops to the graph
return g
# tf require using a special op to multiply IndexedSliced by scalar
if K.backend() == 'tensorflow':
condition = n >= c
then_expression = tf.scalar_mul(c / n, g)
else_expression = g
# saving the shape to avoid converting sparse tensor to dense
if isinstance(then_expression, tf.Tensor):
g_shape = copy.copy(then_expression.get_shape())
elif isinstance(then_expression, tf.IndexedSlices):
g_shape = copy.copy(then_expression.dense_shape)
if condition.dtype != tf.bool:
condition = tf.cast(condition, 'bool')
g = tf.cond(condition,
lambda: then_expression,
lambda: else_expression)
if isinstance(then_expression, tf.Tensor):
g.set_shape(g_shape)
elif isinstance(then_expression, tf.IndexedSlices):
g._dense_shape = g_shape
else:
g = K.switch(K.greater_equal(n, c), g * c / n, g)
if c > 0:
g = K.switch(n >= c, g * c / n, g)
return g
@@ -158,7 +136,7 @@ class SGD(Optimizer):
self.updates .append(K.update_add(self.iterations, 1))
# momentum
shapes = [K.get_variable_shape(p) for p in params]
shapes = [K.int_shape(p) for p in params]
moments = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + moments
for p, g, m in zip(params, grads, moments):
@@ -188,6 +166,7 @@ class SGD(Optimizer):
class RMSprop(Optimizer):
# pylint: disable=line-too-long
"""RMSProp optimizer.
It is recommended to leave the parameters of this optimizer
@@ -206,6 +185,7 @@ class RMSprop(Optimizer):
# References
- [rmsprop: Divide the gradient by a running average of its recent magnitude](http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf)
"""
# pylint: enable=line-too-long
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-8, decay=0.,
**kwargs):
@@ -219,7 +199,8 @@ class RMSprop(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [K.zeros(K.get_variable_shape(p), dtype=K.dtype(p)) for p in params]
shapes = [K.int_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
@@ -251,6 +232,7 @@ class RMSprop(Optimizer):
class Adagrad(Optimizer):
# pylint: disable=line-too-long
"""Adagrad optimizer.
It is recommended to leave the parameters of this optimizer
@@ -264,6 +246,7 @@ class Adagrad(Optimizer):
# References
- [Adaptive Subgradient Methods for Online Learning and Stochastic Optimization](http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf)
"""
# pylint: enable=line-too-long
def __init__(self, lr=0.01, epsilon=1e-8, decay=0., **kwargs):
super(Adagrad, self).__init__(**kwargs)
@@ -275,7 +258,7 @@ class Adagrad(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
shapes = [K.get_variable_shape(p) for p in params]
shapes = [K.int_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
@@ -305,6 +288,7 @@ class Adagrad(Optimizer):
class Adadelta(Optimizer):
# pylint: disable=line-too-long
"""Adadelta optimizer.
It is recommended to leave the parameters of this optimizer
@@ -320,6 +304,7 @@ class Adadelta(Optimizer):
# References
- [Adadelta - an adaptive learning rate method](http://arxiv.org/abs/1212.5701)
"""
# pylint: enable=line-too-long
def __init__(self, lr=1.0, rho=0.95, epsilon=1e-8, decay=0.,
**kwargs):
@@ -333,7 +318,7 @@ class Adadelta(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
shapes = [K.get_variable_shape(p) for p in params]
shapes = [K.int_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
delta_accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators + delta_accumulators
@@ -374,6 +359,7 @@ class Adadelta(Optimizer):
class Adam(Optimizer):
# pylint: disable=line-too-long
"""Adam optimizer.
Default parameters follow those provided in the original paper.
@@ -388,6 +374,7 @@ class Adam(Optimizer):
# References
- [Adam - A Method for Stochastic Optimization](http://arxiv.org/abs/1412.6980v8)
"""
# pylint: enable=line-too-long
def __init__(self, lr=0.001, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, decay=0., **kwargs):
@@ -412,8 +399,9 @@ class Adam(Optimizer):
lr_t = lr * (K.sqrt(1. - K.pow(self.beta_2, t)) /
(1. - K.pow(self.beta_1, t)))
ms = [K.zeros(K.get_variable_shape(p), dtype=K.dtype(p)) for p in params]
vs = [K.zeros(K.get_variable_shape(p), dtype=K.dtype(p)) for p in params]
shapes = [K.int_shape(p) for p in params]
ms = [K.zeros(shape) for shape in shapes]
vs = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + ms + vs
for p, g, m, v in zip(params, grads, ms, vs):
@@ -443,6 +431,7 @@ class Adam(Optimizer):
class Adamax(Optimizer):
# pylint: disable=line-too-long
"""Adamax optimizer from Adam paper's Section 7.
It is a variant of Adam based on the infinity norm.
@@ -457,6 +446,7 @@ class Adamax(Optimizer):
# References
- [Adam - A Method for Stochastic Optimization](http://arxiv.org/abs/1412.6980v8)
"""
# pylint: enable=line-too-long
def __init__(self, lr=0.002, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, decay=0., **kwargs):
@@ -480,7 +470,7 @@ class Adamax(Optimizer):
t = self.iterations + 1
lr_t = lr / (1. - K.pow(self.beta_1, t))
shapes = [K.get_variable_shape(p) for p in params]
shapes = [K.int_shape(p) for p in params]
# zero init of 1st moment
ms = [K.zeros(shape) for shape in shapes]
# zero init of exponentially weighted infinity norm
@@ -515,6 +505,7 @@ class Adamax(Optimizer):
class Nadam(Optimizer):
# pylint: disable=line-too-long
"""Nesterov Adam optimizer.
Much like Adam is essentially RMSprop with momentum,
@@ -533,6 +524,7 @@ class Nadam(Optimizer):
- [Nadam report](http://cs229.stanford.edu/proj2015/054_report.pdf)
- [On the importance of initialization and momentum in deep learning](http://www.cs.toronto.edu/~fritz/absps/momentum.pdf)
"""
# pylint: enable=line-too-long
def __init__(self, lr=0.002, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, schedule_decay=0.004, **kwargs):
@@ -558,7 +550,7 @@ class Nadam(Optimizer):
m_schedule_next = self.m_schedule * momentum_cache_t * momentum_cache_t_1
self.updates.append((self.m_schedule, m_schedule_new))
shapes = [K.get_variable_shape(p) for p in params]
shapes = [K.int_shape(p) for p in params]
ms = [K.zeros(shape) for shape in shapes]
vs = [K.zeros(shape) for shape in shapes]
@@ -600,7 +592,7 @@ class TFOptimizer(Optimizer):
"""Wrapper class for native TensorFlow optimizers.
"""
def __init__(self, optimizer):
def __init__(self, optimizer): # pylint: disable=super-init-not-called
self.optimizer = optimizer
self.iterations = K.variable(0., name='iterations')
self.updates = []
@@ -630,6 +622,7 @@ class TFOptimizer(Optimizer):
# Aliases.
# pylint: disable=invalid-name
sgd = SGD
rmsprop = RMSprop
adagrad = Adagrad
@@ -637,6 +630,7 @@ adadelta = Adadelta
adam = Adam
adamax = Adamax
nadam = Nadam
# pylint: enable=invalid-name
def serialize(optimizer):
@@ -692,10 +686,9 @@ def get(identifier):
# Raises
ValueError: If `identifier` cannot be interpreted.
"""
if K.backend() == 'tensorflow':
# Wrap TF optimizer instances
if isinstance(identifier, tf.train.Optimizer):
return TFOptimizer(identifier)
# Wrap TF optimizer instances
if isinstance(identifier, tf_optimizer_module.Optimizer):
return TFOptimizer(identifier)
if isinstance(identifier, dict):
return deserialize(identifier)
elif isinstance(identifier, six.string_types):
+9
Ver Arquivo
@@ -0,0 +1,9 @@
"""Data preprocessing module.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from . import image
from . import sequence
from . import text
+57 -103
Ver Arquivo
@@ -1,27 +1,33 @@
"""Fairly basic set of tools for real-time data augmentation on image data.
Can easily be extended to include new transformations,
new preprocessing methods, etc...
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import re
from scipy import linalg
import scipy.ndimage as ndi
from six.moves import range
import os
import re
import threading
import warnings
import multiprocessing.pool
from functools import partial
from .. import backend as K
import numpy as np
from six.moves import range
# pylint: disable=g-import-not-at-top
try:
from PIL import Image as pil_image
except ImportError:
pil_image = None
try:
from scipy import linalg
import scipy.ndimage as ndi
except ImportError:
linalg = None
ndi = None
# pylint: enable=g-import-not-at-top
def random_rotation(x, rg, row_axis=1, col_axis=2, channel_axis=0,
@@ -139,7 +145,7 @@ def random_zoom(x, zoom_range, row_axis=1, col_axis=2, channel_axis=0,
ValueError: if `zoom_range` isn't a tuple.
"""
if len(zoom_range) != 2:
raise ValueError('`zoom_range` should be a tuple or list of two floats. '
raise ValueError('zoom_range should be a tuple or list of two floats. '
'Received arg: ', zoom_range)
if zoom_range[0] == 1 and zoom_range[1] == 1:
@@ -252,7 +258,7 @@ def array_to_img(x, data_format=None, scale=True):
if data_format == 'channels_first':
x = x.transpose(1, 2, 0)
if scale:
x = x + max(-np.min(x), 0)
x = x + max(-np.min(x), 0) # pylint: disable=g-no-augmented-assignment
x_max = np.max(x)
if x_max != 0:
x /= x_max
@@ -421,8 +427,8 @@ class ImageDataGenerator(object):
self.preprocessing_function = preprocessing_function
if data_format not in {'channels_last', 'channels_first'}:
raise ValueError('`data_format` should be `"channels_last"` (channel after row and '
'column) or `"channels_first"` (channel before row and column). '
raise ValueError('data_format should be "channels_last" (channel after row and '
'column) or "channels_first" (channel before row and column). '
'Received arg: ', data_format)
self.data_format = data_format
if data_format == 'channels_first':
@@ -443,7 +449,7 @@ class ImageDataGenerator(object):
elif len(zoom_range) == 2:
self.zoom_range = [zoom_range[0], zoom_range[1]]
else:
raise ValueError('`zoom_range` should be a float or '
raise ValueError('zoom_range should be a float or '
'a tuple or list of two floats. '
'Received arg: ', zoom_range)
@@ -534,7 +540,13 @@ class ImageDataGenerator(object):
# Returns
A randomly transformed version of the input (same shape).
# Raises
ImportError: if Scipy is not available.
"""
if ndi is None:
raise ImportError('Scipy is required for image transformations.')
# x is a single image, so it doesn't have image number at index 0
img_row_axis = self.row_axis - 1
img_col_axis = self.col_axis - 1
@@ -633,13 +645,14 @@ class ImageDataGenerator(object):
# Raises
ValueError: in case of invalid input `x`.
ImportError: if Scipy is not available.
"""
x = np.asarray(x, dtype=K.floatx())
if x.ndim != 4:
raise ValueError('Input to `.fit()` should have rank 4. '
'Got array with shape: ' + str(x.shape))
if x.shape[self.channel_axis] not in {3, 4}:
warnings.warn(
if x.shape[self.channel_axis] not in {1, 3, 4}:
raise ValueError(
'Expected input to be images (as Numpy array) '
'following the data format convention "' + self.data_format + '" '
'(channels on axis ' + str(self.channel_axis) + '), i.e. expected '
@@ -673,6 +686,9 @@ class ImageDataGenerator(object):
x /= (self.std + K.epsilon())
if self.zca_whitening:
if linalg is None:
raise ImportError('Scipy is required for zca_whitening.')
flat_x = np.reshape(x, (x.shape[0], x.shape[1] * x.shape[2] * x.shape[3]))
sigma = np.dot(flat_x.T, flat_x) / flat_x.shape[0]
u, s, _ = linalg.svd(sigma)
@@ -723,7 +739,7 @@ class Iterator(object):
yield (index_array[current_index: current_index + current_batch_size],
current_index, current_batch_size)
def __iter__(self):
def __iter__(self): # pylint: disable=non-iterator-returned
# Needed if we want to do something like:
# for x, y in data_gen.flow(...):
return self
@@ -823,73 +839,6 @@ class NumpyArrayIterator(Iterator):
return batch_x, batch_y
def _count_valid_files_in_directory(directory, white_list_formats, follow_links):
"""Count files with extension in `white_list_formats` contained in a directory.
# Arguments
directory: absolute path to the directory containing files to be counted
white_list_formats: set of strings containing allowed extensions for
the files to be counted.
# Returns
the count of files with extension in `white_list_formats` contained in
the directory.
"""
def _recursive_list(subpath):
return sorted(os.walk(subpath, followlinks=follow_links), key=lambda tpl: tpl[0])
samples = 0
for root, _, files in _recursive_list(directory):
for fname in files:
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
samples += 1
return samples
def _list_valid_filenames_in_directory(directory, white_list_formats,
class_indices, follow_links):
"""List paths of files in `subdir` relative from `directory` whose extensions are in `white_list_formats`.
# Arguments
directory: absolute path to a directory containing the files to list.
The directory name is used as class label and must be a key of `class_indices`.
white_list_formats: set of strings containing allowed extensions for
the files to be counted.
class_indices: dictionary mapping a class name to its index.
# Returns
classes: a list of class indices
filenames: the path of valid files in `directory`, relative from
`directory`'s parent (e.g., if `directory` is "dataset/class1",
the filenames will be ["class1/file1.jpg", "class1/file2.jpg", ...]).
"""
def _recursive_list(subpath):
return sorted(os.walk(subpath, followlinks=follow_links), key=lambda tpl: tpl[0])
classes = []
filenames = []
subdir = os.path.basename(directory)
basedir = os.path.dirname(directory)
for root, _, files in _recursive_list(directory):
for fname in files:
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
classes.append(class_indices[subdir])
# add filename relative to directory
absolute_path = os.path.join(root, fname)
filenames.append(os.path.relpath(absolute_path, basedir))
return classes, filenames
class DirectoryIterator(Iterator):
"""Iterator capable of reading images from a directory on disk.
@@ -982,33 +931,38 @@ class DirectoryIterator(Iterator):
def _recursive_list(subpath):
return sorted(os.walk(subpath, followlinks=follow_links), key=lambda tpl: tpl[0])
pool = multiprocessing.pool.ThreadPool()
function_partial = partial(_count_valid_files_in_directory,
white_list_formats=white_list_formats,
follow_links=follow_links)
self.samples = sum(pool.map(function_partial,
(os.path.join(directory, subdir)
for subdir in classes)))
for subdir in classes:
subpath = os.path.join(directory, subdir)
for root, _, files in _recursive_list(subpath):
for fname in files:
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
self.samples += 1
print('Found %d images belonging to %d classes.' % (self.samples, self.num_class))
# second, build an index of the images in the different class subfolders
results = []
self.filenames = []
self.classes = np.zeros((self.samples,), dtype='int32')
i = 0
for dirpath in (os.path.join(directory, subdir) for subdir in classes):
results.append(pool.apply_async(_list_valid_filenames_in_directory,
(dirpath, white_list_formats,
self.class_indices, follow_links)))
for res in results:
classes, filenames = res.get()
self.classes[i:i + len(classes)] = classes
self.filenames += filenames
i += len(classes)
pool.close()
pool.join()
for subdir in classes:
subpath = os.path.join(directory, subdir)
for root, _, files in _recursive_list(subpath):
for fname in files:
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
self.classes[i] = self.class_indices[subdir]
i += 1
# add filename relative to directory
absolute_path = os.path.join(root, fname)
self.filenames.append(os.path.relpath(absolute_path, directory))
super(DirectoryIterator, self).__init__(self.samples, batch_size, shuffle, seed)
def next(self):
+11 -25
Ver Arquivo
@@ -1,8 +1,13 @@
# -*- coding: utf-8 -*-
"""Preprocessing utilities for sequence data.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import random
import numpy as np
import random
from six.moves import range
@@ -50,16 +55,16 @@ def pad_sequences(sequences, maxlen=None, dtype='int32',
# checking for consistency in the main loop below.
sample_shape = tuple()
for s in sequences:
if len(s) > 0:
if len(s) > 0: # pylint: disable=g-explicit-length-test
sample_shape = np.asarray(s).shape[1:]
break
x = (np.ones((num_samples, maxlen) + sample_shape) * value).astype(dtype)
for idx, s in enumerate(sequences):
if not len(s):
if not len(s): # pylint: disable=g-explicit-length-test
continue # empty list/array was found
if truncating == 'pre':
trunc = s[-maxlen:]
trunc = s[-maxlen:] # pylint: disable=invalid-unary-operand-type
elif truncating == 'post':
trunc = s[:maxlen]
else:
@@ -104,7 +109,7 @@ def make_sampling_table(size, sampling_factor=1e-5):
is the probability that a word of rank i should be sampled.
"""
gamma = 0.577
rank = np.arange(size)
rank = np.array(list(range(size)))
rank[0] = 1
inv_fq = rank * (np.log(rank) + gamma) + 0.5 - 1. / (12. * rank)
f = sampling_factor * inv_fq
@@ -127,7 +132,7 @@ def skipgrams(sequence, vocabulary_size,
of word indices (integers). If using a `sampling_table`,
word indices are expected to match the rank
of the words in a reference dataset (e.g. 10 would encode
the 10-th most frequently occurring token).
the 10-th most frequently occuring token).
Note that index 0 is expected to be a non-word and will be skipped.
vocabulary_size: int. maximum possible word index + 1
window_size: int. actually half-window.
@@ -191,22 +196,3 @@ def skipgrams(sequence, vocabulary_size,
random.shuffle(labels)
return couples, labels
def _remove_long_seq(maxlen, seq, label):
"""Removes sequences that exceed the maximum length.
# Arguments
maxlen: int, maximum length
seq: list of lists where each sublist is a sequence
label: list where each element is an integer
# Returns
new_seq, new_label: shortened lists for `seq` and `label`.
"""
new_seq, new_label = [], []
for x, y in zip(seq, label):
if len(x) < maxlen:
new_seq.append(x)
new_label.append(y)
return new_seq, new_label
+4 -52
Ver Arquivo
@@ -5,16 +5,15 @@ May benefit from a fast Cython rewrite.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import string
import sys
import warnings
from collections import OrderedDict
from hashlib import md5
import numpy as np
from six.moves import range
from six.moves import zip
from collections import OrderedDict
import warnings
if sys.version_info < (3,):
maketrans = string.maketrans
@@ -47,58 +46,11 @@ def one_hot(text, n,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=' '):
"""One-hot encodes a text into a list of word indexes of size n.
This is a wrapper to the `hashing_trick` function using `hash` as the
hashing function, unicity of word to index mapping non-guaranteed.
"""
return hashing_trick(text, n,
hash_function=hash,
filters=filters,
lower=lower,
split=split)
def hashing_trick(text, n,
hash_function=None,
filters='!"#$%&()*+,-./:;<=>?@[\\]^_`{|}~\t\n',
lower=True,
split=' '):
"""Converts a text to a sequence of indexes in a fixed-size hashing space.
# Arguments
text: Input text (string).
n: Dimension of the hashing space.
hash_function: if `None` uses python `hash` function, can be 'md5' or
any function that takes in input a string and returns a int.
Note that `hash` is not a stable hashing function, so
it is not consistent across different runs, while 'md5'
is a stable hashing function.
filters: Sequence of characters to filter out.
lower: Whether to convert the input to lowercase.
split: Sentence split marker (string).
# Returns
A list of integer word indices (unicity non-guaranteed).
`0` is a reserved index that won't be assigned to any word.
Two or more words may be assigned to the same index, due to possible
collisions by the hashing function.
The [probability](https://en.wikipedia.org/wiki/Birthday_problem#Probability_table)
of a collision is in relation to the dimension of the hashing space and
the number of distinct objects.
"""
if hash_function is None:
hash_function = hash
elif hash_function == 'md5':
hash_function = lambda w: int(md5(w.encode()).hexdigest(), 16)
seq = text_to_word_sequence(text,
filters=filters,
lower=lower,
split=split)
return [(hash_function(w) % (n - 1) + 1) for w in seq]
return [(abs(hash(w)) % (n - 1) + 1) for w in seq]
class Tokenizer(object):
+9 -4
Ver Arquivo
@@ -1,8 +1,13 @@
"""Keras built-in regularizers.
"""
from __future__ import absolute_import
import six
from __future__ import division
from __future__ import print_function
from . import backend as K
from .utils.generic_utils import serialize_keras_object
import six
from .utils.generic_utils import deserialize_keras_object
from .utils.generic_utils import serialize_keras_object
class Regularizer(object):
@@ -25,7 +30,7 @@ class L1L2(Regularizer):
l2: Float; L2 regularization factor.
"""
def __init__(self, l1=0., l2=0.):
def __init__(self, l1=0., l2=0.): # pylint: disable=redefined-outer-name
self.l1 = K.cast_to_floatx(l1)
self.l2 = K.cast_to_floatx(l2)
@@ -53,7 +58,7 @@ def l2(l=0.01):
return L1L2(l2=l)
def l1_l2(l1=0.01, l2=0.01):
def l1_l2(l1=0.01, l2=0.01): # pylint: disable=redefined-outer-name
return L1L2(l1=l1, l2=l2)
+9 -7
Ver Arquivo
@@ -1,16 +1,18 @@
"""Keras utilities.
"""
from __future__ import absolute_import
from . import np_utils
from . import generic_utils
from . import data_utils
from . import io_utils
from __future__ import division
from __future__ import print_function
from . import conv_utils
from . import data_utils
from . import generic_utils
from . import io_utils
from . import np_utils
# Globally-importable utils.
from .io_utils import HDF5Matrix
from .data_utils import get_file
from .data_utils import Sequence
from .data_utils import GeneratorEnqueuer
from .data_utils import OrderedEnqueuer
from .generic_utils import CustomObjectScope
from .generic_utils import custom_object_scope
from .generic_utils import get_custom_objects
+16 -13
Ver Arquivo
@@ -1,6 +1,12 @@
from six.moves import range
import numpy as np
"""Utilities used by convolution layers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .. import backend as K
import numpy as np
from six.moves import range
def normalize_tuple(value, n, name):
@@ -55,11 +61,9 @@ def normalize_data_format(value):
def normalize_padding(value):
padding = value.lower()
allowed = {'valid', 'same', 'causal'}
if K.backend() == 'theano':
allowed.add('full')
if padding not in allowed:
raise ValueError('The `padding` argument must be one of "valid", "same" (or "causal" for Conv1D). '
if padding not in {'valid', 'same', 'causal'}:
raise ValueError('The `padding` argument must be one of '
'"valid", "same" (or "causal", only for `Conv1D). '
'Received: ' + str(padding))
return padding
@@ -109,10 +113,10 @@ def conv_output_length(input_length, filter_size,
output_length = input_length
elif padding == 'valid':
output_length = input_length - dilated_filter_size + 1
elif padding == 'causal':
output_length = input_length
elif padding == 'full':
output_length = input_length + dilated_filter_size - 1
elif padding == 'causal':
output_length = input_length
return (output_length + stride - 1) // stride
@@ -143,10 +147,9 @@ def conv_input_length(output_length, filter_size, padding, stride):
def deconv_length(dim_size, stride_size, kernel_size, padding):
if dim_size is None:
return None
dim_size *= stride_size
if padding == 'valid':
dim_size = dim_size * stride_size + max(kernel_size - stride_size, 0)
dim_size += max(kernel_size - stride_size, 0)
elif padding == 'full':
dim_size = dim_size * stride_size - (stride_size + kernel_size - 2)
elif padding == 'same':
dim_size = dim_size * stride_size
dim_size -= (stride_size + kernel_size - 2)
return dim_size
+7 -358
Ver Arquivo
@@ -1,33 +1,22 @@
"""Utilities for file download and caching."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import hashlib
import multiprocessing
import os
import random
import shutil
import sys
import tarfile
import threading
import time
import zipfile
from abc import abstractmethod
from multiprocessing.pool import ThreadPool
import numpy as np
import os
import shutil
import six
import sys
from six.moves.urllib.error import HTTPError
from six.moves.urllib.error import URLError
from six.moves.urllib.request import urlopen
try:
import queue
except ImportError:
import Queue as queue
from ..utils.generic_utils import Progbar
if sys.version_info[0] == 2:
def urlretrieve(url, filename, reporthook=None, data=None):
"""Replacement for `urlretrive` for Python 2.
@@ -46,7 +35,6 @@ if sys.version_info[0] == 2:
a block size in bytes, and the total size of the file.
data: `data` argument passed to `urlopen`.
"""
def chunk_read(response, chunk_size=8192, reporthook=None):
content_type = response.info().get('Content-Length')
total_size = -1
@@ -68,7 +56,7 @@ if sys.version_info[0] == 2:
for chunk in chunk_read(response, reporthook=reporthook):
fd.write(chunk)
else:
from six.moves.urllib.request import urlretrieve
from six.moves.urllib.request import urlretrieve # pylint: disable=g-import-not-at-top
def _extract_archive(file_path, path='.', archive_format='auto'):
@@ -295,342 +283,3 @@ def validate_file(fpath, file_hash, algorithm='auto', chunk_size=65535):
return True
else:
return False
class Sequence(object):
"""Base object for fitting to a sequence of data, such as a dataset.
Every `Sequence` must implements the `__getitem__` and the `__len__` methods.
# Examples
```python
from skimage.io import imread
from skimage.transform import resize
import numpy as np
# Here, `x_set` is list of path to the images
# and `y_set` are the associated classes.
class CIFAR10Sequence(Sequence):
def __init__(self, x_set, y_set, batch_size):
self.X,self.y = x_set,y_set
self.batch_size = batch_size
def __len__(self):
return len(self.X) // self.batch_size
def __getitem__(self,idx):
batch_x = self.X[idx*self.batch_size:(idx+1)*self.batch_size]
batch_y = self.y[idx*self.batch_size:(idx+1)*self.batch_size]
return np.array([
resize(imread(file_name), (200,200))
for file_name in batch_x]), np.array(batch_y)
```
"""
@abstractmethod
def __getitem__(self, index):
"""Gets batch at position `index`.
# Arguments
index: position of the batch in the Sequence.
# Returns
A batch
"""
raise NotImplementedError
@abstractmethod
def __len__(self):
"""Number of batch in the Sequence.
# Returns
The number of batches in the Sequence.
"""
raise NotImplementedError
def get_index(ds, i):
"""Quick fix for Python2, otherwise, it cannot be pickled.
# Arguments
ds: a Sequence object
i: index
# Returns
The value at index `i`.
"""
return ds[i]
class SequenceEnqueuer(object):
"""Base class to enqueue inputs.
The task of an Enqueuer is to use parallelism to speed up preprocessing.
This is done with processes or threads.
# Examples
```python
enqueuer = SequenceEnqueuer(...)
enqueuer.start()
datas = enqueuer.get()
for data in datas:
# Use the inputs; training, evaluating, predicting.
# ... stop sometime.
enqueuer.close()
```
The `enqueuer.get()` should be an infinite stream of datas.
"""
@abstractmethod
def is_running(self):
raise NotImplementedError
@abstractmethod
def start(self, workers=1, max_queue_size=10):
"""Starts the handler's workers.
# Arguments
workers: number of worker threads
max_queue_size: queue size
(when full, threads could block on `put()`).
"""
raise NotImplementedError
@abstractmethod
def stop(self, timeout=None):
"""Stop running threads and wait for them to exit, if necessary.
Should be called by the same thread which called start().
# Arguments
timeout: maximum time to wait on thread.join()
"""
raise NotImplementedError
@abstractmethod
def get(self):
"""Creates a generator to extract data from the queue.
Skip the data if it is `None`.
# Returns
Generator yielding tuples `(inputs, targets)`
or `(inputs, targets, sample_weights)`.
"""
raise NotImplementedError
class OrderedEnqueuer(SequenceEnqueuer):
"""Builds a Enqueuer from a Sequence.
Used in `fit_generator`, `evaluate_generator`, `predict_generator`.
# Arguments
sequence: A `keras.utils.data_utils.Sequence` object.
use_multiprocessing: use multiprocessing if True, otherwise threading
scheduling: Sequential querying of datas if 'sequential', random otherwise.
"""
def __init__(self, sequence,
use_multiprocessing=False,
scheduling='sequential'):
self.sequence = sequence
self.use_multiprocessing = use_multiprocessing
self.scheduling = scheduling
self.workers = 0
self.executor = None
self.queue = None
self.run_thread = None
self.stop_signal = None
def is_running(self):
return self.stop_signal is not None and not self.stop_signal.is_set()
def start(self, workers=1, max_queue_size=10):
"""Start the handler's workers.
# Arguments
workers: number of worker threads
max_queue_size: queue size
(when full, workers could block on `put()`)
"""
if self.use_multiprocessing:
self.executor = multiprocessing.Pool(workers)
else:
self.executor = ThreadPool(workers)
self.queue = queue.Queue(max_queue_size)
self.stop_signal = threading.Event()
self.run_thread = threading.Thread(target=self._run)
self.run_thread.daemon = True
self.run_thread.start()
def _run(self):
"""Function to submit request to the executor and queue the `Future` objects."""
sequence = list(range(len(self.sequence)))
while True:
if self.scheduling is not 'sequential':
random.shuffle(sequence)
for i in sequence:
if self.stop_signal.is_set():
return
self.queue.put(
self.executor.apply_async(get_index,
(self.sequence, i)), block=True)
def get(self):
"""Creates a generator to extract data from the queue.
Skip the data if it is `None`.
# Returns
Generator yielding tuples (inputs, targets)
or (inputs, targets, sample_weights)
"""
try:
while self.is_running():
inputs = self.queue.get(block=True).get()
if inputs is not None:
yield inputs
except Exception as e:
self.stop()
raise StopIteration(e)
def stop(self, timeout=None):
"""Stops running threads and wait for them to exit, if necessary.
Should be called by the same thread which called `start()`.
# Arguments
timeout: maximum time to wait on `thread.join()`
"""
self.stop_signal.set()
with self.queue.mutex:
self.queue.queue.clear()
self.queue.unfinished_tasks = 0
self.queue.not_full.notify()
self.executor.close()
self.executor.join()
self.run_thread.join(timeout)
class GeneratorEnqueuer(SequenceEnqueuer):
"""Builds a queue out of a data generator.
Used in `fit_generator`, `evaluate_generator`, `predict_generator`.
# Arguments
generator: a generator function which endlessly yields data
use_multiprocessing: use multiprocessing if True, otherwise threading
wait_time: time to sleep in-between calls to `put()`
random_seed: Initial seed for workers,
will be incremented by one for each workers.
"""
def __init__(self, generator,
use_multiprocessing=False,
wait_time=0.05,
random_seed=None):
self.wait_time = wait_time
self._generator = generator
self._use_multiprocessing = use_multiprocessing
self._threads = []
self._stop_event = None
self.queue = None
self.random_seed = random_seed
def start(self, workers=1, max_queue_size=10):
"""Kicks off threads which add data from the generator into the queue.
# Arguments
workers: number of worker threads
max_queue_size: queue size
(when full, threads could block on `put()`)
"""
def data_generator_task():
while not self._stop_event.is_set():
try:
if self._use_multiprocessing or self.queue.qsize() < max_queue_size:
generator_output = next(self._generator)
self.queue.put(generator_output)
else:
time.sleep(self.wait_time)
except Exception:
self._stop_event.set()
raise
try:
if self._use_multiprocessing:
self.queue = multiprocessing.Queue(maxsize=max_queue_size)
self._stop_event = multiprocessing.Event()
else:
self.queue = queue.Queue()
self._stop_event = threading.Event()
for _ in range(workers):
if self._use_multiprocessing:
# Reset random seed else all children processes
# share the same seed
np.random.seed(self.random_seed)
thread = multiprocessing.Process(target=data_generator_task)
thread.daemon = True
if self.random_seed is not None:
self.random_seed += 1
else:
thread = threading.Thread(target=data_generator_task)
self._threads.append(thread)
thread.start()
except:
self.stop()
raise
def is_running(self):
return self._stop_event is not None and not self._stop_event.is_set()
def stop(self, timeout=None):
"""Stops running threads and wait for them to exit, if necessary.
Should be called by the same thread which called `start()`.
# Arguments
timeout: maximum time to wait on `thread.join()`.
"""
if self.is_running():
self._stop_event.set()
for thread in self._threads:
if thread.is_alive():
if self._use_multiprocessing:
thread.terminate()
else:
thread.join(timeout)
if self._use_multiprocessing:
if self.queue is not None:
self.queue.close()
self._threads = []
self._stop_event = None
self.queue = None
def get(self):
"""Creates a generator to extract data from the queue.
Skip the data if it is `None`.
# Returns
A generator
"""
while self.is_running():
if not self.queue.empty():
inputs = self.queue.get()
if inputs is not None:
yield inputs
else:
time.sleep(self.wait_time)
+10 -49
Ver Arquivo
@@ -1,14 +1,16 @@
"""Python utilities required by Keras."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import inspect
import marshal
import sys
import time
import types as python_types
import numpy as np
import time
import sys
import six
import marshal
import types as python_types
import inspect
_GLOBAL_CUSTOM_OBJECTS = {}
@@ -132,8 +134,9 @@ def deserialize_keras_object(identifier, module_objects=None,
raise ValueError('Unknown ' + printable_module_name +
': ' + class_name)
if hasattr(cls, 'from_config'):
arg_spec = inspect.getargspec(cls.from_config)
custom_objects = custom_objects or {}
if has_arg(cls.from_config, 'custom_objects'):
if 'custom_objects' in arg_spec.args:
return cls.from_config(config['config'],
custom_objects=dict(list(_GLOBAL_CUSTOM_OBJECTS.items()) +
list(custom_objects.items())))
@@ -206,48 +209,6 @@ def func_load(code, defaults=None, closure=None, globs=None):
closure=closure)
def has_arg(fn, name, accept_all=False):
"""Checks if a callable accepts a given keyword argument.
For Python 2, checks if there is an argument with the given name.
For Python 3, checks if there is an argument with the given name, and
also whether this argument can be called with a keyword (i.e. if it is
not a positional-only argument).
# Arguments
fn: Callable to inspect.
name: Check if `fn` can be called with `name` as a keyword argument.
accept_all: What to return if there is no parameter called `name`
but the function accepts a `**kwargs` argument.
# Returns
bool, whether `fn` accepts a `name` keyword argument.
"""
if sys.version_info < (3,):
arg_spec = inspect.getargspec(fn)
if accept_all and arg_spec.keywords is not None:
return True
return (name in arg_spec.args)
elif sys.version_info < (3, 3):
arg_spec = inspect.getfullargspec(fn)
if accept_all and arg_spec.varkw is not None:
return True
return (name in arg_spec.args or
name in arg_spec.kwonlyargs)
else:
signature = inspect.signature(fn)
parameter = signature.parameters.get(name)
if parameter is None:
if accept_all:
for param in signature.parameters.values():
if param.kind == inspect.Parameter.VAR_KEYWORD:
return True
return False
return (parameter.kind in (inspect.Parameter.POSITIONAL_OR_KEYWORD,
inspect.Parameter.KEYWORD_ONLY))
class Progbar(object):
"""Displays a progress bar.
+5 -35
Ver Arquivo
@@ -1,13 +1,15 @@
"""Utilities related to disk I/O."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
import sys
from collections import defaultdict
import sys
import numpy as np
try:
import h5py
import h5py # pylint:disable=g-import-not-at-top
except ImportError:
h5py = None
@@ -96,40 +98,8 @@ class HDF5Matrix(object):
@property
def shape(self):
"""Gets a numpy-style shape tuple giving the dataset dimensions.
# Returns
A numpy-style shape tuple.
"""
return (self.end - self.start,) + self.data.shape[1:]
@property
def dtype(self):
"""Gets the datatype of the dataset.
# Returns
A numpy dtype string.
"""
return self.data.dtype
@property
def ndim(self):
"""Gets the number of dimensions (rank) of the dataset.
# Returns
An integer denoting the number of dimensions (rank) of the dataset.
"""
return self.data.ndim
@property
def size(self):
"""Gets the total dataset size (number of elements).
# Returns
An integer denoting the number of elements in the dataset.
"""
return np.prod(self.shape)
def ask_to_proceed_with_overwrite(filepath):
"""Produces a prompt asking about overwriting a file.
+17 -19
Ver Arquivo
@@ -1,24 +1,22 @@
"""Utilities related to Keras layers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from .conv_utils import convert_kernel
from .. import backend as K
from .conv_utils import convert_kernel
import numpy as np
def print_summary(model, line_length=None, positions=None, print_fn=print):
def print_summary(model, line_length=None, positions=None):
"""Prints a summary of a model.
# Arguments
model: Keras model instance.
line_length: Total length of printed lines
(e.g. set this to adapt the display to different
terminal window sizes).
positions: Relative or absolute positions of log elements in each line.
line_length: total length of printed lines
positions: relative or absolute positions of log elements in each line.
If not provided, defaults to `[.33, .55, .67, 1.]`.
print_fn: Print function to use.
It will be called on each line of the summary.
You can set it to a custom function
in order to capture the string summary.
"""
if model.__class__.__name__ == 'Sequential':
sequential_like = True
@@ -57,11 +55,11 @@ def print_summary(model, line_length=None, positions=None, print_fn=print):
line += str(fields[i])
line = line[:positions[i]]
line += ' ' * (positions[i] - len(line))
print_fn(line)
print(line)
print_fn('_' * line_length)
print('_' * line_length)
print_row(to_display, positions)
print_fn('=' * line_length)
print('=' * line_length)
def print_layer_summary(layer):
try:
@@ -114,19 +112,19 @@ def print_summary(model, line_length=None, positions=None, print_fn=print):
else:
print_layer_summary_with_connections(layers[i])
if i == len(layers) - 1:
print_fn('=' * line_length)
print('=' * line_length)
else:
print_fn('_' * line_length)
print('_' * line_length)
trainable_count = int(
np.sum([K.count_params(p) for p in set(model.trainable_weights)]))
non_trainable_count = int(
np.sum([K.count_params(p) for p in set(model.non_trainable_weights)]))
print_fn('Total params: {:,}'.format(trainable_count + non_trainable_count))
print_fn('Trainable params: {:,}'.format(trainable_count))
print_fn('Non-trainable params: {:,}'.format(non_trainable_count))
print_fn('_' * line_length)
print('Total params: {:,}'.format(trainable_count + non_trainable_count))
print('Trainable params: {:,}'.format(trainable_count))
print('Non-trainable params: {:,}'.format(non_trainable_count))
print('_' * line_length)
def convert_all_kernels_in_model(model):
+2
Ver Arquivo
@@ -1,5 +1,7 @@
"""Numpy-related utilities."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
+9 -9
Ver Arquivo
@@ -1,12 +1,15 @@
"""Utilities related to Keras unit tests."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import numpy as np
from numpy.testing import assert_allclose
import inspect
import six
from .generic_utils import has_arg
from ..engine import Model, Input
from ..models import Sequential
from ..models import model_from_json
from .. import backend as K
@@ -71,9 +74,7 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
layer.set_weights(weights)
# test and instantiation from weights
# Checking for empty weights array to avoid a problem where some
# legacy layers return bad values from get_weights()
if has_arg(layer_cls.__init__, 'weights') and len(weights):
if 'weights' in inspect.getargspec(layer_cls.__init__):
kwargs['weights'] = weights
layer = layer_cls(**kwargs)
@@ -87,7 +88,7 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
# check shape inference
model = Model(x, y)
expected_output_shape = layer.compute_output_shape(input_shape)
expected_output_shape = tuple(layer._compute_output_shape(input_shape).as_list())
actual_output = model.predict(input_data)
actual_output_shape = actual_output.shape
for expected_dim, actual_dim in zip(expected_output_shape,
@@ -144,7 +145,7 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
def keras_test(func):
"""Function wrapper to clean up after TensorFlow tests.
"""Function wrapper to clean up after tests.
# Arguments
func: test function to clean up after.
@@ -155,7 +156,6 @@ def keras_test(func):
@six.wraps(func)
def wrapper(*args, **kwargs):
output = func(*args, **kwargs)
if K.backend() == 'tensorflow':
K.clear_session()
K.clear_session()
return output
return wrapper
+10 -10
Ver Arquivo
@@ -1,19 +1,19 @@
"""Utilities related to model visualization."""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
try:
# pydot-ng is a fork of pydot that is better maintained.
import pydot_ng as pydot
import pydot_ng as pydot # pylint: disable=g-import-not-at-top
except ImportError:
# pydotplus is an improved version of pydot
# Fall back on pydot if necessary.
try:
import pydotplus as pydot
import pydot # pylint: disable=g-import-not-at-top
except ImportError:
# Fall back on pydot if necessary.
try:
import pydot
except ImportError:
pydot = None
pydot = None
def _check_pydot():
@@ -46,8 +46,8 @@ def model_to_dot(model,
# Returns
A `pydot.Dot` instance representing the Keras model.
"""
from ..layers.wrappers import Wrapper
from ..models import Sequential
from ..layers.wrappers import Wrapper # pylint: disable=g-import-not-at-top
from ..models import Sequential # pylint: disable=g-import-not-at-top
_check_pydot()
dot = pydot.Dot()
+7
Ver Arquivo
@@ -0,0 +1,7 @@
"""Keras API wrappers.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from . import scikit_learn
+17 -11
Ver Arquivo
@@ -1,13 +1,16 @@
"""API wrapper allowing to use certain Keras models with the Scikit-Learn API.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import copy
import inspect
import types
import numpy as np
from ..utils.np_utils import to_categorical
from ..utils.generic_utils import has_arg
from ..models import Sequential
import numpy as np
from ..utils.np_utils import to_categorical
class BaseWrapper(object):
@@ -75,20 +78,22 @@ class BaseWrapper(object):
else:
legal_params_fns.append(self.build_fn)
legal_params = []
for fn in legal_params_fns:
legal_params += inspect.getargspec(fn)[0]
legal_params = set(legal_params)
for params_name in params:
for fn in legal_params_fns:
if has_arg(fn, params_name):
break
else:
if params_name not in legal_params:
if params_name != 'nb_epoch':
raise ValueError(
'{} is not a legal parameter'.format(params_name))
def get_params(self, **params):
def get_params(self, **params): # pylint: disable=unused-argument
"""Gets parameters for this estimator.
# Arguments
**params: ignored (exists for API compatibility).
**params: ignored (exists for API compatiblity).
# Returns
Dictionary of parameter names mapped to their values.
@@ -161,8 +166,9 @@ class BaseWrapper(object):
"""
override = override or {}
res = {}
fn_args = inspect.getargspec(fn)[0]
for name, value in self.sk_params.items():
if has_arg(fn, name):
if name in fn_args:
res.update({name: value})
res.update(override)
return res
+2 -2
Ver Arquivo
@@ -3,12 +3,12 @@ from setuptools import find_packages
setup(name='Keras',
version='2.0.5',
version='2.0.4-tf',
description='Deep Learning for Python',
author='Francois Chollet',
author_email='francois.chollet@gmail.com',
url='https://github.com/fchollet/keras',
download_url='https://github.com/fchollet/keras/tarball/2.0.5',
download_url='https://github.com/fchollet/keras/tarball/2.0.4',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
@@ -6,8 +6,7 @@ import string
from keras.utils.test_utils import get_test_data, keras_test
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras import layers, optimizers
import keras.backend as K
from keras import layers
import keras
@@ -205,14 +204,5 @@ def test_masked_temporal():
ground_truth = -np.log(0.5)
assert(np.abs(history.history['loss'][-1] - ground_truth) < 0.06)
@pytest.mark.skipif(K.backend() != 'tensorflow', reason='Requires TF backend')
@keras_test
def test_embedding_with_clipnorm():
model = Sequential()
model.add(layers.Embedding(input_dim=1, output_dim=1))
model.compile(optimizer=optimizers.SGD(clipnorm=0.1), loss='mse')
model.fit(np.array([[0]]), np.array([[[0.5]]]), epochs=1)
if __name__ == '__main__':
pytest.main([__file__])
+1 -28
Ver Arquivo
@@ -15,7 +15,7 @@ def get_standard_values():
def test_serialization():
all_activations = ['softmax', 'relu', 'elu', 'tanh',
'sigmoid', 'hard_sigmoid', 'linear',
'softplus', 'softsign', 'selu']
'softplus', 'softsign']
for name in all_activations:
fn = activations.get(name)
ref_fn = getattr(activations, name)
@@ -136,39 +136,12 @@ def test_elu():
assert_allclose(result, test_values, rtol=1e-05)
negative_values = np.array([[-1, -2]], dtype=K.floatx())
# cntk can't rebind the input shape, so create the model again to test different batch size
if (K.backend() == 'cntk'):
x2 = K.placeholder(ndim=2)
f = K.function([x2], [activations.elu(x2, 0.5)])
result = f([negative_values])[0]
true_result = (np.exp(negative_values) - 1) / 2
assert_allclose(result, true_result)
def test_selu():
x = K.placeholder(ndim=2)
f = K.function([x], [activations.selu(x)])
alpha = 1.6732632423543772848170429916717
scale = 1.0507009873554804934193349852946
positive_values = get_standard_values()
result = f([positive_values])[0]
assert_allclose(result, positive_values * scale, rtol=1e-05)
negative_values = np.array([[-1, -2]], dtype=K.floatx())
# cntk can't rebind the input shape, so create the model again to test different batch size
if (K.backend() == 'cntk'):
x2 = K.placeholder(ndim=2)
f = K.function([x2], [activations.selu(x2)])
result = f([negative_values])[0]
true_result = (np.exp(negative_values) - 1) * scale * alpha
assert_allclose(result, true_result)
def test_tanh():
test_values = get_standard_values()
+3 -137
Ver Arquivo
@@ -1,8 +1,5 @@
import pytest
from keras.utils.test_utils import keras_test
from keras.utils.test_utils import layer_test
from keras.utils.generic_utils import CustomObjectScope
from keras.models import Sequential
from keras import applications
from keras import backend as K
@@ -14,24 +11,12 @@ def test_resnet50():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_resnet50_notop():
model = applications.ResNet50(weights=None, include_top=False)
assert model.output_shape == (None, None, None, 2048)
@keras_test
def test_resnet50_notop_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.ResNet50(weights=None, include_top=False, input_shape=input_shape)
output_shape = (None, 2048, 1, 1) if K.image_data_format() == 'channels_first' else (None, 1, 1, 2048)
assert model.output_shape == output_shape
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_resnet50_pooling():
model = applications.ResNet50(weights=None,
include_top=False,
@@ -39,16 +24,6 @@ def test_resnet50_pooling():
assert model.output_shape == (None, 2048)
@keras_test
def test_resnet50_pooling_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.ResNet50(weights=None,
include_top=False,
pooling='avg',
input_shape=input_shape)
assert model.output_shape == (None, 2048)
@keras_test
def test_vgg16():
model = applications.VGG16(weights=None)
@@ -56,36 +31,17 @@ def test_vgg16():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_vgg16_notop():
model = applications.VGG16(weights=None, include_top=False)
assert model.output_shape == (None, None, None, 512)
@keras_test
def test_vgg16_notop_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.VGG16(weights=None, include_top=False, input_shape=input_shape)
output_shape = (None, 512, 9, 9) if K.image_data_format() == 'channels_first' else (None, 9, 9, 512)
assert model.output_shape == output_shape
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_vgg16_pooling():
model = applications.VGG16(weights=None, include_top=False, pooling='avg')
assert model.output_shape == (None, 512)
@keras_test
def test_vgg16_pooling_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.VGG16(weights=None, include_top=False, pooling='avg', input_shape=input_shape)
assert model.output_shape == (None, 512)
@keras_test
def test_vgg19():
model = applications.VGG19(weights=None)
@@ -93,36 +49,17 @@ def test_vgg19():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_vgg19_notop():
model = applications.VGG19(weights=None, include_top=False)
model = applications.VGG16(weights=None, include_top=False)
assert model.output_shape == (None, None, None, 512)
@keras_test
def test_vgg19_notop_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.VGG19(weights=None, include_top=False, input_shape=input_shape)
output_shape = (None, 512, 9, 9) if K.image_data_format() == 'channels_first' else (None, 9, 9, 512)
assert model.output_shape == output_shape
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_vgg19_pooling():
model = applications.VGG16(weights=None, include_top=False, pooling='avg')
assert model.output_shape == (None, 512)
@keras_test
def test_vgg19_pooling_specified_input_shape():
input_shape = (3, 300, 300) if K.image_data_format() == 'channels_first' else (300, 300, 3)
model = applications.VGG16(weights=None, include_top=False, pooling='avg', input_shape=input_shape)
assert model.output_shape == (None, 512)
@keras_test
@pytest.mark.skipif((K.backend() != 'tensorflow'),
reason='Requires tensorflow backend')
@@ -154,88 +91,17 @@ def test_inceptionv3():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_inceptionv3_notop():
model = applications.InceptionV3(weights=None, include_top=False)
assert model.output_shape == (None, None, None, 2048)
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support padding with non-concrete dimension")
def test_inceptionv3_pooling():
model = applications.InceptionV3(weights=None, include_top=False, pooling='avg')
assert model.output_shape == (None, 2048)
@keras_test
@pytest.mark.skipif((K.backend() != 'tensorflow'),
reason="MobileNets are supported only on Tensorflow")
def test_mobilenet():
model = applications.MobileNet(weights=None)
assert model.output_shape == (None, 1000)
@keras_test
@pytest.mark.skipif((K.backend() != 'tensorflow'),
reason="MobileNets are supported only on Tensorflow")
def test_mobilenet_no_top():
model = applications.MobileNet(weights=None, include_top=False)
assert model.output_shape == (None, None, None, 1024)
@keras_test
@pytest.mark.skipif((K.backend() != 'tensorflow'),
reason="MobileNets are supported only on Tensorflow")
def test_mobilenet_pooling():
model = applications.MobileNet(weights=None, include_top=False, pooling='avg')
assert model.output_shape == (None, 1024)
@pytest.mark.skipif(K.backend() != 'tensorflow', reason='Requires TF backend')
@keras_test
def test_depthwise_conv_2d():
_convolution_paddings = ['valid', 'same']
num_samples = 2
stack_size = 3
num_row = 7
num_col = 6
with CustomObjectScope({'relu6': applications.mobilenet.relu6,
'DepthwiseConv2D': applications.mobilenet.DepthwiseConv2D}):
for padding in _convolution_paddings:
for strides in [(1, 1), (2, 2)]:
for multiplier in [1, 2]:
if padding == 'same' and strides != (1, 1):
continue
layer_test(applications.mobilenet.DepthwiseConv2D,
kwargs={'kernel_size': (3, 3),
'padding': padding,
'strides': strides,
'depth_multiplier': multiplier},
input_shape=(num_samples, num_row, num_col, stack_size))
layer_test(applications.mobilenet.DepthwiseConv2D,
kwargs={'kernel_size': 3,
'padding': padding,
'data_format': 'channels_first',
'activation': None,
'depthwise_regularizer': 'l2',
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
'depthwise_constraint': 'unit_norm',
'strides': strides,
'depth_multiplier': multiplier},
input_shape=(num_samples, stack_size, num_row, num_col))
# Test invalid use case
with pytest.raises(ValueError):
model = Sequential([applications.mobilenet.DepthwiseConv2D(kernel_size=3,
padding=padding,
batch_input_shape=(None, None, 5, None))])
if __name__ == '__main__':
pytest.main([__file__])
# pytest.main([__file__])
test_vgg16()
@@ -1,112 +0,0 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.applications import imagenet_utils as utils
def test_preprocess_input():
x = np.random.uniform(0, 255, (2, 3, 2, 3))
assert utils.preprocess_input(x).shape == x.shape
out1 = utils.preprocess_input(x, 'channels_last')
out2 = utils.preprocess_input(np.transpose(x, (0, 3, 1, 2)), 'channels_first')
assert_allclose(out1, out2.transpose(0, 2, 3, 1))
def test_decode_predictions():
x = np.zeros((2, 1000))
x[0, 372] = 1.0
x[1, 549] = 1.0
outs = utils.decode_predictions(x, top=1)
scores = [out[0][2] for out in outs]
assert scores[0] == scores[1]
# the numbers of columns and ImageNet classes are not identical.
with pytest.raises(ValueError):
utils.decode_predictions(np.ones((2, 100)))
def test_obtain_input_shape():
# input_shape and default_size are not identical.
with pytest.raises(ValueError):
utils._obtain_input_shape(
input_shape=(224, 224, 3),
default_size=299,
min_size=139,
data_format='channels_last',
include_top=True)
# Test invalid use cases
for data_format in ['channels_last', 'channels_first']:
# input_shape is smaller than min_size.
shape = (100, 100)
input_shape = shape + (3,) if data_format == 'channels_last' else (3,) + shape
with pytest.raises(ValueError):
utils._obtain_input_shape(
input_shape=input_shape,
default_size=None,
min_size=139,
data_format=data_format,
include_top=False)
# shape is 1D.
shape = (100,)
input_shape = shape + (3,) if data_format == 'channels_last' else (3,) + shape
with pytest.raises(ValueError):
utils._obtain_input_shape(
input_shape=input_shape,
default_size=None,
min_size=139,
data_format=data_format,
include_top=False)
# the number of channels is 5 not 3.
shape = (100, 100)
input_shape = shape + (5,) if data_format == 'channels_last' else (5,) + shape
with pytest.raises(ValueError):
utils._obtain_input_shape(
input_shape=input_shape,
default_size=None,
min_size=139,
data_format=data_format,
include_top=False)
assert utils._obtain_input_shape(
input_shape=None,
default_size=None,
min_size=139,
data_format='channels_last',
include_top=False) == (None, None, 3)
assert utils._obtain_input_shape(
input_shape=None,
default_size=None,
min_size=139,
data_format='channels_first',
include_top=False) == (3, None, None)
assert utils._obtain_input_shape(
input_shape=None,
default_size=None,
min_size=139,
data_format='channels_last',
include_top=False) == (None, None, 3)
assert utils._obtain_input_shape(
input_shape=(150, 150, 3),
default_size=None,
min_size=139,
data_format='channels_last',
include_top=False) == (150, 150, 3)
assert utils._obtain_input_shape(
input_shape=(3, None, None),
default_size=None,
min_size=139,
data_format='channels_first',
include_top=False) == (3, None, None)
if __name__ == '__main__':
pytest.main([__file__])
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+44 -50
Ver Arquivo
@@ -1,6 +1,7 @@
import pytest
import json
import numpy as np
import tensorflow as tf
from keras.layers import Dense, Dropout, InputLayer
from keras import layers
@@ -77,8 +78,6 @@ def test_trainable_weights():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support add learning_phase() as input")
def test_learning_phase():
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
@@ -146,7 +145,7 @@ def test_node_construction():
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
assert a._keras_shape == (None, 32)
assert a.get_shape().as_list() == [None, 32]
a_layer, a_node_index, a_tensor_index = a._keras_history
b_layer, b_node_index, b_tensor_index = b._keras_history
assert len(a_layer.inbound_nodes) == 1
@@ -187,7 +186,7 @@ def test_node_construction():
# test layer properties
test_layer = Dense(16, name='test_layer')
a_test = test_layer(a)
assert K.int_shape(test_layer.kernel) == (32, 16)
assert test_layer.kernel.get_shape().as_list() == [32, 16]
assert test_layer.input == a
assert test_layer.output == a_test
assert test_layer.input_mask is None
@@ -195,13 +194,13 @@ def test_node_construction():
assert test_layer.input_shape == (None, 32)
assert test_layer.output_shape == (None, 16)
with pytest.raises(AttributeError):
with pytest.raises(Exception):
dense.input
with pytest.raises(AttributeError):
with pytest.raises(Exception):
dense.output
with pytest.raises(AttributeError):
with pytest.raises(Exception):
dense.input_mask
with pytest.raises(AttributeError):
with pytest.raises(Exception):
dense.output_mask
assert dense.get_input_at(0) == a
@@ -230,7 +229,7 @@ def test_multi_input_layer():
b_2 = dense(b)
merged = layers.concatenate([a_2, b_2], name='merge')
assert merged._keras_shape == (None, 16 * 2)
assert merged.get_shape().as_list() == [None, 16 * 2]
merge_layer, merge_node_index, merge_tensor_index = merged._keras_history
assert merge_node_index == 0
@@ -252,15 +251,14 @@ def test_multi_input_layer():
print('model.input_layers_tensor_indices:', model.input_layers_tensor_indices)
print('model.output_layers', model.output_layers)
print('output_shape:', model.compute_output_shape([(None, 32), (None, 32)]))
assert model.compute_output_shape([(None, 32), (None, 32)]) == [(None, 64), (None, 5)]
print('output_shape:', model._compute_output_shape([(None, 32), (None, 32)]))
output_shapes = model._compute_output_shape([(None, 32), (None, 32)])
assert output_shapes[0].as_list() == [None, 64]
assert output_shapes[1].as_list() == [None, 5]
print('mask:', model.compute_mask([a, b], [None, None]))
assert model.compute_mask([a, b], [None, None]) == [None, None]
print('output_shape:', model.compute_output_shape([(None, 32), (None, 32)]))
assert model.compute_output_shape([(None, 32), (None, 32)]) == [(None, 64), (None, 5)]
# we don't check names of first 2 layers (inputs) because
# ordering of same-level layers is not fixed
print('layers:', [layer.name for layer in model.layers])
@@ -322,10 +320,8 @@ def test_recursion():
f = Input(shape=(32,), name='input_f')
g, h = model([e, f])
# g2, h2 = model([e, f])
assert g._keras_shape == c._keras_shape
assert h._keras_shape == d._keras_shape
assert g.get_shape().as_list() == c.get_shape().as_list()
assert h.get_shape().as_list() == d.get_shape().as_list()
# test separate manipulation of different layer outputs
i = Dense(7, name='dense_4')(h)
@@ -343,8 +339,8 @@ def test_recursion():
print(model.compute_mask([e, f], [None, None]))
assert model.compute_mask([e, f], [None, None]) == [None, None]
print(final_model.compute_output_shape([(10, 32), (10, 32)]))
assert final_model.compute_output_shape([(10, 32), (10, 32)]) == [(10, 7), (10, 64)]
print(final_model._compute_output_shape([(10, 32), (10, 32)]))
assert final_model._compute_output_shape([(10, 32), (10, 32)]) == [(10, 7), (10, 64)]
# run recursive model
fn = K.function(final_model.inputs, final_model.outputs)
@@ -375,10 +371,10 @@ def test_recursion():
p = Input(shape=(32,), name='input_p')
q, r = model([o, p])
assert n._keras_shape == (None, 5)
assert q._keras_shape == (None, 64)
assert n.get_shape().as_list() == [None, 5]
assert q.get_shape().as_list() == [None, 64]
s = layers.concatenate([n, q], name='merge_nq')
assert s._keras_shape == (None, 64 + 5)
assert s.get_shape().as_list() == [None, 64 + 5]
# test with single output as 1-elem list
multi_io_model = Model([j, k, o, p], [s])
@@ -431,63 +427,62 @@ def test_recursion():
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
with pytest.raises(TypeError):
with pytest.raises(Exception):
Model([j, k], [m, n])
# disconnected graph
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
with pytest.raises(RuntimeError):
with pytest.raises(Exception) as e:
Model([j], [m, n])
# redundant outputs
# redudant outputs
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
# this should work with a warning
# this should work lol
# TODO: raise a warning
Model([j, k], [m, n, n])
# redundant inputs
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
with pytest.raises(ValueError):
with pytest.raises(Exception):
Model([j, k, j], [m, n])
# i have not idea what I'm doing: garbage as inputs/outputs
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
with pytest.raises(TypeError):
with pytest.raises(Exception):
Model([j, k], [m, n, 0])
####################################################
# test calling layers/models on TF tensors
if K._BACKEND == 'tensorflow':
import tensorflow as tf
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
tf_model = Model([j, k], [m, n])
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
tf_model = Model([j, k], [m, n])
j_tf = tf.placeholder(dtype=K.floatx())
k_tf = tf.placeholder(dtype=K.floatx())
m_tf, n_tf = tf_model([j_tf, k_tf])
assert m_tf.get_shape().as_list() == [None, 64]
assert n_tf.get_shape().as_list() == [None, 5]
j_tf = tf.placeholder(dtype=K.floatx())
k_tf = tf.placeholder(dtype=K.floatx())
m_tf, n_tf = tf_model([j_tf, k_tf])
assert m_tf.get_shape().as_list() == [None, 64]
assert n_tf.get_shape().as_list() == [None, 5]
# test merge
layers.concatenate([j_tf, k_tf], axis=1)
layers.add([j_tf, k_tf])
# test merge
layers.concatenate([j_tf, k_tf], axis=1)
layers.add([j_tf, k_tf])
# test tensor input
x = tf.placeholder(shape=(None, 2), dtype=K.floatx())
InputLayer(input_tensor=x)
# test tensor input
x = tf.placeholder(shape=(None, 2), dtype=K.floatx())
InputLayer(input_tensor=x)
x = Input(tensor=x)
Dense(2)(x)
x = Input(tensor=x)
Dense(2)(x)
@keras_test
@@ -496,7 +491,7 @@ def test_load_layers():
from keras.models import Model
from keras.engine.topology import preprocess_weights_for_loading
if K.backend() == 'tensorflow' or K.backend() == 'cntk':
if K.backend() == 'tensorflow':
inputs = Input(shape=(10, 20, 20, 1))
else:
inputs = Input(shape=(10, 1, 20, 20))
@@ -552,7 +547,6 @@ def test_load_layers():
assert np.all(K.eval(model.layers[2].weights[5]) == weight_tensor_bi_convlstm_new[5])
@keras_test
def test_recursion_with_bn_and_loss():
model1 = Sequential([
layers.Dense(5, input_dim=5, activity_regularizer='l1'),
+9 -242
Ver Arquivo
@@ -1,91 +1,16 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
import sys
import scipy.sparse as sparse
from keras.layers import Dense, Dropout
from keras.engine.topology import Input
from keras.engine.training import Model
from keras.engine.training import Model
from keras.engine.training import _check_loss_and_target_compatibility
from keras.engine.training import _weighted_masked_objective
from keras.engine.training import _check_array_lengths
from keras.engine.training import _slice_arrays
from keras.engine.training import Model, _check_loss_and_target_compatibility
from keras.models import Sequential
from keras import backend as K
from keras.utils import Sequence
from keras.utils.test_utils import keras_test
from keras.callbacks import LambdaCallback
class RandomSequence(Sequence):
def __init__(self, batch_size):
self.batch_size = batch_size
def __len__(self):
return 12
def __getitem__(self, idx):
return [np.random.random((self.batch_size, 3)), np.random.random((self.batch_size, 3))], [
np.random.random((self.batch_size, 4)),
np.random.random((self.batch_size, 3))]
@keras_test
def test_check_array_lengths():
_check_array_lengths(None, None, None)
a_np = np.random.random((4, 3, 3))
_check_array_lengths(a_np, a_np, a_np)
_check_array_lengths([a_np, a_np], [a_np, a_np], [a_np, a_np])
_check_array_lengths([None], [None], [None])
b_np = np.random.random((3, 4))
with pytest.raises(ValueError):
_check_array_lengths(a_np, None, None)
with pytest.raises(ValueError):
_check_array_lengths(a_np, a_np, None)
with pytest.raises(ValueError):
_check_array_lengths([a_np], [None], None)
with pytest.raises(ValueError):
_check_array_lengths([a_np], [b_np], None)
with pytest.raises(ValueError):
_check_array_lengths([a_np], None, [b_np])
@keras_test
def test_slice_arrays():
input_a = np.random.random((10, 3))
_slice_arrays(None)
_slice_arrays(input_a, 0)
_slice_arrays(input_a, 0, 1)
_slice_arrays(input_a, stop=2)
input_a = [None, [1, 1], None, [1, 1]]
_slice_arrays(input_a, 0)
_slice_arrays(input_a, 0, 1)
_slice_arrays(input_a, stop=2)
input_a = [None]
_slice_arrays(input_a, 0)
_slice_arrays(input_a, 0, 1)
_slice_arrays(input_a, stop=2)
input_a = None
_slice_arrays(input_a, 0)
_slice_arrays(input_a, 0, 1)
_slice_arrays(input_a, stop=2)
@keras_test
def test_weighted_masked_objective():
a = Input(shape=(3,), name='input_a')
# weighted_masked_objective
def mask_dummy(y_true=None, y_pred=None, weight=None):
return K.placeholder(y_true.shape)
weighted_function = _weighted_masked_objective(K.categorical_crossentropy)
weighted_function(a, a, None)
@keras_test
def test_model_methods():
a = Input(shape=(3,), name='input_a')
@@ -100,6 +25,8 @@ def test_model_methods():
optimizer = 'rmsprop'
loss = 'mse'
loss_weights = [1., 0.5]
model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
sample_weight_mode=None)
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
@@ -107,13 +34,6 @@ def test_model_methods():
output_a_np = np.random.random((10, 4))
output_b_np = np.random.random((10, 3))
# training/testing doesn't work before compiling.
with pytest.raises(RuntimeError):
model.train_on_batch([input_a_np, input_b_np], [output_a_np, output_b_np])
model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
sample_weight_mode=None)
# test train_on_batch
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
@@ -154,9 +74,7 @@ def test_model_methods():
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np},
epochs=1, batch_size=4, validation_split=0.5,
validation_data=(
{'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np}))
validation_data=({'input_a': input_a_np, 'input_b': input_b_np}, {'dense_1': output_a_np, 'dropout': output_b_np}))
# test_on_batch
out = model.test_on_batch([input_a_np, input_b_np],
@@ -250,7 +168,6 @@ def test_model_methods():
while True:
yield ([np.random.random((batch_sz, 3)), np.random.random((batch_sz, 3))],
[np.random.random((batch_sz, 4)), np.random.random((batch_sz, 3))])
out = model.fit_generator(gen_data(4), steps_per_epoch=3, epochs=5,
initial_epoch=2, callbacks=[tracker_cb])
assert trained_epochs == [2, 3, 4]
@@ -280,154 +197,6 @@ def test_model_methods():
out = model.evaluate([input_a_np, input_b_np], [output_a_np, output_b_np], batch_size=4)
out = model.predict([input_a_np, input_b_np], batch_size=4)
# empty batch
with pytest.raises(ValueError):
def gen_data():
while True:
yield (np.asarray([]), np.asarray([]))
out = model.evaluate_generator(gen_data(), steps=1)
# x is not a list of numpy arrays.
with pytest.raises(ValueError):
out = model.predict([None])
# x does not match _feed_input_names.
with pytest.raises(ValueError):
out = model.predict([input_a_np, None, input_b_np])
with pytest.raises(ValueError):
out = model.predict([None, input_a_np, input_b_np])
# all input/output/weight arrays should have the same number of samples.
with pytest.raises(ValueError):
out = model.train_on_batch([input_a_np, input_b_np[:2]],
[output_a_np, output_b_np],
sample_weight=sample_weight)
with pytest.raises(ValueError):
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np[:2]],
sample_weight=sample_weight)
with pytest.raises(ValueError):
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=[sample_weight[1], sample_weight[1][:2]])
# `sample_weight` is neither a dict nor a list.
with pytest.raises(TypeError):
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=tuple(sample_weight))
# `validation_data` is neither a tuple nor a triple.
with pytest.raises(ValueError):
out = model.fit([input_a_np, input_b_np],
[output_a_np, output_b_np],
epochs=1, batch_size=4,
validation_data=([input_a_np, input_b_np],))
# `loss` does not match outputs.
with pytest.raises(ValueError):
model.compile(optimizer, loss=['mse', 'mae', 'mape'])
# `loss_weights` does not match output_names.
with pytest.raises(ValueError):
model.compile(optimizer, loss='mse', loss_weights={'lstm': 0.5})
# `loss_weights` does not match outputs.
with pytest.raises(ValueError):
model.compile(optimizer, loss='mse', loss_weights=[0.5])
# `loss_weights` is invalid type.
with pytest.raises(TypeError):
model.compile(optimizer, loss='mse', loss_weights=(0.5, 0.5))
# `sample_weight_mode` does not match output_names.
with pytest.raises(ValueError):
model.compile(optimizer, loss='mse', sample_weight_mode={'lstm': 'temporal'})
# `sample_weight_mode` does not match output_names.
with pytest.raises(ValueError):
model.compile(optimizer, loss='mse', sample_weight_mode=['temporal'])
# `sample_weight_mode` matches output_names partially.
with pytest.raises(ValueError):
model.compile(optimizer, loss='mse', sample_weight_mode={'dense_1': 'temporal'})
# `loss` does not exist.
with pytest.raises(RuntimeError):
model.compile(optimizer, loss=[])
model.compile(optimizer, loss=['mse', 'mae'])
model.compile(optimizer, loss='mse', loss_weights={'dense_1': 0.2, 'dropout': 0.8})
model.compile(optimizer, loss='mse', loss_weights=[0.2, 0.8])
# the rank of weight arrays should be 1.
with pytest.raises(ValueError):
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=[None, np.random.random((10, 20, 30))])
model.compile(optimizer, loss='mse', sample_weight_mode={'dense_1': None, 'dropout': 'temporal'})
model.compile(optimizer, loss='mse', sample_weight_mode=[None, 'temporal'])
# the rank of output arrays should be at least 3D.
with pytest.raises(ValueError):
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=sample_weight)
model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
sample_weight_mode=None)
trained_epochs = []
out = model.fit_generator(generator=RandomSequence(3), steps_per_epoch=4, epochs=5,
initial_epoch=0, validation_data=RandomSequence(4),
validation_steps=3, callbacks=[tracker_cb])
assert trained_epochs == [0, 1, 2, 3, 4]
@pytest.mark.skipif(sys.version_info < (3,), reason='Cannot catch warnings in python 2')
@keras_test
def test_warnings():
a = Input(shape=(3,), name='input_a')
b = Input(shape=(3,), name='input_b')
a_2 = Dense(4, name='dense_1')(a)
dp = Dropout(0.5, name='dropout')
b_2 = dp(b)
model = Model([a, b], [a_2, b_2])
optimizer = 'rmsprop'
loss = 'mse'
loss_weights = [1., 0.5]
model.compile(optimizer, loss, metrics=[], loss_weights=loss_weights,
sample_weight_mode=None)
def gen_data(batch_sz):
while True:
yield ([np.random.random((batch_sz, 3)), np.random.random((batch_sz, 3))],
[np.random.random((batch_sz, 4)), np.random.random((batch_sz, 3))])
with pytest.warns(Warning) as w:
out = model.fit_generator(gen_data(4), steps_per_epoch=10, use_multiprocessing=True, workers=2)
warning_raised = any(['Sequence' in str(w_.message) for w_ in w])
assert warning_raised, 'No warning raised when using generator with processes.'
with pytest.warns(None) as w:
out = model.fit_generator(RandomSequence(3), steps_per_epoch=4, use_multiprocessing=True, workers=2)
assert all(['Sequence' not in str(w_.message) for w_ in w]), 'A warning was raised for Sequence.'
@pytest.mark.skipif(K.backend() != 'tensorflow', reason='sparse operations supported only by TF')
@keras_test
def test_sparse_input_validation_split():
test_input = sparse.random(6, 3, density=0.25).tocsr()
in1 = Input(shape=(3,), sparse=True)
out1 = Dense(4)(in1)
test_output = np.random.random((6, 4))
model = Model(in1, out1)
model.compile('rmsprop', 'mse')
model.fit(test_input, test_output, epochs=1, batch_size=2, validation_split=0.2)
@keras_test
def test_trainable_argument():
@@ -443,9 +212,9 @@ def test_trainable_argument():
assert_allclose(out, out_2)
# test with nesting
inputs = Input(shape=(3,))
outputs = model(inputs)
model = Model(inputs, outputs)
input = Input(shape=(3,))
output = model(input)
model = Model(input, output)
model.compile('rmsprop', 'mse')
out = model.predict(x)
model.train_on_batch(x, y)
@@ -463,7 +232,7 @@ def test_check_not_failing():
@keras_test
def test_check_last_is_one():
a = np.random.random((2, 3, 1))
with pytest.raises(ValueError) as exc:
with pytest.raises(Exception) as exc:
_check_loss_and_target_compatibility([a], [K.categorical_crossentropy], [a.shape])
assert 'You are passing a target array' in str(exc)
@@ -472,7 +241,7 @@ def test_check_last_is_one():
@keras_test
def test_check_bad_shape():
a = np.random.random((2, 3, 5))
with pytest.raises(ValueError) as exc:
with pytest.raises(Exception) as exc:
_check_loss_and_target_compatibility([a], [K.categorical_crossentropy], [(2, 3, 6)])
assert 'targets to have the same shape' in str(exc)
@@ -664,8 +433,6 @@ def test_model_with_partial_loss():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support external loss yet")
def test_model_with_external_loss():
# None loss, only regularization loss.
a = Input(shape=(3,), name='input_a')
+1 -9
Ver Arquivo
@@ -90,14 +90,6 @@ def test_he_normal(tensor_shape):
target_mean=0., target_std=None, target_max=2 * scale)
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_lecun_normal(tensor_shape):
fan_in, _ = initializers._compute_fans(tensor_shape)
scale = np.sqrt(1. / fan_in)
_runner(initializers.lecun_normal(), tensor_shape,
target_mean=0., target_std=scale)
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_orthogonal(tensor_shape):
_runner(initializers.orthogonal(), tensor_shape,
@@ -107,7 +99,7 @@ def test_orthogonal(tensor_shape):
@pytest.mark.parametrize('tensor_shape', [(100, 100), (1, 2, 3, 4)], ids=['FC', 'CONV'])
def test_identity(tensor_shape):
if len(tensor_shape) > 2:
with pytest.raises(ValueError):
with pytest.raises(Exception):
_runner(initializers.identity(), tensor_shape,
target_mean=1. / tensor_shape[0], target_max=1.)
else:
+54 -56
Ver Arquivo
@@ -43,69 +43,67 @@ def test_convolutional_recurrent():
if data_format == 'channels_first' or return_sequences:
continue
# cntk doesn't support statefulness on LSTM yet, will enable it on cntk later
if K.backend() != 'cntk':
# Tests for statefulness
model = Sequential()
kwargs = {'data_format': data_format,
'return_sequences': return_sequences,
'filters': filters,
'kernel_size': (num_row, num_col),
'stateful': True,
'batch_input_shape': inputs.shape,
'padding': 'same'}
layer = convolutional_recurrent.ConvLSTM2D(**kwargs)
# Tests for statefulness
model = Sequential()
kwargs = {'data_format': data_format,
'return_sequences': return_sequences,
'filters': filters,
'kernel_size': (num_row, num_col),
'stateful': True,
'batch_input_shape': inputs.shape,
'padding': 'same'}
layer = convolutional_recurrent.ConvLSTM2D(**kwargs)
model.add(layer)
model.compile(optimizer='sgd', loss='mse')
out1 = model.predict(np.ones_like(inputs))
model.add(layer)
model.compile(optimizer='sgd', loss='mse')
out1 = model.predict(np.ones_like(inputs))
# train once so that the states change
model.train_on_batch(np.ones_like(inputs),
np.random.random(out1.shape))
out2 = model.predict(np.ones_like(inputs))
# train once so that the states change
model.train_on_batch(np.ones_like(inputs),
np.random.random(out1.shape))
out2 = model.predict(np.ones_like(inputs))
# if the state is not reset, output should be different
assert(out1.max() != out2.max())
# if the state is not reset, output should be different
assert(out1.max() != out2.max())
# check that output changes after states are reset
# (even though the model itself didn't change)
layer.reset_states()
out3 = model.predict(np.ones_like(inputs))
assert(out2.max() != out3.max())
# check that output changes after states are reset
# (even though the model itself didn't change)
layer.reset_states()
out3 = model.predict(np.ones_like(inputs))
assert(out2.max() != out3.max())
# check that container-level reset_states() works
model.reset_states()
out4 = model.predict(np.ones_like(inputs))
assert_allclose(out3, out4, atol=1e-5)
# check that container-level reset_states() works
model.reset_states()
out4 = model.predict(np.ones_like(inputs))
assert_allclose(out3, out4, atol=1e-5)
# check that the call to `predict` updated the states
out5 = model.predict(np.ones_like(inputs))
assert(out4.max() != out5.max())
# check that the call to `predict` updated the states
out5 = model.predict(np.ones_like(inputs))
assert(out4.max() != out5.max())
# check regularizers
kwargs = {'data_format': data_format,
'return_sequences': return_sequences,
'kernel_size': (num_row, num_col),
'stateful': True,
'filters': filters,
'batch_input_shape': inputs.shape,
'kernel_regularizer': regularizers.L1L2(l1=0.01),
'recurrent_regularizer': regularizers.L1L2(l1=0.01),
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
'kernel_constraint': 'max_norm',
'recurrent_constraint': 'max_norm',
'bias_constraint': 'max_norm',
'padding': 'same'}
# check regularizers
kwargs = {'data_format': data_format,
'return_sequences': return_sequences,
'kernel_size': (num_row, num_col),
'stateful': True,
'filters': filters,
'batch_input_shape': inputs.shape,
'kernel_regularizer': regularizers.L1L2(l1=0.01),
'recurrent_regularizer': regularizers.L1L2(l1=0.01),
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
'kernel_constraint': 'max_norm',
'recurrent_constraint': 'max_norm',
'bias_constraint': 'max_norm',
'padding': 'same'}
layer = convolutional_recurrent.ConvLSTM2D(**kwargs)
layer.build(inputs.shape)
assert len(layer.losses) == 3
assert layer.activity_regularizer
output = layer(K.variable(np.ones(inputs.shape)))
assert len(layer.losses) == 4
K.eval(output)
layer = convolutional_recurrent.ConvLSTM2D(**kwargs)
layer.build(inputs.shape)
assert len(layer.losses) == 3
assert layer.activity_regularizer
output = layer(K.variable(np.ones(inputs.shape)))
assert len(layer.losses) == 4
K.eval(output)
# check dropout
layer_test(convolutional_recurrent.ConvLSTM2D,
@@ -128,7 +126,7 @@ def test_convolutional_recurrent():
initial_state = layer.get_initial_state(x)
y = layer(x, initial_state=initial_state)
model = Model(x, y)
assert model.predict(inputs).shape == layer.compute_output_shape(inputs.shape)
assert model.predict(inputs).shape == layer._compute_output_shape(inputs.shape)
if __name__ == '__main__':
+29 -129
Ver Arquivo
@@ -5,10 +5,8 @@ from numpy.testing import assert_allclose
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import keras_test
from keras import backend as K
from keras.engine.topology import InputLayer
from keras.layers import convolutional
from keras.layers import pooling
from keras.models import Sequential
# TensorFlow does not support full convolution.
@@ -19,8 +17,6 @@ else:
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support dilated conv")
def test_causal_dilated_conv():
# Causal:
layer_test(convolutional.Conv1D,
@@ -101,15 +97,9 @@ def test_conv_1d():
kwargs={'filters': filters,
'kernel_size': kernel_size,
'padding': padding,
'dilation_rate': 2,
'activation': None},
'dilation_rate': 2},
input_shape=(batch_size, steps, input_dim))
convolutional.Conv1D(filters=filters,
kernel_size=kernel_size,
padding=padding,
input_shape=(input_dim,))
@keras_test
def test_maxpooling_1d():
@@ -132,8 +122,6 @@ def test_averagepooling_1d():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support dilated conv")
def test_convolution_2d():
num_samples = 2
filters = 2
@@ -159,8 +147,6 @@ def test_convolution_2d():
kwargs={'filters': filters,
'kernel_size': 3,
'padding': padding,
'data_format': 'channels_last',
'activation': None,
'kernel_regularizer': 'l2',
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
@@ -177,13 +163,6 @@ def test_convolution_2d():
'dilation_rate': (2, 2)},
input_shape=(num_samples, num_row, num_col, stack_size))
# Test invalid use case
with pytest.raises(ValueError):
model = Sequential([convolutional.Conv2D(filters=filters,
kernel_size=kernel_size,
padding=padding,
batch_input_shape=(None, None, 5, None))])
@keras_test
def test_conv2d_transpose():
@@ -211,7 +190,6 @@ def test_conv2d_transpose():
'kernel_size': 3,
'padding': padding,
'data_format': 'channels_first',
'activation': None,
'kernel_regularizer': 'l2',
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
@@ -221,13 +199,6 @@ def test_conv2d_transpose():
input_shape=(num_samples, stack_size, num_row, num_col),
fixed_batch_size=True)
# Test invalid use case
with pytest.raises(ValueError):
model = Sequential([convolutional.Conv2DTranspose(filters=filters,
kernel_size=3,
padding=padding,
batch_input_shape=(None, None, 5, None))])
@pytest.mark.skipif(K.backend() != 'tensorflow', reason='Requires TF backend')
@keras_test
@@ -256,8 +227,6 @@ def test_separable_conv_2d():
kwargs={'filters': filters,
'kernel_size': 3,
'padding': padding,
'data_format': 'channels_first',
'activation': None,
'depthwise_regularizer': 'l2',
'pointwise_regularizer': 'l2',
'bias_regularizer': 'l2',
@@ -266,14 +235,7 @@ def test_separable_conv_2d():
'depthwise_constraint': 'unit_norm',
'strides': strides,
'depth_multiplier': multiplier},
input_shape=(num_samples, stack_size, num_row, num_col))
# Test invalid use case
with pytest.raises(ValueError):
model = Sequential([convolutional.SeparableConv2D(filters=filters,
kernel_size=3,
padding=padding,
batch_input_shape=(None, None, 5, None))])
input_shape=(num_samples, num_row, num_col, stack_size))
@keras_test
@@ -376,7 +338,6 @@ def test_convolution_3d():
kwargs={'filters': filters,
'kernel_size': (1, 2, 3),
'padding': padding,
'activation': None,
'kernel_regularizer': 'l2',
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
@@ -388,51 +349,6 @@ def test_convolution_3d():
stack_size))
@keras_test
def test_conv3d_transpose():
filters = 2
stack_size = 3
num_depth = 7
num_row = 5
num_col = 6
for padding in _convolution_paddings:
for strides in [(1, 1, 1), (2, 2, 2)]:
for data_format in ['channels_first', 'channels_last']:
if padding == 'same' and strides != (1, 1, 1):
continue
layer_test(convolutional.Conv3DTranspose,
kwargs={'filters': filters,
'kernel_size': 3,
'padding': padding,
'strides': strides,
'data_format': data_format},
input_shape=(None, num_depth, num_row, num_col, stack_size),
fixed_batch_size=True)
layer_test(convolutional.Conv3DTranspose,
kwargs={'filters': filters,
'kernel_size': 3,
'padding': padding,
'data_format': 'channels_first',
'activation': None,
'kernel_regularizer': 'l2',
'bias_regularizer': 'l2',
'activity_regularizer': 'l2',
'kernel_constraint': 'max_norm',
'bias_constraint': 'max_norm',
'strides': strides},
input_shape=(None, stack_size, num_depth, num_row, num_col),
fixed_batch_size=True)
# Test invalid use case
with pytest.raises(ValueError):
model = Sequential([convolutional.Conv3DTranspose(filters=filters,
kernel_size=3,
padding=padding,
batch_input_shape=(None, None, 5, None, None))])
@keras_test
def test_maxpooling_3d():
pool_size = (3, 3, 3)
@@ -473,29 +389,29 @@ def test_zero_padding_1d():
input_dim = 2
num_steps = 5
shape = (num_samples, num_steps, input_dim)
inputs = np.ones(shape)
input = np.ones(shape)
# basic test
layer_test(convolutional.ZeroPadding1D,
kwargs={'padding': 2},
input_shape=inputs.shape)
input_shape=input.shape)
layer_test(convolutional.ZeroPadding1D,
kwargs={'padding': (1, 2)},
input_shape=inputs.shape)
input_shape=input.shape)
# correctness test
layer = convolutional.ZeroPadding1D(padding=2)
layer.build(shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(input))
np_output = K.eval(output)
for offset in [0, 1, -1, -2]:
assert_allclose(np_output[:, offset, :], 0.)
assert_allclose(np_output[:, 2:-2, :], 1.)
layer = convolutional.ZeroPadding1D(padding=(1, 2))
layer.build(shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(input))
np_output = K.eval(output)
for left_offset in [0]:
assert_allclose(np_output[:, left_offset, :], 0.)
for right_offset in [-1, -2]:
@@ -526,8 +442,8 @@ def test_zero_padding_2d():
layer = convolutional.ZeroPadding2D(padding=(2, 2),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_last':
for offset in [0, 1, -1, -2]:
assert_allclose(np_output[:, offset, :, :], 0.)
@@ -542,8 +458,8 @@ def test_zero_padding_2d():
layer = convolutional.ZeroPadding2D(padding=((1, 2), (3, 4)),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_last':
for top_offset in [0]:
assert_allclose(np_output[:, top_offset, :, :], 0.)
@@ -590,8 +506,8 @@ def test_zero_padding_3d():
layer = convolutional.ZeroPadding3D(padding=(2, 2, 2),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_last':
for offset in [0, 1, -1, -2]:
assert_allclose(np_output[:, offset, :, :, :], 0.)
@@ -608,8 +524,8 @@ def test_zero_padding_3d():
layer = convolutional.ZeroPadding3D(padding=((1, 2), (3, 4), (0, 2)),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_last':
for dim1_offset in [0, -1, -2]:
assert_allclose(np_output[:, dim1_offset, :, :, :], 0.)
@@ -661,8 +577,8 @@ def test_upsampling_2d():
size=(length_row, length_col),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_first':
assert np_output.shape[2] == length_row * input_num_row
assert np_output.shape[3] == length_col * input_num_col
@@ -681,8 +597,6 @@ def test_upsampling_2d():
assert_allclose(np_output, expected_out)
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support it yet")
def test_upsampling_3d():
num_samples = 2
stack_size = 2
@@ -712,8 +626,8 @@ def test_upsampling_3d():
size=(length_dim1, length_dim2, length_dim3),
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
if data_format == 'channels_first':
assert np_output.shape[2] == length_dim1 * input_len_dim1
assert np_output.shape[3] == length_dim2 * input_len_dim2
@@ -737,8 +651,6 @@ def test_upsampling_3d():
@keras_test
@pytest.mark.skipif((K.backend() == 'cntk'),
reason="cntk does not support slice to 0 dimension")
def test_cropping_1d():
num_samples = 2
time_length = 4
@@ -774,8 +686,8 @@ def test_cropping_2d():
layer = convolutional.Cropping2D(cropping=cropping,
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
# compare with numpy
if data_format == 'channels_first':
expected_out = inputs[:,
@@ -802,17 +714,11 @@ def test_cropping_2d():
layer = convolutional.Cropping2D(cropping=cropping,
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
# compare with input
assert_allclose(np_output, inputs)
# Test invalid use cases
with pytest.raises(ValueError):
layer = convolutional.Cropping2D(cropping=((1, 1),))
with pytest.raises(ValueError):
layer = convolutional.Cropping2D(cropping=lambda x: x)
def test_cropping_3d():
num_samples = 2
@@ -839,8 +745,8 @@ def test_cropping_3d():
layer = convolutional.Cropping3D(cropping=cropping,
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
# compare with numpy
if data_format == 'channels_first':
expected_out = inputs[:,
@@ -869,16 +775,10 @@ def test_cropping_3d():
layer = convolutional.Cropping3D(cropping=cropping,
data_format=data_format)
layer.build(inputs.shape)
outputs = layer(K.variable(inputs))
np_output = K.eval(outputs)
output = layer(K.variable(inputs))
np_output = K.eval(output)
# compare with input
assert_allclose(np_output, inputs)
# Test invalid use cases
with pytest.raises(ValueError):
layer = convolutional.Cropping3D(cropping=((1, 1),))
with pytest.raises(ValueError):
layer = convolutional.Cropping3D(cropping=lambda x: x)
if __name__ == '__main__':
pytest.main([__file__])
+4 -49
Ver Arquivo
@@ -32,23 +32,9 @@ def test_dropout():
kwargs={'rate': 0.5},
input_shape=(2, 3, 4))
for data_format in ['channels_last', 'channels_first']:
for shape in [(4, 5), (4, 5, 6)]:
if data_format == 'channels_last':
input_shape = (2,) + shape + (3,)
else:
input_shape = (2, 3) + shape
layer_test(layers.SpatialDropout2D if len(shape) == 2 else layers.SpatialDropout3D,
kwargs={'rate': 0.5,
'data_format': data_format},
input_shape=input_shape)
# Test invalid use cases
with pytest.raises(ValueError):
layer_test(layers.SpatialDropout2D if len(shape) == 2 else layers.SpatialDropout3D,
kwargs={'rate': 0.5,
'data_format': 'channels_middle'},
input_shape=input_shape)
layer_test(layers.SpatialDropout2D,
kwargs={'rate': 0.5},
input_shape=(2, 3, 4, 5))
@keras_test
@@ -111,24 +97,6 @@ def test_lambda():
'arguments': {'a': 0.6, 'b': 0.4}},
input_shape=(3, 2))
def antirectifier(x):
x -= K.mean(x, axis=1, keepdims=True)
x = K.l2_normalize(x, axis=1)
pos = K.relu(x)
neg = K.relu(-x)
return K.concatenate([pos, neg], axis=1)
def antirectifier_output_shape(input_shape):
shape = list(input_shape)
assert len(shape) == 2 # only valid for 2D tensors
shape[-1] *= 2
return tuple(shape)
layer_test(layers.Lambda,
kwargs={'function': antirectifier,
'output_shape': antirectifier_output_shape},
input_shape=(3, 2))
# test serialization with function
def f(x):
return x + 1
@@ -138,23 +106,10 @@ def test_lambda():
ld = deserialize_layer({'class_name': 'Lambda', 'config': config})
# test with lambda
ld = layers.Lambda(
lambda x: K.concatenate([K.square(x), x]),
output_shape=lambda s: tuple(list(s)[:-1] + [2 * s[-1]]))
ld = layers.Lambda(lambda x: K.concatenate([K.square(x), x]))
config = ld.get_config()
ld = layers.Lambda.from_config(config)
# test serialization with output_shape function
def f(x):
return K.concatenate([K.square(x), x])
def f_shape(s):
return tuple(list(s)[:-1] + [2 * s[-1]])
ld = layers.Lambda(f, output_shape=f_shape)
config = ld.get_config()
ld = deserialize_layer({'class_name': 'Lambda', 'config': config})
@keras_test
def test_dense():

Alguns arquivos não foram exibidos porque demasiados arquivos foram alterados neste diff Mostrar Mais