Comparar commits

...

98 Commits

Autor SHA1 Mensagem Data
Francois Chollet 141e05e3a7 Update Theano installation instruction 2016-04-11 08:51:01 -07:00
Francois Chollet cadd3e4e2c Make TimeDistributed accept a mask 2016-04-11 08:18:39 -07:00
Francois Chollet 09034d9e17 Add badges to README 2016-04-11 07:49:29 -07:00
Francois Chollet 5706d1d688 Bugfix 2016-04-10 08:36:00 -07:00
Francois Chollet 41b9777746 Clean up training a bit 2016-04-10 07:45:54 -07:00
Francois Chollet d31fe1ac34 Fix LSTM regularizers 2016-04-10 07:45:54 -07:00
Francois Chollet c0eedfeca0 change optimizer in example 2016-04-10 07:45:54 -07:00
Francois Chollet dc8b5509f3 Small fixes in topology engine 2016-04-10 07:45:54 -07:00
Nic Eggert ddec052dab Remove restriction on strides in theano backend conv2d. (#2238)
Previously, strides were required to be smaller than the convolution
kernel. Usually, this is what a user wants, but there are edge
cases where one might want to do this (for instance, projection
shortcuts in Residual Networks).
2016-04-09 18:48:05 -07:00
Francois Chollet 2e45022c95 Clarify interface of in_train_phase 2016-04-08 14:14:22 -07:00
Francois Chollet cec7f73bca Fix irnn example 2016-04-08 14:11:40 -07:00
Francois Chollet 30989dc997 Fix generator methods. 2016-04-08 12:59:09 -07:00
Fariz Rahman 50a0d1cad4 Update topology.py (#2239) 2016-04-08 10:40:58 -07:00
Fariz Rahman 3db1f132a7 call : remove train arg from doc string (#2235) 2016-04-08 08:59:55 -07:00
Fariz Rahman 3b196feda5 Typo fix (#2234) 2016-04-08 08:59:43 -07:00
berleon dd766c68d9 Fix LeakyReLU return dtype (#2214)
LeakyReLU returns a tensor with float64 dtype.
It is stupid, but this line actually produces a float64 array:

```
    0.5*np.array(0.2, dtype=np.float32)
```

The theano nnet.relu function does something similar like this with the
LeakyReLU alpha parameter, which lead to a float64 tensor.
The solution is to not cast the alpha to float32.

Furthermore I tighten the `test_utils.layer_test`. It is now
required that the layer's output dtype is equal to the input dtype.
2016-04-07 17:02:03 -07:00
Francois Chollet 599e070824 Small fixes to the docs. 2016-04-07 16:52:09 -07:00
Francois Chollet 04c998a742 Fix typos 2016-04-07 14:25:41 -07:00
Francois Chollet cc985c3a9c Update docs, visualization utils 2016-04-07 14:23:34 -07:00
Francois Chollet 36cc508030 New documentation 2016-04-06 17:34:25 -07:00
Francois Chollet 444cd56740 Update README 2016-04-06 17:33:39 -07:00
Francois Chollet 88a86f7e45 Merge branch 'keras-1' of https://github.com/fchollet/keras into keras-1 2016-04-06 17:23:21 -07:00
Francois Chollet d6f94c0bc9 Fix docstring 2016-04-06 17:21:31 -07:00
Francois Chollet 2157aa6172 Make function compilation lazy 2016-04-06 17:21:21 -07:00
Francois Chollet 2013527840 Add docstrings to TF backend 2016-04-06 17:21:00 -07:00
Francois Chollet 8c73c6f218 Simplify lstm example 2016-04-06 17:20:43 -07:00
Michael Oliver 63059f6063 Bug fix to set correct uses_learning_phase flag
```test_on_batch``` and ```predict_on_batch``` had the wrong ```uses_learning_phase``` flag
2016-04-06 16:56:31 -07:00
Francois Chollet e179198410 Cache recursive calls in build_map_of_graph 2016-04-06 13:30:07 -07:00
Francois Chollet ed4a95bdad Slight cleanup of build_map_of_graph 2016-04-06 11:46:18 -07:00
Francois Chollet 1baddb9094 Docstrings cleanup 2016-04-06 11:46:01 -07:00
Francois Chollet 3160a445a8 Merge branch 'keras-1' of https://github.com/fchollet/keras into keras-1 2016-04-06 09:05:04 -07:00
Francois Chollet d627fd8781 Docstrings improvements 2016-04-06 09:04:53 -07:00
Michael Oliver b4bdc5a0fa add in predict_generator and tests
* add in predict_generator and tests

* fix PEP8 details

* Pre-allocate predictions

* make predictions return list if neccessary

* reset batch_size for other tests, make less wonky generator
2016-04-06 09:03:37 -07:00
Francois Chollet 6911fa2cba Fix typos in functional API guide 2016-04-05 10:27:11 -07:00
Francois Chollet 0d7c8711bd Fix JSON serialization issue 2016-04-05 10:26:57 -07:00
Francois Chollet d8b0fe0957 Correct functional API guide 2016-04-04 21:49:16 -07:00
Francois Chollet 263de77a5a Improve README, functional API guide 2016-04-04 21:46:27 -07:00
Francois Chollet d3615e682e Small fixes. 2016-04-04 15:00:06 -07:00
Michael Oliver 35da9d6ef2 Make tensorflow backend fully mimic theano.dot
* Squashed commit of the following:

commit f25b56f3a7547da94ffecee8701da5b34e757104
Author: Michael Oliver <michael.d.oliver@gmail.com>
Date:   Mon Apr 4 19:01:49 2016 +0000

    add proper shape inference

commit 5544f66148676d86cb53309701eee6a4e99a3aeb
Author: Michael Oliver <michael.d.oliver@gmail.com>
Date:   Mon Apr 4 18:03:05 2016 +0000

    Make PEP8 compliant and use int_shape

commit 0fe6e02699e2da553f8f1a866aaaa081c26a1cbd
Author: Michael Oliver <michael.d.oliver@gmail.com>
Date:   Mon Apr 4 03:35:29 2016 +0000

    Make tensorflow backend fully mimic theano dot

* fix None comparison
2016-04-04 14:30:55 -07:00
cmyr dbe7662e72 add sparse_categorical_crossentropy 2016-04-04 14:24:41 -07:00
Francois Chollet 30118bbab0 Improve docstrings, UX of common user mistakes 2016-04-04 14:22:28 -07:00
Francois Chollet 2902149f77 Finish PR backporting 2016-04-04 11:30:24 -07:00
Francois Chollet eb8b40cccd Fix captioning example in docs 2016-04-04 11:09:20 -07:00
Francois Chollet 76da13dff6 Backport of conv2d PRs by @ns 2016-04-04 11:09:06 -07:00
Francois Chollet f7cbdff79c Improve model training tests 2016-04-04 10:25:58 -07:00
Francois Chollet 81233b3cd3 Fix lambda serialization issue in Py3 2016-04-04 10:11:29 -07:00
Fariz Rahman af88e051fa Typo fix 2016-04-04 07:38:54 -07:00
berleon 6ad6b19bd6 Merge layer handle none in input_shapes 2016-04-04 07:34:36 -07:00
Francois Chollet 0242ca59ac Update version numbers 2016-04-03 20:58:13 -07:00
Francois Chollet c064963ef8 Fix Py3 compatibility issue in test 2016-04-03 20:22:29 -07:00
Francois Chollet 4318718769 Fix PEP8 2016-04-03 20:22:17 -07:00
Francois Chollet f981bdb551 Update functional API guide 2016-04-03 20:04:14 -07:00
Francois Chollet 3860e078a5 Small fixes in optimizers docstrings 2016-04-03 20:04:14 -07:00
Eder Santana d09e2a67bb fix batch_dot tests on backend
* Fix merge_dot tests

* Make batch_dot unique

batch_dot is not tensordot! It only accepts one reduce dimension at a
time. Other reduce dimensions should be dome afterwards with K.sum
This means that K.batch_dot will have the same behavior in both
tensorflow and theano. This also means that we have less parenthesis and
less nested lists.

New usage:

merge_mode = 'dot', dot_axes=[axis1, axis2]

Before:

merge_mode = 'dot', dot_axes=[[axis1], [axis2]]

* Backport sign by @the-moliver

* Fix docstrings

* Fix backend batch_dot tests
2016-04-03 20:04:00 -07:00
Francois Chollet 56ba6b9c7e Merge branch 'keras-1' of https://github.com/fchollet/keras into keras-1 2016-04-03 18:58:18 -07:00
berleon a9c6f26412 Add defaults for _gather_[list/dict]_attr
For example the Dense Layer does not have a update attribute, which

results in an error.
2016-04-03 18:58:08 -07:00
Francois Chollet 73817b8b77 More thorough tests for TimeDistributed 2016-04-03 13:38:46 -07:00
Francois Chollet 3f128b9838 Merge branch 'keras-1' of https://github.com/fchollet/keras into keras-1 2016-04-03 13:19:38 -07:00
berleon 9621bb5b8e fix h5py string encoding
When saving the weights a TypeError is raised by h5py.

See this issue https://github.com/h5py/h5py/issues/289 for details.

As it is recommended in the issue, the strings are now encoded as utf8.
2016-04-03 13:19:12 -07:00
Francois Chollet 836fb03aa0 Merge branch 'keras-1' of https://github.com/fchollet/keras into keras-1 2016-04-03 10:32:38 -07:00
Eder Santana c3aaf50b64 Update complete_guide_to_the_keras_functional_api.md
small changes
2016-04-03 10:29:02 -07:00
Francois Chollet fe00f5ff64 Fix learning phase issue with regularizers 2016-04-03 10:28:06 -07:00
Eder Santana 8b3543fca9 Fix merge_dot tests
* Fix merge_dot tests

* Make batch_dot unique

batch_dot is not tensordot! It only accepts one reduce dimension at a
time. Other reduce dimensions should be dome afterwards with K.sum
This means that K.batch_dot will have the same behavior in both
tensorflow and theano. This also means that we have less parenthesis and
less nested lists.

New usage:

merge_mode = 'dot', dot_axes=[axis1, axis2]

Before:

merge_mode = 'dot', dot_axes=[[axis1], [axis2]]

* Backport sign by @the-moliver

* Fix docstrings
2016-04-03 10:03:09 -07:00
Leon Chen a6fe2ae341 test against latest tensorflow in travis 2016-04-03 10:02:31 -07:00
graham 3ca7751445 fixed slice_X import location 2016-04-02 19:00:26 -07:00
Francois Chollet ebfde534c0 Add weight deduping before updates computation 2016-04-02 10:37:57 -07:00
Eder Santana f8c7dbb758 Backport #2123 by @carlthome
Backport #2123 by @carlthome
2016-04-01 21:27:20 -07:00
Francois Chollet 62f9053330 Fix babi_rnn example 2016-04-01 21:14:05 -07:00
Francois Chollet c429e651c1 Fix weight regularizers 2016-04-01 21:13:57 -07:00
Francois Chollet dacf017d38 Fix potential issue in topology engine 2016-04-01 21:13:34 -07:00
Francois Chollet dc3c1488bb Fix unit tests for Merge 2016-04-01 18:01:41 -07:00
Francois Chollet 4d7ff76cfb Fix some more tests 2016-04-01 16:45:05 -07:00
Francois Chollet 8ad6865952 Fix conv3d tests 2016-04-01 16:12:04 -07:00
Francois Chollet 2a4f6b942d Add more tests 2016-04-01 15:58:19 -07:00
Francois Chollet 91a819fb34 Fix engine issue 2016-04-01 15:58:07 -07:00
Francois Chollet 52dbeb1f26 Reintroduce failing siamese test 2016-04-01 15:57:45 -07:00
Francois Chollet 0836e47dfc Theano: warn on unused input 2016-04-01 15:56:30 -07:00
Francois Chollet 75bef59016 Unify dot behavior in TF and Theano 2016-04-01 15:56:19 -07:00
Francois Chollet 337c0c66cf Remove shape infer test (now incl in layers tests) 2016-04-01 13:36:28 -07:00
Francois Chollet f8e2df16f1 Fix TF batch_dot 2016-04-01 13:36:03 -07:00
Francois Chollet 10deb8f267 Add batchnorm unit tests 2016-04-01 13:25:59 -07:00
Francois Chollet efe5916109 Fix convolutional tests 2016-04-01 13:25:48 -07:00
Francois Chollet 64449c196e Fix recurrent tests 2016-04-01 13:25:37 -07:00
Francois Chollet f57128bd3d Fix wrappers 2016-04-01 13:25:13 -07:00
Francois Chollet 8740791d5c Small fixes to core layers 2016-04-01 13:24:48 -07:00
François Chollet 6ddb5a0452 Merge pull request #2158 from EderSantana/keras-1
Add batch_dot to backend
2016-04-01 08:38:29 -07:00
EderSantana 133699c2f3 keras.engine.topology.Merge uses K.batch_dot 2016-04-01 10:56:12 -04:00
EderSantana b0ea92bc12 Add batch_dot to backend 2016-04-01 00:15:28 -04:00
Francois Chollet e754581ecb Fix noise layers 2016-03-31 19:08:07 -07:00
Francois Chollet fcb6ae8eed Fix activity regularization 2016-03-31 18:46:24 -07:00
Francois Chollet bf4dab3501 Update core layers 2016-03-31 18:17:17 -07:00
Francois Chollet a066cf8680 Fix advanced activations. 2016-03-31 16:43:10 -07:00
Francois Chollet 7448dcea65 Fix optimizers tests 2016-03-31 13:41:30 -07:00
Francois Chollet cf3b3dff32 Fix regularizers 2016-03-31 13:41:21 -07:00
Francois Chollet ca96737b20 Fix callbacks 2016-03-31 13:41:07 -07:00
Francois Chollet 61ade48343 Some cleanup 2016-03-31 11:50:30 -07:00
Francois Chollet 295bfe4e3a Keras 1.0 preview. 2016-03-31 11:35:27 -07:00
Francois Chollet 1145fec39f Update backend 2016-03-19 09:06:52 -07:00
99 arquivos alterados com 10658 adições e 7578 exclusões
+2 -2
Ver Arquivo
@@ -49,9 +49,9 @@ install:
# install TensorFlow
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.6.0-cp27-none-linux_x86_64.whl;
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl;
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.6.0-cp34-none-linux_x86_64.whl;
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp34-none-linux_x86_64.whl;
fi
# command to run tests
script:
+14 -15
Ver Arquivo
@@ -1,6 +1,7 @@
# Keras: Deep Learning library for Theano and TensorFlow
![Build status](https://api.travis-ci.org/fchollet/keras.svg)
[![Build Status](https://travis-ci.org/fchollet/keras.svg?branch=master)](https://travis-ci.org/fchollet/keras)
[![PyPI version](https://badge.fury.io/py/keras.svg)](https://badge.fury.io/py/keras)
## You have just found Keras.
@@ -37,9 +38,9 @@ Keras is compatible with: __Python 2.7-3.5__.
## Getting started: 30 seconds to Keras
The core data structure of Keras is a __model__, a way to organize layers. There are two types of models: [`Sequential`](http://keras.io/models/#sequential) and [`Graph`](http://keras.io/models/#graph).
The core data structure of Keras is a __model__, a way to organize layers. The main type of model is the [`Sequential`](http://keras.io/getting-started/sequential-model-guide) model, a linear stack of layers. For more complex architectures, you should use the [Keras function API](http://keras.io/getting-started/functional-api-guide).
Here's the `Sequential` model (a linear pile of layers):
Here's the `Sequential` model:
```python
from keras.models import Sequential
@@ -52,15 +53,15 @@ Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100, init="glorot_uniform"))
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
model.add(Dense(output_dim=10, init="glorot_uniform"))
model.add(Dense(output_dim=10))
model.add(Activation("softmax"))
```
Once your model looks good, configure its learning process with `.compile()`:
```python
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
```
If you need to, you can further configure your optimizer. A core principle of Keras is to make things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).
@@ -81,7 +82,7 @@ model.train_on_batch(X_batch, Y_batch)
Evaluate your performance in one line:
```python
objective_score = model.evaluate(X_test, Y_test, batch_size=32)
loss_and_metrics = model.evaluate(X_test, Y_test, batch_size=32)
```
Or generate predictions on new data:
@@ -90,11 +91,14 @@ classes = model.predict_classes(X_test, batch_size=32)
proba = model.predict_proba(X_test, batch_size=32)
```
Building a network of LSTMs, a deep CNN, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
Building a question answering system, an image classification model, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
Have a look at these [starter examples](http://keras.io/examples/).
For a more in-depth tutorial about Keras, you can check out:
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repo, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, neural turing machines, etc.
- [Getting started with the Sequential model](http://keras.io/getting-started/sequential-model-guide)
- [Getting started with the functional API](http://keras.io/getting-started/functional-api-guide)
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repository, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, etc.
------------------
@@ -114,11 +118,6 @@ Keras uses the following dependencies:
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
**Note**: You should use the latest version of Theano, not the PyPI version. Install it with:
```
sudo pip install git+git://github.com/Theano/Theano.git
```
*When using the TensorFlow backend:*
- TensorFlow
+363 -107
Ver Arquivo
@@ -1,4 +1,57 @@
# -*- coding: utf-8 -*-
'''
General documentation architecture:
Home
Index
- Getting started
Getting started with the sequential model
Getting started with the functional api
Examples
FAQ
Installation guide
- Models
About Keras models
explain when one should use Sequential or functional API
explain compilation step
explain weight saving, weight loading
explain serialization, deserialization
Sequential
Model (functional API)
- Layers
About Keras layers
explain common layer functions: get_weights, set_weights, get_config
explain input_shape
explain usage on non-Keras tensors
Core layers
Convolutional
Recurrent
Embeddings
Normalization
Advanced activations
Noise
- Preprocessing
Image preprocessing
Text preprocessing
Sequence preprocessing
Objectives
Optimizers
Activations
Callbacks
Datasets
Backend
Initializations
Regularizers
Constraints
Visualization
Scikit-learn API
'''
from __future__ import print_function
import re
import inspect
@@ -11,35 +64,147 @@ from keras.layers import core
from keras.layers import noise
from keras.layers import normalization
from keras.layers import advanced_activations
from keras.layers import containers
from keras.layers import embeddings
from keras.layers import wrappers
from keras import optimizers
from keras import callbacks
from keras import models
from keras.engine import topology
from keras import objectives
from keras import backend
from keras import constraints
from keras import activations
from keras import regularizers
MODULES = [(convolutional, 'keras.layers.convolutional'),
(recurrent, 'keras.layers.recurrent'),
(noise, 'keras.layers.noise'),
(normalization, 'keras.layers.normalization'),
(advanced_activations, 'keras.layers.advanced_activations'),
(containers, 'keras.layers.containers'),
(core, 'keras.layers.core'),
(embeddings, 'keras.layers.embeddings'),
(optimizers, 'keras.optimizers'),
(callbacks, 'keras.callbacks'),
(models, 'keras.models')]
EXCLUDE = {
'Optimizer',
'Wrapper',
'get_session',
'set_session',
}
SKIP = ['build', 'get_params', 'MaskedLayer',
'SiameseHead', 'MaskedLambda',
'CallbackList']
ROOT = 'http://keras.io/'
INCLUDE_METHODS_FOR = [
'Layer',
'Graph',
'Sequential',
'Callback',
PAGES = [
{
'page': 'models/sequential.md',
'functions': [
models.Sequential.compile,
models.Sequential.fit,
models.Sequential.evaluate,
models.Sequential.predict,
models.Sequential.predict_classes,
models.Sequential.predict_proba,
models.Sequential.train_on_batch,
models.Sequential.test_on_batch,
models.Sequential.predict_on_batch,
models.Sequential.fit_generator,
models.Sequential.evaluate_generator,
],
},
{
'page': 'models/model.md',
'functions': [
models.Model.compile,
models.Model.fit,
models.Model.evaluate,
models.Model.predict,
models.Model.train_on_batch,
models.Model.test_on_batch,
models.Model.predict_on_batch,
models.Model.fit_generator,
models.Model.evaluate_generator,
models.Model.get_layer,
]
},
{
'page': 'layers/core.md',
'classes': [
core.Dense,
core.Activation,
core.Dropout,
core.Flatten,
core.Reshape,
core.Permute,
core.RepeatVector,
topology.Merge,
core.Lambda,
core.ActivityRegularization,
core.Masking,
core.Highway,
core.MaxoutDense,
core.TimeDistributedDense,
],
},
{
'page': 'layers/convolutional.md',
'classes': [
convolutional.Convolution1D,
convolutional.Convolution2D,
convolutional.Convolution3D,
convolutional.MaxPooling1D,
convolutional.MaxPooling2D,
convolutional.MaxPooling3D,
convolutional.AveragePooling1D,
convolutional.AveragePooling2D,
convolutional.AveragePooling3D,
convolutional.UpSampling1D,
convolutional.UpSampling2D,
convolutional.UpSampling3D,
convolutional.ZeroPadding1D,
convolutional.ZeroPadding2D,
convolutional.ZeroPadding3D,
],
},
{
'page': 'layers/recurrent.md',
'classes': [
recurrent.Recurrent,
recurrent.SimpleRNN,
recurrent.GRU,
recurrent.LSTM,
],
},
{
'page': 'layers/embeddings.md',
'classes': [
embeddings.Embedding,
],
},
{
'page': 'layers/normalization.md',
'classes': [
normalization.BatchNormalization,
],
},
{
'page': 'layers/advanced-activations.md',
'all_module_classes': [advanced_activations],
},
{
'page': 'layers/noise.md',
'all_module_classes': [noise],
},
{
'page': 'layers/wrappers.md',
'all_module_classes': [wrappers],
},
{
'page': 'optimizers.md',
'all_module_classes': [optimizers],
},
{
'page': 'callbacks.md',
'all_module_classes': [callbacks],
},
{
'page': 'backend.md',
'all_module_functions': [backend],
},
]
ROOT = 'http://keras.io/'
def get_earliest_class_that_defined_member(member, cls):
ancestors = get_classes_ancestors([cls])
@@ -67,16 +232,19 @@ def get_classes_ancestors(classes):
return filtered_ancestors
def get_method_signature(method):
signature = inspect.getargspec(method)
def get_function_signature(function, method=True):
signature = inspect.getargspec(function)
defaults = signature.defaults
args = signature.args[1:]
if method:
args = signature.args[1:]
else:
args = signature.args
if defaults:
kwargs = zip(args[-len(defaults):], defaults)
args = args[:-len(defaults)]
else:
kwargs = []
st = '%s.%s(' % (method.__module__, method.__name__)
st = '%s.%s(' % (function.__module__, function.__name__)
for a in args:
st += str(a) + ', '
for a, v in kwargs:
@@ -91,6 +259,17 @@ def get_method_signature(method):
return st + ')'
def get_class_signature(cls):
try:
class_signature = get_function_signature(cls.__init__)
class_signature = class_signature.replace('__init__', cls.__name__)
except:
# in case the class inherits from object and does not
# define __init__
class_signature = cls.__module__ + '.' + cls.__name__ + '()'
return class_signature
def class_to_docs_link(cls):
module_name = cls.__module__
assert module_name[:6] == 'keras.'
@@ -131,7 +310,10 @@ def process_class_docstring(docstring):
return docstring
def process_method_docstring(docstring):
def process_function_docstring(docstring):
docstring = re.sub(r'\n # (.*)\n',
r'\n __\1__\n\n',
docstring)
docstring = re.sub(r'\n # (.*)\n',
r'\n __\1__\n\n',
docstring)
@@ -160,101 +342,175 @@ for subdir, dirs, fnames in os.walk('templates'):
shutil.copy(fpath, new_fpath)
print('Starting autogeneration.')
covered_so_far = set()
for module, module_name in MODULES:
class_pages = []
for name in dir(module):
if name in SKIP:
continue
if name[0] == '_':
continue
module_member = getattr(module, name)
if module_member in covered_so_far:
continue
if inspect.isclass(module_member):
cls = module_member
if cls.__module__ == module_name:
for page_data in PAGES:
blocks = []
classes = page_data.get('classes', [])
for module in page_data.get('all_module_classes', []):
module_classes = []
for name in dir(module):
if name[0] == '_' or name in EXCLUDE:
continue
module_member = getattr(module, name)
if inspect.isclass(module_member):
cls = module_member
if cls.__module__ == module.__name__:
if cls not in module_classes:
module_classes.append(cls)
module_classes.sort(key=lambda x: id(x))
classes += module_classes
try:
class_signature = get_method_signature(cls.__init__)
class_signature = class_signature.replace('__init__', cls.__name__)
except:
# in case the class inherits from object and does not
# define __init__
class_signature = module_name + '.' + cls.__name__ + '()'
for cls in classes:
subblocks = []
signature = get_class_signature(cls)
subblocks.append('<span style="float:right;">' + class_to_source_link(cls) + '</span>')
subblocks.append('### ' + cls.__name__ + '\n')
subblocks.append(code_snippet(signature))
docstring = cls.__doc__
if docstring:
subblocks.append(process_class_docstring(docstring))
blocks.append('\n'.join(subblocks))
methods = []
methods_not_defined_here = []
for name in dir(cls):
if name in SKIP:
continue
if name[0] == '_':
continue
cls_member = getattr(cls, name)
if inspect.ismethod(cls_member):
method = cls_member
signature = inspect.getargspec(method)
defaults = signature.defaults
args = signature.args[1:]
if defaults:
kwargs = zip(args[-len(defaults):], defaults)
args = args[:-len(defaults)]
else:
kwargs = []
functions = page_data.get('functions', [])
for module in page_data.get('all_module_functions', []):
module_functions = []
for name in dir(module):
if name[0] == '_' or name in EXCLUDE:
continue
module_member = getattr(module, name)
if inspect.isfunction(module_member):
function = module_member
if module.__name__ in function.__module__:
if function not in module_functions:
module_functions.append(function)
module_functions.sort(key=lambda x: id(x))
functions += module_functions
defined_by = get_earliest_class_that_defined_member(method.__name__, cls)
if cls == defined_by:
methods.append(method)
else:
methods_not_defined_here.append((method, defined_by))
blocks = []
blocks.append('<span style="float:right;">' + class_to_source_link(cls) + '</span>')
blocks.append('# ' + cls.__name__ + '\n')
blocks.append(code_snippet(class_signature))
docstring = cls.__doc__
if docstring:
blocks.append(process_class_docstring(docstring))
if cls.__name__ in INCLUDE_METHODS_FOR:
if methods or methods_not_defined_here:
blocks.append('### Methods\n')
for method in methods:
signature = get_method_signature(method)
signature = signature.replace(module_name + '.', '')
blocks.append(code_snippet(signature))
docstring = method.__doc__
if docstring:
blocks.append(process_method_docstring(docstring))
for method, defined_by in methods_not_defined_here:
signature = get_method_signature(method)
method_module_name = method.__module__
signature = signature.replace(method_module_name + '.', '')
link = '[' + defined_by.__name__ + '](' + class_to_docs_link(defined_by) + ')'
blocks.append(code_snippet(signature))
blocks.append('Defined by ' + link + '.\n')
mkdown = '\n'.join(blocks)
class_pages.append((id(cls), mkdown))
covered_so_far.add(module_member)
class_pages.sort(key=lambda x: x[0])
class_pages = [x[1] for x in class_pages]
module_page = '\n----\n\n'.join(class_pages)
for function in functions:
subblocks = []
signature = get_function_signature(function, method=False)
signature = signature.replace(function.__module__ + '.', '')
subblocks.append('### ' + function.__name__ + '\n')
subblocks.append(code_snippet(signature))
docstring = function.__doc__
if docstring:
subblocks.append(process_function_docstring(docstring))
blocks.append('\n\n'.join(subblocks))
mkdown = '\n----\n\n'.join(blocks)
# save module page.
# Either insert content into existing page,
# or create page otherwise
path = 'sources/' + module_name.replace('.', '/')[6:] + '.md'
page_name = page_data['page']
path = os.path.join('sources', page_name)
if os.path.exists(path):
template = open(path).read()
assert '{{autogenerated}}' in template, ('Template found for ' + path +
' but missing {{autogenerated}} tag.')
module_page = template.replace('{{autogenerated}}', module_page)
mkdown = template.replace('{{autogenerated}}', mkdown)
print('...inserting autogenerated content into template:', path)
else:
print('...creating new page with autogenerated content:', path)
subdir = os.path.dirname(path)
if not os.path.exists(subdir):
os.makedirs(subdir)
open(path, 'w').write(module_page)
open(path, 'w').write(mkdown)
# covered_so_far = set()
# for module, module_name in MODULES:
# class_pages = []
# for name in dir(module):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# module_member = getattr(module, name)
# if module_member in covered_so_far:
# continue
# if inspect.isclass(module_member):
# cls = module_member
# if cls.__module__ == module_name:
# try:
# class_signature = get_function_signature(cls.__init__)
# class_signature = class_signature.replace('__init__', cls.__name__)
# except:
# # in case the class inherits from object and does not
# # define __init__
# class_signature = module_name + '.' + cls.__name__ + '()'
# functions = []
# functions_not_defined_here = []
# for name in dir(cls):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# cls_member = getattr(cls, name)
# if inspect.isfunction(cls_member):
# function = cls_member
# signature = inspect.getargspec(function)
# defaults = signature.defaults
# args = signature.args[1:]
# if defaults:
# kwargs = zip(args[-len(defaults):], defaults)
# args = args[:-len(defaults)]
# else:
# kwargs = []
# defined_by = get_earliest_class_that_defined_member(function.__name__, cls)
# if cls == defined_by:
# functions.append(function)
# else:
# functions_not_defined_here.append((function, defined_by))
# blocks = []
# blocks.append('<span style="float:right;">' + class_to_source_link(cls) + '</span>')
# blocks.append('# ' + cls.__name__ + '\n')
# blocks.append(code_snippet(class_signature))
# docstring = cls.__doc__
# if docstring:
# blocks.append(process_class_docstring(docstring))
# if cls.__name__ in INCLUDE_functionS_FOR:
# if functions or functions_not_defined_here:
# blocks.append('### functions\n')
# for function in functions:
# signature = get_function_signature(function)
# signature = signature.replace(module_name + '.', '')
# blocks.append(code_snippet(signature))
# docstring = function.__doc__
# if docstring:
# blocks.append(process_function_docstring(docstring))
# for function, defined_by in functions_not_defined_here:
# signature = get_function_signature(function)
# function_module_name = function.__module__
# signature = signature.replace(function_module_name + '.', '')
# link = '[' + defined_by.__name__ + '](' + class_to_docs_link(defined_by) + ')'
# blocks.append(code_snippet(signature))
# blocks.append('Defined by ' + link + '.\n')
# mkdown = '\n'.join(blocks)
# class_pages.append((id(cls), mkdown))
# covered_so_far.add(module_member)
# class_pages.sort(key=lambda x: x[0])
# class_pages = [x[1] for x in class_pages]
# module_page = '\n----\n\n'.join(class_pages)
# # save module page.
# # Either insert content into existing page,
# # or create page otherwise
# path = 'sources/' + module_name.replace('.', '/')[6:] + '.md'
# if os.path.exists(path):
# template = open(path).read()
# assert '{{autogenerated}}' in template, ('Template found for ' + path +
# ' but missing {{autogenerated}} tag.')
# module_page = template.replace('{{autogenerated}}', module_page)
# print('...inserting autogenerated content into template:', path)
# else:
# print('...creating new page with autogenerated content:', path)
# subdir = os.path.dirname(path)
# if not os.path.exists(subdir):
# os.makedirs(subdir)
# open(path, 'w').write(module_page)
+29 -19
Ver Arquivo
@@ -3,8 +3,8 @@ theme: readthedocs
docs_dir: sources
repo_url: http://github.com/fchollet/keras
site_url: http://keras.io/
#theme_dir: theme
site_description: Documentation for fast and lightweight Keras Deep Learning library.
# theme_dir: theme
site_description: 'Documentation for Keras, the Python Deep Learning library.'
dev_addr: '0.0.0.0:8000'
google_analytics: ['UA-61785484-1', 'keras.io']
@@ -12,31 +12,41 @@ google_analytics: ['UA-61785484-1', 'keras.io']
pages:
- Home: index.md
- Index: documentation.md
- Examples: examples.md
- FAQ: faq.md
- Backends: backend.md
- Optimizers: optimizers.md
- Objectives: objectives.md
- Models: models.md
- Activations: activations.md
- Initializations: initializations.md
- Regularizers: regularizers.md
- Constraints: constraints.md
- Callbacks: callbacks.md
- Datasets: datasets.md
- Visualization: visualization.md
- Getting started:
- Guide to the Sequential model: getting-started/sequential-model-guide.md
- Guide to the Functional API: getting-started/functional-api-guide.md
- FAQ: getting-started/faq.md
- Models:
- About Keras models: models/about-keras-models.md
- Sequential: models/sequential.md
- Model (functional API): models/model.md
- Layers:
- About Keras layers: layers/about-keras-layers.md
- Core Layers: layers/core.md
- Convolutional Layers: layers/convolutional.md
- Recurrent Layers: layers/recurrent.md
- Advanced Activations Layers: layers/advanced_activations.md
- Normalization Layers: layers/normalization.md
- Embedding Layers: layers/embeddings.md
- Advanced Activations Layers: layers/advanced-activations.md
- Normalization Layers: layers/normalization.md
- Noise layers: layers/noise.md
- Containers: layers/containers.md
- Layer wrappers: layers/wrappers.md
- Writing your own Keras layers: layers/writing-your-own-keras-layers.md
- Preprocessing:
- Sequence Preprocessing: preprocessing/sequence.md
- Text Preprocessing: preprocessing/text.md
- Image Preprocessing: preprocessing/image.md
- Objectives: objectives.md
- Optimizers: optimizers.md
- Activations: activations.md
- Callbacks: callbacks.md
- Datasets: datasets.md
- Backend: backend.md
- Initializations: initializations.md
- Regularizers: regularizers.md
- Constraints: constraints.md
- Visualization: visualization.md
- Scikit-learn API: scikit-learn-api.md
+1 -1
Ver Arquivo
@@ -38,4 +38,4 @@ model.add(Activation(tanh))
## On Advanced Activations
Activations that are more complex than a simple Theano/TensorFlow function (eg. learnable activations, configurable activations, etc.) are available as [Advanced Activation layers](layers/advanced_activations.md), and can be found in the module `keras.layers.advanced_activations`. These include PReLU and LeakyReLU.
Activations that are more complex than a simple Theano/TensorFlow function (eg. learnable activations, configurable activations, etc.) are available as [Advanced Activation layers](layers/advanced-activations.md), and can be found in the module `keras.layers.advanced_activations`. These include PReLU and LeakyReLU.
+10 -2
Ver Arquivo
@@ -9,6 +9,8 @@ At this time, Keras has two backend implementations available: the **Theano** ba
- [Theano](http://deeplearning.net/software/theano/) is an open-source symbolic tensor manipulation framework developed by LISA/MILA Lab at Université de Montréal.
- [TensorFlow](http://www.tensorflow.org/) is an open-source symbolic tensor manipulation framework developed by Google, Inc.
----
## Switching from one backend to another
If you have run Keras at least once, you will find the Keras configuration file at:
@@ -32,6 +34,8 @@ Using TensorFlow backend.
tensorflow
```
----
## Using the abstract Keras backend to write new code
If you want the Keras modules you write to be compatible with both Theano and TensorFlow, you have to write them via the abstract Keras backend API. Here's an intro.
@@ -74,8 +78,12 @@ a = concatenate([b, c], axis=-1)
# etc...
```
For more information, see the code at `keras/backend/theano_backend.py` and `keras/backend/tensorflow_backend.py`.
----
## Backend functions
{{autogenerated}}
+20 -14
Ver Arquivo
@@ -2,13 +2,13 @@
## CIFAR10 small image classification
`keras.datasets.cifar10`
Dataset of 50,000 32x32 color training images, labeled over 10 categories, and 10,000 test images.
### Usage:
```python
from keras.datasets import cifar10
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
```
@@ -21,13 +21,13 @@ Dataset of 50,000 32x32 color training images, labeled over 10 categories, and 1
## CIFAR100 small image classification
`keras.datasets.cifar100`
Dataset of 50,000 32x32 color training images, labeled over 100 categories, and 10,000 test images.
### Usage:
```python
from keras.datasets import cifar100
(X_train, y_train), (X_test, y_test) = cifar100.load_data(label_mode='fine')
```
@@ -44,8 +44,6 @@ Dataset of 50,000 32x32 color training images, labeled over 100 categories, and
## IMDB Movie reviews sentiment classification
`keras.datasets.imdb`
Dataset of 25,000 movies reviews from IMDB, labeled by sentiment (positive/negative). Reviews have been preprocessed, and each review is encoded as a [sequence](preprocessing/sequence.md) of word indexes (integers). For convenience, words are indexed by overall frequency in the dataset, so that for instance the integer "3" encodes the 3rd most frequent word in the data. This allows for quick filtering operations such as: "only consider the top 10,000 most common words, but eliminate the top 20 most common words".
As a convention, "0" does not stand for a specific word, but instead is used to encode any unknown word.
@@ -53,8 +51,13 @@ As a convention, "0" does not stand for a specific word, but instead is used to
### Usage:
```python
(X_train, y_train), (X_test, y_test) = imdb.load_data(path="imdb.pkl", \
nb_words=None, skip_top=0, maxlen=None, test_split=0.1, seed=113)
from keras.datasets import imdb
(X_train, y_train), (X_test, y_test) = imdb.load_data(path="imdb.pkl",
nb_words=None,
skip_top=0,
maxlen=None,
test_split=0.1)
```
- __Return:__
- 2 tuples:
@@ -74,15 +77,18 @@ nb_words=None, skip_top=0, maxlen=None, test_split=0.1, seed=113)
## Reuters newswire topics classification
`keras.datasets.reuters`
Dataset of 11,228 newswires from Reuters, labeled over 46 topics. As with the IMDB dataset, each wire is encoded as a sequence of word indexes (same conventions).
### Usage:
```python
(X_train, y_train), (X_test, y_test) = reuters.load_data(path="reuters.pkl", \
nb_words=None, skip_top=0, maxlen=None, test_split=0.1, seed=113)
from keras.datasets import reuters
(X_train, y_train), (X_test, y_test) = reuters.load_data(path="reuters.pkl",
nb_words=None,
skip_top=0,
maxlen=None,
test_split=0.1)
```
The specifications are the same as that of the IMDB dataset.
@@ -101,13 +107,13 @@ word_index = reuters.get_word_index(path="reuters_word_index.pkl")
## MNIST database of handwritten digits
`keras.datasets.mnist`
Dataset of 60,000 28x28 grayscale images of the 10 digits, along with a test set of 10,000 images.
### Usage:
```python
from keras.datasets import mnist
(X_train, y_train), (X_test, y_test) = mnist.load_data()
```
-40
Ver Arquivo
@@ -1,40 +0,0 @@
# Keras Documentation Index
## Introduction
- [Home](index.md)
- [Index](documentation.md)
- [Examples](examples.md)
- [FAQ](faq.md)
- [Backend](backend.md)
---
## Base functionality
- [Optimizers](optimizers.md)
- [Objectives](objectives.md)
- [Models](models.md)
- [Activations](activations.md)
- [Initializations](initializations.md)
- [Regularizers](regularizers.md)
- [Constraints](constraints.md)
- [Callbacks](callbacks.md)
- [Datasets](datasets.md)
---
## Layers
- [Core](layers/core.md)
- [Convolutional](layers/convolutional.md)
- [Recurrent](layers/recurrent.md)
- [Advanced Activations](layers/advanced_activations.md)
- [Normalization](layers/normalization.md)
- [Embeddings](layers/embeddings.md)
---
## Preprocessing
- [Sequence](preprocessing/sequence.md)
- [Text](preprocessing/text.md)
- [Image](preprocessing/image.md)
@@ -1,26 +1,16 @@
# Keras FAQ: Frequently Asked Keras Questions
[How should I cite Keras?](#how-should-i-cite-keras)
[How can I run Keras on GPU?](#how-can-i-run-keras-on-gpu)
[How can I save a Keras model?](#how-can-i-save-a-keras-model)
[Why is the training loss much higher than the testing loss?](#why-is-the-training-loss-much-higher-than-the-testing-loss)
[How can I visualize the output of an intermediate layer?](#how-can-i-visualize-the-output-of-an-intermediate-layer)
[How can I use Keras with datasets that don't fit in memory?](#how-can-i-use-keras-with-datasets-that-dont-fit-in-memory)
[How can I interrupt training when the validation loss isn't decreasing anymore?](#how-can-i-interrupt-training-when-the-validation-loss-isnt-decreasing-anymore)
[How is the validation split computed?](#how-is-the-validation-split-computed)
[Is the data shuffled during training?](#is-the-data-shuffled-during-training)
[How can I record the training / validation loss / accuracy at each epoch?](#how-can-i-record-the-training-validation-loss-accuracy-at-each-epoch)
[How can I use stateful RNNs?](#how-can-i-use-stateful-rnns)
- [How should I cite Keras?](#how-should-i-cite-keras)
- [How can I run Keras on GPU?](#how-can-i-run-keras-on-gpu)
- [How can I save a Keras model?](#how-can-i-save-a-keras-model)
- [Why is the training loss much higher than the testing loss?](#why-is-the-training-loss-much-higher-than-the-testing-loss)
- [How can I visualize the output of an intermediate layer?](#how-can-i-visualize-the-output-of-an-intermediate-layer)
- [How can I use Keras with datasets that don't fit in memory?](#how-can-i-use-keras-with-datasets-that-dont-fit-in-memory)
- [How can I interrupt training when the validation loss isn't decreasing anymore?](#how-can-i-interrupt-training-when-the-validation-loss-isnt-decreasing-anymore)
- [How is the validation split computed?](#how-is-the-validation-split-computed)
- [Is the data shuffled during training?](#is-the-data-shuffled-during-training)
- [How can I record the training / validation loss / accuracy at each epoch?](#how-can-i-record-the-training-validation-loss-accuracy-at-each-epoch)
- [How can I use stateful RNNs?](#how-can-i-use-stateful-rnns)
---
@@ -131,22 +121,31 @@ from keras import backend as K
# with a Sequential model
get_3rd_layer_output = K.function([model.layers[0].input],
[model.layers[3].get_output(train=False)])
[model.layers[3].output])
layer_output = get_3rd_layer_output([X])[0]
# with a Graph model
get_conv_layer_output = K.function([model.inputs[i].input for i in model.input_order],
[model.nodes['conv'].get_output(train=False)])
conv_output = get_conv_layer_output([input_data_dict[i] for i in model.input_order])[0]
```
Similarly, you could build a Theano and TensorFlow function directly.
Note that if your model has a different behavior in training and testing phase (e.g. if it uses `Dropout`, `BatchNormalization`, etc.), you will need
to pass the learning phase flag to your function:
```python
get_3rd_layer_output = K.function([model.layers[0].input, K.learning_phase()],
[model.layers[3].output])
# output in train mode
layer_output = get_3rd_layer_output([X, 1])[0]
# output in test mode
layer_output = get_3rd_layer_output([X, 1])[0]
```
---
### How can I use Keras with datasets that don't fit in memory?
You can do batch training using `model.train_on_batch(X, y)` and `model.test_on_batch(X, y)`. See the [models documentation](models.md).
You can do batch training using `model.train_on_batch(X, y)` and `model.test_on_batch(X, y)`. See the [models documentation](/models/sequential).
Alternatively, you can write a generator that yields batches of training data and use the method `model.fit_generator(data_generator, samples_per_epoch, nb_epoch)`.
@@ -164,7 +163,7 @@ early_stopping = EarlyStopping(monitor='val_loss', patience=2)
model.fit(X, y, validation_split=0.2, callbacks=[early_stopping])
```
Find out more in the [callbacks documentation](callbacks.md).
Find out more in the [callbacks documentation](/callbacks).
---
@@ -179,14 +178,14 @@ If you set the `validation_split` argument in `model.fit` to e.g. 0.1, then the
Yes, if the `shuffle` argument in `model.fit` is set to `True` (which is the default), the training data will be randomly shuffled at each epoch.
Validation data isn't shuffled.
Validation data is never shuffled.
---
### How can I record the training / validation loss / accuracy at each epoch?
The `model.fit` method returns an `History` callback, which has a `history` attribute containing the lists of successive losses / accuracies.
The `model.fit` method returns an `History` callback, which has a `history` attribute containing the lists of successive losses and other metrics.
```python
hist = model.fit(X, y, validation_split=0.2)
+421
Ver Arquivo
@@ -0,0 +1,421 @@
# Getting started with the Keras functional API
The Keras functional API is the way to go for defining complex models, such as multi-output models, directed acyclic graphs, or models with shared layers.
This guide assumes that you are already familiar with the `Sequential` model.
Let's start with something simple.
-----
## First example: fully connected network
The `Sequential` model is probably a better choice to implement such a network, but it helps to start with something really simple.
- A layer instance is callable (on a tensor), and it returns a tensor
- Input tensor(s) and output tensor(s) can then be used to define a `Model`
- Such a model can be trained just like Keras `Sequential` models.
```python
from keras.layers import Input, Dense
from keras.models import Model
# this returns a tensor
inputs = Input(shape=(784,))
# a layer instance is callable on a tensor, and returns a tensor
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
# this creates a model that includes
# the Input layer and three Dense layers
model = Model(input=inputs, output=predictions)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.fit(data, labels) # starts training
```
-----
## All models are callable, just like layers
With the functional API, it is easy to re-use trained models: you can treat any model as if it were a layer, by calling it on a tensor. Note that by calling a model you aren't just re-using the *architecture* of the model, you are also re-using its weights.
```python
x = Input(shape=(784,))
# this works, and returns the 10-way softmax we defined above.
y = model(x)
```
This can allow, for instance, to quickly create models that can process *sequences* of inputs. You could turn an image classification model into a video classification model, in just one line.
```python
from keras.layers import TimeDistributed
# input tensor for sequences of 20 timesteps,
# each containing a 784-dimensional vector
input_sequences = Input(shape=(20, 784))
# this applies our previous model to every timestep in the input sequences.
# the output of the previous model was a 10-way softmax,
# so the output of the layer below will be a sequence of 20 vectors of size 10.
processed_sequences = TimeDistributed(model)(input_sequences)
```
-----
## Multi-input and multi-output models
Here's a good use case for the functional API: models with multiple inputs and outputs. The functional API makes it easy to manipulate a large number of intertwined datastreams.
Let's consider the following model. We seek to predict how many retweets and likes a news headline will receive on Twitter. The main input to the model will be the headline itself, as a sequence of words, but to spice things up, our model will also have an auxiliary input, receiving extra data such as the time of day when the headline was posted, etc.
The model will also be supervised via two loss functions. Using the main loss function earlier in a model is a good regularization mechanism for deep models.
Here's what our model looks like:
<img src="http://s3.amazonaws.com/keras.io/img/multi-input-multi-output-graph.png" alt="multi-input-multi-output-graph" style="width: 400px;"/>
Let's implement it with the functional API.
The main input will receive the headline, as a sequence of integers (each integer encodes a word).
The integers will be between 1 and 10,000 (a vocabulary of 10,000 words) and the sequences will be 100 words long.
```python
from keras.layers import Input, Embedding, LSTM, Dense, merge
from keras.models import Model
# headline input: meant to receive sequences of 100 integers, between 1 and 10000.
# note that we can name any layer by passing it a "name" argument.
main_input = Input(shape=(100,), dtype='int32', name='main_input')
# this embedding layer will encode the input sequence
# into a sequence of dense 512-dimensional vectors.
x = Embedding(output_dim=512, input_dim=10000, input_length=100)(main_input)
# a LSTM will transform the vector sequence into a single vector,
# containing information about the entire sequence
lstm_out = LSTM(32)(x)
```
Here we insert the auxiliary loss, allowing the LSTM and Embedding layer to be trained smoothly even though the main loss will be much higher in the model.
```python
auxiliary_loss = Dense(1, activation='sigmoid', name='aux_output')(lstm_out)
```
At this point, we feed into the model our auxiliary input data by concatenating it with the LSTM output:
```python
auxiliary_input = Input(shape=(5,), name='aux_input')
x = merge([lstm_out, auxiliary_input], mode='concat')
# we stack a deep fully-connected network on top
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
x = Dense(64, activation='relu')(x)
# and finally we add the main logistic regression layer
main_loss = Dense(1, activation='sigmoid', name='main_output')(x)
```
This defines a model with two inputs and two outputs:
```python
model = Model(input=[main_input, auxiliary_input], output=[main_loss, auxiliary_loss])
```
We compile the model and assign a weight of 0.2 to the auxiliary loss.
To specify different `loss_weight` or `loss` for each different output, you can use a list or a dictionary.
Here we pass a single loss as the `loss` argument, so the same loss will be used on all outputs.
```python
model.compile(optimizer='rmsprop', loss='binary_crossentropy',
loss_weight=[1., 0.2])
```
We can train the model by passing it lists of input arrays and target arrays:
```python
model.fit([headline_data, additional_data], [labels, labels],
nb_epoch=50, batch_size=32)
```
Since our inputs and outputs are named (we passed them a "name" argument),
We could also have compiled the model via:
```python
model.compile(optimizer='rmsprop',
loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
loss_weight={'main_output': 1., 'aux_output': 0.2})
# and trained it via:
model.fit({'main_input': headline_data, 'aux_input': additional_data},
{'main_output': labels, 'aux_output': labels},
nb_epoch=50, batch_size=32)
```
-----
## Shared layers
Another good use for the functional API are models that use shared layers. Let's take a look at shared layers.
Let's consider a dataset of tweets. We want to build a model that can tell whether two tweets are from the same person or not (this can allow us to compare users by the similarity of their tweets, for instance).
One way to achieve this is to build a model that encodes two tweets into two vectors, concatenates the vectors and adds a logistic regression of top, outputting a probability that the two tweets share the same author. The model would then be trained on positive tweet pairs and negative tweet pairs.
Because the problem is symetric, the mechanism that encodes the first tweet should be reused (weights and all) to encode the second tweet. Here we use a shared LSTM layer to encode the tweets.
Let's build this with the functional API. We will take as input for a tweet a binary matrix of shape `(140, 256)`, i.e. a sequence of 140 vectors of size 256, where each dimension in the 256-dimensional vector encodes the presence/absence of a character (out of an alphabet of 256 frequent characters).
```python
from keras.layers import Input, LSTM, Dense, merge
from keras.models import Model
tweet_a = Input(shape=(140, 256))
tweet_b = Input(shape=(140, 256))
```
To share a layer across different inputs, simply instantiate the layer once, then call it on as many inputs as you want:
```python
# this layer can take as input a matrix
# and will return a vector of size 64
shared_lstm = LSTM(64)
# when we reuse the same layer instance
# multiple times, the weights of the layer
# are also being reused
# (it is effectively *the same* layer)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
# we can then concatenate the two vectors:
merged_vector = merge([encoded_a, encoded_b], mode='concat', concat_axis=-1)
# and add a logistic regression on top
predictions = Dense(1, activation='sigmoid')(merged_vector)
# we define a trainable model linking the
# tweet inputs to the predictions
model = Model(input=[tweet_a, tweet_b], output=predictions)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit([data_a, data_b], labels, nb_epoch=10)
```
Let's pause to take a look at how to read the shared layer's output or output shape.
-----
## The concept of layer "node"
Whenever you are calling a layer on some input, you are creating a new tensor (the output of the layer), and you are adding a "node" to the layer, linking the input tensor to the output tensor. When you are calling the same layer multiple times, that layer owns multiple nodes indexed as 0, 1, 2...
In previous versions of Keras, you could obtain the output tensor of a layer instance via `layer.get_output()`, or its output shape via `layer.output_shape`. You still can (except `get_output()` has been replaced by the property `output`). But what if a layer is connected to multiple inputs?
As long as a layer is only connected to one input, there is no confusion, and `.output` will return the one output of the layer:
```python
a = Input(shape=(140, 256))
lstm = LSTM(32)
encoded_a = lstm(a)
assert lstm.output == encoded_a
```
Not so if the layer has multiple inputs:
```python
a = Input(shape=(140, 256))
b = Input(shape=(140, 256))
lstm = LSTM(32)
encoded_a = lstm(a)
encoded_b = lstm(b)
lstm.output
```
```
>> AssertionError: Layer lstm_1 has multiple inbound nodes,
hence the notion of "layer output" is ill-defined.
Use `get_output_at(node_index)` instead.
```
Okay then. The following works:
```python
assert lstm.get_output_at(0) == encoded_a
assert lstm.get_output_at(1) == encoded_b
```
Simple enough, right?
The same is true for the properties `input_shape` and `output_shape`: as long as the layer has only one node, or as long as all nodes have the same input/output shape, then the notion of "layer output/input shape" is well defined, and that one shape will be returned by `layer.output_shape`/`layer.input_shape`. But if, for instance, you apply a same `Convolution2D` layer to an input of shape `(3, 32, 32)`, and then to an input of shape `(3, 64, 64)`, the layer will have multiple input/output shapes, and you will have to fetch them by specifying the index of the node they belong to:
```python
a = Input(shape=(3, 32, 32))
b = Input(shape=(3, 64, 64))
conv = Convolution2D(16, 3, 3, border_mode='same')
conved_a = conv(a)
# only one input so far, the following will work:
assert conv.input_shape == (None, 3, 32, 32)
conved_b = conv(b)
# now the `.input_shape` property wouldn't work, but this does:
assert conv.get_input_shape_at(0) == (None, 3, 32, 32)
assert conv.get_input_shape_at(1) == (None, 3, 64, 64)
```
-----
## More examples
Code examples are still the best way to get started, so here are a few more.
### Inception module
For more information about the Inception architecture, see [Going Deeper with Convolutions](http://arxiv.org/abs/1409.4842).
```python
from keras.layers import merge, Convolution2D, MaxPooling2D, Input
input_img = Input(shape=(3, 256, 256))
tower_1 = Convolution2D(64, 1, 1, border_mode='same', activation='relu')(input_img)
tower_1 = Convolution2D(64, 3, 3, border_mode='same', activation='relu')(tower_1)
tower_2 = Convolution2D(64, 1, 1, border_mode='same', activation='relu')(input_img)
tower_2 = Convolution2D(64, 5, 5, border_mode='same', activation='relu')(tower_2)
tower_3 = MaxPooling2D((3, 3), strides=(1, 1), border_mode='same')(input_img)
tower_3 = Convolution2D(64, 1, 1, border_mode='same', activation='relu')(tower_3)
output = merge([tower_1, tower_2, tower_3], mode='concat', concat_axis=1)
```
### Residual connection on a convolution layer
For more information about residual networks, see [Deep Residual Learning for Image Recognition](http://arxiv.org/abs/1512.03385).
```python
from keras.layers import merge, Convolution2D, Input
# input tensor for a 3-channel 256x256 image
x = Input(shape=(3, 256, 256))
# 3x3 conv with 16 output channels
y = Convolution2D(16, 3, 3, border_mode='same')
# this returns x + y.
z = merge([x, y], mode='sum')
```
### Shared vision model
This model re-uses the same image-processing module on two inputs, to classify whether two MNIST digits are the same digit or different digits.
```python
from keras.layers import merge, Convolution2D, MaxPooling2D, Input, Dense, Flatten
from keras.models import Model
# first, define the vision modules
digit_input = Input(shape=(1, 27, 27))
x = Convolution2D(64, 3, 3)(digit_input)
x = Convolution2D(64, 3, 3)(x)
x = MaxPooling2D((2, 2))(x)
out = Flatten()(x)
vision_model = Model(digit_input, out)
# then define the tell-digits-apart model
digit_a = Input(shape=(1, 27, 27))
digit_b = Input(shape=(1, 27, 27))
# the vision model will be shared, weights and all
out_a = vision_model(digit_a)
out_b = vision_model(digit_b)
concatenated = merge([out_a, out_b], mode='concat')
out = Dense(1, activation='sigmoid')(concatenated)
classification_model = Model([digit_a, digit_b], out)
```
### Visual question answering model
This model can select the correct one-word answer when asked a natural-language question about a picture.
It works by encoding the question into a vector, encoding the image into a vector, concatenating the two, and training on top a logistic regression over some vocabulary of potential answers.
```python
from keras.layers import Convolution2D, MaxPooling2D, Flatten
from keras.layers import Input, LSTM, Embedding, Dense, merge
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(Convolution2D(64, 3, 3, activation='relu', border_mode='same', input_shape=(3, 224, 224)))
vision_model.add(Convolution2D(64, 3, 3, activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Convolution2D(128, 3, 3, activation='relu', border_mode='same'))
vision_model.add(Convolution2D(128, 3, 3, activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Convolution2D(256, 3, 3, activation='relu', border_mode='same'))
vision_model.add(Convolution2D(256, 3, 3, activation='relu'))
vision_model.add(Convolution2D(256, 3, 3, activation='relu'))
vision_model.add(MaxPooling2D((2, 2)))
vision_model.add(Flatten())
# now let's get a tensor with the output of our vision model:
image_input = Input(shape=(3, 224, 224))
encoded_image = vision_model(image_input)
# next, let's define a language model to encode the question into a vector.
# each question will be at most 100 word long,
# and we will index words as integers from 1 to 9999.
question_input = Input(shape=(100,), dtype='int32')
embedded_question = Embedding(input_dim=10000, output_dim=256, input_length=100)(question_input)
encoded_question = LSTM(256)(embedded_question)
# let's concatenate the question vector and the image vector:
merged = merge([encoded_question, encoded_image], mode='concat')
# and let's train a logistic regression over 1000 words on top:
output = Dense(1000, activation='softmax')(merged)
# this is our final model:
vqa_model = Model(input=[image_input, question_input], output=output)
# the next stage would be training this model on actual data.
```
### Video question answering model
Now that we have trained our image QA model, we can quickly turn it into a video QA model. With appropriate training, you will be able to show it a short video (e.g. 100-frame human action) and ask a natural language question about the video (e.g. "what sport is the boy playing?" -> "football").
```python
from keras.layers import TimeDistributed
video_input = Input(shape=(100, 3, 224, 224))
# this is our video encoded via the previously trained vision_model (weights are reused)
encoded_frame_sequence = TimeDistributed(vision_model)(video_input) # the output will be a sequence of vectors
encoded_video = LSTM(256)(encoded_frame_sequence) # the output will be a vector
# this is a model-level representation of the question encoder, reusing the same weights as before:
question_encoder = Model(input=question_input, output=encoded_question)
# let's use it to encode the question:
video_question_input = Input(shape=(100,), dtype='int32')
encoded_video_question = question_encoder(video_question_input)
# and this is our video question answering model:
merged = merge([encoded_video, encoded_video_question], mode='concat')
output = Dense(1000, activation='softmax')(merged)
video_qa_model = Model(input=[video_input, video_question_input], output=output)
```
@@ -1,3 +1,201 @@
# Getting started with the Keras Sequential model
The `Sequential` model is a linear stack of layers.
You can create a `Sequential` model by passing a list of layer instances to the constructor:
```python
from keras.models import Sequential
model = Sequential([
Dense(32, input_dim=784),
Activation('relu'),
Dense(10),
Activation('softmax'),
])
```
You can also simply add layers via the `.add()` method:
```python
model = Sequential()
model.add(Dense(32, input_dim=784))
model.add(Activation('relu'))
```
----
## Specifying the input shape
The model needs to know what input shape it should expect. For this reason, the first layer in a `Sequential` model (and only the first, because following layers can do automatic shape inference) needs to receive information about its input shape. There are several possible ways to do this:
- pass an `input_shape` argument to the first layer. This is a shape tuple (a tuple of integers or `None` entries, where `None` indicates that any positive integer may be expected). In `input_shape`, the batch dimension is not included.
- pass instead a `batch_input_shape` argument, where the batch dimension is included. This is useful for specifying a fixed batch size (e.g. with stateful RNNs).
- some 2D layers, such as `Dense`, support the specification of their input shape via the argument `input_dim`, and some 3D temporal layers support the arguments `input_dim` and `input_length`.
As such, the following three snippets are strictly equivalent:
```python
model = Sequential()
model.add(Dense(32, input_shape=(784,)))
```
```python
model = Sequential()
model.add(Dense(32, batch_input_shape=(None, 784)))
# note that batch dimension is "None" here,
# so the model will be able to process batches of any size.
```
```python
model = Sequential()
model.add(Dense(32, input_dim=784))
```
And so are the following three snippets:
```python
model = Sequential()
model.add(LSTM(32, input_shape=(10, 64)))
```
```python
model = Sequential()
model.add(LSTM(32, batch_input_shape=(None, 10, 64)))
```
```python
model = Sequential()
model.add(LSTM(32, input_length=10, input_dim=64))
```
----
## The Merge layer
Multiple `Sequential` instances can be merged into a single output via a `Merge` layer. The output is a layer that can be added as first layer in a new `Sequential` model. For instance, here's a model with two separate input branches getting merged:
```python
from keras.layers import Merge
left_branch = Sequential()
left_branch.add(Dense(32, input_dim=784))
right_branch = Sequential()
right_branch.add(Dense(32, input_dim=784))
merged = Merge([left_branch, right_branch], mode='concat')
final_model = Sequential()
final_model.add(merged)
final_model.add(Dense(10, activation='softmax'))
```
<img src="http://s3.amazonaws.com/keras.io/img/two_branches_sequential_model.png" alt="two branch Sequential" style="width: 400px;"/>
The `Merge` layer supports a number of pre-defined modes:
- `sum` (default): element-wise sum
- `concat`: tensor concatenation. You can specify the concatenation axis via the argument `concat_axis`.
- `mul`: element-wise multiplication
- `ave`: tensor average
- `dot`: dot product. You can specify which axes to reduce along via the argument `dot_axes`.
- `cos`: cosine proximity between vectors in 2D tensors.
You can also pass a function as the `mode` argument, allowing for arbitrary transformations:
```python
merged = Merge([left_branch, right_branch], mode=lambda x, y: x - y)
```
Now you know enough to be able to define *almost* any model with Keras. For complex models that cannot be expressed via `Sequential` and `Merge`, you can use [the functional API](/getting-started/functional-api-guide).
----
## Compilation
Before training a model, you need to configure the learning process, which is done via the `compile` method. It receives three arguments:
- an optimizer. This could be the string identifier of an existing optimizer (such as `rmsprop` or `adagrad`), or an instance of the `Optimizer` class. See: [optimizers](/optimizers).
- a loss function. This is the objective that the model will try to minimize. If can be the string identifier of an existing loss function (such as `categorical_crossentropy` or `mse`), or it can be an objective function. See: [objectives](/objectives).
- a list of metrics. For any classification problem you will want to set this to `metrics=['accuracy']`. A metric could be the string identifier of an existing metric (only `accuracy` is supported at this point), or a custom metric function.
```python
# for a multi-class classification problem
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# for a binary classification problem
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
# for a mean squared error regression problem
model.compile(optimizer='rmsprop',
loss='mse')
```
----
## Training
Keras models are trained on Numpy arrays of input data and labels. For training a model, you will typically use the `fit` function. [Read its documentation here](/models/sequential).
```python
# for a single-input model with 2 classes (binary):
model = Sequential()
model.add(Dense(1, input_dim=784, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
# generate dummy data
import numpy as np
data = np.random.random((1000, 784))
labels = np.random.randint(2, size=(1000, 1))
# train the model, iterating on the data in batches
# of 32 samples
model.fit(data, labels, nb_epoch=10, batch_size=32)
```
```python
# for a multi-input model with 10 classes:
left_branch = Sequential()
left_branch.add(Dense(32, input_dim=784))
right_branch = Sequential()
right_branch.add(Dense(32, input_dim=784))
merged = Merge([left_branch, right_branch], mode='concat')
model = Sequential()
model.add(merged)
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# generate dummy data
import numpy as np
from keras.utils.np_utils import to_categorical
data_1 = np.random.random((1000, 784))
data_2 = np.random.random((1000, 784))
# these are integers between 0 and 9
labels = np.random.randint(10, size=(1000, 1))
# we convert the labels to a binary matrix of size (1000, 10)
# for use with categorical_crossentropy
labels = to_categorical(labels, 10)
# train the model
# note that we are passing a list of Numpy arrays as training data
# since the model has 2 inputs
model.fit([data_1, data_2], labels, nb_epoch=10, batch_size=32)
```
----
## Examples
Here are a few examples to get you started!
@@ -11,7 +209,6 @@ In the examples folder, you will also find example models for real datasets:
...and more.
------------------
### Multilayer Perceptron (MLP) for multi-class softmax classification:
@@ -35,16 +232,15 @@ model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy',
optimizer=sgd)
optimizer=sgd,
metrics=['accuracy'])
model.fit(X_train, y_train,
nb_epoch=20,
batch_size=16,
show_accuracy=True)
batch_size=16)
score = model.evaluate(X_test, y_test, batch_size=16)
```
------------------
### Alternative implementation of a similar MLP:
@@ -56,10 +252,11 @@ model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
```
------------------
### MLP for binary classification:
```python
@@ -71,10 +268,10 @@ model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop')
optimizer='rmsprop',
metrics=['accuracy'])
```
------------------
### VGG-like convnet:
@@ -114,10 +311,8 @@ sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=1)
```
------------------
### Sequence classification with LSTM:
@@ -134,7 +329,9 @@ model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop')
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size=16, nb_epoch=10)
score = model.evaluate(X_test, Y_test, batch_size=16)
@@ -183,9 +380,10 @@ image_model.add(RepeatVector(max_caption_len))
# the output of both models will be tensors of shape (samples, max_caption_len, 128).
# let's concatenate these 2 vector sequences.
model = Merge([image_model, language_model], mode='concat', concat_axis=-1)
model = Sequential()
model.add(Merge([image_model, language_model], mode='concat', concat_axis=-1))
# let's encode this vector sequence into a single vector
model.add(GRU(256, 256, return_sequences=False))
model.add(GRU(256, return_sequences=False))
# which will be used to compute a probability
# distribution over what the next word in the caption should be!
model.add(Dense(vocab_size))
@@ -202,7 +400,6 @@ model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([images, partial_captions], next_words, batch_size=16, nb_epoch=100)
```
------------------
### Stacked LSTM for sequence classification
@@ -215,9 +412,6 @@ the last step in its output sequence, thus dropping the temporal dimension
<img src="http://keras.io/img/regular_stacked_lstm.png" alt="stacked LSTM" style="width: 300px;"/>
(N.B.: in Keras, "None" in an input shape indicates a variable dimension. In the graph above, the batch size is "None",
meaning that any batch size is allowed for the input data).
```python
from keras.models import Sequential
from keras.layers import LSTM, Dense
@@ -235,7 +429,9 @@ model.add(LSTM(32, return_sequences=True)) # returns a sequence of vectors of d
model.add(LSTM(32)) # return a single vector of dimension 32
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# generate dummy training data
x_train = np.random.random((1000, timesteps, data_dim))
@@ -246,11 +442,10 @@ x_val = np.random.random((100, timesteps, data_dim))
y_val = np.random.random((100, nb_classes))
model.fit(x_train, y_train,
batch_size=64, nb_epoch=5, show_accuracy=True,
batch_size=64, nb_epoch=5,
validation_data=(x_val, y_val))
```
------------------
### Same stacked LSTM model, rendered "stateful"
@@ -280,7 +475,9 @@ model.add(LSTM(32, return_sequences=True, stateful=True))
model.add(LSTM(32, stateful=True))
model.add(Dense(10, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# generate dummy training data
x_train = np.random.random((batch_size * 10, timesteps, data_dim))
@@ -291,11 +488,10 @@ x_val = np.random.random((batch_size * 3, timesteps, data_dim))
y_val = np.random.random((batch_size * 3, nb_classes))
model.fit(x_train, y_train,
batch_size=batch_size, nb_epoch=5, show_accuracy=True,
batch_size=batch_size, nb_epoch=5,
validation_data=(x_val, y_val))
```
------------------
### Two merged LSTM encoders for classification over two parallel sequences
@@ -303,7 +499,7 @@ In this model, two input sequences are encoded into vectors by two separate LSTM
These two vectors are then concatenated, and a fully connected network is trained on top of the concatenated representations.
![Dual LSTM](http://keras.io/img/dual_lstm.png)
<img src="http://keras.io/img/dual_lstm.png" alt="Dual LSTM" style="width: 600px;"/>
```python
from keras.models import Sequential
@@ -325,7 +521,9 @@ decoder.add(Merge([encoder_a, encoder_b], mode='concat'))
decoder.add(Dense(32, activation='relu'))
decoder.add(Dense(nb_classes, activation='softmax'))
decoder.compile(loss='categorical_crossentropy', optimizer='rmsprop')
decoder.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# generate dummy training data
x_train_a = np.random.random((1000, timesteps, data_dim))
@@ -338,52 +536,6 @@ x_val_b = np.random.random((100, timesteps, data_dim))
y_val = np.random.random((100, nb_classes))
decoder.fit([x_train_a, x_train_b], y_train,
batch_size=64, nb_epoch=5, show_accuracy=True,
batch_size=64, nb_epoch=5,
validation_data=([x_val_a, x_val_b], y_val))
```
------------------
### Single shared LSTM over two parallel sequences, for classification
This is a similar setup as above, but now a single LSTM encoder is used for both input sequences.
Such a setup makes sense if the two input sequences are the same type of object.
<img src="http://keras.io/img/shared_lstm.png" alt="Shared LSTM" style="width: 500px;"/>
```python
from keras.models import Graph
from keras.layers import LSTM, Dense
import numpy as np
data_dim = 16
timesteps = 8
nb_classes = 10
encoder = Sequential()
encoder.add(LSTM(32, input_shape=(timesteps, data_dim)))
model = Graph()
model.add_input(name='input_a', input_shape=(timesteps, data_dim))
model.add_input(name='input_b', input_shape=(timesteps, data_dim))
model.add_shared_node(encoder, name='shared_encoder', inputs=['input_a', 'input_b'],
merge_mode='concat')
model.add_node(Dense(64, activation='relu'), name='fc1', input='shared_encoder')
model.add_node(Dense(3, activation='softmax'), name='output', input='fc1', create_output=True)
model.compile(optimizer='adam', loss={'output': 'categorical_crossentropy'})
# generate dummy training data
x_train_a = np.random.random((1000, timesteps, data_dim))
x_train_b = np.random.random((1000, timesteps, data_dim))
y_train = np.random.random((1000, 3))
# generate dummy validation data
x_val_a = np.random.random((100, timesteps, data_dim))
x_val_b = np.random.random((100, timesteps, data_dim))
y_val = np.random.random((100, 3))
model.fit({'input_a': x_train_a, 'input_b': x_train_b, 'output': y_train},
batch_size=64, nb_epoch=5,
validation_data={'input_a': x_val_a, 'input_b': x_val_b, 'output': y_val})
```
+12 -14
Ver Arquivo
@@ -33,11 +33,12 @@ Keras is compatible with: __Python 2.7-3.5__.
------------------
## Getting started: 30 seconds to Keras
The core datastructure of Keras is a __model__, a way to organize layers. There are two types of models: [`Sequential`](http://keras.io/models/#sequential) and [`Graph`](http://keras.io/models/#graph).
The core data structure of Keras is a __model__, a way to organize layers. The main type of model is the [`Sequential`](http://keras.io/getting-started/sequential-model-guide) model, a linear stack of layers. For more complex architectures, you should use the [Keras function API](http://keras.io/getting-started/functional-api-guide).
Here's the `Sequential` model (a linear pile of layers):
Here's the `Sequential` model:
```python
from keras.models import Sequential
@@ -50,15 +51,15 @@ Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100, init="glorot_uniform"))
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
model.add(Dense(output_dim=10, init="glorot_uniform"))
model.add(Dense(output_dim=10))
model.add(Activation("softmax"))
```
Once your model looks good, configure its learning process with `.compile()`:
```python
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
```
If you need to, you can further configure your optimizer. A core principle of Keras is to make things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).
@@ -79,7 +80,7 @@ model.train_on_batch(X_batch, Y_batch)
Evaluate your performance in one line:
```python
objective_score = model.evaluate(X_test, Y_test, batch_size=32)
loss_and_metrics = model.evaluate(X_test, Y_test, batch_size=32)
```
Or generate predictions on new data:
@@ -88,12 +89,14 @@ classes = model.predict_classes(X_test, batch_size=32)
proba = model.predict_proba(X_test, batch_size=32)
```
Building a network of LSTMs, a deep CNN, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
Building a question answering system, an image classification model, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
Have a look at these [starter examples](http://keras.io/examples/).
For a more in-depth tutorial about Keras, you can check out:
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repo, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, neural turing machines, etc.
- [Getting started with the Sequential model](http://keras.io/getting-started/sequential-model-guide)
- [Getting started with the functional API](http://keras.io/getting-started/functional-api-guide)
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repository, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, etc.
------------------
@@ -112,11 +115,6 @@ Keras uses the following dependencies:
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
**Note**: You should use the latest version of Theano, not the PyPI version. Install it with:
```
sudo pip install git+git://github.com/Theano/Theano.git
```
*When using the TensorFlow backend:*
- TensorFlow
+27
Ver Arquivo
@@ -0,0 +1,27 @@
# About Keras layers
All Keras layers have a number of methods in common:
- `layer.get_weights()`: returns the weights of the layer as a list of Numpy arrays.
- `layer.set_weights(weights)`: sets the weights of the layer from a list of Numpy arrays (with the same shapes as the output of `get_weights`).
- `layer.get_config()`: returns a dictionary containing the configuration of the layer. The layer can be reinstantiated from its config via:
```python
from keras.utils.layer_utils import layer_from_config
config = layer.get_config()
layer = layer_from_config(config)
```
If a layer has a single node (i.e. if it isn't a shared layer), you can get its input tensor, output tensor, input shape and output shape via:
- `layer.input`
- `layer.output`
- `layer.input_shape`
- `layer.output_shape`
If the layer has multiple nodes (see: [the concept of layer node and shared layers](/getting-started/functional-api-guide/#the-concept-of-layer-node)), you can use the following methods:
- `layer.get_input_at(node_index)`
- `layer.get_output_at(node_index)`
- `layer.get_input_shape_at(node_index)`
- `layer.get_output_shape_at(node_index)`
-114
Ver Arquivo
@@ -1,114 +0,0 @@
Keras has two models: __Sequential__, a linear stack of layers, and __Graph__, a directed acyclic graph of layers.
# Using the Sequential model
```python
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
model = Sequential()
model.add(Dense(2, init='uniform', input_dim=64))
model.add(Activation('softmax'))
model.compile(optimizer='sgd', loss='mse')
'''
Train the model for 3 epochs, in batches of 16 samples,
on data stored in the Numpy array X_train,
and labels stored in the Numpy array y_train:
'''
model.fit(X_train, y_train, nb_epoch=3, batch_size=16, verbose=1)
'''
What you will see with mode verbose=1:
Train on 37800 samples, validate on 4200 samples
Epoch 0
37800/37800 [==============================] - 7s - loss: 0.0385
Epoch 1
37800/37800 [==============================] - 8s - loss: 0.0140
Epoch 2
10960/37800 [=======>......................] - ETA: 4s - loss: 0.0109
'''
model.fit(X_train, y_train, nb_epoch=3, batch_size=16, verbose=2)
'''
What you will see with mode verbose=2:
Train on 37800 samples, validate on 4200 samples
Epoch 0
loss: 0.0190
Epoch 1
loss: 0.0146
Epoch 2
loss: 0.0049
'''
'''
Demonstration of the show_accuracy argument
'''
model.fit(X_train, y_train, nb_epoch=3, batch_size=16, verbose=2, show_accuracy=True)
'''
Train on 37800 samples, validate on 4200 samples
Epoch 0
loss: 0.0190 - acc.: 0.8750
Epoch 1
loss: 0.0146 - acc.: 0.8750
Epoch 2
loss: 0.0049 - acc.: 1.0000
'''
'''
Demonstration of the validation_split argument
'''
model.fit(X_train, y_train, nb_epoch=3, batch_size=16,
validation_split=0.1, show_accuracy=True, verbose=1)
'''
Train on 37800 samples, validate on 4200 samples
Epoch 0
37800/37800 [==============================] - 7s - loss: 0.0385 - acc.: 0.7258 - val. loss: 0.0160 - val. acc.: 0.9136
Epoch 1
37800/37800 [==============================] - 8s - loss: 0.0140 - acc.: 0.9265 - val. loss: 0.0109 - val. acc.: 0.9383
Epoch 2
10960/37800 [=======>......................] - ETA: 4s - loss: 0.0109 - acc.: 0.9420
'''
```
# Using the Graph model
```python
# graph model with one input and two outputs
graph = Graph()
graph.add_input(name='input', input_shape=(32,))
graph.add_node(Dense(16), name='dense1', input='input')
graph.add_node(Dense(4), name='dense2', input='input')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_output(name='output1', input='dense2')
graph.add_output(name='output2', input='dense3')
graph.compile(optimizer='rmsprop', loss={'output1':'mse', 'output2':'mse'})
history = graph.fit({'input':X_train, 'output1':y_train, 'output2':y2_train}, nb_epoch=10)
```
```python
# graph model with two inputs and one output
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_input(name='input2', input_shape=(32,))
graph.add_node(Dense(16), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense2', input='input2')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_output(name='output', inputs=['dense2', 'dense3'], merge_mode='sum')
graph.compile(optimizer='rmsprop', loss={'output':'mse'})
history = graph.fit({'input1':X_train, 'input2':X2_train, 'output':y_train}, nb_epoch=10)
predictions = graph.predict({'input1':X_test, 'input2':X2_test}) # {'output':...}
```
----
# Model API documentation
{{autogenerated}}
+33
Ver Arquivo
@@ -0,0 +1,33 @@
# About Keras models
There are two types of models available in Keras: [the Sequential model](/models/sequential) and [the Model class used with functional API](/models/model).
These models have a number of methods in common:
- `model.summary()`: prints a summary representation of your model.
- `model.get_config()`: returns a dictionary containing the configuration of the model. The model can be reinstantiated from its config via:
```python
config = model.get_config()
model = Model.from_config(config)
# or, for Sequential:
model = Sequential.from_config(config)
```
- `model.get_weights()`: returns a list of all weight tensors in the model, as Numpy arrays.
- `model.set_weights(weights)`: sets the values of the weights of the model, from a list of Numpy arrays. The arrays in the list should have the same shape as those returned by `get_weights()`.
- `model.to_json()`: returns a representation of the model as a JSON string. Note that the representation does not include the weights, only the architecture. You can reinstantiate the same model (with reinitialized weights) from the JSON string via:
```python
from models import model_from_json
json_string = model.to_json()
model = model_from_json(json_string)
```
- `model.to_yaml()`: returns a representation of the model as a YAML string. Note that the representation does not include the weights, only the architecture. You can reinstantiate the same model (with reinitialized weights) from the YAML string via:
```python
from models import model_from_yaml
yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)
```
- `model.save_weights(filepath)`: saves the weights of the model as a HDF5 file.
- `model.load_weights(filepath)`: loads the weights of the model from a HDF5 file (created by `save_weights`).
+32
Ver Arquivo
@@ -0,0 +1,32 @@
# Model class API
In the functional API, given an input tensor and output tensor, you can instantiate a `Model` via:
```python
from keras.models import Model
from keras.layers import Input, Dense
a = Input(shape=(32,))
b = Dense(32)(a)
model = Model(input=a, output=b)
```
This model will include all layers required in the computation of `a` given `b`.
In the case of multi-input or multi-output models, you can use lists as well:
```python
model = Model(input=[a1, a2], output=[b1, b3, b3])
```
For a detailed introduction of what `Model` can do, read [this guide to the Keras functional API](/getting-started/functional-api-guide).
## Useful attributes of Model
- `model.layers` is a flattened list of the layers comprising the model graph.
- `model.inputs` is the list of input tensors.
- `model.outputs` is the list of output tensors.
## Methods
{{autogenerated}}
+14
Ver Arquivo
@@ -0,0 +1,14 @@
# The Sequential model API
To get started, read [this guide to the Keras Sequential model](/getting-started/sequential-model-guide).
## Useful attributes of Model
- `model.layers` is a list of the layers added to the model.
----
## Sequential model methods
{{autogenerated}}
+45
Ver Arquivo
@@ -0,0 +1,45 @@
# Wrappers for the Sciki-Learn API
You can use `Sequential` Keras models (single-input only) as part of your Scikit-Learn workflow via the wrappers found at `keras.wrappers.sklearn.py`.
There are two wrappers available:
`keras.wrappers.sklearn.KerasClassifier(build_fn=None, **sk_params)`, which implements the sklearn classifier interface,
`keras.wrappers.sklearn.KerasRegressor(build_fn=None, **sk_params)`, which implements the sklearn regressor interface.
### Arguments
- __build_fn__: callable function or class instance
- __sk_params__: model parameters & fitting parameters
`build_fn` should construct, compile and return a Keras model, which
will then be used to fit/predict. One of the following
three values could be passed to build_fn:
1. A function
2. An instance of a class that implements the __call__ method
3. None. This means you implement a class that inherits from either
`KerasClassifier` or `KerasRegressor`. The __call__ method of the
present class will then be treated as the default build_fn.
`sk_params` takes both model parameters and fitting parameters. Legal model
parameters are the arguments of `build_fn`. Note that like all other
estimators in scikit-learn, 'build_fn' should provide defalult values for
its arguments, so that you could create the estimator without passing any
values to `sk_params`.
`sk_params` could also accept parameters for calling `fit`, `predict`,
`predict_proba`, and `score` methods (e.g., `nb_epoch`, `batch_size`).
fitting (predicting) parameters are selected in the following order:
1. Values passed to the dictionary arguments of
`fit`, `predict`, `predict_proba`, and `score` methods
2. Values passed to `sk_params`
3. The default values of the `keras.models.Sequential`
`fit`, `predict`, `predict_proba` and `score` methods
When using scikit-learn's `grid_search` API, legal tunable parameters are
those you could pass to `sk_params`, including fitting parameters.
In other words, you could use `grid_search` to search for the best
`batch_size` or `nb_epoch` as well as the model parameters.
+4 -5
Ver Arquivo
@@ -10,16 +10,15 @@ from keras.utils.visualize_util import plot
plot(model, to_file='model.png')
```
`plot` takes two optional arguments:
`plot` takes one optional arguments:
- `recursive` (defaults to True) controls whether we recursively explore container layers.
- `show_shape` (defaults to False) controls whether output shapes are shown in the graph.
- `show_shapes` (defaults to False) controls whether output shapes are shown in the graph.
You can also directly obtain the `pydot.Graph` object and render it yourself,
for example to show it in an ipython notebook :
```python
from IPython.display import SVG
from keras.utils.visualize_util import to_graph
from keras.utils.visualize_util import model_to_dot
SVG(to_graph(model).create(prog='dot', format='svg'))
SVG(model_to_dot(model).create(prog='dot', format='svg'))
```
+6 -3
Ver Arquivo
@@ -27,7 +27,8 @@ Five digits inverted:
'''
from __future__ import print_function
from keras.models import Sequential, slice_X
from keras.models import Sequential
from keras.engine.training import slice_X
from keras.layers.core import Activation, TimeDistributedDense, RepeatVector
from keras.layers import recurrent
import numpy as np
@@ -142,7 +143,9 @@ for _ in range(LAYERS):
model.add(TimeDistributedDense(len(chars)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
# Train the model each generation and show predictions against the validation dataset
for iteration in range(1, 200):
@@ -150,7 +153,7 @@ for iteration in range(1, 200):
print('-' * 50)
print('Iteration', iteration)
model.fit(X_train, y_train, batch_size=BATCH_SIZE, nb_epoch=1,
validation_data=(X_val, y_val), show_accuracy=True)
validation_data=(X_val, y_val))
###
# Select 10 samples from the validation set at random so we can visualize errors
for i in range(10):
+8 -10
Ver Arquivo
@@ -11,7 +11,6 @@ backend (`K`), our code can run both on TensorFlow and Theano.
'''
from __future__ import print_function
import numpy as np
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Layer, Activation
from keras.datasets import mnist
@@ -46,15 +45,13 @@ class Antirectifier(Layer):
with twice less parameters yet with comparable
classification accuracy as an equivalent ReLU-based network.
'''
@property
def output_shape(self):
shape = list(self.input_shape)
def get_output_shape_for(self, input_shape):
shape = list(input_shape)
assert len(shape) == 2 # only valid for 2D tensors
shape[-1] *= 2
return tuple(shape)
def get_output(self, train):
x = self.get_input(train)
def call(self, x, mask=None):
x -= K.mean(x, axis=1, keepdims=True)
x = K.l2_normalize(x, axis=1)
pos = K.relu(x)
@@ -66,7 +63,7 @@ batch_size = 128
nb_classes = 10
nb_epoch = 40
# the data, shuffled and split between tran and test sets
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 784)
@@ -94,13 +91,14 @@ model.add(Dense(10))
model.add(Activation('softmax'))
# compile the model
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# train the model
model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=1,
validation_data=(X_test, Y_test))
verbose=1, validation_data=(X_test, Y_test))
# next, compare with an equivalent network
# with2x bigger Dense layers and ReLU
+4 -4
Ver Arquivo
@@ -1,4 +1,4 @@
'''Train a memory network on the bAbI dataset.
'''Trains a memory network on the bAbI dataset.
References:
- Jason Weston, Antoine Bordes, Sumit Chopra, Tomas Mikolov, Alexander M. Rush,
@@ -167,7 +167,7 @@ question_encoder.add(Dropout(0.3))
match = Sequential()
match.add(Merge([input_encoder_m, question_encoder],
mode='dot',
dot_axes=[(2,), (2,)]))
dot_axes=[2, 2]))
# output: (samples, story_maxlen, query_maxlen)
# embed the input into a single vector with size = story_maxlen:
input_encoder_c = Sequential()
@@ -195,10 +195,10 @@ answer.add(Dense(vocab_size))
# we output a probability distribution over the vocabulary
answer.add(Activation('softmax'))
answer.compile(optimizer='rmsprop', loss='categorical_crossentropy')
answer.compile(optimizer='rmsprop', loss='categorical_crossentropy',
metrics=['accuracy'])
# Note: you could use a Graph model to avoid repeat the input twice
answer.fit([inputs_train, queries_train, inputs_train], answers_train,
batch_size=32,
nb_epoch=120,
show_accuracy=True,
validation_data=([inputs_test, queries_test, inputs_test], answers_test))
+9 -5
Ver Arquivo
@@ -178,11 +178,13 @@ print('story_maxlen, query_maxlen = {}, {}'.format(story_maxlen, query_maxlen))
print('Build model...')
sentrnn = Sequential()
sentrnn.add(Embedding(vocab_size, EMBED_HIDDEN_SIZE, input_length=story_maxlen, mask_zero=True))
sentrnn.add(Embedding(vocab_size, EMBED_HIDDEN_SIZE,
input_length=story_maxlen))
sentrnn.add(Dropout(0.3))
qrnn = Sequential()
qrnn.add(Embedding(vocab_size, EMBED_HIDDEN_SIZE, input_length=query_maxlen))
qrnn.add(Embedding(vocab_size, EMBED_HIDDEN_SIZE,
input_length=query_maxlen))
qrnn.add(Dropout(0.3))
qrnn.add(RNN(EMBED_HIDDEN_SIZE, return_sequences=False))
qrnn.add(RepeatVector(story_maxlen))
@@ -193,9 +195,11 @@ model.add(RNN(EMBED_HIDDEN_SIZE, return_sequences=False))
model.add(Dropout(0.3))
model.add(Dense(vocab_size, activation='softmax'))
model.compile(optimizer='adam', loss='categorical_crossentropy', class_mode='categorical')
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
print('Training')
model.fit([X, Xq], Y, batch_size=BATCH_SIZE, nb_epoch=EPOCHS, validation_split=0.05, show_accuracy=True)
loss, acc = model.evaluate([tX, tXq], tY, batch_size=BATCH_SIZE, show_accuracy=True)
model.fit([X, Xq], Y, batch_size=BATCH_SIZE, nb_epoch=EPOCHS, validation_split=0.05)
loss, acc = model.evaluate([tX, tXq], tY, batch_size=BATCH_SIZE)
print('Test loss / test accuracy = {:.4f} / {:.4f}'.format(loss, acc))
+12 -8
Ver Arquivo
@@ -66,7 +66,9 @@ model.add(Activation('softmax'))
# let's train the model using SGD + momentum (how original).
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.compile(loss='categorical_crossentropy',
optimizer=sgd,
metrics=['accuracy'])
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
@@ -75,9 +77,11 @@ X_test /= 255
if not data_augmentation:
print('Not using data augmentation.')
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch, show_accuracy=True,
validation_data=(X_test, Y_test), shuffle=True)
model.fit(X_train, Y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, Y_test),
shuffle=True)
else:
print('Using real-time data augmentation.')
@@ -99,8 +103,8 @@ else:
datagen.fit(X_train)
# fit the model on the batches generated by datagen.flow()
model.fit_generator(datagen.flow(X_train, Y_train, batch_size=batch_size),
model.fit_generator(datagen.flow(X_train, Y_train,
batch_size=batch_size),
samples_per_epoch=X_train.shape[0],
nb_epoch=nb_epoch, show_accuracy=True,
validation_data=(X_test, Y_test),
nb_worker=1)
nb_epoch=nb_epoch,
validation_data=(X_test, Y_test))
+7 -9
Ver Arquivo
@@ -47,15 +47,13 @@ def deprocess_image(x):
x = np.clip(x, 0, 255).astype('uint8')
return x
# this will contain our generated image
input_img = K.placeholder((1, 3, img_width, img_height))
# build the VGG16 network with our input_img as input
first_layer = ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height))
first_layer.input = input_img
# build the VGG16 network
model = Sequential()
model.add(first_layer)
model.add(ZeroPadding2D((1, 1), batch_input_shape=(1, 3, img_width, img_height)))
first_layer = model.layers[-1]
# this is a placeholder tensor that will contain our generated images
input_img = first_layer.input
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
@@ -125,7 +123,7 @@ for filter_index in range(0, 200):
# we build a loss function that maximizes the activation
# of the nth filter of the layer considered
layer_output = layer_dict[layer_name].get_output()
layer_output = layer_dict[layer_name].output
loss = K.mean(layer_output[:, filter_index, :, :])
# we compute the gradient of the input picture wrt this loss
+7 -9
Ver Arquivo
@@ -74,15 +74,13 @@ def deprocess_image(x):
x = np.clip(x, 0, 255).astype('uint8')
return x
# this will contain our generated image
dream = K.placeholder((1, 3, img_width, img_height))
# build the VGG16 network with our dream as input
first_layer = ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height))
first_layer.input = dream
# build the VGG16 network
model = Sequential()
model.add(first_layer)
model.add(ZeroPadding2D((1, 1), batch_input_shape=(1, 3, img_width, img_height)))
first_layer = model.layers[-1]
# this is a placeholder tensor that will contain our generated images
dream = first_layer.input
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
@@ -150,7 +148,7 @@ for layer_name in settings['features']:
# add the L2 norm of the features of a layer to the loss
assert layer_name in layer_dict.keys(), 'Layer ' + layer_name + ' not found in model.'
coeff = settings['features'][layer_name]
x = layer_dict[layer_name].get_output()
x = layer_dict[layer_name].output
shape = layer_dict[layer_name].output_shape
# we avoid border artifacts by only involving non-border pixels in the loss
loss -= coeff * K.sum(K.square(x[:, :, 2: shape[2]-2, 2: shape[3]-2])) / np.prod(shape[1:])
+24 -25
Ver Arquivo
@@ -1,8 +1,5 @@
'''Train a Bidirectional LSTM on the IMDB sentiment classification task.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_bidirectional_lstm.py
Output after 4 epochs on CPU: ~0.8146
Time per epoch on CPU (Core i7): ~150s.
'''
@@ -12,11 +9,8 @@ import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.utils.np_utils import accuracy
from keras.models import Graph
from keras.layers.core import Dense, Dropout
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.models import Model
from keras.layers import Dense, Dropout, Embedding, LSTM, Input, merge
from keras.datasets import imdb
@@ -38,25 +32,30 @@ print('X_test shape:', X_test.shape)
y_train = np.array(y_train)
y_test = np.array(y_test)
print('Build model...')
model = Graph()
model.add_input(name='input', input_shape=(maxlen,), dtype=int)
model.add_node(Embedding(max_features, 128, input_length=maxlen),
name='embedding', input='input')
model.add_node(LSTM(64), name='forward', input='embedding')
model.add_node(LSTM(64, go_backwards=True), name='backward', input='embedding')
model.add_node(Dropout(0.5), name='dropout', inputs=['forward', 'backward'])
model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', input='dropout')
model.add_output(name='output', input='sigmoid')
# this is the placeholder tensor for the input sequences
sequence = Input(shape=(maxlen,), dtype='int32')
# this embedding layer will transform the sequences of integers
# into vectors of size 128
embedded = Embedding(max_features, 128, input_length=maxlen)(sequence)
# apply forwards LSTM
forwards = LSTM(64)(embedded)
# apply backwards LSTM
backwards = LSTM(64, go_backwards=True)(embedded)
# concatenate the outputs of the 2 LSTMs
merged = merge([forwards, backwards], mode='concat', concat_axis=-1)
after_dp = Dropout(0.5)(merged)
output = Dense(1, activation='sigmoid')(after_dp)
model = Model(input=sequence, output=output)
# try using different optimizers and different optimizer configs
model.compile('adam', {'output': 'binary_crossentropy'})
model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])
print('Train...')
model.fit({'input': X_train, 'output': y_train},
model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=4, show_accuracy=True)
acc = accuracy(y_test,
np.round(np.array(model.predict({'input': X_test},
batch_size=batch_size)['output'])))
print('Test accuracy:', acc)
nb_epoch=4,
validation_data=[X_test, y_test])
+6 -6
Ver Arquivo
@@ -1,8 +1,6 @@
'''This example demonstrates the use of Convolution1D for text classification.
Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_cnn.py
Get to 0.835 test accuracy after 2 epochs. 100s/epoch on K520 GPU.
Gets to 0.835 test accuracy after 2 epochs. 100s/epoch on K520 GPU.
'''
from __future__ import print_function
@@ -71,7 +69,9 @@ model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop')
model.fit(X_train, y_train, batch_size=batch_size,
nb_epoch=nb_epoch, show_accuracy=True,
optimizer='rmsprop',
metrics=['accuracy'])
model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
+4 -9
Ver Arquivo
@@ -1,12 +1,8 @@
'''Train a recurrent convolutional network on the IMDB sentiment
classification task.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_cnn_lstm.py
Get to 0.8498 test accuracy after 2 epochs. 41s/epoch on K520 GPU.
Gets to 0.8498 test accuracy after 2 epochs. 41s/epoch on K520 GPU.
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
@@ -71,12 +67,11 @@ model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
class_mode='binary')
metrics=['accuracy'])
print('Train...')
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,
validation_data=(X_test, y_test), show_accuracy=True)
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size,
show_accuracy=True)
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
+11 -14
Ver Arquivo
@@ -1,4 +1,4 @@
'''Train a LSTM on the IMDB sentiment classification task.
'''Trains a LSTM on the IMDB sentiment classification task.
The dataset is actually too small for LSTM to be of any advantage
compared to simpler, much faster methods such as TF-IDF+LogReg.
@@ -11,11 +11,7 @@ Some configurations won't converge.
- LSTM loss decrease patterns during training can be quite different
from what you see with CNNs/MLPs/etc.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_lstm.py
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
@@ -25,11 +21,11 @@ from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.layers.recurrent import LSTM, SimpleRNN, GRU
from keras.datasets import imdb
max_features = 20000
maxlen = 100 # cut texts after this number of words (among top max_features most common words)
maxlen = 80 # cut texts after this number of words (among top max_features most common words)
batch_size = 32
print('Loading data...')
@@ -46,21 +42,22 @@ print('X_test shape:', X_test.shape)
print('Build model...')
model = Sequential()
model.add(Embedding(max_features, 128, input_length=maxlen, dropout=0.5))
model.add(LSTM(128, dropout_W=0.5, dropout_U=0.1)) # try using a GRU instead, for fun
model.add(Dropout(0.5))
model.add(Embedding(max_features, 128, input_length=maxlen, dropout=0.2))
model.add(LSTM(128, dropout_W=0.2, dropout_U=0.2)) # try using a GRU instead, for fun
model.add(Dense(1))
model.add(Activation('sigmoid'))
# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy',
optimizer='adam')
optimizer='adam',
metrics=['accuracy'])
print('Train...')
print(X_train.shape)
print(y_train.shape)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=15,
validation_data=(X_test, y_test), show_accuracy=True)
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test, y_test,
batch_size=batch_size,
show_accuracy=True)
batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)
-121
Ver Arquivo
@@ -1,121 +0,0 @@
'''This demonstrates how to reach a score of 0.4890 (local validation)
on the Kaggle Otto challenge, with a deep net using Keras.
Requires Scikit-Learn and Pandas.
Recommended to run on GPU:
Command: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python kaggle_otto_nn.py
On EC2 g2.2xlarge instance: 19s/epoch. 6-7 minutes total training time.
Best validation score at epoch 21: 0.4881
Try it at home:
- with/without BatchNormalization (BatchNormalization helps!)
- with ReLU or with PReLU (PReLU helps!)
- with smaller layers, largers layers
- with more layers, less layers
- with different optimizers (SGD+momentum+decay is probably better than Adam!)
Get the data from Kaggle:
https://www.kaggle.com/c/otto-group-product-classification-challenge/data
'''
from __future__ import print_function
import numpy as np
import pandas as pd
np.random.seed(1337) # for reproducibility
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.normalization import BatchNormalization
from keras.layers.advanced_activations import PReLU
from keras.utils import np_utils, generic_utils
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
def load_data(path, train=True):
df = pd.read_csv(path)
X = df.values.copy()
if train:
np.random.shuffle(X) # https://youtu.be/uyUXoap67N8
X, labels = X[:, 1:-1].astype(np.float32), X[:, -1]
return X, labels
else:
X, ids = X[:, 1:].astype(np.float32), X[:, 0].astype(str)
return X, ids
def preprocess_data(X, scaler=None):
if not scaler:
scaler = StandardScaler()
scaler.fit(X)
X = scaler.transform(X)
return X, scaler
def preprocess_labels(labels, encoder=None, categorical=True):
if not encoder:
encoder = LabelEncoder()
encoder.fit(labels)
y = encoder.transform(labels).astype(np.int32)
if categorical:
y = np_utils.to_categorical(y)
return y, encoder
def make_submission(y_prob, ids, encoder, fname):
with open(fname, 'w') as f:
f.write('id,')
f.write(','.join([str(i) for i in encoder.classes_]))
f.write('\n')
for i, probs in zip(ids, y_prob):
probas = ','.join([i] + [str(p) for p in probs.tolist()])
f.write(probas)
f.write('\n')
print('Wrote submission to file {}.'.format(fname))
print('Loading data...')
X, labels = load_data('train.csv', train=True)
X, scaler = preprocess_data(X)
y, encoder = preprocess_labels(labels)
X_test, ids = load_data('test.csv', train=False)
X_test, _ = preprocess_data(X_test, scaler)
nb_classes = y.shape[1]
print(nb_classes, 'classes')
dims = X.shape[1]
print(dims, 'dims')
print('Building model...')
model = Sequential()
model.add(Dense(512, input_shape=(dims,)))
model.add(PReLU())
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(512))
model.add(PReLU())
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(512))
model.add(PReLU())
model.add(BatchNormalization())
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
print('Training model...')
model.fit(X, y, nb_epoch=20, batch_size=128, validation_split=0.15)
print('Generating submission...')
proba = model.predict_proba(X_test)
make_submission(proba, ids, encoder, fname='keras-otto.csv')
+1 -1
Ver Arquivo
@@ -29,7 +29,7 @@ char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
# cut the text in semi-redundant sequences of maxlen characters
maxlen = 20
maxlen = 40
step = 3
sentences = []
next_chars = []
+9 -8
Ver Arquivo
@@ -1,8 +1,7 @@
'''Train a simple convnet on the MNIST dataset.
'''Trains a simple convnet on the MNIST dataset.
Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python mnist_cnn.py
Get to 99.25% test accuracy after 12 epochs (there is still a lot of margin for parameter tuning).
Gets to 99.25% test accuracy after 12 epochs
(there is still a lot of margin for parameter tuning).
16 seconds per epoch on a GRID K520 GPU.
'''
@@ -29,7 +28,7 @@ nb_pool = 2
# convolution kernel size
nb_conv = 3
# the data, shuffled and split between tran and test sets
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
@@ -64,10 +63,12 @@ model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=1, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
verbose=1, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
+10 -25
Ver Arquivo
@@ -14,18 +14,15 @@ Reaches 0.93 train/test accuracy after 900 epochs
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.initializations import normal, identity
from keras.layers.recurrent import SimpleRNN, LSTM
from keras.layers.recurrent import SimpleRNN
from keras.optimizers import RMSprop
from keras.utils import np_utils
batch_size = 32
nb_classes = 10
nb_epochs = 200
@@ -54,32 +51,20 @@ Y_test = np_utils.to_categorical(y_test, nb_classes)
print('Evaluate IRNN...')
model = Sequential()
model.add(SimpleRNN(output_dim=hidden_units,
init=lambda shape: normal(shape, scale=0.001),
inner_init=lambda shape: identity(shape, scale=1.0),
activation='relu', input_shape=X_train.shape[1:]))
init=lambda shape, name: normal(shape, scale=0.001, name=name),
inner_init=lambda shape, name: identity(shape, scale=1.0, name=name),
activation='relu',
input_shape=X_train.shape[1:]))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
rmsprop = RMSprop(lr=learning_rate)
model.compile(loss='categorical_crossentropy', optimizer=rmsprop)
model.compile(loss='categorical_crossentropy',
optimizer=rmsprop,
metrics=['accuracy'])
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epochs,
show_accuracy=True, verbose=1, validation_data=(X_test, Y_test))
verbose=1, validation_data=(X_test, Y_test))
scores = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
scores = model.evaluate(X_test, Y_test, verbose=0)
print('IRNN test score:', scores[0])
print('IRNN test accuracy:', scores[1])
print('Compare to LSTM...')
model = Sequential()
model.add(LSTM(hidden_units, input_shape=X_train.shape[1:]))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
rmsprop = RMSprop(lr=learning_rate)
model.compile(loss='categorical_crossentropy', optimizer=rmsprop)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epochs,
show_accuracy=True, verbose=1, validation_data=(X_test, Y_test))
scores = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
print('LSTM test score:', scores[0])
print('LSTM test accuracy:', scores[1])
+12 -11
Ver Arquivo
@@ -1,6 +1,6 @@
'''Train a simple deep NN on the MNIST dataset.
'''Trains a simple deep NN on the MNIST dataset.
Get to 98.40% test accuracy after 20 epochs
Gets to 98.40% test accuracy after 20 epochs
(there is *a lot* of margin for parameter tuning).
2 seconds per epoch on a K520 GPU.
'''
@@ -20,7 +20,7 @@ batch_size = 128
nb_classes = 10
nb_epoch = 20
# the data, shuffled and split between tran and test sets
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 784)
@@ -46,14 +46,15 @@ model.add(Dropout(0.2))
model.add(Dense(10))
model.add(Activation('softmax'))
rms = RMSprop()
model.compile(loss='categorical_crossentropy', optimizer=rms)
model.summary()
model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=2,
validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test,
show_accuracy=True, verbose=0)
model.compile(loss='categorical_crossentropy',
optimizer=RMSprop(),
metrics=['accuracy'])
history = model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
verbose=1, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
+27 -26
Ver Arquivo
@@ -7,8 +7,6 @@ for mode details).
[1] "Dimensionality Reduction by Learning an Invariant Mapping"
http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python mnist_siamese_graph.py
Gets to 99.5% test accuracy after 20 epochs.
3 seconds per epoch on a Titan X GPU
'''
@@ -19,25 +17,23 @@ np.random.seed(1337) # for reproducibility
import random
from keras.datasets import mnist
from keras.models import Sequential, Graph
from keras.layers.core import Dense, Dropout, Lambda
from keras.models import Sequential, Model
from keras.layers import Dense, Dropout, Input, Lambda
from keras.optimizers import SGD, RMSprop
from keras import backend as K
def euclidean_distance(inputs):
assert len(inputs) == 2, ('Euclidean distance needs '
'2 inputs, %d given' % len(inputs))
u, v = inputs.values()
return K.sqrt(K.sum(K.square(u - v), axis=1, keepdims=True))
def euclidean_distance(vects):
x, y = vects
return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True))
def contrastive_loss(y, d):
def contrastive_loss(y_true, y_pred):
'''Contrastive loss from Hadsell-et-al.'06
http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
'''
margin = 1
return K.mean(y * K.square(d) + (1 - y) * K.square(K.maximum(margin - d, 0)))
return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0)))
def create_pairs(x, digit_indices):
@@ -77,7 +73,7 @@ def compute_accuracy(predictions, labels):
return labels[predictions.ravel() < 0.5].mean()
# the data, shuffled and split between tran and test sets
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)
@@ -98,26 +94,31 @@ te_pairs, te_y = create_pairs(X_test, digit_indices)
# network definition
base_network = create_base_network(input_dim)
g = Graph()
g.add_input(name='input_a', input_shape=(input_dim,))
g.add_input(name='input_b', input_shape=(input_dim,))
g.add_shared_node(base_network, name='shared', inputs=['input_a', 'input_b'],
merge_mode='join')
g.add_node(Lambda(euclidean_distance), name='d', input='shared')
g.add_output(name='output', input='d')
input_a = Input(shape=(input_dim,))
input_b = Input(shape=(input_dim,))
# because we re-use the same instance `base_network`,
# the weights of the network
# will be shared across the two branches
processed_a = base_network(input_a)
processed_b = base_network(input_b)
distance = Lambda(euclidean_distance)([processed_a, processed_b])
model = Model(input=[input_a, input_b], output=distance)
# train
rms = RMSprop()
g.compile(loss={'output': contrastive_loss}, optimizer=rms)
g.fit({'input_a': tr_pairs[:, 0], 'input_b': tr_pairs[:, 1], 'output': tr_y},
validation_data={'input_a': te_pairs[:, 0], 'input_b': te_pairs[:, 1], 'output': te_y},
batch_size=128,
nb_epoch=nb_epoch)
model.compile(loss=contrastive_loss, optimizer=rms)
model.fit([tr_pairs[:, 0], tr_pairs[:, 1]], tr_y,
validation_data=([te_pairs[:, 0], te_pairs[:, 1]], te_y),
batch_size=128,
nb_epoch=nb_epoch)
# compute final accuracy on training and test sets
pred = g.predict({'input_a': tr_pairs[:, 0], 'input_b': tr_pairs[:, 1]})['output']
pred = model.predict([tr_pairs[:, 0], tr_pairs[:, 1]])
tr_acc = compute_accuracy(pred, tr_y)
pred = g.predict({'input_a': te_pairs[:, 0], 'input_b': te_pairs[:, 1]})['output']
pred = model.predict([te_pairs[:, 0], te_pairs[:, 1]])
te_acc = compute_accuracy(pred, te_y)
print('* Accuracy on training set: %0.2f%%' % (100 * tr_acc))
+5 -3
Ver Arquivo
@@ -55,15 +55,17 @@ def train_model(model, train, test, nb_classes):
Y_train = np_utils.to_categorical(train[1], nb_classes)
Y_test = np_utils.to_categorical(test[1], nb_classes)
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
t = now()
model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=1,
verbose=1,
validation_data=(X_test, Y_test))
print('Training time: %s' % (now() - t))
score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
score = model.evaluate(X_test, Y_test, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
+3 -3
Ver Arquivo
@@ -111,8 +111,8 @@ input_tensor = K.concatenate([base_image,
combination_image], axis=0)
# build the VGG16 network with our 3 images as input
first_layer = ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height))
first_layer.input = input_tensor
first_layer = ZeroPadding2D((1, 1))
first_layer.set_input(input_tensor, shape=(3, 3, img_width, img_height))
model = Sequential()
model.add(first_layer)
@@ -168,7 +168,7 @@ f.close()
print('Model loaded.')
# get the symbolic outputs of each "key" layer (we gave them unique names).
outputs_dict = dict([(layer.name, layer.get_output()) for layer in model.layers])
outputs_dict = dict([(layer.name, layer.output) for layer in model.layers])
# compute the neural style loss
# first we need to define 4 util functions
+10 -8
Ver Arquivo
@@ -1,8 +1,5 @@
'''Train and evaluate a simple MLP on the Reuters newswire topic classification task.
GPU run command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python examples/reuters_mlp.py
CPU run command:
python examples/reuters_mlp.py
'''Trains and evaluate a simple MLP
on the Reuters newswire topic classification task.
'''
from __future__ import print_function
@@ -49,9 +46,14 @@ model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.compile(loss='categorical_crossentropy',
optimizer='adam',
metrics=['accuracy'])
history = model.fit(X_train, Y_train, nb_epoch=nb_epoch, batch_size=batch_size, verbose=1, show_accuracy=True, validation_split=0.1)
score = model.evaluate(X_test, Y_test, batch_size=batch_size, verbose=1, show_accuracy=True)
history = model.fit(X_train, Y_train,
nb_epoch=nb_epoch, batch_size=batch_size,
verbose=1, validation_split=0.1)
score = model.evaluate(X_test, Y_test,
batch_size=batch_size, verbose=1)
print('Test score:', score[0])
print('Test accuracy:', score[1])
+1 -1
Ver Arquivo
@@ -1 +1 @@
__version__ = '0.3.2'
__version__ = '1.0.0'
+7 -2
Ver Arquivo
@@ -3,7 +3,12 @@ from __future__ import print_function
import os
import json
import sys
from .common import epsilon, floatx, set_epsilon, set_floatx
from .common import epsilon
from .common import floatx
from .common import set_epsilon
from .common import set_floatx
from .common import get_uid
from .common import cast_to_floatx
_keras_base_dir = os.path.expanduser('~')
if not os.access(_keras_base_dir, os.W_OK):
@@ -18,7 +23,7 @@ _config_path = os.path.expanduser(os.path.join(_keras_dir, 'keras.json'))
if os.path.exists(_config_path):
_config = json.load(open(_config_path))
_floatx = _config.get('floatx', floatx())
assert _floatx in {'float32', 'float64'}
assert _floatx in {'float16', 'float32', 'float64'}
_epsilon = _config.get('epsilon', epsilon())
assert type(_epsilon) == float
_backend = _config.get('backend', _BACKEND)
+14 -1
Ver Arquivo
@@ -3,6 +3,7 @@ import numpy as np
# the type of float to use throughout the session.
_FLOATX = 'float32'
_EPSILON = 10e-8
_UID_PREFIXES = {}
def epsilon():
@@ -15,12 +16,15 @@ def set_epsilon(e):
def floatx():
'''Returns the default float type, as a string
(e.g. 'float16', 'float32', 'float64').
'''
return _FLOATX
def set_floatx(floatx):
global _FLOATX
if floatx not in {'float32', 'float64'}:
if floatx not in {'float16', 'float32', 'float64'}:
raise Exception('Unknown floatx type: ' + str(floatx))
floatx = str(floatx)
_FLOATX = floatx
@@ -30,3 +34,12 @@ def cast_to_floatx(x):
'''Cast a Numpy array to floatx.
'''
return np.asarray(x, dtype=_FLOATX)
def get_uid(prefix=''):
if prefix not in _UID_PREFIXES:
_UID_PREFIXES[prefix] = 1
return 1
else:
_UID_PREFIXES[prefix] += 1
return _UID_PREFIXES[prefix]
+333 -55
Ver Arquivo
@@ -1,15 +1,29 @@
import tensorflow as tf
import numpy as np
import os
import copy
import warnings
from .common import _FLOATX, _EPSILON
# INTERNAL UTILS
_SESSION = None
_LEARNING_PHASE = tf.placeholder(dtype='uint8', name='keras_learning_phase') # 0 = test, 1 = train
def learning_phase():
'''Returns the learning phase flag.
The learning phase flag is an integer tensor (0 = test, 1 = train)
to be passed as input to any Keras function
that uses a different behavior at train time and test time.
'''
return _LEARNING_PHASE
def get_session():
'''Returns the TF session in use by the backend.
'''
global _SESSION
if _SESSION is None:
if not os.environ.get('OMP_NUM_THREADS'):
@@ -21,6 +35,8 @@ def get_session():
def set_session(session):
'''Sets the TF session.
'''
global _SESSION
_SESSION = session
@@ -28,90 +44,199 @@ def set_session(session):
# VARIABLE MANIPULATION
def variable(value, dtype=_FLOATX, name=None):
'''Instantiates a tensor.
# Arguments
value: numpy array, initial value of the tensor.
dtype: tensor type.
name: optional name string for the tensor.
# Returns
Tensor variable instance.
'''
v = tf.Variable(np.asarray(value, dtype=dtype), name=name)
get_session().run(v.initializer)
return v
def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
'''Instantiates a placeholder.
# Arguments
shape: shape of the placeholder
(integer tuple, may include None entries).
ndim: number of axes of the tensor.
At least one of {`shape`, `ndim`} must be specified.
If both are specified, `shape` is used.
dtype: placeholder type.
name: optional name string for the placeholder.
# Returns
Placeholder tensor instance.
'''
if not shape:
if ndim:
shape = [None for _ in range(ndim)]
return tf.placeholder(dtype, shape=shape, name=name)
shape = tuple([None for _ in range(ndim)])
x = tf.placeholder(dtype, shape=shape, name=name)
x._keras_shape = shape
x._uses_learning_phase = False
return x
def shape(x):
# symbolic shape
'''Returns the symbolic shape of a tensor.
'''
return tf.shape(x)
def int_shape(x):
'''Returns the shape of a tensor as a tuple of
integers or None entries.
'''
shape = x.get_shape()
return tuple([i.__int__() for i in shape])
def ndim(x):
return len(x.get_shape())
'''Returns the number of axes in a tensor, as an integer.
'''
dims = x.get_shape()._dims
if dims is not None:
return len(dims)
return None
def dtype(x):
'''Returns the dtype of a tensor, as a string.
'''
return x.dtype.name
def eval(x):
'''Run a graph.
'''Evaluates the value of a tensor.
Returns a Numpy array.
'''
return x.eval(session=get_session())
def zeros(shape, dtype=_FLOATX, name=None):
'''Instantiates an all-zeros tensor variable.
'''
return variable(np.zeros(shape), dtype, name)
def ones(shape, dtype=_FLOATX, name=None):
'''Instantiates an all-ones tensor variable.
'''
return variable(np.ones(shape), dtype, name)
def ones_like(x, name=None):
return tf.ones_like(x, name=name)
def zeros_like(x, name=None):
'''Instantiates an all-zeros tensor
of the same shape as another tensor.
'''
return tf.zeros_like(x, name=name)
def ones_like(x, name=None):
'''Instantiates an all-ones tensor
of the same shape as another tensor.
'''
return tf.ones_like(x, name=name)
def count_params(x):
'''Return number of scalars in a tensor.
'''Returns the number of scalars in a tensor.
'''
shape = x.get_shape()
return np.prod([shape[i]._value for i in range(len(shape))])
def cast(x, dtype):
'''Casts a tensor to a different dtype.
'''
return tf.cast(x, dtype)
# LINEAR ALGEBRA
def dot(x, y):
return tf.matmul(x, y)
'''Multiplies 2 tensors.
When attempting to multiply a ND tensor
with a ND tensor, reproduces the Theano behavior
(e.g. (2, 3).(4, 3, 5) = (2, 4, 5))
'''
if ndim(x) is not None and (ndim(x) > 2 or ndim(y) > 2):
x_shape = (-1,) + int_shape(x)[1:]
y_shape = int_shape(y)
y_permute_dim = list(range(ndim(y)))
y_permute_dim = [y_permute_dim.pop(-2)] + y_permute_dim
xt = tf.reshape(x, [-1, x_shape[-1]])
yt = tf.reshape(tf.transpose(y, perm=y_permute_dim), [y_shape[-2], -1])
return tf.reshape(tf.matmul(xt, yt), x_shape[:-1] + y_shape[:-2] + y_shape[-1:])
out = tf.matmul(x, y)
return out
def batch_dot(x, y, axes=None):
'''Batchwise dot product.
batch_dot results in a tensor with less dimensions than the input.
If the number of dimensions is reduced to 1, we use `expand_dims` to
make sure that ndim is at least 2.
# Example
Assume x = [[1, 2] and y = [[5, 6]
[3, 4]] [7, 8]]
batch_dot(x, y, axes=1) = [[17, 53]] which is the main diagonal
of x.dot(y.T), although we never have to calculate the off-diagonal
elements.
# Arguments
x, y: tensors with ndim >= 2
axes: list (or single) int with target dimensions
# Returns
Tensor with ndim >= 2
'''
if type(axes) == int:
axes = (axes, axes)
if axes is not None:
adj_x = None if axes[0] == ndim(x) - 1 else True
adj_y = True if axes[1] == ndim(y) - 1 else None
else:
adj_x = None
adj_y = None
out = tf.batch_matmul(x, y, adj_x=adj_x, adj_y=adj_y)
if ndim(out) == 1:
out = expand_dims(out, 1)
return out
def transpose(x):
'''Transposes a matrix.
'''
return tf.transpose(x)
def gather(reference, indices):
'''
'''Retrieves the vectors of indices `indices`
in the 2D tensor `reference`.
# Arguments
reference: a tensor.
reference: a 2D tensor.
indices: an int tensor of indices.
# Returns
a tensor of same type as `reference`.
A 3D tensor of same type as `reference`.
'''
return tf.gather(reference, indices)
# ELEMENT-WISE OPERATIONS
def normalize_axis(axis, ndim):
def _normalize_axis(axis, ndim):
if type(axis) is tuple:
axis = list(axis)
if type(axis) is list:
@@ -125,31 +250,37 @@ def normalize_axis(axis, ndim):
def max(x, axis=None, keepdims=False):
axis = normalize_axis(axis, ndim(x))
'''Maximum value in a tensor.
'''
axis = _normalize_axis(axis, ndim(x))
return tf.reduce_max(x, reduction_indices=axis, keep_dims=keepdims)
def min(x, axis=None, keepdims=False):
axis = normalize_axis(axis, ndim(x))
'''Minimum value in a tensor.
'''
axis = _normalize_axis(axis, ndim(x))
return tf.reduce_min(x, reduction_indices=axis, keep_dims=keepdims)
def sum(x, axis=None, keepdims=False):
'''Sum of the values in a tensor, alongside the specified axis.
'''
axis = normalize_axis(axis, ndim(x))
axis = _normalize_axis(axis, ndim(x))
return tf.reduce_sum(x, reduction_indices=axis, keep_dims=keepdims)
def prod(x, axis=None, keepdims=False):
'''Multiply the values in a tensor, alongside the specified axis.
'''Multiplies the values in a tensor, alongside the specified axis.
'''
axis = normalize_axis(axis, ndim(x))
axis = _normalize_axis(axis, ndim(x))
return tf.reduce_prod(x, reduction_indices=axis, keep_dims=keepdims)
def std(x, axis=None, keepdims=False):
axis = normalize_axis(axis, ndim(x))
'''Standard deviation of a tensor, alongside the specificied axis.
'''
axis = _normalize_axis(axis, ndim(x))
if x.dtype.base_dtype == tf.bool:
x = tf.cast(x, _FLOATX)
m = tf.reduce_mean(x, reduction_indices=axis, keep_dims=True)
@@ -160,7 +291,9 @@ def std(x, axis=None, keepdims=False):
def mean(x, axis=None, keepdims=False):
axis = normalize_axis(axis, ndim(x))
'''Mean of a tensor, alongside the specificied axis.
'''
axis = _normalize_axis(axis, ndim(x))
if x.dtype.base_dtype == tf.bool:
x = tf.cast(x, _FLOATX)
return tf.reduce_mean(x, reduction_indices=axis, keep_dims=keepdims)
@@ -169,57 +302,85 @@ def mean(x, axis=None, keepdims=False):
def any(x, axis=None, keepdims=False):
'''Bitwise reduction (logical OR).
Return array of uint8 (0s and 1s).
Returns an uint8 tensor (0s and 1s).
'''
axis = normalize_axis(axis, ndim(x))
axis = _normalize_axis(axis, ndim(x))
x = tf.cast(x, tf.bool)
x = tf.reduce_any(x, reduction_indices=axis, keep_dims=keepdims)
return tf.cast(x, tf.uint8)
def argmax(x, axis=-1):
'''Returns the index of the maximum value
along a tensor axis.
'''
if axis < 0:
axis = axis % len(x.get_shape())
return tf.argmax(x, axis)
def argmin(x, axis=-1):
'''Returns the index of the minimum value
along a tensor axis.
'''
if axis < 0:
axis = axis % len(x.get_shape())
return tf.argmin(x, axis)
def square(x):
'''Element-wise square.
'''
return tf.square(x)
def abs(x):
'''Element-wise absolute value.
'''
return tf.abs(x)
def sqrt(x):
'''Element-wise square root.
'''
x = tf.clip_by_value(x, tf.cast(0., dtype=_FLOATX),
tf.cast(np.inf, dtype=_FLOATX))
return tf.sqrt(x)
def exp(x):
'''Element-wise exponential.
'''
return tf.exp(x)
def log(x):
'''Element-wise log.
'''
return tf.log(x)
def round(x):
'''Element-wise rounding to the closest integer.
'''
return tf.round(x)
def sign(x):
'''Element-wise sign.
'''
return tf.sign(x)
def pow(x, a):
'''Element-wise exponentiation.
'''
return tf.pow(x, a)
def clip(x, min_value, max_value):
'''Element-wise value clipping.
'''
if max_value < min_value:
max_value = min_value
return tf.clip_by_value(x, tf.cast(min_value, dtype=_FLOATX),
@@ -227,24 +388,36 @@ def clip(x, min_value, max_value):
def equal(x, y):
'''Element-wise equality between two tensors.
Returns a bool tensor.
'''
return tf.equal(x, y)
def not_equal(x, y):
'''Element-wise inequality between two tensors.
Returns a bool tensor.
'''
return tf.not_equal(x, y)
def maximum(x, y):
'''Element-wise maximum of two tensors.
'''
return tf.maximum(x, y)
def minimum(x, y):
'''Element-wise minimum of two tensors.
'''
return tf.minimum(x, y)
# SHAPE OPERATIONS
def concatenate(tensors, axis=-1):
'''Concantes a list of tensors alongside the specified axis.
'''
if axis < 0:
if len(tensors[0].get_shape()):
axis = axis % len(tensors[0].get_shape())
@@ -254,21 +427,23 @@ def concatenate(tensors, axis=-1):
def reshape(x, shape):
'''Reshapes a tensor to the specified shape.
'''
return tf.reshape(x, shape)
def permute_dimensions(x, pattern):
'''Transpose dimensions.
'''Permutes axes in a tensor.
# Arguments
pattern: should be a tuple or list of
dimension indices, e.g. [0, 2, 1].
pattern: should be a tuple of
dimension indices, e.g. (0, 2, 1).
'''
return tf.transpose(x, perm=pattern)
def resize_images(X, height_factor, width_factor, dim_ordering):
'''Resize the images contained in a 4D tensor of shape
'''Resizes the images contained in a 4D tensor of shape
- [batch, channels, height, width] (for 'th' dim_ordering)
- [batch, height, width, channels] (for 'tf' dim_ordering)
by a factor of (height_factor, width_factor). Both factors should be
@@ -303,7 +478,7 @@ def repeat_elements(x, rep, axis):
def repeat(x, n):
'''Repeat a 2D tensor:
'''Repeats a 2D tensor:
if x has shape (samples, dim) and n=2,
the output will have shape (samples, 2, dim)
@@ -331,19 +506,19 @@ def batch_flatten(x):
def expand_dims(x, dim=-1):
'''Add a 1-sized dimension at index "dim".
'''Adds a 1-sized dimension at index "dim".
'''
return tf.expand_dims(x, dim)
def squeeze(x, axis):
'''Remove a 1-dimension from the tensor at index "axis".
'''Removes a 1-dimension from the tensor at index "axis".
'''
return tf.squeeze(x, [axis])
def temporal_padding(x, padding=1):
'''Pad the middle dimension of a 3D tensor
'''Pads the middle dimension of a 3D tensor
with "padding" zeros left and right.
'''
pattern = [[0, 0], [padding, padding], [0, 0]]
@@ -351,7 +526,7 @@ def temporal_padding(x, padding=1):
def spatial_2d_padding(x, padding=(1, 1), dim_ordering='th'):
'''Pad the 2nd and 3rd dimensions of a 4D tensor
'''Pads the 2nd and 3rd dimensions of a 4D tensor
with "padding[0]" and "padding[1]" (resp.) zeros left and right.
'''
if dim_ordering == 'th':
@@ -372,12 +547,16 @@ def pack(x):
def get_value(x):
'''Technically the same as eval() for TF.
'''Returns the value of a tensor variable,
as a Numpy array.
'''
return x.eval(session=get_session())
def set_value(x, value):
'''Sets the value of a tensor variable,
from a Numpy array.
'''
tf.assign(x, np.asarray(value)).op.run(session=get_session())
@@ -404,6 +583,13 @@ class Function(object):
def function(inputs, outputs, updates=[], **kwargs):
'''Instantiates a Keras function.
# Arguments
inputs: list of placeholder/variable tensors.
outputs: list of output tensors.
updates: list of update tuples (old_tensor, new_tensor).
'''
if len(kwargs) > 0:
msg = [
"Expected no kwargs, you passed %s" % len(kwargs),
@@ -414,13 +600,17 @@ def function(inputs, outputs, updates=[], **kwargs):
def gradients(loss, variables):
'''Returns the gradients of `variables` (list of tensor variables)
with regard to `loss`.
'''
return tf.gradients(loss, variables)
# CONTROL FLOW
def rnn(step_function, inputs, initial_states,
go_backwards=False, mask=None, constants=None):
go_backwards=False, mask=None, constants=None,
unroll=False, input_length=None):
'''Iterates over the time dimension of a tensor.
# Arguments
@@ -444,15 +634,20 @@ def rnn(step_function, inputs, initial_states,
mask: binary tensor with shape (samples, time, 1),
with a zero for every element that is masked.
constants: a list of constant values passed at each step.
unroll: with TensorFlow the RNN is always unrolled, but with Theano you
can use this boolean flag to unroll the RNN.
input_length: not relevant in the TensorFlow implementation.
Must be specified if using unrolling with Theano.
# Returns
A tuple (last_output, outputs, new_states).
last_output: the latest output of the rnn, of shape (samples, ...)
outputs: tensor with shape (samples, time, ...) where each
entry outputs[s, t] is the output of the step function
at time t for sample s.
new_states: list of tensors, latest states returned by
the step function, of shape (samples, ...).
last_output: the latest output of the rnn, of shape (samples, ...)
outputs: tensor with shape (samples, time, ...) where each
entry outputs[s, t] is the output of the step function
at time t for sample s.
new_states: list of tensors, latest states returned by
the step function, of shape (samples, ...).
'''
ndim = len(inputs.get_shape())
assert ndim >= 3, "Input should be at least 3D."
@@ -522,22 +717,53 @@ def rnn(step_function, inputs, initial_states,
def switch(condition, then_expression, else_expression):
'''Switch between two operations depending on a scalar value.
'''Switches between two operations depending on a scalar value (int or bool).
Note that both `then_expression` and `else_expression`
should be symbolic tensors of the *same shape*.
# Arguments
condition: scalar tensor.
then_expression: TensorFlow operation.
else_expression: TensorFlow operation.
'''
return tf.python.control_flow_ops.cond(condition,
lambda: then_expression,
lambda: else_expression)
x_shape = copy.copy(then_expression.get_shape())
x = tf.python.control_flow_ops.cond(tf.cast(condition, 'bool'),
lambda: then_expression,
lambda: else_expression)
x.set_shape(x_shape)
return x
def in_train_phase(x, alt):
'''Selects `x` in train phase, and `alt` otherwise.
Note that `alt` should have the *same shape* as `x`.
'''
x_shape = copy.copy(x.get_shape())
x = tf.python.control_flow_ops.cond(tf.cast(_LEARNING_PHASE, 'bool'),
lambda: x,
lambda: alt)
x._uses_learning_phase = True
x.set_shape(x_shape)
return x
def in_test_phase(x, alt):
'''Selects `x` in test phase, and `alt` otherwise.
Note that `alt` should have the *same shape* as `x`.
'''
x_shape = copy.copy(x.get_shape())
x = tf.python.control_flow_ops.cond(tf.cast(_LEARNING_PHASE, 'bool'),
lambda: alt,
lambda: x)
x._uses_learning_phase = True
x.set_shape(x_shape)
return x
# NN OPERATIONS
def relu(x, alpha=0., max_value=None):
'''ReLU.
'''Rectified linear unit
# Arguments
alpha: slope of negative section.
@@ -555,17 +781,24 @@ def relu(x, alpha=0., max_value=None):
def softmax(x):
'''Softmax of a tensor.
'''
return tf.nn.softmax(x)
def softplus(x):
'''Softplus of a tensor.
'''
return tf.nn.softplus(x)
def categorical_crossentropy(output, target, from_logits=False):
'''Note: tf.nn.softmax_cross_entropy_with_logits
expects logits, Keras expects probabilities.
'''Categorical crossentropy between an output tensor
and a target tensor, where the target is a tensor of the same
shape as the output.
'''
# Note: tf.nn.softmax_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
# scale preds so that the class probas of each sample sum to 1
output /= tf.reduce_sum(output,
@@ -580,10 +813,33 @@ def categorical_crossentropy(output, target, from_logits=False):
return tf.nn.softmax_cross_entropy_with_logits(output, target)
def binary_crossentropy(output, target, from_logits=False):
'''Note: tf.nn.sigmoid_cross_entropy_with_logits
expects logits, Keras expects probabilities.
def sparse_categorical_crossentropy(output, target, from_logits=False):
'''Categorical crossentropy between an output tensor
and a target tensor, where the target is an integer tensor.
'''
# Note: tf.nn.softmax_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
output = tf.clip_by_value(output, tf.cast(_EPSILON, dtype=_FLOATX),
tf.cast(1.-_EPSILON, dtype=_FLOATX))
output = tf.log(output)
output_shape = output.get_shape()
res = tf.nn.sparse_softmax_cross_entropy_with_logits(
tf.reshape(output, [-1, int(output_shape[-1])]),
cast(flatten(target), 'int64'))
if len(output_shape) == 3:
# if our output includes timesteps we need to reshape
return tf.reshape(res, [-1, int(output_shape[-2])])
else:
return res
def binary_crossentropy(output, target, from_logits=False):
'''Binary crossentropy between an output tensor and a target tensor.
'''
# Note: tf.nn.softmax_cross_entropy_with_logits
# expects logits, Keras expects probabilities.
if not from_logits:
# transform back to logits
output = tf.clip_by_value(output, tf.cast(_EPSILON, dtype=_FLOATX),
@@ -593,10 +849,15 @@ def binary_crossentropy(output, target, from_logits=False):
def sigmoid(x):
'''Element-wise sigmoid.
'''
return tf.nn.sigmoid(x)
def hard_sigmoid(x):
'''Segment-wise linear approximation of sigmoid.
Faster than sigmoid.
'''
x = (0.2 * x) + 0.5
x = tf.clip_by_value(x, tf.cast(0., dtype=_FLOATX),
tf.cast(1., dtype=_FLOATX))
@@ -604,10 +865,21 @@ def hard_sigmoid(x):
def tanh(x):
'''Element-wise tanh.
'''
return tf.nn.tanh(x)
def dropout(x, level, seed=None):
'''Sets entries in `x` to zero at random,
while scaling the entire tensor.
# Arguments
x: tensor
level: fraction of the entries in the tensor
that will be set to 0
seed: random seed to ensure determinism.
'''
retain_prob = 1. - level
if seed is None:
seed = np.random.randint(10e6)
@@ -617,6 +889,8 @@ def dropout(x, level, seed=None):
def l2_normalize(x, axis):
'''Normalizes a tensor wrt the L2 norm alonside the specified axis.
'''
if axis < 0:
axis = axis % len(x.get_shape())
return tf.nn.l2_normalize(x, dim=axis)
@@ -627,11 +901,13 @@ def l2_normalize(x, axis):
def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th',
image_shape=None, filter_shape=None):
'''Runs on cuDNN if available.
'''2D convolution.
# Arguments
kernel: kernel tensor.
strides: strides tuple.
border_mode: string, "same" or "valid".
dim_ordering: whether to use Theano or TensorFlow dimension ordering
dim_ordering: "tf" or "th". Whether to use Theano or TensorFlow dimension ordering
in inputs/kernels/ouputs.
'''
if border_mode == 'same':
@@ -671,12 +947,14 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th',
def pool2d(x, pool_size, strides=(1, 1),
border_mode='valid', dim_ordering='th', pool_mode='max'):
'''
'''2D Pooling.
# Arguments
pool_size: tuple of 2 integers.
strides: tuple of 2 integers.
border_mode: one of "valid", "same".
dim_ordering: one of "th", "tf".
pool_mode: one of "max", "avg".
'''
if border_mode == 'same':
padding = 'SAME'
@@ -736,5 +1014,5 @@ def random_uniform(shape, low=0.0, high=1.0, dtype=_FLOATX, seed=None):
def random_binomial(shape, p=0.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
return tf.select(tf.random_uniform(shape, dtype=dtype, seed=seed) <= p,
return tf.select(tf.random_uniform(shape, dtype=dtype, seed=seed) <= p,
tf.ones(shape), tf.zeros(shape))
+202 -95
Ver Arquivo
@@ -10,21 +10,12 @@ from .common import _FLOATX, _EPSILON
# INTERNAL UTILS
theano.config.floatX = _FLOATX
_LEARNING_PHASE = T.scalar(dtype='uint8', name='keras_learning_phase') # 0 = test, 1 = train
def _on_gpu():
'''Return whether the session is set to
run on GPU or not (i.e. on CPU).
'''
return theano.config.device[:3] == 'gpu' or theano.sandbox.cuda.cuda_enabled
if _on_gpu():
'''Import cuDNN only if running on GPU:
not having Cuda installed should not
prevent from running the present code.
'''
from theano.sandbox.cuda import dnn
def learning_phase():
# False = test, True = train
return _LEARNING_PHASE
# VARIABLE MANIPULATION
@@ -43,9 +34,14 @@ def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
raise Exception('Specify either a shape or ndim value.')
if shape is not None:
ndim = len(shape)
else:
shape = tuple([None for _ in range(ndim)])
broadcast = (False,) * ndim
return T.TensorType(dtype, broadcast)(name)
x = T.TensorType(dtype, broadcast)(name)
x._keras_shape = shape
x._uses_learning_phase = False
return x
def shape(x):
@@ -61,6 +57,10 @@ def ndim(x):
return x.ndim
def dtype(x):
return x.dtype
def eval(x):
'''Run a graph.
'''
@@ -111,6 +111,38 @@ def dot(x, y):
return T.dot(x, y)
def batch_dot(x, y, axes=None):
'''batchwise dot product
batch_dot results in a tensor with less dimensions than the input.
If the number of dimensions is reduced to 1, we use `expand_dims` to
make sure that ndim is at least 2.
# Example
Assume x = [[1, 2] and y = [[5, 6]
[3, 4]] [7, 8]]
batch_dot(x, y, axes=1) = [[17, 53]] which is the main diagonal
of x.dot(y.T), although we never have to calculate the off-diagonal
elements.
# Arguments
x, y: tensors with ndim >= 2
axes: list (or single) int with target dimensions
# Returns
Tensor with ndim >= 2
'''
if type(axes) == int:
axes = (axes, axes)
if axes is None:
# behaves like tf.batch_matmul as default
axes = [x.ndim - 1, y.ndim - 2]
out = T.batched_tensordot(x, y, axes=axes)
if ndim(out) == 1:
out = expand_dims(out, 1)
return out
def transpose(x):
return T.transpose(x)
@@ -197,6 +229,10 @@ def round(x):
return T.round(x)
def sign(x):
return T.sgn(x)
def pow(x, a):
return T.pow(x, a)
@@ -443,7 +479,9 @@ class Function(object):
def __init__(self, inputs, outputs, updates=[], **kwargs):
self.function = theano.function(inputs, outputs, updates=updates,
allow_input_downcast=True, **kwargs)
allow_input_downcast=True,
on_unused_input='warn',
**kwargs)
def __call__(self, inputs):
assert type(inputs) in {list, tuple}
@@ -467,7 +505,8 @@ def gradients(loss, variables):
# CONTROL FLOW
def rnn(step_function, inputs, initial_states,
go_backwards=False, mask=None, constants=None):
go_backwards=False, mask=None, constants=None,
unroll=False, input_length=None):
'''Iterates over the time dimension of a tensor.
# Arguments
@@ -491,7 +530,8 @@ def rnn(step_function, inputs, initial_states,
mask: binary tensor with shape (samples, time),
with a zero for every element that is masked.
constants: a list of constant values passed at each step.
unroll: whether to unroll the RNN or to use a symbolic loop (`scan`).
input_length: must be specified if using `unroll`.
# Returns
A tuple (last_output, outputs, new_states).
@@ -505,6 +545,11 @@ def rnn(step_function, inputs, initial_states,
ndim = inputs.ndim
assert ndim >= 3, 'Input should be at least 3D.'
if unroll:
if input_length is None:
raise Exception('When specifying `unroll=True`, an `input_length` '
'must be provided to `rnn`.')
axes = [1, 0] + list(range(2, ndim))
inputs = inputs.dimshuffle(axes)
@@ -516,45 +561,102 @@ def rnn(step_function, inputs, initial_states,
if constants is None:
constants = []
# build an all-zero tensor of shape (samples, output_dim)
initial_output = step_function(inputs[0], initial_states + constants)[0] * 0
# Theano gets confused by broadcasting patterns in the scan op
initial_output = T.unbroadcast(initial_output, 0, 1)
def _step(input, mask, output_tm1, *states):
output, new_states = step_function(input, states)
# output previous output if masked.
output = T.switch(mask, output, output_tm1)
return_states = []
for state, new_state in zip(states, new_states):
return_states.append(T.switch(mask, new_state, state))
return [output] + return_states
if unroll:
indices = list(range(input_length))
if go_backwards:
indices = indices[::-1]
results, _ = theano.scan(
_step,
sequences=[inputs, mask],
outputs_info=[initial_output] + initial_states,
non_sequences=constants,
go_backwards=go_backwards)
successive_outputs = []
successive_states = []
states = initial_states
for i in indices:
output, new_states = step_function(inputs[i], states)
if len(successive_outputs) == 0:
prev_output = zeros_like(output)
else:
prev_output = successive_outputs[-1]
output = T.switch(mask[i], output, prev_output)
kept_states = []
for state, new_state in zip(states, new_states):
kept_states.append(T.switch(mask[i], new_state, state))
states = kept_states
successive_outputs.append(output)
successive_states.append(states)
outputs = T.stack(*successive_outputs)
states = []
for i in range(len(successive_states[-1])):
states.append(T.stack(*[states_at_step[i] for states_at_step in successive_states]))
else:
# build an all-zero tensor of shape (samples, output_dim)
initial_output = step_function(inputs[0], initial_states + constants)[0] * 0
# Theano gets confused by broadcasting patterns in the scan op
initial_output = T.unbroadcast(initial_output, 0, 1)
def _step(input, mask, output_tm1, *states):
output, new_states = step_function(input, states)
# output previous output if masked.
output = T.switch(mask, output, output_tm1)
return_states = []
for state, new_state in zip(states, new_states):
return_states.append(T.switch(mask, new_state, state))
return [output] + return_states
results, _ = theano.scan(
_step,
sequences=[inputs, mask],
outputs_info=[initial_output] + initial_states,
non_sequences=constants,
go_backwards=go_backwards)
# deal with Theano API inconsistency
if type(results) is list:
outputs = results[0]
states = results[1:]
else:
outputs = results
states = []
else:
def _step(input, *states):
output, new_states = step_function(input, states)
return [output] + new_states
if unroll:
indices = list(range(input_length))
if go_backwards:
indices = indices[::-1]
results, _ = theano.scan(
_step,
sequences=inputs,
outputs_info=[None] + initial_states,
non_sequences=constants,
go_backwards=go_backwards)
successive_outputs = []
successive_states = []
states = initial_states
for i in indices:
output, states = step_function(inputs[i], states)
successive_outputs.append(output)
successive_states.append(states)
outputs = T.stack(*successive_outputs)
states = []
for i in range(len(successive_states[-1])):
states.append(T.stack(*[states_at_step[i] for states_at_step in successive_states]))
# deal with Theano API inconsistency
if type(results) is list:
outputs = results[0]
states = results[1:]
else:
outputs = results
states = []
else:
def _step(input, *states):
output, new_states = step_function(input, states)
return [output] + new_states
results, _ = theano.scan(
_step,
sequences=inputs,
outputs_info=[None] + initial_states,
non_sequences=constants,
go_backwards=go_backwards)
# deal with Theano API inconsistency
if type(results) is list:
outputs = results[0]
states = results[1:]
else:
outputs = results
states = []
outputs = T.squeeze(outputs)
last_output = outputs[-1]
@@ -571,6 +673,18 @@ def switch(condition, then_expression, else_expression):
return T.switch(condition, then_expression, else_expression)
def in_train_phase(x, alt):
x = T.switch(_LEARNING_PHASE, x, alt)
x._uses_learning_phase = True
return x
def in_test_phase(x, alt):
x = T.switch(_LEARNING_PHASE, alt, x)
x._uses_learning_phase = True
return x
# NN OPERATIONS
def relu(x, alpha=0., max_value=None):
@@ -603,6 +717,13 @@ def categorical_crossentropy(output, target, from_logits=False):
return T.nnet.categorical_crossentropy(output, target)
def sparse_categorical_crossentropy(output, target, from_logits=False):
target = T.cast(T.flatten(target), 'int32')
target = T.extra_ops.to_one_hot(target, nb_class=output.shape[-1])
target = reshape(target, shape(output))
return categorical_crossentropy(output, target, from_logits)
def binary_crossentropy(output, target, from_logits=False):
if from_logits:
output = T.nnet.sigmoid(output)
@@ -645,7 +766,6 @@ def l2_normalize(x, axis):
def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th',
image_shape=None, filter_shape=None):
'''
Run on cuDNN if available.
border_mode: string, "same" or "valid".
'''
if dim_ordering not in {'th', 'tf'}:
@@ -667,52 +787,39 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th',
filter_shape = (filter_shape[3], filter_shape[2],
filter_shape[0], filter_shape[1])
if _on_gpu() and dnn.dnn_available():
if border_mode == 'same':
np_kernel = kernel.eval()
assert strides[0] <= np_kernel.shape[2], 'strides should be smaller than the convolution window.'
assert strides[1] <= np_kernel.shape[3], 'strides should be smaller than the convolution window.'
conv_out = dnn.dnn_conv(img=x,
kerns=kernel,
border_mode='full')
shift_x = (np_kernel.shape[2] - strides[0]) // 2
shift_y = (np_kernel.shape[3] - strides[1]) // 2
expected_width = (x.shape[2] + strides[0] - 1) // strides[0]
expected_height = (x.shape[3] + strides[1] - 1) // strides[1]
conv_out = conv_out[:, :,
shift_x: shift_x + expected_width,
shift_y: shift_y + expected_height]
else:
conv_out = dnn.dnn_conv(img=x,
kerns=kernel,
border_mode=border_mode,
subsample=strides)
if border_mode == 'same':
th_border_mode = 'half'
np_kernel = kernel.eval()
elif border_mode == 'valid':
th_border_mode = 'valid'
else:
if border_mode == 'same':
th_border_mode = 'full'
np_kernel = kernel.eval()
assert strides[0] <= np_kernel.shape[2], 'strides should be smaller than the convolution window.'
assert strides[1] <= np_kernel.shape[3], 'strides should be smaller than the convolution window.'
elif border_mode == 'valid':
th_border_mode = 'valid'
else:
raise Exception('Border mode not supported: ' + str(border_mode))
raise Exception('Border mode not supported: ' + str(border_mode))
conv_out = T.nnet.conv.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
image_shape=image_shape,
filter_shape=filter_shape)
if border_mode == 'same':
shift_x = (np_kernel.shape[2] - strides[0]) // 2
shift_y = (np_kernel.shape[3] - strides[1]) // 2
expected_width = (x.shape[2] + strides[0] - 1) // strides[0]
expected_height = (x.shape[3] + strides[1] - 1) // strides[1]
# Theano might not accept long type
def int_or_none(value):
try:
return int(value)
except TypeError:
return None
if image_shape is not None:
image_shape = tuple(int_or_none(v) for v in image_shape)
if filter_shape is not None:
filter_shape = tuple(int_or_none(v) for v in filter_shape)
conv_out = T.nnet.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
input_shape=image_shape,
filter_shape=filter_shape)
if border_mode == 'same':
if np_kernel.shape[2] % 2 == 0:
conv_out = conv_out[:, :, :(x.shape[2] + strides[0] - 1) // strides[0], :]
if np_kernel.shape[3] % 2 == 0:
conv_out = conv_out[:, :, :, :(x.shape[3] + strides[1] - 1) // strides[1]]
conv_out = conv_out[:, :,
shift_x: shift_x + expected_width,
shift_y: shift_y + expected_height]
if dim_ordering == 'tf':
conv_out = conv_out.dimshuffle((0, 2, 3, 1))
return conv_out
+11 -23
Ver Arquivo
@@ -448,23 +448,15 @@ class TensorBoard(Callback):
self.model = model
self.sess = KTF.get_session()
if self.histogram_freq and not self.merged:
mod_type = self.model.get_config()['name']
if mod_type == 'Sequential':
layers = {l.get_config()['name']: l for l in self.model.layers}
elif mod_type == 'Graph':
layers = self.model.nodes
else:
raise Exception('Unrecognized model:',
self.model.get_config()['name'])
for l in layers:
cur_layer = layers[l]
if hasattr(cur_layer, 'W'):
tf.histogram_summary('{}_W'.format(l), cur_layer.W)
if hasattr(cur_layer, 'b'):
tf.histogram_summary('{}_b'.format(l), cur_layer.b)
if hasattr(cur_layer, 'get_output'):
tf.histogram_summary('{}_out'.format(l),
cur_layer.get_output())
layers = self.model.layers
for layer in layers:
if hasattr(layer, 'W'):
tf.histogram_summary('{}_W'.format(layer), layer.W)
if hasattr(layer, 'b'):
tf.histogram_summary('{}_b'.format(layer), layer.b)
if hasattr(layer, 'output'):
tf.histogram_summary('{}_out'.format(layer),
layer.output)
self.merged = tf.merge_all_summaries()
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph_def)
@@ -474,14 +466,10 @@ class TensorBoard(Callback):
if self.model.validation_data and self.histogram_freq:
if epoch % self.histogram_freq == 0:
if self.params.get('show_accuracy'):
test_function = self.model._test_with_acc
else:
test_function = self.model._test
names = [v.name for v in test_function.inputs]
# TODO: implement batched calls to sess.run
# (current call will likely go OOM on GPU)
feed_dict = dict(zip(names, self.model.validation_data))
feed_dict = dict(zip(self.model.inputs,
self.model.validation_data))
result = self.sess.run([self.merged], feed_dict=feed_dict)
summary_str = result[0]
self.writer.add_summary(summary_str, epoch)
+8 -10
Ver Arquivo
@@ -7,7 +7,7 @@ class Constraint(object):
return p
def get_config(self):
return {"name": self.__class__.__name__}
return {'name': self.__class__.__name__}
class MaxNorm(Constraint):
@@ -42,9 +42,9 @@ class MaxNorm(Constraint):
return p
def get_config(self):
return {"name": self.__class__.__name__,
"m": self.m,
"axis": self.axis}
return {'name': self.__class__.__name__,
'm': self.m,
'axis': self.axis}
class NonNeg(Constraint):
@@ -79,17 +79,15 @@ class UnitNorm(Constraint):
return p / (K.epsilon() + K.sqrt(K.sum(K.square(p), axis=self.axis, keepdims=True)))
def get_config(self):
return {"name": self.__class__.__name__,
"axis": self.axis}
return {'name': self.__class__.__name__,
'axis': self.axis}
identity = Constraint
maxnorm = MaxNorm
nonneg = NonNeg
unitnorm = UnitNorm
from .utils.generic_utils import get_from_module
def get(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'constraint', instantiate=True, kwargs=kwargs)
return get_from_module(identifier, globals(), 'constraint',
instantiate=True, kwargs=kwargs)
+4 -4
Ver Arquivo
@@ -60,10 +60,10 @@ def load_data(path="imdb.pkl", nb_words=None, skip_top=0,
nX.append(nx)
X = nX
X_train = X[:int(len(X) * (1 - test_split))]
y_train = labels[:int(len(X) * (1 - test_split))]
X_train = np.array(X[:int(len(X) * (1 - test_split))])
y_train = np.array(labels[:int(len(X) * (1 - test_split))])
X_test = X[int(len(X) * (1 - test_split)):]
y_test = labels[int(len(X) * (1 - test_split)):]
X_test = np.array(X[int(len(X) * (1 - test_split)):])
y_test = np.array(labels[int(len(X) * (1 - test_split)):])
return (X_train, y_train), (X_test, y_test)
+10
Ver Arquivo
@@ -0,0 +1,10 @@
# note: topology.Node is an internal class,
# it isn't meant to be used by Keras users.
from .topology import InputSpec
from .topology import Input
from .topology import InputLayer
from .topology import Layer
from .topology import Merge
from .topology import merge
from .topology import get_source_inputs
from .training import Model
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+2
Ver Arquivo
@@ -1,4 +1,5 @@
from __future__ import absolute_import
from ..engine import Layer, Input, InputLayer, Merge, merge, InputSpec
from .core import *
from .convolutional import *
from .recurrent import *
@@ -6,3 +7,4 @@ from .normalization import *
from .embeddings import *
from .noise import *
from .advanced_activations import *
from .wrappers import *
+90 -111
Ver Arquivo
@@ -1,13 +1,14 @@
from .. import initializations
from ..layers.core import MaskedLayer
from ..engine import Layer
from .. import backend as K
import numpy as np
class LeakyReLU(MaskedLayer):
class LeakyReLU(Layer):
'''Special version of a Rectified Linear Unit
that allows a small gradient when the unit is not active:
`f(x) = alpha*x for x < 0`.
`f(x) = alpha * x for x < 0`,
`f(x) = x for x >= 0`.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
@@ -21,22 +22,25 @@ class LeakyReLU(MaskedLayer):
alpha: float >= 0. Negative slope coefficient.
'''
def __init__(self, alpha=0.3, **kwargs):
super(LeakyReLU, self).__init__(**kwargs)
self.supports_masking = True
self.alpha = alpha
super(LeakyReLU, self).__init__(**kwargs)
def get_output(self, train):
X = self.get_input(train)
return K.relu(X, alpha=self.alpha)
def call(self, x, mask=None):
return K.relu(x, alpha=self.alpha)
def get_config(self):
config = {'name': self.__class__.__name__,
'alpha': self.alpha}
config = {'alpha': self.alpha}
base_config = super(LeakyReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class PReLU(MaskedLayer):
'''
class PReLU(Layer):
'''Parametric Rectified Linear Unit:
`f(x) = alphas * x for x < 0`,
`f(x) = x for x >= 0`,
where `alphas` is a learned array with the same shape as x.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
(tuple of integers, does not include the samples axis)
@@ -45,21 +49,21 @@ class PReLU(MaskedLayer):
# Output shape
Same shape as the input.
# Arguments:
# Arguments
init: initialization function for the weights.
weights: initial weights, as a list of a single numpy array.
# References:
# References
- [Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](http://arxiv.org/pdf/1502.01852v1.pdf)
'''
def __init__(self, init='zero', weights=None, **kwargs):
self.supports_masking = True
self.init = initializations.get(init)
self.initial_weights = weights
super(PReLU, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape[1:]
self.alphas = self.init(input_shape,
def build(self, input_shape):
self.alphas = self.init(input_shape[1:],
name='{}_alphas'.format(self.name))
self.trainable_weights = [self.alphas]
@@ -67,21 +71,22 @@ class PReLU(MaskedLayer):
self.set_weights(self.initial_weights)
del self.initial_weights
def get_output(self, train):
X = self.get_input(train)
pos = K.relu(X)
neg = self.alphas * (X - abs(X)) * 0.5
def call(self, x, mask=None):
pos = K.relu(x)
neg = self.alphas * (x - abs(x)) * 0.5
return pos + neg
def get_config(self):
config = {'name': self.__class__.__name__,
'init': self.init.__name__}
config = {'init': self.init.__name__}
base_config = super(PReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class ELU(MaskedLayer):
'''
class ELU(Layer):
'''Exponential Linear Unit:
`f(x) = alpha * (exp(x) - 1.) for x < 0`,
`f(x) = x for x >= 0`.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
(tuple of integers, does not include the samples axis)
@@ -97,24 +102,24 @@ class ELU(MaskedLayer):
- [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)](http://arxiv.org/pdf/1511.07289v1.pdf)
'''
def __init__(self, alpha=1.0, **kwargs):
self.supports_masking = True
self.alpha = K.cast_to_floatx(alpha)
super(ELU, self).__init__(**kwargs)
self.alpha = alpha
def get_output(self, train):
X = self.get_input(train)
pos = K.relu(X)
neg = (X - abs(X)) * 0.5
def call(self, x, mask=None):
pos = K.relu(x)
neg = (x - abs(x)) * 0.5
return pos + self.alpha * (K.exp(neg) - 1.)
def get_config(self):
config = {'name': self.__class__.__name__,
'alpha': self.alpha}
config = {'alpha': self.alpha}
base_config = super(ELU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class ParametricSoftplus(MaskedLayer):
'''Parametric Softplus of the form: alpha * log(1 + exp(beta * X))
class ParametricSoftplus(Layer):
'''Parametric Softplus:
`alpha * log(1 + exp(beta * x))`
# Input shape
Arbitrary. Use the keyword argument `input_shape`
@@ -129,18 +134,19 @@ class ParametricSoftplus(MaskedLayer):
beta_init: float. Initial values of the beta weights.
weights: initial weights, as a list of 2 numpy arrays.
# References:
# References
- [Inferring Nonlinear Neuronal Computation Based on Physiologically Plausible Inputs](http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1003143)
'''
def __init__(self, alpha_init=0.2, beta_init=5.0,
weights=None, **kwargs):
self.alpha_init = alpha_init
self.beta_init = beta_init
self.supports_masking = True
self.alpha_init = K.cast_to_floatx(alpha_init)
self.beta_init = K.cast_to_floatx(beta_init)
self.initial_weights = weights
super(ParametricSoftplus, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape[1:]
def build(self, input_shape):
input_shape = input_shape[1:]
self.alphas = K.variable(self.alpha_init * np.ones(input_shape),
name='{}_alphas'.format(self.name))
self.betas = K.variable(self.beta_init * np.ones(input_shape),
@@ -151,20 +157,20 @@ class ParametricSoftplus(MaskedLayer):
self.set_weights(self.initial_weights)
del self.initial_weights
def get_output(self, train):
X = self.get_input(train)
return K.softplus(self.betas * X) * self.alphas
def call(self, x, mask=None):
return K.softplus(self.betas * x) * self.alphas
def get_config(self):
config = {'name': self.__class__.__name__,
'alpha_init': self.alpha_init,
config = {'alpha_init': self.alpha_init,
'beta_init': self.beta_init}
base_config = super(ParametricSoftplus, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class ThresholdedLinear(MaskedLayer):
'''Thresholded Linear Activation.
class ThresholdedReLU(Layer):
'''Thresholded Rectified Linear Unit:
`f(x) = x for x > theta`
`f(x) = 0 otherwise`.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
@@ -178,57 +184,24 @@ class ThresholdedLinear(MaskedLayer):
theta: float >= 0. Threshold location of activation.
# References
[Zero-Bias Autoencoders and the Benefits of Co-Adapting Features](http://arxiv.org/pdf/1402.3337.pdf)
'''
def __init__(self, theta=1.0, **kwargs):
super(ThresholdedLinear, self).__init__(**kwargs)
self.theta = theta
def get_output(self, train):
X = self.get_input(train)
return K.switch(K.abs(X) < self.theta, 0, X)
def get_config(self):
config = {'name': self.__class__.__name__,
'theta': self.theta}
base_config = super(ThresholdedLinear, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class ThresholdedReLU(MaskedLayer):
'''Thresholded Rectified Activation.
# 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 the input.
# Arguments
theta: float >= 0. Threshold location of activation.
# References
[Zero-Bias Autoencoders and the Benefits of Co-Adapting Features](http://arxiv.org/pdf/1402.3337.pdf)
- [Zero-Bias Autoencoders and the Benefits of Co-Adapting Features](http://arxiv.org/pdf/1402.3337.pdf)
'''
def __init__(self, theta=1.0, **kwargs):
self.supports_masking = True
self.theta = K.cast_to_floatx(theta)
super(ThresholdedReLU, self).__init__(**kwargs)
self.theta = theta
def get_output(self, train):
X = self.get_input(train)
return K.switch(X > self.theta, X, 0)
def call(self, x, mask=None):
return x * K.cast(x > self.theta, K.floatx())
def get_config(self):
config = {'name': self.__class__.__name__,
'theta': self.theta}
config = {'theta': self.theta}
base_config = super(ThresholdedReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class SReLU(MaskedLayer):
'''SReLU
class SReLU(Layer):
'''S-shaped Rectified Linear Unit.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
@@ -245,43 +218,49 @@ class SReLU(MaskedLayer):
a_right_init: initialization function for the right part slope
# References
[Deep Learning with S-shaped Rectified Linear Activation Units](http://arxiv.org/abs/1512.07030)
- [Deep Learning with S-shaped Rectified Linear Activation Units](http://arxiv.org/abs/1512.07030)
'''
def __init__(self, t_left_init='zero', a_left_init='glorot_uniform',
t_right_init='glorot_uniform', a_right_init='one', **kwargs):
self.t_left_init = initializations.get(t_left_init)
self.a_left_init = initializations.get(a_left_init)
self.t_right_init = initializations.get(t_right_init)
self.a_right_init = initializations.get(a_right_init)
self.supports_masking = True
self.t_left_init = t_left_init
self.a_left_init = a_left_init
self.t_right_init = t_right_init
self.a_right_init = a_right_init
super(SReLU, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape[1:]
self.t_left = self.t_left_init(input_shape,
name='{}_t_left'.format(self.name))
self.a_left = self.a_left_init(input_shape,
name='{}_a_left'.format(self.name))
self.t_right = self.t_right_init(input_shape,
name='{}_t_right'.format(self.name))
self.a_right = self.a_right_init(input_shape,
name='{}_a_right'.format(self.name))
def build(self, input_shape):
input_shape = input_shape[1:]
t_left_init = initializations.get(self.t_left_init)
a_left_init = initializations.get(self.a_left_init)
t_right_init = initializations.get(self.t_right_init)
a_right_init = initializations.get(self.a_right_init)
self.t_left = t_left_init(input_shape,
name='{}_t_left'.format(self.name))
self.a_left = a_left_init(input_shape,
name='{}_a_left'.format(self.name))
self.t_right = t_right_init(input_shape,
name='{}_t_right'.format(self.name))
self.a_right = a_right_init(input_shape,
name='{}_a_right'.format(self.name))
# ensure the the right part is always to the right of the left
self.t_right_actual = self.t_left + abs(self.t_right)
self.trainable_weights = [self.t_left, self.a_left,
self.t_right, self.a_right]
def get_output(self, train=False):
X = self.get_input(train)
Y_left_and_center = self.t_left + K.relu(X - self.t_left,
def call(self, x, mask=None):
Y_left_and_center = self.t_left + K.relu(x - self.t_left,
self.a_left,
self.t_right_actual - self.t_left)
Y_right = K.relu(X - self.t_right_actual) * self.a_right
Y_right = K.relu(x - self.t_right_actual) * self.a_right
return Y_left_and_center + Y_right
def get_config(self):
return {'name': self.__class__.__name__,
'input_shape': self.input_shape,
't_left_init': self.t_left_init,
'a_left_init': self.a_left_init,
't_right_init': self.t_right_init,
'a_right_init': self.a_right_init}
config = {'t_left_init': self.t_left_init,
'a_left_init': self.a_left_init,
't_right_init': self.t_right_init,
'a_right_init': self.a_right_init}
base_config = super(SReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
-616
Ver Arquivo
@@ -1,616 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import print_function
from collections import OrderedDict
from .. import backend as K
from ..layers.core import Layer, Merge, Siamese, SiameseHead
from six.moves import range
class Sequential(Layer):
'''The Sequential container is a linear stack of layers.
Apart from the `add` methods and the `layers` constructor argument,
the API is identical to that of the `Layer` class.
This class is also the basis for the `keras.models.Sequential` model.
# Arguments
layers: list of layers to be added to the container.
'''
def __init__(self, layers=[]):
self.layers = []
self.layer_cache = {}
self.shape_cache = {}
for layer in layers:
self.add(layer)
self._cache_enabled = True
@property
def cache_enabled(self):
return self._cache_enabled
@cache_enabled.setter
def cache_enabled(self, value):
self._cache_enabled = value
for l in self.layers:
l.cache_enabled = value
@property
def layer_cache(self):
return super(Sequential, self).layer_cache
@layer_cache.setter
def layer_cache(self, value):
self._layer_cache = value
for layer in self.layers:
layer.layer_cache = self._layer_cache
@property
def shape_cache(self):
return super(Sequential, self).shape_cache
@shape_cache.setter
def shape_cache(self, value):
self._shape_cache = value
for layer in self.layers:
layer.shape_cache = self._shape_cache
def set_previous(self, layer, reset_weights=True):
self.layers[0].set_previous(layer, reset_weights)
def clear_previous(self, reset_weights=True):
self.layers[0].clear_previous(reset_weights)
def add(self, layer):
layer.layer_cache = self.layer_cache
layer.shape_cache = self.shape_cache
self.layers.append(layer)
if len(self.layers) > 1:
self.layers[-1].set_previous(self.layers[-2])
if not hasattr(self.layers[0], 'input'):
self.set_input()
@property
def trainable_weights(self):
weights = []
for l in self.layers:
if l.trainable:
weights += l.get_params()[0]
return weights
@property
def regularizers(self):
regularizers = []
for l in self.layers:
if l.trainable:
regularizers += l.get_params()[1]
return regularizers
@property
def constraints(self):
constraints = []
for l in self.layers:
if l.trainable:
constraints += l.get_params()[2]
return constraints
@property
def updates(self):
updates = []
for l in self.layers:
if l.trainable:
updates += l.get_params()[3]
return updates
@property
def state_updates(self):
"""
Return the `updates` from all layers in the sequence that are
stateful. This is useful for separating _training_ updates and
_prediction_ updates for when we need to update a layers internal state
during a stateful prediction.
"""
state_updates = []
for l in self.layers:
if getattr(l, 'stateful', False):
state_updates += l.get_params()[3]
return state_updates
def reset_states(self):
for l in self.layers:
if hasattr(l, 'reset_states') and getattr(l, 'stateful', False):
l.reset_states()
@property
def output_shape(self):
return self.layers[-1].output_shape
def get_output(self, train=False):
return self.layers[-1].get_output(train)
def set_input(self):
for l in self.layers:
if hasattr(l, 'input'):
ndim = K.ndim(l.input)
self.layers[0].input = K.placeholder(ndim=ndim)
break
def get_input(self, train=False):
if not hasattr(self.layers[0], 'input'):
self.set_input()
return self.layers[0].get_input(train)
@property
def input_shape(self):
return self.layers[0].input_shape
@property
def input(self):
return self.get_input()
def get_weights(self):
weights = []
for layer in self.layers:
weights += layer.get_weights()
return weights
def set_weights(self, weights):
for layer in self.layers:
nb_param = len(layer.get_weights())
layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
def get_config(self):
return {'name': self.__class__.__name__,
'layers': [layer.get_config() for layer in self.layers]}
def count_params(self):
return sum([layer.count_params() for layer in self.layers])
class Graph(Layer):
'''Implement a NN graph with arbitrary layer connections,
arbitrary number of inputs and arbitrary number of outputs.
This class is also the basis for the `keras.models.Graph` model.
Note: `Graph` can only be used as a layer
(connect, input, get_input, get_output)
when it has exactly one input and one output.
'''
def __init__(self):
self.namespace = set() # strings
self.nodes = OrderedDict() # layer-like
self.inputs = {} # layer-like
self.input_order = [] # strings
self.outputs = {} # layer-like
self.output_order = [] # strings
self.input_config = [] # dicts
self.output_config = [] # dicts
self.node_config = [] # dicts
self.layer_cache = {}
self.shape_cache = {}
self._cache_enabled = True
def __call__(self, X, mask=None, train=False):
if type(X) != dict:
return super(Graph, self).__call__(X, mask, train)
else:
# turn off layer cache temporarily
tmp_cache_enabled = self.cache_enabled
self.cache_enabled = False
# create a temporary layer for each input
tmp_previous = {}
for name, input in self.inputs.items():
layer = Layer(batch_input_shape=input.input_shape)
layer.input = X[name]
if hasattr(self, 'get_input_mask'):
layer.get_input_mask = lambda _: mask[name]
# set temporary previous
if hasattr(input, 'previous'):
tmp_previous[name] = input.previous
input.set_previous(layer, False)
Y = self.get_output(train=train)
# return previous to what it was
for name, input in self.inputs.items():
if name in tmp_previous:
input.set_previous(tmp_previous[name], False)
else:
input.clear_previous(False)
self.cache_enabled = tmp_cache_enabled
return Y
@property
def cache_enabled(self):
return self._cache_enabled
@cache_enabled.setter
def cache_enabled(self, value):
self._cache_enabled = value
for l in self.nodes.values():
l.cache_enabled = value
for l in self.inputs.values():
l.cache_enabled = value
@property
def layer_cache(self):
return super(Graph, self).layer_cache
@layer_cache.setter
def layer_cache(self, value):
self._layer_cache = value
for layer in self.nodes.values():
layer.layer_cache = self._layer_cache
for layer in self.inputs.values():
layer.layer_cache = self._layer_cache
@property
def shape_cache(self):
return super(Graph, self).shape_cache
@shape_cache.setter
def shape_cache(self, value):
self._shape_cache = value
for layer in self.nodes.values():
layer.shape_cache = self._shape_cache
for layer in self.inputs.values():
layer.shape_cache = self._shape_cache
@property
def nb_input(self):
return len(self.inputs)
@property
def nb_output(self):
return len(self.outputs)
@property
def trainable_weights(self):
weights = []
for l in self.nodes.values():
if l.trainable:
weights += l.get_params()[0]
return weights
@property
def regularizers(self):
regularizers = []
for l in self.nodes.values():
if l.trainable:
regularizers += l.get_params()[1]
return regularizers
@property
def constraints(self):
constraints = []
for l in self.nodes.values():
if l.trainable:
constraints += l.get_params()[2]
return constraints
@property
def updates(self):
updates = []
for l in self.nodes.values():
if l.trainable:
updates += l.get_params()[3]
return updates
@property
def state_updates(self):
"""
Return the `updates` from all nodes in that graph for nodes that are
stateful. This is useful for separating _training_ updates and
_prediction_ updates for when we need to update a layers internal state
during a stateful prediction.
"""
state_updates = []
for l in self.nodes.values():
if getattr(l, 'stateful', False):
state_updates += l.get_params()[3]
return state_updates
def reset_states(self):
for l in self.nodes.values():
if hasattr(l, 'reset_states') and getattr(l, 'stateful', False):
l.reset_states()
def set_previous(self, layer, connection_map={}, reset_weights=True):
if self.nb_input != layer.nb_output:
raise Exception('Cannot connect layers: '
'input count does not match output count.')
if self.nb_input == 1:
self.inputs[self.input_order[0]].set_previous(layer, reset_weights)
else:
if not connection_map:
raise Exception('Cannot attach multi-input layer: '
'no connection_map provided.')
for k, v in connection_map.items():
if k in self.inputs and v in layer.outputs:
self.inputs[k].set_previous(layer.outputs[v], reset_weights)
else:
raise Exception('Invalid connection map.')
def clear_previous(self, reset_weights=True):
for k in self.inputs.values():
k.clear_previous(reset_weights)
@property
def input_shape(self):
if self.nb_input == 1:
# return tuple
return self.inputs[self.input_order[0]].input_shape
else:
# return dictionary mapping input names to shape tuples
return dict([(k, v.input_shape) for k, v in self.inputs.items()])
def get_input(self, train=False):
if len(self.inputs) == len(self.outputs) == 1:
return self.inputs[self.input_order[0]].get_input(train)
else:
return dict([(k, v.get_input(train)) for k, v in self.inputs.items()])
@property
def input(self):
return self.get_input()
@property
def output_shape(self):
if self.nb_output == 1:
# return tuple
return self.outputs[self.output_order[0]].output_shape
else:
# return dictionary mapping output names to shape tuples
return dict([(k, v.output_shape) for k, v in self.outputs.items()])
def get_output(self, train=False):
if len(self.inputs) == len(self.outputs) == 1:
return self.outputs[self.output_order[0]].get_output(train)
else:
return dict([(k, v.get_output(train)) for k, v in self.outputs.items()])
def add_input(self, name, input_shape=None,
batch_input_shape=None, dtype='float'):
'''Add an input to the graph.
# Arguments:
name: string. The name of the new input. Must be unique in the graph.
input_shape: a tuple of integers, the expected shape of the input samples.
Does not include the batch size.
batch_input_shape: a tuple of integers, the expected shape of the
whole input batch, including the batch size.
dtype: 'float' or 'int'.
'''
if name in self.namespace:
raise Exception('Duplicate node identifier: ' + name)
self.namespace.add(name)
self.input_order.append(name)
layer = Layer(name=name) # empty layer
if input_shape:
layer.set_input_shape((None,) + tuple(input_shape))
elif batch_input_shape:
layer.set_input_shape(batch_input_shape)
if dtype == 'float':
layer.input = K.placeholder(shape=layer.input_shape, name=name)
else:
if (input_shape and len(input_shape) == 1) or (batch_input_shape and len(batch_input_shape) == 2):
layer.input = K.placeholder(shape=layer.input_shape,
dtype='int32',
name=name)
else:
raise Exception('Type "int" can only be used with ndim==2 (Embedding).')
self.inputs[name] = layer
config = {'name': name, 'dtype': dtype}
if batch_input_shape:
config['batch_input_shape'] = batch_input_shape
else:
config['input_shape'] = input_shape
self.input_config.append(config)
def add_node(self, layer, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1, dot_axes=-1,
create_output=False):
'''Add a node in the graph. It can be connected to multiple
inputs, which will first be merged into one tensor
according to the mode specified.
# Arguments
layer: the layer at the node.
name: name for the node.
input: when connecting the layer to a single input,
this is the name of the incoming node.
inputs: when connecting the layer to multiple inputs,
this is a list of names of incoming nodes.
merge_mode: one of {concat, sum, dot, ave, mul}
concat_axis: when `merge_mode=='concat'`, this is the
input concatenation axis.
dot_axes: when `merge_mode='dot'`, this is the contraction axes
specification; see the `Merge layer for details.
create_output: boolean. Set this to `True` if you want the output
of your node to be an output of the graph.
'''
if name in self.namespace:
raise Exception('Duplicate node identifier: ' + name)
layer.name = name
if input:
if input not in self.namespace:
raise Exception('Unknown node/input identifier: ' + input)
if input in self.nodes:
layer.set_previous(self.nodes[input])
elif input in self.inputs:
layer.set_previous(self.inputs[input])
if inputs:
to_merge = []
for n in inputs:
if n in self.nodes:
to_merge.append(self.nodes[n])
elif n in self.inputs:
to_merge.append(self.inputs[n])
else:
raise Exception('Unknown identifier: ' + n)
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes)
layer.set_previous(merge)
self.namespace.add(name)
layer.layer_cache = self.layer_cache
layer.shape_cache = self.shape_cache
self.nodes[name] = layer
self.node_config.append({'name': name,
'input': input,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'create_output': create_output})
if create_output:
self.add_output(name, input=name)
def add_shared_node(self, layer, name, inputs=[], merge_mode=None,
concat_axis=-1, dot_axes=-1, outputs=[],
create_output=False):
'''Used to share a same layer across multiple nodes.
Supposed, for instance, that you want to apply one same `Dense`
layer after to the output of two different nodes.
You can then add the `Dense` layer as a shared node.
# Arguments
layer: The layer to be shared across multiple inputs
name: Name of the shared node
inputs: List of names of input nodes
merge_mode: Same meaning as `merge_mode` argument of `add_node()`
concat_axis: Same meaning as `concat_axis` argument of `add_node()`
dot_axes: Same meaning as `dot_axes` argument of `add_node()`
outputs: Used when `merge_mode=None`. Names for the output nodes.
create_output: Same meaning as `create_output` argument of `add_node()`.
'''
if name in self.namespace:
raise Exception('Duplicate node identifier: ' + name)
for o in outputs:
if o in self.namespace:
raise Exception('Duplicate node identifier: ' + o)
if merge_mode:
if merge_mode not in {'sum', 'ave', 'mul', 'dot', 'cos', 'concat', 'join'}:
raise Exception('Invalid merge mode')
layers = []
for i in range(len(inputs)):
input = inputs[i]
if input in self.nodes:
n = self.nodes[input]
if n.__class__.__name__ == 'Siamese':
if n.merge_mode is None:
for j in range(len(n.inputs)):
sh = SiameseHead(j)
sh.previous = n
layers.append(sh)
else:
layers.append(n)
else:
layers.append(n)
elif input in self.inputs:
n = self.inputs[input]
layers.append(n)
else:
raise Exception('Unknown identifier: ' + input)
s = Siamese(layer, layers, merge_mode,
concat_axis=concat_axis,
dot_axes=dot_axes,
is_graph=True)
self.namespace.add(name)
self.nodes[name] = s
self.node_config.append({'name': name,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'create_output': create_output if merge_mode else False})
if not merge_mode:
for i in range(len(outputs)):
sh = SiameseHead(i)
sh.previous = s
sh_name = outputs[i]
sh.name = sh_name
self.namespace.add(sh_name)
self.nodes[sh_name] = sh
self.node_config.append({'name': sh_name,
'inputs': [name],
'create_output': create_output})
if create_output:
self.add_output(sh_name, input=sh_name)
if create_output and merge_mode:
if merge_mode == 'join':
raise Exception('Output can not be of type OrderedDict')
self.add_output(name, input=name)
def add_output(self, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1, dot_axes=-1):
'''Add an output to the graph.
This output can merge several node outputs into a single output.
# Arguments
name: name of the output.
input: when connecting the layer to a single input,
this is the name of the incoming node.
inputs: when connecting the layer to multiple inputs,
this is a list of names of incoming nodes.
merge_mode: one of {concat, sum, dot, ave, mul}
concat_axis: when `merge_mode=='concat'`, this is the
input concatenation axis.
dot_axes: when `merge_mode='dot'`, this is the contraction axes
specification; see the `Merge layer for details.
'''
if name in self.output_order:
raise Exception('Duplicate output identifier: ' + name)
if input:
if input not in self.namespace:
raise Exception('Unknown node/input identifier: ' + input)
if input in self.nodes:
self.outputs[name] = self.nodes[input]
elif input in self.inputs:
self.outputs[name] = self.inputs[input]
if inputs:
to_merge = []
for n in inputs:
if n not in self.nodes:
raise Exception('Unknown identifier: ' + n)
to_merge.append(self.nodes[n])
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes)
self.outputs[name] = merge
self.output_order.append(name)
self.output_config.append({'name': name,
'input': input,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes})
def get_config(self):
return {'name': self.__class__.__name__,
'input_config': self.input_config,
'node_config': self.node_config,
'output_config': self.output_config,
'input_order': self.input_order,
'output_order': self.output_order,
'nodes': dict([(c['name'], self.nodes[c['name']].get_config()) for c in self.node_config])}
def count_params(self):
return sum([layer.count_params() for layer in self.nodes.values()])
def get_weights(self):
weights = []
for layer in self.nodes.values():
weights += layer.get_weights()
return weights
def set_weights(self, weights):
for layer in self.nodes.values():
nb_param = len(layer.get_weights())
layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
+230 -236
Ver Arquivo
@@ -3,7 +3,7 @@ from __future__ import absolute_import
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..layers.core import Layer
from ..engine import Layer, InputSpec
def conv_output_length(input_length, filter_size, border_mode, stride):
@@ -25,12 +25,19 @@ class Convolution1D(Layer):
or `input_shape` (tuple of integers, e.g. (10, 128) for sequences
of 10 vectors of 128-dimensional vectors).
# Input shape
3D tensor with shape: `(samples, steps, input_dim)`.
# Example
# Output shape
3D tensor with shape: `(samples, new_steps, nb_filter)`.
`steps` value might have changed due to padding.
```python
# apply a convolution 1d of length 3 to a sequence with 10 timesteps,
# with 64 output filters
model = Sequential()
model.add(Convolution1D(64, 3, border_mode='same', input_shape=(10, 32)))
# now model.output_shape == (None, 10, 64)
# add a new conv1d on top
model.add(Convolution1D(32, 3, border_mode='same'))
# now model.output_shape == (None, 10, 32)
```
# Arguments
nb_filter: Number of convolution kernels to use
@@ -65,9 +72,14 @@ class Convolution1D(Layer):
This argument is required if you are going to connect
`Flatten` then `Dense` layers upstream
(without it, the shape of the dense outputs cannot be computed).
'''
input_ndim = 3
# Input shape
3D tensor with shape: `(samples, steps, input_dim)`.
# Output shape
3D tensor with shape: `(samples, new_steps, nb_filter)`.
`steps` value might have changed due to padding.
'''
def __init__(self, nb_filter, filter_length,
init='uniform', activation='linear', weights=None,
border_mode='valid', subsample_length=1,
@@ -93,18 +105,17 @@ class Convolution1D(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.constraints = [self.W_constraint, self.b_constraint]
self.input_spec = [InputSpec(ndim=3)]
self.initial_weights = weights
self.input_dim = input_dim
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
super(Convolution1D, self).__init__(**kwargs)
def build(self):
input_dim = self.input_shape[2]
def build(self, input_shape):
input_dim = input_shape[2]
self.W_shape = (self.nb_filter, input_dim, self.filter_length, 1)
self.W = self.init(self.W_shape, name='{}_W'.format(self.name))
self.b = K.zeros((self.nb_filter,), name='{}_b'.format(self.name))
@@ -123,23 +134,27 @@ class Convolution1D(Layer):
self.activity_regularizer.set_layer(self)
self.regularizers.append(self.activity_regularizer)
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
@property
def output_shape(self):
length = conv_output_length(self.input_shape[1],
def get_output_shape_for(self, input_shape):
length = conv_output_length(input_shape[1],
self.filter_length,
self.border_mode,
self.subsample[0])
return (self.input_shape[0], length, self.nb_filter)
return (input_shape[0], length, self.nb_filter)
def get_output(self, train=False):
X = self.get_input(train)
X = K.expand_dims(X, -1) # add a dimension of the right
X = K.permute_dimensions(X, (0, 2, 1, 3))
conv_out = K.conv2d(X, self.W, strides=self.subsample,
def call(self, x, mask=None):
x = K.expand_dims(x, -1) # add a dimension of the right
x = K.permute_dimensions(x, (0, 2, 1, 3))
conv_out = K.conv2d(x, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering='th')
@@ -150,8 +165,7 @@ class Convolution1D(Layer):
return output
def get_config(self):
config = {'name': self.__class__.__name__,
'nb_filter': self.nb_filter,
config = {'nb_filter': self.nb_filter,
'filter_length': self.filter_length,
'init': self.init.__name__,
'activation': self.activation.__name__,
@@ -175,19 +189,18 @@ class Convolution2D(Layer):
(tuple of integers, does not include the sample axis),
e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures.
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Examples
# Output shape
4D tensor with shape:
`(samples, nb_filter, new_rows, new_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, new_rows, new_cols, nb_filter)` if dim_ordering='tf'.
`rows` and `cols` values might have changed due to padding.
```python
# apply a 3x3 convolution with 64 output filters on a 256x256 image:
model = Sequential()
model.add(Convolution2D(64, 3, 3, border_mode='same', input_shape=(3, 256, 256)))
# now model.output_shape == (None, 64, 256, 256)
# add a 3x3 convolution on top, with 32 output filters:
model.add(Convolution2D(32, 3, 3, border_mode='same'))
# now model.output_shape == (None, 32, 256, 256)
```
# Arguments
nb_filter: Number of convolution filters to use.
@@ -219,9 +232,20 @@ class Convolution2D(Layer):
applied to the bias.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
'''
input_ndim = 4
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Output shape
4D tensor with shape:
`(samples, nb_filter, new_rows, new_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, new_rows, new_cols, nb_filter)` if dim_ordering='tf'.
`rows` and `cols` values might have changed due to padding.
'''
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1), dim_ordering='th',
@@ -247,17 +271,17 @@ class Convolution2D(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.constraints = [self.W_constraint, self.b_constraint]
self.input_spec = [InputSpec(ndim=4)]
self.initial_weights = weights
super(Convolution2D, self).__init__(**kwargs)
def build(self):
def build(self, input_shape):
if self.dim_ordering == 'th':
stack_size = self.input_shape[1]
stack_size = input_shape[1]
self.W_shape = (self.nb_filter, stack_size, self.nb_row, self.nb_col)
elif self.dim_ordering == 'tf':
stack_size = self.input_shape[3]
stack_size = input_shape[3]
self.W_shape = (self.nb_row, self.nb_col, stack_size, self.nb_filter)
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
@@ -278,13 +302,17 @@ class Convolution2D(Layer):
self.activity_regularizer.set_layer(self)
self.regularizers.append(self.activity_regularizer)
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
rows = input_shape[2]
cols = input_shape[3]
@@ -306,12 +334,10 @@ class Convolution2D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
conv_out = K.conv2d(X, self.W, strides=self.subsample,
def call(self, x, mask=None):
conv_out = K.conv2d(x, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering,
image_shape=self.input_shape,
filter_shape=self.W_shape)
if self.dim_ordering == 'th':
output = conv_out + K.reshape(self.b, (1, self.nb_filter, 1, 1))
@@ -323,8 +349,7 @@ class Convolution2D(Layer):
return output
def get_config(self):
config = {'name': self.__class__.__name__,
'nb_filter': self.nb_filter,
config = {'nb_filter': self.nb_filter,
'nb_row': self.nb_row,
'nb_col': self.nb_col,
'init': self.init.__name__,
@@ -350,19 +375,6 @@ class Convolution3D(Layer):
Note: this layer will only work with Theano for the time being.
# Input shape
5D tensor with shape:
`(samples, channels, conv_dim1, conv_dim2, conv_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, conv_dim1, conv_dim2, conv_dim3, channels)` if dim_ordering='tf'.
# Output shape
5D tensor with shape:
`(samples, nb_filter, new_conv_dim1, new_conv_dim2, new_conv_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, new_conv_dim1, new_conv_dim2, new_conv_dim3, nb_filter)` if dim_ordering='tf'.
`new_conv_dim1`, `new_conv_dim2` and `new_conv_dim3` values might have changed due to padding.
# Arguments
nb_filter: Number of convolution filters to use.
kernel_dim1: Length of the first dimension in the covolution kernel.
@@ -395,8 +407,20 @@ class Convolution3D(Layer):
applied to the bias.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
# Input shape
5D tensor with shape:
`(samples, channels, conv_dim1, conv_dim2, conv_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, conv_dim1, conv_dim2, conv_dim3, channels)` if dim_ordering='tf'.
# Output shape
5D tensor with shape:
`(samples, nb_filter, new_conv_dim1, new_conv_dim2, new_conv_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, new_conv_dim1, new_conv_dim2, new_conv_dim3, nb_filter)` if dim_ordering='tf'.
`new_conv_dim1`, `new_conv_dim2` and `new_conv_dim3` values might have changed due to padding.
'''
input_ndim = 5
def __init__(self, nb_filter, kernel_dim1, kernel_dim2, kernel_dim3,
init='glorot_uniform', activation='linear', weights=None,
@@ -426,19 +450,21 @@ class Convolution3D(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.constraints = [self.W_constraint, self.b_constraint]
self.input_spec = [InputSpec(ndim=5)]
self.initial_weights = weights
super(Convolution3D, self).__init__(**kwargs)
def build(self):
def build(self, input_shape):
assert len(input_shape) == 5
self.input_spec = [InputSpec(shape=input_shape)]
if self.dim_ordering == 'th':
stack_size = self.input_shape[1]
stack_size = input_shape[1]
self.W_shape = (self.nb_filter, stack_size,
self.kernel_dim1, self.kernel_dim2, self.kernel_dim3)
elif self.dim_ordering == 'tf':
stack_size = self.input_shape[4]
stack_size = input_shape[4]
self.W_shape = (self.kernel_dim1, self.kernel_dim2, self.kernel_dim3,
stack_size, self.nb_filter)
else:
@@ -461,13 +487,17 @@ class Convolution3D(Layer):
self.activity_regularizer.set_layer(self)
self.regularizers.append(self.activity_regularizer)
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
conv_dim1 = input_shape[2]
conv_dim2 = input_shape[3]
@@ -493,12 +523,12 @@ class Convolution3D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
conv_out = K.conv3d(X, self.W, strides=self.subsample,
def call(self, x, mask=None):
input_shape = self.input_spec[0].shape
conv_out = K.conv3d(x, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering,
volume_shape=self.input_shape,
volume_shape=input_shape,
filter_shape=self.W_shape)
if self.dim_ordering == 'th':
@@ -511,8 +541,7 @@ class Convolution3D(Layer):
return output
def get_config(self):
config = {"name": self.__class__.__name__,
"nb_filter": self.nb_filter,
config = {"nb_filter": self.nb_filter,
"kernel_dim1": self.kernel_dim1,
"kernel_dim2": self.kernel_dim2,
"kernel_dim3": self.kernel_dim3,
@@ -546,10 +575,9 @@ class _Pooling1D(Layer):
self.pool_size = (pool_length, 1)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
self.input_spec = [InputSpec(ndim=3)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
length = conv_output_length(input_shape[1], self.pool_length,
self.border_mode, self.stride)
return (input_shape[0], length, input_shape[2])
@@ -558,11 +586,10 @@ class _Pooling1D(Layer):
border_mode, dim_ordering):
raise NotImplementedError
def get_output(self, train=False):
X = self.get_input(train)
X = K.expand_dims(X, -1) # add dummy last dimension
X = K.permute_dimensions(X, (0, 2, 1, 3))
output = self._pooling_function(inputs=X, pool_size=self.pool_size,
def call(self, x, mask=None):
x = K.expand_dims(x, -1) # add dummy last dimension
x = K.permute_dimensions(x, (0, 2, 1, 3))
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.st,
border_mode=self.border_mode,
dim_ordering='th')
@@ -570,8 +597,7 @@ class _Pooling1D(Layer):
return K.squeeze(output, 3) # remove dummy last dimension
def get_config(self):
config = {'name': self.__class__.__name__,
'stride': self.stride,
config = {'stride': self.stride,
'pool_length': self.pool_length,
'border_mode': self.border_mode}
base_config = super(_Pooling1D, self).get_config()
@@ -609,17 +635,17 @@ class MaxPooling1D(_Pooling1D):
class AveragePooling1D(_Pooling1D):
'''Average pooling for temporal data.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
3D tensor with shape: `(samples, downsampled_steps, features)`.
# Arguments
pool_length: factor by which to downscale. 2 will halve the input.
stride: integer or None. Stride value.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
3D tensor with shape: `(samples, downsampled_steps, features)`.
'''
def __init__(self, pool_length=2, stride=None,
@@ -637,7 +663,6 @@ class AveragePooling1D(_Pooling1D):
class _Pooling2D(Layer):
'''Abstract class for different pooling 2D layers.
'''
input_ndim = 4
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
@@ -650,10 +675,9 @@ class _Pooling2D(Layer):
self.border_mode = border_mode
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=4)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
rows = input_shape[2]
cols = input_shape[3]
@@ -679,17 +703,15 @@ class _Pooling2D(Layer):
border_mode, dim_ordering):
raise NotImplementedError
def get_output(self, train=False):
X = self.get_input(train)
output = self._pooling_function(inputs=X, pool_size=self.pool_size,
def call(self, x, mask=None):
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.strides,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
return output
def get_config(self):
config = {'name': self.__class__.__name__,
'pool_size': self.pool_size,
config = {'pool_size': self.pool_size,
'border_mode': self.border_mode,
'strides': self.strides,
'dim_ordering': self.dim_ordering}
@@ -700,6 +722,16 @@ class _Pooling2D(Layer):
class MaxPooling2D(_Pooling2D):
'''Max pooling operation for spatial data.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
@@ -711,16 +743,6 @@ class MaxPooling2D(_Pooling2D):
`(nb_samples, channels, pooled_rows, pooled_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, pooled_rows, pooled_cols, channels)` if dim_ordering='tf'.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
@@ -738,6 +760,16 @@ class MaxPooling2D(_Pooling2D):
class AveragePooling2D(_Pooling2D):
'''Average pooling operation for spatial data.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
@@ -749,16 +781,6 @@ class AveragePooling2D(_Pooling2D):
`(nb_samples, channels, pooled_rows, pooled_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, pooled_rows, pooled_cols, channels)` if dim_ordering='tf'.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
@@ -776,7 +798,6 @@ class AveragePooling2D(_Pooling2D):
class _Pooling3D(Layer):
'''Abstract class for different pooling 3D layers.
'''
input_ndim = 5
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
@@ -789,10 +810,9 @@ class _Pooling3D(Layer):
self.border_mode = border_mode
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
len_dim1 = input_shape[2]
len_dim2 = input_shape[3]
@@ -822,17 +842,15 @@ class _Pooling3D(Layer):
border_mode, dim_ordering):
raise NotImplementedError
def get_output(self, train=False):
X = self.get_input(train)
output = self._pooling_function(inputs=X, pool_size=self.pool_size,
def call(self, x, mask=None):
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.strides,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
return output
def get_config(self):
config = {'name': self.__class__.__name__,
'pool_size': self.pool_size,
config = {'pool_size': self.pool_size,
'border_mode': self.border_mode,
'strides': self.strides,
'dim_ordering': self.dim_ordering}
@@ -845,6 +863,15 @@ class MaxPooling3D(_Pooling3D):
Note: this layer will only work with Theano for the time being.
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
# Input shape
5D tensor with shape:
`(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
@@ -856,15 +883,6 @@ class MaxPooling3D(_Pooling3D):
`(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)` if dim_ordering='tf'.
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
@@ -887,6 +905,15 @@ class AveragePooling3D(_Pooling3D):
Note: this layer will only work with Theano for the time being.
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
# Input shape
5D tensor with shape:
`(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
@@ -898,15 +925,6 @@ class AveragePooling3D(_Pooling3D):
`(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)` if dim_ordering='tf'.
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
@@ -927,34 +945,30 @@ class AveragePooling3D(_Pooling3D):
class UpSampling1D(Layer):
'''Repeat each temporal step `length` times along the time axis.
# Arguments
length: integer. Upsampling factor.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
3D tensor with shape: `(samples, upsampled_steps, features)`.
# Arguments:
length: integer. Upsampling factor.
'''
input_ndim = 3
def __init__(self, length=2, **kwargs):
super(UpSampling1D, self).__init__(**kwargs)
self.length = length
self.input_spec = [InputSpec(ndim=3)]
super(UpSampling1D, self).__init__(**kwargs)
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.length * input_shape[1], input_shape[2])
def get_output(self, train=False):
X = self.get_input(train)
output = K.repeat_elements(X, self.length, axis=1)
def call(self, x, mask=None):
output = K.repeat_elements(x, self.length, axis=1)
return output
def get_config(self):
config = {'name': self.__class__.__name__,
'length': self.length}
config = {'length': self.length}
base_config = super(UpSampling1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -963,6 +977,12 @@ class UpSampling2D(Layer):
'''Repeat the rows and columns of the data
by size[0] and size[1] respectively.
# Arguments
size: tuple of 2 integers. The upsampling factors for rows and columns.
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 3.
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
@@ -974,24 +994,16 @@ class UpSampling2D(Layer):
`(samples, channels, upsampled_rows, upsampled_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, upsampled_rows, upsampled_cols, channels)` if dim_ordering='tf'.
# Arguments
size: tuple of 2 integers. The upsampling factors for rows and columns.
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 3.
'''
input_ndim = 4
def __init__(self, size=(2, 2), dim_ordering='th', **kwargs):
super(UpSampling2D, self).__init__(**kwargs)
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=4)]
super(UpSampling2D, self).__init__(**kwargs)
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
return (input_shape[0],
input_shape[1],
@@ -1005,14 +1017,12 @@ class UpSampling2D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
return K.resize_images(X, self.size[0], self.size[1],
def call(self, x, mask=None):
return K.resize_images(x, self.size[0], self.size[1],
self.dim_ordering)
def get_config(self):
config = {'name': self.__class__.__name__,
'size': self.size}
config = {'size': self.size}
base_config = super(UpSampling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -1023,6 +1033,12 @@ class UpSampling3D(Layer):
Note: this layer will only work with Theano for the time being.
# Arguments
size: tuple of 3 integers. The upsampling factors for dim1, dim2 and dim3.
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 4.
# Input shape
5D tensor with shape:
`(samples, channels, dim1, dim2, dim3)` if dim_ordering='th'
@@ -1034,27 +1050,19 @@ class UpSampling3D(Layer):
`(samples, channels, upsampled_dim1, upsampled_dim2, upsampled_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, upsampled_dim1, upsampled_dim2, upsampled_dim3, channels)` if dim_ordering='tf'.
# Arguments
size: tuple of 3 integers. The upsampling factors for dim1, dim2 and dim3.
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 4.
'''
input_ndim = 5
def __init__(self, size=(2, 2, 2), dim_ordering='th', **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
super(UpSampling3D, self).__init__(**kwargs)
' is currently only working with Theano backend.')
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
super(UpSampling3D, self).__init__(**kwargs)
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
return (input_shape[0],
input_shape[1],
@@ -1070,14 +1078,12 @@ class UpSampling3D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
return K.resize_volumes(X, self.size[0], self.size[1], self.size[2],
def call(self, x, mask=None):
return K.resize_volumes(x, self.size[0], self.size[1], self.size[2],
self.dim_ordering)
def get_config(self):
config = {'name': self.__class__.__name__,
'size': self.size}
config = {'size': self.size}
base_config = super(UpSampling3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -1085,38 +1091,34 @@ class UpSampling3D(Layer):
class ZeroPadding1D(Layer):
'''Zero-padding layer for 1D input (e.g. temporal sequence).
# Arguments
padding: int
How many zeros to add at the beginning and end of
the padding dimension (axis 1).
# Input shape
3D tensor with shape (samples, axis_to_pad, features)
# Output shape
3D tensor with shape (samples, padded_axis, features)
# Arguments
padding: int
How many zeros to add at the beginning and end of
the padding dimension (axis 1).
'''
input_ndim = 3
def __init__(self, padding=1, **kwargs):
super(ZeroPadding1D, self).__init__(**kwargs)
self.padding = padding
self.input_spec = [InputSpec(ndim=3)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
length = input_shape[1] + self.padding * 2 if input_shape[1] is not None else None
return (input_shape[0],
length,
input_shape[2])
def get_output(self, train=False):
X = self.get_input(train)
return K.temporal_padding(X, padding=self.padding)
def call(self, x, mask=None):
return K.temporal_padding(x, padding=self.padding)
def get_config(self):
config = {'name': self.__class__.__name__,
'padding': self.padding}
config = {'padding': self.padding}
base_config = super(ZeroPadding1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -1124,6 +1126,11 @@ class ZeroPadding1D(Layer):
class ZeroPadding2D(Layer):
'''Zero-padding layer for 2D input (e.g. picture).
# Arguments
padding: tuple of int (length 2)
How many zeros to add at the beginning and end of
the 2 padding dimensions (axis 3 and 4).
# Input shape
4D tensor with shape:
(samples, depth, first_axis_to_pad, second_axis_to_pad)
@@ -1131,23 +1138,16 @@ class ZeroPadding2D(Layer):
# Output shape
4D tensor with shape:
(samples, depth, first_padded_axis, second_padded_axis)
# Arguments
padding: tuple of int (length 2)
How many zeros to add at the beginning and end of
the 2 padding dimensions (axis 3 and 4).
'''
input_ndim = 4
def __init__(self, padding=(1, 1), dim_ordering='th', **kwargs):
super(ZeroPadding2D, self).__init__(**kwargs)
self.padding = tuple(padding)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=4)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
width = input_shape[2] + 2 * self.padding[0] if input_shape[2] is not None else None
height = input_shape[3] + 2 * self.padding[1] if input_shape[3] is not None else None
@@ -1165,14 +1165,12 @@ class ZeroPadding2D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
return K.spatial_2d_padding(X, padding=self.padding,
def call(self, x, mask=None):
return K.spatial_2d_padding(x, padding=self.padding,
dim_ordering=self.dim_ordering)
def get_config(self):
config = {'name': self.__class__.__name__,
'padding': self.padding}
config = {'padding': self.padding}
base_config = super(ZeroPadding2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -1182,6 +1180,11 @@ class ZeroPadding3D(Layer):
Note: this layer will only work with Theano for the time being.
# Arguments
padding: tuple of int (length 3)
How many zeros to add at the beginning and end of
the 3 padding dimensions (axis 3, 4 and 5).
# Input shape
5D tensor with shape:
(samples, depth, first_axis_to_pad, second_axis_to_pad, third_axis_to_pad)
@@ -1189,13 +1192,7 @@ class ZeroPadding3D(Layer):
# Output shape
5D tensor with shape:
(samples, depth, first_padded_axis, second_padded_axis, third_axis_to_pad)
# Arguments
padding: tuple of int (length 3)
How many zeros to add at the beginning and end of
the 3 padding dimensions (axis 3, 4 and 5).
'''
input_ndim = 5
def __init__(self, padding=(1, 1, 1), dim_ordering='th', **kwargs):
if K._BACKEND != 'theano':
@@ -1205,10 +1202,9 @@ class ZeroPadding3D(Layer):
self.padding = tuple(padding)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
dim1 = input_shape[2] + 2 * self.padding[0] if input_shape[2] is not None else None
dim2 = input_shape[3] + 2 * self.padding[1] if input_shape[3] is not None else None
@@ -1230,13 +1226,11 @@ class ZeroPadding3D(Layer):
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
return K.spatial_3d_padding(X, padding=self.padding,
def call(self, x, mask=None):
return K.spatial_3d_padding(x, padding=self.padding,
dim_ordering=self.dim_ordering)
def get_config(self):
config = {'name': self.__class__.__name__,
'padding': self.padding}
config = {'padding': self.padding}
base_config = super(ZeroPadding3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+578 -1572
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+47 -33
Ver Arquivo
@@ -2,7 +2,7 @@ from __future__ import absolute_import
from .. import backend as K
from .. import initializations, regularizers, constraints
from ..layers.core import Layer
from ..engine import Layer
class Embedding(Layer):
@@ -11,11 +11,21 @@ class Embedding(Layer):
This layer can only be used as the first layer in a model.
# Input shape
2D tensor with shape: `(nb_samples, sequence_length)`.
# Example
# Output shape
3D tensor with shape: `(nb_samples, sequence_length, output_dim)`.
```python
model = Sequential()
model.add(Embedding(1000, 64, input_length=10))
# the model will take as input an integer matrix of size (batch, input_length).
# the largest integer (i.e. word index) in the input should be no larger than 1000 (vocabulary size).
# now model.output_shape == (None, 10, 64), where None is the batch dimension.
input_array = np.random.randint(1000, size=(32, 10))
model.compile('rmsprop', 'mse')
output_array = model.predict(input_array)
assert output_array.shape == (32, 10, 64)
```
# Arguments
input_dim: int >= 0. Size of the vocabulary, ie.
@@ -42,6 +52,12 @@ class Embedding(Layer):
(without it, the shape of the dense outputs cannot be computed).
dropout: float between 0 and 1. Fraction of the embeddings to drop.
# Input shape
2D tensor with shape: `(nb_samples, sequence_length)`.
# Output shape
3D tensor with shape: `(nb_samples, sequence_length, output_dim)`.
# References
- [A Theoretically Grounded Application of Dropout in Recurrent Neural Networks](http://arxiv.org/abs/1512.05287)
'''
@@ -66,13 +82,14 @@ class Embedding(Layer):
self.W_regularizer = regularizers.get(W_regularizer)
self.activity_regularizer = regularizers.get(activity_regularizer)
if 0. < self.dropout < 1.:
self.uses_learning_phase = True
self.initial_weights = weights
kwargs['input_shape'] = (self.input_dim,)
kwargs['input_shape'] = (self.input_length,)
kwargs['input_dtype'] = 'int32'
super(Embedding, self).__init__(**kwargs)
def build(self):
self.input = K.placeholder(shape=(self.input_shape[0], self.input_length),
dtype='int32')
def build(self, input_shape):
self.W = self.init((self.input_dim, self.output_dim),
name='{}_W'.format(self.name))
self.trainable_weights = [self.W]
@@ -88,38 +105,35 @@ class Embedding(Layer):
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
def get_output_mask(self, train=None):
X = self.get_input(train)
def compute_mask(self, x, mask=None):
if not self.mask_zero:
return None
else:
return K.not_equal(X, 0)
return K.not_equal(x, 0)
@property
def output_shape(self):
return (self.input_shape[0], self.input_length, self.output_dim)
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.input_length, self.output_dim)
def get_output(self, train=False):
X = self.get_input(train)
retain_p = 1. - self.dropout
if train and self.dropout > 0:
B = K.random_binomial((self.input_dim,), p=retain_p)
def call(self, x, mask=None):
if 0. < self.dropout < 1.:
retain_p = 1. - self.dropout
B = K.random_binomial((self.input_dim,), p=retain_p) * (1. / retain_p)
B = K.expand_dims(B)
W = K.in_train_phase(self.W * B, self.W)
else:
B = K.ones((self.input_dim)) * retain_p
# we zero-out rows of W at random
out = K.gather(self.W * K.expand_dims(B), X)
W = self.W
out = K.gather(W, x)
return out
def get_config(self):
config = {"name": self.__class__.__name__,
"input_dim": self.input_dim,
"output_dim": self.output_dim,
"init": self.init.__name__,
"input_length": self.input_length,
"mask_zero": self.mask_zero,
"activity_regularizer": self.activity_regularizer.get_config() if self.activity_regularizer else None,
"W_regularizer": self.W_regularizer.get_config() if self.W_regularizer else None,
"W_constraint": self.W_constraint.get_config() if self.W_constraint else None,
"dropout": self.dropout}
config = {'input_dim': self.input_dim,
'output_dim': self.output_dim,
'init': self.init.__name__,
'input_length': self.input_length,
'mask_zero': self.mask_zero,
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'dropout': self.dropout}
base_config = super(Embedding, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+52 -46
Ver Arquivo
@@ -1,9 +1,9 @@
from __future__ import absolute_import
from .core import MaskedLayer
from ..engine import Layer
from .. import backend as K
class GaussianNoise(MaskedLayer):
class GaussianNoise(Layer):
'''Apply to the input an additive zero-centred gaussian noise with
standard deviation `sigma`. This is useful to mitigate overfitting
(you could see it as a kind of random data augmentation).
@@ -12,6 +12,44 @@ class GaussianNoise(MaskedLayer):
As it is a regularization layer, it is only active at training time.
# Arguments
sigma: float, standard deviation of the noise distribution.
# 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.
'''
def __init__(self, sigma, **kwargs):
self.supports_masking = True
self.sigma = sigma
self.uses_learning_phase = True
super(GaussianNoise, self).__init__(**kwargs)
def call(self, x, mask=None):
noise_x = x + K.random_normal(shape=K.shape(x),
mean=0.,
std=self.sigma)
return K.in_train_phase(noise_x, x)
def get_config(self):
config = {'sigma': self.sigma}
base_config = super(GaussianNoise, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class GaussianDropout(Layer):
'''Apply to the input an multiplicative one-centred gaussian noise
with standard deviation `sqrt(p/(1-p))`.
As it is a regularization layer, it is only active at training time.
# Arguments
p: float, drop probability (as with `Dropout`).
# Input shape
Arbitrary. Use the keyword argument `input_shape`
(tuple of integers, does not include the samples axis)
@@ -20,56 +58,24 @@ class GaussianNoise(MaskedLayer):
# Output shape
Same shape as input.
# Arguments
sigma: float, standard deviation of the noise distribution.
'''
def __init__(self, sigma, **kwargs):
super(GaussianNoise, self).__init__(**kwargs)
self.sigma = sigma
def get_output(self, train=False):
X = self.get_input(train)
if not train or self.sigma == 0:
return X
else:
return X + K.random_normal(shape=K.shape(X),
mean=0.,
std=self.sigma)
def get_config(self):
config = {"name": self.__class__.__name__,
"sigma": self.sigma}
base_config = super(GaussianNoise, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class GaussianDropout(MaskedLayer):
'''Apply to the input an multiplicative one-centred gaussian noise
with standard deviation `sqrt(p/(1-p))`.
As it is a regularization layer, it is only active at training time.
# Arguments
p: float, drop probability (as with `Dropout`).
# References:
# References
[Dropout: A Simple Way to Prevent Neural Networks from Overfitting Srivastava, Hinton, et al. 2014](http://www.cs.toronto.edu/~rsalakhu/papers/srivastava14a.pdf)
'''
def __init__(self, p, **kwargs):
super(GaussianDropout, self).__init__(**kwargs)
self.supports_masking = True
self.p = p
if 0 < p < 1:
self.uses_learning_phase = True
super(GaussianDropout, self).__init__(**kwargs)
def get_output(self, train):
X = self.get_input(train)
if train:
# self.p refers to drop probability rather than
# retain probability (as in paper), for consistency
X *= K.random_normal(shape=K.shape(X), mean=1.0,
std=K.sqrt(self.p / (1.0 - self.p)))
return X
def call(self, x, mask=None):
if 0 < self.p < 1:
noise_x = x * K.random_normal(shape=K.shape(x), mean=1.0,
std=K.sqrt(self.p / (1.0 - self.p)))
return K.in_train_phase(noise_x, x)
return x
def get_config(self):
config = {"name": self.__class__.__name__,
"p": self.p}
config = {'p': self.p}
base_config = super(GaussianDropout, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+44 -37
Ver Arquivo
@@ -1,4 +1,4 @@
from ..layers.core import Layer
from ..engine import Layer, InputSpec
from .. import initializations
from .. import backend as K
@@ -8,14 +8,6 @@ class BatchNormalization(Layer):
i.e. applies a transformation that maintains the mean activation
close to 0 and the activation standard deviation close to 1.
# 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.
# Arguments
epsilon: small float > 0. Fuzz parameter.
mode: integer, 0 or 1.
@@ -45,6 +37,15 @@ class BatchNormalization(Layer):
[initializations](../initializations.md)), or alternatively,
Theano/TensorFlow function to use for weights initialization.
This parameter is only relevant if you don't pass a `weights` argument.
# 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
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](http://arxiv.org/pdf/1502.03167v3.pdf)
'''
@@ -57,10 +58,11 @@ class BatchNormalization(Layer):
self.axis = axis
self.momentum = momentum
self.initial_weights = weights
self.uses_learning_phase = True
super(BatchNormalization, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape # starts with samples axis
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
shape = (input_shape[self.axis],)
self.gamma = self.gamma_init(shape, name='{}_gamma'.format(self.name))
@@ -77,41 +79,46 @@ class BatchNormalization(Layer):
self.set_weights(self.initial_weights)
del self.initial_weights
def get_output(self, train):
X = self.get_input(train)
def call(self, x, mask=None):
if self.mode == 0:
input_shape = self.input_shape
input_shape = self.input_spec[0].shape
reduction_axes = list(range(len(input_shape)))
del reduction_axes[self.axis]
broadcast_shape = [1] * len(input_shape)
broadcast_shape[self.axis] = input_shape[self.axis]
if train:
m = K.mean(X, axis=reduction_axes)
brodcast_m = K.reshape(m, broadcast_shape)
std = K.mean(K.square(X - brodcast_m) + self.epsilon, axis=reduction_axes)
std = K.sqrt(std)
brodcast_std = K.reshape(std, broadcast_shape)
mean_update = self.momentum * self.running_mean + (1-self.momentum) * m
std_update = self.momentum * self.running_std + (1-self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
X_normed = (X - brodcast_m) / (brodcast_std + self.epsilon)
else:
brodcast_m = K.reshape(self.running_mean, broadcast_shape)
brodcast_std = K.reshape(self.running_std, broadcast_shape)
X_normed = ((X - brodcast_m) /
(brodcast_std + self.epsilon))
out = K.reshape(self.gamma, broadcast_shape) * X_normed + K.reshape(self.beta, broadcast_shape)
# case: train mode (uses stats of the current batch)
mean = K.mean(x, axis=reduction_axes)
brodcast_mean = K.reshape(mean, broadcast_shape)
std = K.mean(K.square(x - brodcast_mean) + self.epsilon, axis=reduction_axes)
std = K.sqrt(std)
brodcast_std = K.reshape(std, broadcast_shape)
mean_update = self.momentum * self.running_mean + (1-self.momentum) * mean
std_update = self.momentum * self.running_std + (1-self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
x_normed = (x - brodcast_mean) / (brodcast_std + self.epsilon)
# case: test mode (uses running averages)
brodcast_running_mean = K.reshape(self.running_mean, broadcast_shape)
brodcast_running_std = K.reshape(self.running_std, broadcast_shape)
x_normed_running = ((x - brodcast_running_mean) / (brodcast_running_std + self.epsilon))
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
out = K.reshape(self.gamma, broadcast_shape) * x_normed + K.reshape(self.beta, broadcast_shape)
elif self.mode == 1:
m = K.mean(X, axis=-1, keepdims=True)
std = K.std(X, axis=-1, keepdims=True)
X_normed = (X - m) / (std + self.epsilon)
out = self.gamma * X_normed + self.beta
# sample-wise normalization
m = K.mean(x, axis=-1, keepdims=True)
std = K.std(x, axis=-1, keepdims=True)
x_normed = (x - m) / (std + self.epsilon)
out = self.gamma * x_normed + self.beta
return out
def get_config(self):
config = {"name": self.__class__.__name__,
"epsilon": self.epsilon,
config = {"epsilon": self.epsilon,
"mode": self.mode,
"axis": self.axis,
"momentum": self.momentum}
+226 -132
Ver Arquivo
@@ -4,7 +4,7 @@ import numpy as np
from .. import backend as K
from .. import activations, initializations, regularizers
from ..layers.core import MaskedLayer
from ..engine import Layer, InputSpec
def time_distributed_dense(x, w, b=None, dropout=None,
@@ -21,12 +21,12 @@ def time_distributed_dense(x, w, b=None, dropout=None,
# won't work with TensorFlow
output_dim = K.shape(w)[1]
if dropout:
if dropout is not None and 0. < dropout < 1.:
# apply the same dropout pattern at every timestep
ones = K.ones_like(K.reshape(x[:, 0, :], (-1, input_dim)))
dropout_matrix = K.dropout(ones, dropout)
expanded_dropout_matrix = K.repeat(dropout_matrix, timesteps)
x *= expanded_dropout_matrix
x = K.in_train_phase(x * expanded_dropout_matrix, x)
# collapse time dimension and batch dimension together
x = K.reshape(x, (-1, input_dim))
@@ -39,21 +39,31 @@ def time_distributed_dense(x, w, b=None, dropout=None,
return x
class Recurrent(MaskedLayer):
class Recurrent(Layer):
'''Abstract base class for recurrent layers.
Do not use in a model -- it's not a functional layer!
Do not use in a model -- it's not a valid layer!
Use its children classes `LSTM`, `GRU` and `SimpleRNN` instead.
All recurrent layers (GRU, LSTM, SimpleRNN) also
All recurrent layers (`LSTM`, `GRU`, `SimpleRNN`) also
follow the specifications of this class and accept
the keyword arguments listed below.
# Input shape
3D tensor with shape `(nb_samples, timesteps, input_dim)`.
# Example
# Output shape
- if `return_sequences`: 3D tensor with shape
`(nb_samples, timesteps, output_dim)`.
- else, 2D tensor with shape `(nb_samples, output_dim)`.
```python
# as the first layer in a Sequential model
model = Sequential()
model.add(LSTM(32, input_shape=(10, 64)))
# now model.output_shape == (None, 10, 32)
# note: `None` is the batch dimension.
# the following is identical:
model = Sequential()
model.add(LSTM(32, input_dim=64, input_length=10))
# for subsequent layers, not need to specify the input size:
model.add(LSTM(16))
```
# Arguments
weights: list of numpy arrays to set as initial weights.
@@ -66,6 +76,17 @@ class Recurrent(MaskedLayer):
stateful: Boolean (default False). If True, the last state
for each sample at index i in a batch will be used as initial
state for the sample of index i in the following batch.
unroll: Boolean (default False). If True, the network will be unrolled,
else a symbolic loop will be used. When using TensorFlow, the network
is always unrolled, so this argument does not do anything.
Unrolling can speed-up a RNN, although it tends to be more memory-intensive.
Unrolling is only suitable for short sequences.
consume_less: one of "cpu", "mem". If set to "cpu", the RNN will use
an implementation that uses fewer, larger matrix products,
thus running faster (at least on CPU) but consuming more memory.
If set to "mem", the RNN will use more matrix products,
but smaller ones, thus running slower (may actually be faster on GPU)
while consuming less memory.
input_dim: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
@@ -79,6 +100,14 @@ class Recurrent(MaskedLayer):
at the level of the first layer
(e.g. via the `input_shape` argument)
# Input shape
3D tensor with shape `(nb_samples, timesteps, input_dim)`.
# Output shape
- if `return_sequences`: 3D tensor with shape
`(nb_samples, timesteps, output_dim)`.
- else, 2D tensor with shape `(nb_samples, output_dim)`.
# Masking
This layer supports masking for input data with a variable number
of timesteps. To introduce masks to your data,
@@ -115,40 +144,41 @@ class Recurrent(MaskedLayer):
When using the TensorFlow backend, specify a fixed batch size for your model
following the notes on statefulness RNNs.
'''
input_ndim = 3
def __init__(self, weights=None,
return_sequences=False, go_backwards=False, stateful=False,
unroll=False, consume_less='cpu',
input_dim=None, input_length=None, **kwargs):
self.return_sequences = return_sequences
self.initial_weights = weights
self.go_backwards = go_backwards
self.stateful = stateful
self.unroll = unroll
self.consume_less = consume_less
self.supports_masking = True
self.input_spec = [InputSpec(ndim=3)]
self.input_dim = input_dim
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
super(Recurrent, self).__init__(**kwargs)
def get_output_mask(self, train=False):
if self.return_sequences:
return super(Recurrent, self).get_output_mask(train)
else:
return None
@property
def output_shape(self):
input_shape = self.input_shape
def get_output_shape_for(self, input_shape):
if self.return_sequences:
return (input_shape[0], input_shape[1], self.output_dim)
else:
return (input_shape[0], self.output_dim)
def compute_mask(self, input, mask):
if self.return_sequences:
return mask
else:
return None
def step(self, x, states):
raise NotImplementedError
def get_constants(self, x, train=False):
def get_constants(self, x):
return []
def get_initial_states(self, x):
@@ -160,38 +190,41 @@ class Recurrent(MaskedLayer):
initial_states = [initial_state for _ in range(len(self.states))]
return initial_states
def preprocess_input(self, x, train=False):
def preprocess_input(self, x):
return x
def get_output(self, train=False):
def call(self, x, mask=None):
# input shape: (nb_samples, time (padded with zeros), input_dim)
X = self.get_input(train)
mask = self.get_input_mask(train)
assert K.ndim(X) == 3
# note that the .build() method of subclasses MUST define
# self.input_sepc with a complete input shape.
input_shape = self.input_spec[0].shape
if K._BACKEND == 'tensorflow':
if not self.input_shape[1]:
raise Exception('When using TensorFlow, you should define ' +
'explicitly the number of timesteps of ' +
'your sequences.\n' +
'If your first layer is an Embedding, ' +
'make sure to pass it an "input_length" ' +
'argument. Otherwise, make sure ' +
'the first layer has ' +
'an "input_shape" or "batch_input_shape" ' +
'argument, including the time axis.')
if not input_shape[1]:
raise Exception('When using TensorFlow, you should define '
'explicitly the number of timesteps of '
'your sequences.\n'
'If your first layer is an Embedding, '
'make sure to pass it an "input_length" '
'argument. Otherwise, make sure '
'the first layer has '
'an "input_shape" or "batch_input_shape" '
'argument, including the time axis. '
'Found input shape at layer ' + self.name +
': ' + str(input_shape))
if self.stateful:
initial_states = self.states
else:
initial_states = self.get_initial_states(X)
constants = self.get_constants(X, train)
preprocessed_input = self.preprocess_input(X, train)
initial_states = self.get_initial_states(x)
constants = self.get_constants(x)
preprocessed_input = self.preprocess_input(x)
last_output, outputs, states = K.rnn(self.step, preprocessed_input,
initial_states,
go_backwards=self.go_backwards,
mask=mask,
constants=constants)
constants=constants,
unroll=self.unroll,
input_length=input_shape[1])
if self.stateful:
self.updates = []
for i in range(len(states)):
@@ -203,12 +236,13 @@ class Recurrent(MaskedLayer):
return last_output
def get_config(self):
config = {"name": self.__class__.__name__,
"return_sequences": self.return_sequences,
"go_backwards": self.go_backwards,
"stateful": self.stateful}
config = {'return_sequences': self.return_sequences,
'go_backwards': self.go_backwards,
'stateful': self.stateful,
'unroll': self.unroll,
'consume_less': self.consume_less}
if self.stateful:
config['batch_input_shape'] = self.input_shape
config['batch_input_shape'] = self.input_spec[0].shape
else:
config['input_dim'] = self.input_dim
config['input_length'] = self.input_length
@@ -254,10 +288,13 @@ class SimpleRNN(Recurrent):
self.U_regularizer = regularizers.get(U_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.dropout_W, self.dropout_U = dropout_W, dropout_U
if self.dropout_W or self.dropout_U:
self.uses_learning_phase = True
super(SimpleRNN, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
if self.stateful:
self.reset_states()
else:
@@ -277,10 +314,10 @@ class SimpleRNN(Recurrent):
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.U_regularizer:
self.W_regularizer.set_param(self.U)
self.U_regularizer.set_param(self.U)
self.regularizers.append(self.U_regularizer)
if self.b_regularizer:
self.W_regularizer.set_param(self.b)
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
self.trainable_weights = [self.W, self.U, self.b]
@@ -291,7 +328,7 @@ class SimpleRNN(Recurrent):
def reset_states(self):
assert self.stateful, 'Layer must be stateful.'
input_shape = self.input_shape
input_shape = self.input_spec[0].shape
if not input_shape[0]:
raise Exception('If a RNN is stateful, a complete ' +
'input_shape must be provided (including batch size).')
@@ -301,33 +338,49 @@ class SimpleRNN(Recurrent):
else:
self.states = [K.zeros((input_shape[0], self.output_dim))]
def preprocess_input(self, x, train=False):
if train and (0 < self.dropout_W < 1):
dropout = self.dropout_W
def preprocess_input(self, x):
if self.consume_less == 'cpu':
input_shape = self.input_spec[0].shape
input_dim = input_shape[2]
timesteps = input_shape[1]
return time_distributed_dense(x, self.W, self.b, self.dropout_W,
input_dim, self.output_dim,
timesteps)
else:
dropout = 0
input_shape = self.input_shape
input_dim = input_shape[2]
timesteps = input_shape[1]
return time_distributed_dense(x, self.W, self.b, dropout,
input_dim, self.output_dim, timesteps)
return x
def step(self, h, states):
def step(self, x, states):
prev_output = states[0]
if len(states) == 2:
B_U = states[1]
B_U = states[1]
B_W = states[2]
if self.consume_less == 'cpu':
h = x
else:
B_U = 1.
h = K.dot(x * B_W, self.W) + self.b
output = self.activation(h + K.dot(prev_output * B_U, self.U))
return output, [output]
def get_constants(self, x, train=False):
if train and (0 < self.dropout_U < 1):
def get_constants(self, x):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
B_U = K.dropout(ones, self.dropout_U)
return [B_U]
return []
B_U = K.in_train_phase(K.dropout(ones, self.dropout_U), ones)
constants.append(B_U)
else:
constants.append(K.cast_to_floatx(1.))
if self.consume_less == 'cpu' and 0 < self.dropout_W < 1:
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
B_W = K.in_train_phase(K.dropout(ones, self.dropout_W), ones)
constants.append(B_W)
else:
constants.append(K.cast_to_floatx(1.))
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
@@ -384,10 +437,13 @@ class GRU(Recurrent):
self.U_regularizer = regularizers.get(U_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.dropout_W, self.dropout_U = dropout_W, dropout_U
if self.dropout_W or self.dropout_U:
self.uses_learning_phase = True
super(GRU, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
input_dim = input_shape[2]
self.input_dim = input_dim
@@ -441,7 +497,7 @@ class GRU(Recurrent):
def reset_states(self):
assert self.stateful, 'Layer must be stateful.'
input_shape = self.input_shape
input_shape = self.input_spec[0].shape
if not input_shape[0]:
raise Exception('If a RNN is stateful, a complete ' +
'input_shape must be provided (including batch size).')
@@ -451,33 +507,35 @@ class GRU(Recurrent):
else:
self.states = [K.zeros((input_shape[0], self.output_dim))]
def preprocess_input(self, x, train=False):
if train and (0 < self.dropout_W < 1):
dropout = self.dropout_W
else:
dropout = 0
input_shape = self.input_shape
input_dim = input_shape[2]
timesteps = input_shape[1]
def preprocess_input(self, x):
if self.consume_less == 'cpu':
input_shape = self.input_spec[0].shape
input_dim = input_shape[2]
timesteps = input_shape[1]
x_z = time_distributed_dense(x, self.W_z, self.b_z, dropout,
input_dim, self.output_dim, timesteps)
x_r = time_distributed_dense(x, self.W_r, self.b_r, dropout,
input_dim, self.output_dim, timesteps)
x_h = time_distributed_dense(x, self.W_h, self.b_h, dropout,
input_dim, self.output_dim, timesteps)
return K.concatenate([x_z, x_r, x_h], axis=2)
x_z = time_distributed_dense(x, self.W_z, self.b_z, self.dropout_W,
input_dim, self.output_dim, timesteps)
x_r = time_distributed_dense(x, self.W_r, self.b_r, self.dropout_W,
input_dim, self.output_dim, timesteps)
x_h = time_distributed_dense(x, self.W_h, self.b_h, self.dropout_W,
input_dim, self.output_dim, timesteps)
return K.concatenate([x_z, x_r, x_h], axis=2)
else:
return x
def step(self, x, states):
h_tm1 = states[0] # previous memory
if len(states) == 2:
B_U = states[1] # dropout matrices for recurrent units
else:
B_U = [1., 1., 1.]
B_U = states[1] # dropout matrices for recurrent units
B_W = states[2]
x_z = x[:, :self.output_dim]
x_r = x[:, self.output_dim: 2 * self.output_dim]
x_h = x[:, 2 * self.output_dim:]
if self.consume_less == 'cpu':
x_z = x[:, :self.output_dim]
x_r = x[:, self.output_dim: 2 * self.output_dim]
x_h = x[:, 2 * self.output_dim:]
else:
x_z = K.dot(x * B_W[0], self.W_z) + self.b_z
x_r = K.dot(x * B_W[1], self.W_r) + self.b_r
x_h = K.dot(x * B_W[2], self.W_h) + self.b_h
z = self.inner_activation(x_z + K.dot(h_tm1 * B_U[0], self.U_z))
r = self.inner_activation(x_r + K.dot(h_tm1 * B_U[1], self.U_r))
@@ -486,13 +544,26 @@ class GRU(Recurrent):
h = z * h_tm1 + (1 - z) * hh
return h, [h]
def get_constants(self, x, train=False):
if train and (0 < self.dropout_U < 1):
def get_constants(self, x):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
B_U = [K.dropout(ones, self.dropout_U) for _ in range(3)]
return [B_U]
return []
constants.append(B_U)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
if self.consume_less == 'cpu' and 0 < self.dropout_W < 1:
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
B_W = [K.dropout(ones, self.dropout_W) for _ in range(3)]
constants.append(B_W)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
@@ -559,10 +630,13 @@ class LSTM(Recurrent):
self.U_regularizer = regularizers.get(U_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.dropout_W, self.dropout_U = dropout_W, dropout_U
if self.dropout_W or self.dropout_U:
self.uses_learning_phase = True
super(LSTM, self).__init__(**kwargs)
def build(self):
input_shape = self.input_shape
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
input_dim = input_shape[2]
self.input_dim = input_dim
@@ -628,7 +702,7 @@ class LSTM(Recurrent):
def reset_states(self):
assert self.stateful, 'Layer must be stateful.'
input_shape = self.input_shape
input_shape = self.input_spec[0].shape
if not input_shape[0]:
raise Exception('If a RNN is stateful, a complete ' +
'input_shape must be provided (including batch size).')
@@ -642,36 +716,43 @@ class LSTM(Recurrent):
K.zeros((input_shape[0], self.output_dim))]
def preprocess_input(self, x, train=False):
if train and (0 < self.dropout_W < 1):
dropout = self.dropout_W
else:
dropout = 0
input_shape = self.input_shape
input_dim = input_shape[2]
timesteps = input_shape[1]
if self.consume_less == 'cpu':
if train and (0 < self.dropout_W < 1):
dropout = self.dropout_W
else:
dropout = 0
input_shape = self.input_spec[0].shape
input_dim = input_shape[2]
timesteps = input_shape[1]
x_i = time_distributed_dense(x, self.W_i, self.b_i, dropout,
input_dim, self.output_dim, timesteps)
x_f = time_distributed_dense(x, self.W_f, self.b_f, dropout,
input_dim, self.output_dim, timesteps)
x_c = time_distributed_dense(x, self.W_c, self.b_c, dropout,
input_dim, self.output_dim, timesteps)
x_o = time_distributed_dense(x, self.W_o, self.b_o, dropout,
input_dim, self.output_dim, timesteps)
return K.concatenate([x_i, x_f, x_c, x_o], axis=2)
x_i = time_distributed_dense(x, self.W_i, self.b_i, dropout,
input_dim, self.output_dim, timesteps)
x_f = time_distributed_dense(x, self.W_f, self.b_f, dropout,
input_dim, self.output_dim, timesteps)
x_c = time_distributed_dense(x, self.W_c, self.b_c, dropout,
input_dim, self.output_dim, timesteps)
x_o = time_distributed_dense(x, self.W_o, self.b_o, dropout,
input_dim, self.output_dim, timesteps)
return K.concatenate([x_i, x_f, x_c, x_o], axis=2)
else:
return x
def step(self, x, states):
h_tm1 = states[0]
c_tm1 = states[1]
if len(states) == 3:
B_U = states[2]
else:
B_U = [1. for _ in range(4)]
B_U = states[2]
B_W = states[3]
x_i = x[:, :self.output_dim]
x_f = x[:, self.output_dim: 2 * self.output_dim]
x_c = x[:, 2 * self.output_dim: 3 * self.output_dim]
x_o = x[:, 3 * self.output_dim:]
if self.consume_less == 'cpu':
x_i = x[:, :self.output_dim]
x_f = x[:, self.output_dim: 2 * self.output_dim]
x_c = x[:, 2 * self.output_dim: 3 * self.output_dim]
x_o = x[:, 3 * self.output_dim:]
else:
x_i = K.dot(x * B_W[0], self.W_i) + self.b_i
x_f = K.dot(x * B_W[1], self.W_f) + self.b_f
x_c = K.dot(x * B_W[2], self.W_c) + self.b_c
x_o = K.dot(x * B_W[3], self.W_o) + self.b_o
i = self.inner_activation(x_i + K.dot(h_tm1 * B_U[0], self.U_i))
f = self.inner_activation(x_f + K.dot(h_tm1 * B_U[1], self.U_f))
@@ -681,13 +762,26 @@ class LSTM(Recurrent):
h = o * self.activation(c)
return h, [h, c]
def get_constants(self, x, train=False):
if train and (0 < self.dropout_U < 1):
def get_constants(self, x):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
B_U = [K.dropout(ones, self.dropout_U) for _ in range(4)]
return [B_U]
return []
constants.append(B_U)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
if self.consume_less == 'cpu' and 0 < self.dropout_W < 1:
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
B_W = [K.dropout(ones, self.dropout_W) for _ in range(4)]
constants.append(B_W)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
+75 -57
Ver Arquivo
@@ -1,8 +1,45 @@
from .core import MaskedLayer
from ..engine import Layer, InputSpec
from .. import backend as K
class TimeDistributed(MaskedLayer):
class Wrapper(Layer):
def __init__(self, layer, **kwargs):
self.layer = layer
super(Wrapper, self).__init__(**kwargs)
def build(self, input_shape=None):
'''Assumes that self.layer is already set.
Should be called at the end of .build() in the
children classes.
'''
self.trainable_weights = getattr(self.layer, 'trainable_weights', [])
self.non_trainable_weights = getattr(self.layer, 'non_trainable_weights', [])
self.updates = getattr(self.layer, 'updates', [])
self.regularizers = getattr(self.layer, 'regularizers', [])
self.constraints = getattr(self.layer, 'constraints', {})
def get_weights(self):
weights = self.layer.get_weights()
return weights
def set_weights(self, weights):
self.layer.set_weights(weights)
def get_config(self):
config = {'layer': {'class_name': self.layer.__class__.__name__,
'config': self.layer.get_config()}}
base_config = super(Wrapper, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@classmethod
def from_config(cls, config):
from keras.utils.layer_utils import layer_from_config
layer = layer_from_config(config.pop('layer'))
return cls(layer, **config)
class TimeDistributed(Wrapper):
"""This wrapper allows to apply a layer to every
temporal slice of an input.
@@ -16,8 +53,14 @@ class TimeDistributed(MaskedLayer):
You can then use `TimeDistributed` to apply a `Dense` layer to each of the 10 timesteps, independently:
```python
# as the first layer in a model
model = Sequential()
model.add(TimeDistributed(Dense(8), input_shape=(10, 16)))
# now model.output_shape == (None, 10, 8)
# subsequent layers: no need for input_shape
model.add(TimeDistributed(Dense(32)))
# now model.output_shape == (None, 10, 32)
```
The output will then have shape `(32, 10, 8)`.
@@ -35,80 +78,55 @@ class TimeDistributed(MaskedLayer):
# Arguments
layer: a layer instance.
"""
def __init__(self, layer, **kwargs):
self.layer = layer
super(TimeDistributed, self).__init__(**kwargs)
self.supports_masking = True
super(TimeDistributed, self).__init__(layer, **kwargs)
def build(self):
input_shape = self.input_shape
def build(self, input_shape):
assert len(input_shape) >= 3
self.input_spec = [InputSpec(shape=input_shape)]
if K._BACKEND == 'tensorflow':
if not input_shape[1]:
raise Exception('When using TensorFlow, you should define '
'explicitly the number of timesteps of '
'your sequences.\n'
'If your first layer is an Embedding, '
'make sure to pass it an "input_length" '
'argument. Otherwise, make sure '
'the first layer has '
'an "input_shape" or "batch_input_shape" '
'argument, including the time axis.')
child_input_shape = (input_shape[0],) + input_shape[2:]
self.layer.set_input_shape(child_input_shape)
self.layer.build()
self.layer.build(child_input_shape)
super(TimeDistributed, self).build()
trainable_weights, regularizers, constraints, updates = self.layer.get_params()
self.trainable_weights = trainable_weights
self.non_trainable_weights = self.layer.non_trainable_weights
self.regularizers = regularizers
self.constraints = constraints
self.updates = updates
@property
def output_shape(self):
child_output_shape = self.layer.output_shape
timesteps = self.input_shape[1]
def get_output_shape_for(self, input_shape):
child_input_shape = (input_shape[0],) + input_shape[2:]
child_output_shape = self.layer.get_output_shape_for(child_input_shape)
timesteps = input_shape[1]
return (child_output_shape[0], timesteps) + child_output_shape[1:]
def get_output(self, train=False):
X = self.get_input(train)
mask = self.get_input_mask(train)
if K._BACKEND == 'tensorflow':
if not self.input_shape[1]:
raise Exception('When using TensorFlow, you should define ' +
'explicitly the number of timesteps of ' +
'your sequences.\n' +
'If your first layer is an Embedding, ' +
'make sure to pass it an "input_length" ' +
'argument. Otherwise, make sure ' +
'the first layer has ' +
'an "input_shape" or "batch_input_shape" ' +
'argument, including the time axis.')
if self.input_shape[0]:
def call(self, X, mask=None):
input_shape = self.input_spec[0].shape
if input_shape[0]:
# batch size matters, use rnn-based implementation
def step(x, states):
output = self.layer(x, train=train)
output = self.layer.call(x)
return output, []
last_output, outputs, states = K.rnn(step, X,
initial_states=[],
mask=mask)
initial_states=[])
y = outputs
else:
# no batch size specified, therefore the layer will be able
# to process batches of any size
# we can go with reshape-based implementation for performance
input_shape = self.input_shape
x = K.reshape(X, (-1, ) + input_shape[2:]) # (nb_samples * timesteps, ...)
y = self.layer(x, train=False) # (nb_samples * timesteps, ...)
X = K.reshape(X, (-1, ) + input_shape[2:]) # (nb_samples * timesteps, ...)
y = self.layer.call(X) # (nb_samples * timesteps, ...)
input_length = input_shape[1]
if not input_length:
input_length = K.shape(X)[1]
# (nb_samples, timesteps, ...)
y = K.reshape(y, (-1, input_length) + self.layer.output_shape[1:])
output_shape = self.get_output_shape_for(input_shape)
y = K.reshape(y, (-1, input_length) + output_shape[2:])
return y
def get_weights(self):
weights = self.layer.get_weights()
return weights
def set_weights(self, weights):
self.layer.set_weights(weights)
def get_config(self):
config = {'name': self.__class__.__name__,
'layer': self.layer.get_config()}
base_config = super(TimeDistributed, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
Ver Arquivo
+768
Ver Arquivo
@@ -0,0 +1,768 @@
from collections import OrderedDict
import warnings
import copy
from .. import backend as K
from ..layers import InputLayer, Layer, Merge
from ..engine.training import Model
class Graph(Model):
'''Arbitrary connection graph.
THIS IS A LEGACY MODEL AND SHOULD NOT BE USED
except for backwards compatibility support.
For multi-inputs/multi-outputs models, or
models using shared layers, use the functional API instead.
'''
def __init__(self, name=None):
# model attributes
self.inbound_nodes = []
self.outbound_nodes = []
self.built = False
self.supports_masking = False
# legacy attributes (we prefix them with _graph_)
self._graph_namespace = set() # strings
self._graph_nodes = OrderedDict() # layer-like
self._graph_inputs = OrderedDict() # layer-like
self._graph_outputs = OrderedDict() # layer-like
self._graph_input_config = [] # dicts
self._graph_output_config = [] # dicts
self._graph_node_config = [] # dicts
self._graph_shared_nodes_names = []
if not name:
prefix = 'graph_'
name = prefix + str(K.get_uid(prefix))
self.name = name
def __call__(self, x, mask=None):
self.build()
return super(Graph, self).__call__(x, mask)
def build(self, input_shape=None):
# this will crash if the input/output layers have multiple nodes
# no plans to support that case since Graph is deprecated
input_tensors = [layer.output for layer in self._graph_inputs.values()]
output_tensors = [layer.output for layer in self._graph_outputs.values()]
# actually create the model
super(Graph, self).__init__(input_tensors,
output_tensors,
name=self.name)
self.built = True
def compile(self, optimizer, loss,
metrics=[],
sample_weight_modes=None,
loss_weights=None,
**kwargs):
'''Configures the learning process.
# Arguments
optimizer: str (name of optimizer) or optimizer object.
See [optimizers](optimizers.md).
loss: dictionary mapping the name(s) of the output(s) to
a loss function (string name of objective function or
objective function. See [objectives](objectives.md)).
metrics: list of str (name of metrics) or
list of metrics functions. See [metrics](metrics.md).
sample_weight_modes: optional dictionary mapping certain
output names to a sample weight mode ("temporal" and None
are the only supported modes). If you need to do
timestep-wise loss weighting on one of your graph outputs,
you will need to set the sample weight mode for this output
to "temporal".
loss_weights: dictionary you can pass to specify a weight
coefficient for each loss function (in a multi-output model).
If no loss weight is specified for an output,
the weight for this output's loss will be considered to be 1.
kwargs: for Theano backend, these are passed into K.function.
Ignored for Tensorflow backend.
'''
# create the underlying Model
if not self.built:
self.build()
super(Graph, self).compile(optimizer, loss,
metrics=metrics,
sample_weight_mode=sample_weight_modes,
loss_weights=loss_weights,
**kwargs)
def add_input(self, name, input_shape=None,
batch_input_shape=None, dtype='float'):
'''Adds an input to the graph.
# Arguments:
name: string. The name of the new input.
Must be unique in the graph.
input_shape: a tuple of integers,
the expected shape of the input samples.
Does not include the batch size.
batch_input_shape: a tuple of integers,
the expected shape of the whole input batch,
including the batch size.
dtype: 'float', or 'int'.
'''
if name in self._graph_namespace:
raise Exception('Duplicate node identifier: ' + name)
self._graph_namespace.add(name)
self.built = False
if dtype[:3] == 'int':
dtype = 'int32'
elif dtype[:5] == 'float':
dtype = K.floatx()
else:
raise Exception('Uknown dtype (should be "int" or "float"): ' +
str(dtype))
# create input layer
input_layer = InputLayer(input_shape=input_shape,
batch_input_shape=batch_input_shape,
name=name, input_dtype=dtype)
self._graph_inputs[name] = input_layer
# append input config to self._graph_input_config
config = {'name': name, 'dtype': dtype}
if batch_input_shape:
config['batch_input_shape'] = batch_input_shape
else:
config['input_shape'] = input_shape
self._graph_input_config.append(config)
def add_node(self, layer, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1, dot_axes=-1,
create_output=False):
'''Adds a node in the graph. It can be connected to multiple
inputs, which will first be merged into one tensor
according to the mode specified.
# Arguments
layer: the layer at the node.
name: name for the node.
input: when connecting the layer to a single input,
this is the name of the incoming node.
inputs: when connecting the layer to multiple inputs,
this is a list of names of incoming nodes.
merge_mode: one of {concat, sum, dot, ave, mul}
concat_axis: when `merge_mode=='concat'`, this is the
input concatenation axis.
dot_axes: when `merge_mode='dot'`,
this is the contraction axes specification;
see the `Merge` layer for details.
create_output: boolean. Set this to `True` if you want the output
of your node to be an output of the graph.
'''
if name in self._graph_namespace:
raise Exception('Duplicate node identifier: ' + name)
self._graph_namespace.add(name)
layer.name = name
self.built = False
if input:
if input not in self._graph_namespace:
raise Exception('Unknown node/input identifier: ' + input)
if input in self._graph_nodes:
layer.add_inbound_node(self._graph_nodes[input])
elif input in self._graph_inputs:
layer.add_inbound_node(self._graph_inputs[input])
if inputs:
to_merge = []
for n in inputs:
if n in self._graph_nodes:
to_merge.append(self._graph_nodes[n])
elif n in self._graph_inputs:
to_merge.append(self._graph_inputs[n])
else:
raise Exception('Unknown identifier: ' + n)
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes,
name='merge_inputs_for_' + name)
layer.add_inbound_node(merge)
self._graph_nodes[name] = layer
self._graph_node_config.append({'name': name,
'input': input,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'create_output': create_output})
if create_output:
self.add_output(name, input=name)
def add_shared_node(self, layer, name, inputs=[], merge_mode=None,
concat_axis=-1, dot_axes=-1, outputs=[],
create_output=False):
'''Used to share a same layer across multiple nodes.
Supposed, for instance, that you want to apply one same `Dense` layer
after two different nodes ('node_a' and 'node_b').
You can then add the dense layer as a shared node by calling:
```python
model.add_shared_node(my_dense, name='shared_dense', inputs=['node_a', 'node_b'], ...)
```
If you want access to the output of dense(node_a) and dense(node_b) separately,
you can add these outputs to the Graph by passing an `outputs` argument:
```python
model.add_shared_node(my_dense, name='shared_dense', inputs=['node_a', 'node_b'],
outputs=['dense_output_a', 'dense_outputs_b'])
```
Otherwise you can merge these different outputs via `merge_mode`.
In that case you can access the merged output
under the identifier `name`.
# Arguments
layer: The layer to be shared across multiple inputs
name: Name of the shared node
inputs: List of names of input nodes
merge_mode: Same meaning as `merge_mode` argument of `add_node()`
concat_axis: Same meaning as `concat_axis` argument of `add_node()`
dot_axes: Same meaning as `dot_axes` argument of `add_node()`
outputs: Used when `merge_mode=None`. Names for the output nodes.
create_output: Same meaning as `create_output` argument of `add_node()`.
'''
if name in self._graph_namespace:
raise Exception('Duplicate node identifier: ' + name)
self._graph_namespace.add(name)
self.built = False
for o in outputs:
if o in self._graph_namespace:
raise Exception('Duplicate node identifier: ' + o)
if merge_mode:
if merge_mode not in {'sum', 'ave', 'mul', 'dot', 'cos', 'concat'}:
raise Exception('Invalid merge mode:', merge_mode)
input_layers = []
for i in range(len(inputs)):
input = inputs[i]
if input in self._graph_nodes:
n = self._graph_nodes[input]
input_layers.append(n)
elif input in self._graph_inputs:
n = self._graph_inputs[input]
input_layers.append(n)
else:
raise Exception('Unknown identifier: ' + input)
created_node_indices = []
for input_layer in input_layers:
created_node_indices.append(len(layer.inbound_nodes))
layer.add_inbound_node(input_layer)
if merge_mode:
layer.name = 'input_for_' + name
# collect all output nodes of layer and merge them into a single output
merge = Merge([layer for _ in range(len(inputs))],
mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes,
node_indices=created_node_indices,
name=name)
self._graph_nodes[name] = merge
if create_output:
self.add_output(name, input=name)
else:
layer.name = name
# create one new layer per output node of layer,
# and add them to the Graph with their own identifiers
if len(outputs) != len(inputs):
raise Exception('When using merge_mode=None, '
'you should provide a list of '
'output names (`output` argument) '
'the same size as `input`.')
for i in range(len(outputs)):
output_layer_name = outputs[i]
output_layer = Layer(name=output_layer_name)
output_layer.add_inbound_node(layer, created_node_indices[i])
self._graph_namespace.add(output_layer_name)
self._graph_nodes[output_layer_name] = output_layer
if create_output:
self.add_output(output_layer_name, input=output_layer_name)
self._graph_node_config.append({'name': name,
'layer': {
'config': layer.get_config(),
'class_name': layer.__class__.__name__,
},
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'outputs': outputs,
'create_output': create_output if merge_mode else False})
self._graph_shared_nodes_names.append(name)
def add_output(self, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1, dot_axes=-1):
'''Adds an output to the graph.
This output can merge several node outputs into a single output.
# Arguments
name: name of the output.
input: when connecting the layer to a single input,
this is the name of the incoming node.
inputs: when connecting the layer to multiple inputs,
this is a list of names of incoming nodes.
merge_mode: one of {concat, sum, dot, ave, mul}
concat_axis: when `merge_mode=='concat'`, this is the
input concatenation axis.
dot_axes: when `merge_mode='dot'`,
this is the contraction axes specification;
see the `Merge layer for details.
'''
if name not in self._graph_namespace:
self._graph_namespace.add(name)
if name in self._graph_outputs:
raise Exception('Duplicate output identifier:', name)
self.built = False
if input:
if input in self._graph_nodes:
layer = self._graph_nodes[input]
elif input in self._graph_inputs:
layer = self._graph_inputs[input]
else:
raise Exception('Unknown node/input identifier: ' + input)
if layer.name == name:
self._graph_outputs[name] = layer
else:
layer.name = name
self._graph_outputs[name] = layer
if inputs:
to_merge = []
for n in inputs:
if n not in self._graph_nodes:
raise Exception('Unknown identifier: ' + n)
to_merge.append(self._graph_nodes[n])
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes,
name=name)
self._graph_outputs[name] = merge
self._graph_output_config.append({'name': name,
'input': input,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes})
def _get_x(self, data):
x = []
for key in self._graph_inputs.keys():
if key not in data:
raise Exception('Expected to be provided an array '
'(in dict argument `data`) for input "' +
key + '".')
x.append(data[key])
return x
def _get_y(self, data):
y = []
for key in self._graph_outputs.keys():
if key not in data:
raise Exception('Expected to be provided an array '
'(in dict argument `data`) for output "' +
key + '".')
y.append(data[key])
return y
def fit(self, data, batch_size=32, nb_epoch=10, verbose=1, callbacks=[],
validation_split=0., validation_data=None, shuffle=True,
class_weight=None, sample_weight=None, **kwargs):
'''Trains the model for a fixed number of epochs.
Returns a history object. Its `history` attribute is a record of
training loss values at successive epochs,
as well as validation loss values (if applicable).
# Arguments
data: dictionary mapping input names and outputs names to
appropriate numpy arrays. All arrays should contain
the same number of samples.
batch_size: int. Number of samples per gradient update.
nb_epoch: int.
verbose: 0 for no logging to stdout,
1 for progress bar logging, 2 for one log line per epoch.
callbacks: `keras.callbacks.Callback` list. List of callbacks
to apply during training. See [callbacks](callbacks.md).
validation_split: float (0. < x < 1). Fraction of the data to
use as held-out validation data.
validation_data: dictionary mapping input names and outputs names
to appropriate numpy arrays to be used as
held-out validation data.
All arrays should contain the same number of samples.
Will override validation_split.
shuffle: boolean. Whether to shuffle the samples at each epoch.
class_weight: dictionary mapping output names to
class weight dictionaries.
sample_weight: dictionary mapping output names to
numpy arrays of sample weights.
'''
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
x = self._get_x(data)
y = self._get_y(data)
if type(validation_data) is tuple:
raise Exception('Cannot used sample_weight with '
'validation data with legacy Graph model. '
'validation_data should be a dictionary.')
if validation_data:
val_x = self._get_x(validation_data)
val_y = self._get_y(validation_data)
validation_data = (val_x, val_y)
return super(Graph, self).fit(x, y,
batch_size=batch_size,
nb_epoch=nb_epoch,
verbose=verbose,
callbacks=callbacks,
validation_split=validation_split,
validation_data=validation_data,
shuffle=shuffle,
class_weight=class_weight,
sample_weight=sample_weight)
def evaluate(self, data, batch_size=128,
verbose=0, sample_weight={}, **kwargs):
'''Computes the loss on some input data, batch by batch.
Returns the scalar test loss over the data,
or a list of metrics values (starting with the test loss)
if applicable.
Arguments: see `fit` method.
'''
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
x = self._get_x(data)
y = self._get_y(data)
return super(Graph, self).evaluate(x, y,
batch_size=batch_size,
verbose=verbose,
sample_weight=sample_weight)
def predict(self, data, batch_size=128, verbose=0):
'''Generates output predictions for the input samples
batch by batch.
Arguments: see `fit` method.
'''
x = self._get_x(data)
output_list = super(Graph, self).predict(x, batch_size=batch_size,
verbose=verbose)
return dict(zip(self._graph_outputs, output_list))
def train_on_batch(self, data,
class_weight={},
sample_weight={}, **kwargs):
'''Single gradient update on a batch of samples.
Returns the scalar train loss over the data,
or a list of metrics values (starting with the test loss)
if applicable.
Arguments: see `fit` method.
'''
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
x = self._get_x(data)
y = self._get_y(data)
return super(Graph, self).train_on_batch(x, y,
sample_weight=sample_weight,
class_weight=class_weight)
def test_on_batch(self, data, sample_weight={}, **kwargs):
'''Test the network on a single batch of samples.
Returns the scalar test loss over the data,
or a list of metrics values (starting with the test loss)
if applicable.
Arguments: see `fit` method.
'''
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
x = self._get_x(data)
y = self._get_y(data)
return super(Graph, self).test_on_batch(x, y,
sample_weight=sample_weight)
def predict_on_batch(self, data):
output_list = super(Graph, self).predict_on_batch(data)
return dict(zip(self._graph_outputs, output_list))
def fit_generator(self, generator, samples_per_epoch, nb_epoch,
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight={}, **kwargs):
'''Fits a model on data generated batch-by-batch by a Python generator.
The generator is run in parallel to the model, for efficiency.
For instance, this allows you to do real-time data augmentation
on images on CPU in parallel to training your model on GPU.
# Arguments
generator: a generator.
The output of the generator must be either a tuple
of dictionaries `(input_data, sample_weight)`
or a dictionary `input_data`
(mapping names of inputs and outputs to Numpy arrays).
All arrays should contain the same number of samples.
The generator is expected to loop over its data
indefinitely. An epoch finishes when `samples_per_epoch`
samples have been seen by the model.
samples_per_epoch: integer, number of samples to process before
going to the next epoch.
nb_epoch: integer, total number of iterations on the data.
verbose: verbosity mode, 0, 1, or 2.
callbacks: list of callbacks to be called during training.
validation_data: dictionary mapping input names and outputs names
to appropriate numpy arrays to be used as
held-out validation data, or a generator yielding such
dictionaries. All arrays should contain the same number
of samples. If a generator, will be called until more than
`nb_val_samples` examples have been generated at the
end of every epoch. These examples will then be used
as the validation data.
nb_val_samples: number of samples to use from validation
generator at the end of every epoch.
class_weight: dictionary mapping class indices to a weight
for the class.
# Returns
A `History` object.
# Examples
```python
def generate_arrays_from_file(path):
while 1:
f = open(path)
for line in f:
# create numpy arrays of input data
# and labels, from each line in the file
x1, x2, y = process_line(line)
yield ({'input_1': x1, 'input_2': x2, 'output': y})
f.close()
graph.fit_generator(generate_arrays_from_file('/my_file.txt'),
samples_per_epoch=10000, nb_epoch=10)
```
'''
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if 'nb_worker' in kwargs:
kwargs.pop('nb_worker')
warnings.warn('The "nb_worker" argument is deprecated, '
'please remove it from your code.')
if 'nb_val_worker' in kwargs:
kwargs.pop('nb_val_worker')
warnings.warn('The "nb_val_worker" argument is deprecated, '
'please remove it from your code.')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
self._train_on_batch = self.train_on_batch
self.train_on_batch = super(Graph, self).train_on_batch
self._evaluate = self.evaluate
self.evaluate = super(Graph, self).evaluate
if validation_data and type(validation_data) is tuple:
raise Exception('Cannot use sample_weight with '
'validation_data in legacy Graph model.')
if validation_data and type(validation_data) is dict:
validation_data = (self._get_x(validation_data),
self._get_y(validation_data))
original_generator = generator
def fixed_generator():
while 1:
data = next(original_generator)
if type(data) is tuple:
data, sample_weight = data
x = self._get_x(data)
y = self._get_y(data)
yield x, y, sample_weight
else:
x = self._get_x(data)
y = self._get_y(data)
yield x, y
generator = fixed_generator()
history = super(Graph, self).fit_generator(generator,
samples_per_epoch,
nb_epoch,
verbose=verbose,
callbacks=callbacks,
validation_data=validation_data,
nb_val_samples=nb_val_samples,
class_weight=class_weight)
self.train_on_batch = self._train_on_batch
self.evaluate = self._evaluate
return history
def evaluate_generator(self, generator, val_samples,
verbose=1, **kwargs):
'''Evaluates the model on a generator. The generator should
return the same kind of data with every yield as accepted
by `evaluate`.
If `show_accuracy`, it returns a tuple `(loss, accuracy)`,
otherwise it returns the loss value.
Arguments:
generator:
generator yielding dictionaries of the kind accepted
by `evaluate`, or tuples of such dictionaries and
associated dictionaries of sample weights.
val_samples:
total number of samples to generate from `generator`
to use in validation.
Other arguments are the same as for `fit`.
'''
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
'instead you should pass the "accuracy" metric to '
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if 'verbose' in kwargs:
kwargs.pop('verbose')
warnings.warn('The "verbose" argument is deprecated.')
if kwargs:
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
self._test_on_batch = self.test_on_batch
self.test_on_batch = super(Graph, self).test_on_batch
original_generator = generator
def fixed_generator():
while 1:
data = next(original_generator)
if type(data) is tuple:
data, sample_weight = data
x = self._get_x(data)
y = self._get_y(data)
yield x, y, sample_weight
else:
x = self._get_x(data)
y = self._get_y(data)
yield x, y
generator = fixed_generator()
history = super(Graph, self).evaluate_generator(generator,
val_samples)
self.test_on_batch = self._test_on_batch
return history
# get_weights, set_weights: inherited
def get_config(self):
config = {'input_config': self._graph_input_config,
'node_config': self._graph_node_config,
'output_config': self._graph_output_config}
nodes = {}
for name, node in self._graph_nodes.items():
nodes[name] = {'class_name': node.__class__.__name__,
'config': node.get_config()}
if name in self._graph_shared_nodes_names:
nodes[name]['shared'] = True
config['nodes'] = nodes
return copy.deepcopy(config)
@classmethod
def from_config(cls, config):
# TODO: test legacy support
from keras.utils.layer_utils import layer_from_config
def normalize_legacy_config(conf):
if 'class_name' not in conf:
class_name = conf['name']
name = conf.get('custom_name')
conf['name'] = name
new_config = {
'class_name': class_name,
'config': conf,
}
return new_config
return conf
graph = cls()
inputs = config.get('input_config')
for input in inputs:
graph.add_input(**input)
nodes = config.get('node_config')
for node in nodes:
layer_config = config['nodes'][node['name']]
layer_config = normalize_legacy_config(layer_config)
if 'layer' in node:
# for add_shared_node
node['layer'] = layer_from_config(node['layer'])
else:
layer = layer_from_config(layer_config)
node['layer'] = layer
node['create_output'] = False # outputs will be added below
if layer_config.get('shared'):
graph.add_shared_node(**node)
else:
graph.add_node(**node)
outputs = config.get('output_config')
for output in outputs:
graph.add_output(**output)
return graph
def load_weights(self, fname):
if not self.built:
self.build()
super(Graph, self).load_weights(fname)
+10
Ver Arquivo
@@ -0,0 +1,10 @@
from . import backend as K
def binary_accuracy(y_true, y_pred):
return K.mean(K.equal(y_true, K.round(y_pred)))
def categorical_accuracy(y_true, y_pred):
return K.mean(K.equal(K.argmax(y_true, axis=-1),
K.argmax(y_pred, axis=-1)))
+595 -1683
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+6
Ver Arquivo
@@ -36,6 +36,12 @@ def categorical_crossentropy(y_true, y_pred):
return K.categorical_crossentropy(y_pred, y_true)
def sparse_categorical_crossentropy(y_true, y_pred):
'''expects a 1-D or 2-D array of integer classes.
'''
return K.sparse_categorical_crossentropy(y_pred, y_true)
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
+107 -38
Ver Arquivo
@@ -31,6 +31,7 @@ class Optimizer(object):
def __init__(self, **kwargs):
self.__dict__.update(kwargs)
self.updates = []
self.weights = []
def get_state(self):
return [K.get_value(u[0]) for u in self.updates]
@@ -52,13 +53,48 @@ class Optimizer(object):
grads = [K.clip(g, -self.clipvalue, self.clipvalue) for g in grads]
return grads
def set_weights(self, weights):
'''Sets the weights of the optimizer, from Numpy arrays.
Should only be called after computing the gradients
(otherwise the optimizer has no weights).
# Arguments
weights: a list of Numpy arrays. The number
of arrays and their shape must match
number of the dimensions of the weights
of the optimizer (i.e. it should match the
output of `get_weights`).
'''
params = self.weights
if len(params) != len(weights):
raise Exception('Provided weight array does not match weights (' +
str(len(params)) + ' optimizer params vs. ' +
str(len(weights)) + ' provided weights)')
for p, w in zip(params, weights):
if K.get_value(p).shape != w.shape:
raise Exception('Optimizer weight shape ' +
str(K.get_value(p).shape) +
' not compatible with '
'provided weight shape ' + str(w.shape))
K.set_value(p, w)
def get_weights(self):
'''Returns the current weights of the optimizer,
as a list of numpy arrays.
'''
weights = []
for p in self.weights:
weights.append(K.get_value(p))
return weights
def get_config(self):
return {"name": self.__class__.__name__}
class SGD(Optimizer):
'''Stochastic gradient descent, with support for momentum,
decay, and Nesterov momentum.
learning rate decay, and Nesterov momentum.
# Arguments
lr: float >= 0. Learning rate.
@@ -77,10 +113,10 @@ class SGD(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
lr = self.lr * (1.0 / (1.0 + self.decay * self.iterations))
lr = self.lr * (1. / (1. + self.decay * self.iterations))
self.updates = [(self.iterations, self.iterations + 1.)]
for p, g, c in zip(params, grads, constraints):
for p, g in zip(params, grads):
m = K.variable(np.zeros(K.get_value(p).shape)) # momentum
v = self.momentum * m - lr * g # velocity
self.updates.append((m, v))
@@ -90,7 +126,11 @@ class SGD(Optimizer):
else:
new_p = p + v
self.updates.append((p, c(new_p))) # apply constraints
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
return self.updates
def get_config(self):
@@ -105,7 +145,8 @@ class RMSprop(Optimizer):
'''RMSProp optimizer.
It is recommended to leave the parameters of this optimizer
at their default values.
at their default values
(except the learning rate, which can be freely tuned).
This optimizer is usually a good choice for recurrent
neural networks.
@@ -123,16 +164,21 @@ class RMSprop(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
# accumulators
self.weights = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.updates = []
for p, g, a, c in zip(params, grads, accumulators, constraints):
for p, g, a in zip(params, grads, self.weights):
# update accumulator
new_a = self.rho * a + (1 - self.rho) * K.square(g)
new_a = self.rho * a + (1. - self.rho) * K.square(g)
self.updates.append((a, new_a))
new_p = p - self.lr * g / K.sqrt(new_a + self.epsilon)
self.updates.append((p, c(new_p))) # apply constraints
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
return self.updates
def get_config(self):
@@ -159,14 +205,19 @@ class Adagrad(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
# accumulators
self.weights = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.updates = []
for p, g, a, c in zip(params, grads, accumulators, constraints):
for p, g, a in zip(params, grads, self.weights):
new_a = a + K.square(g) # update accumulator
self.updates.append((a, new_a))
new_p = p - self.lr * g / K.sqrt(new_a + self.epsilon)
self.updates.append((p, c(new_p))) # apply constraints
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
return self.updates
def get_config(self):
@@ -182,7 +233,8 @@ class Adadelta(Optimizer):
at their default values.
# Arguments
lr: float >= 0. Learning rate. It is recommended to leave it at the default value.
lr: float >= 0. Learning rate.
It is recommended to leave it at the default value.
rho: float >= 0.
epsilon: float >= 0. Fuzz factor.
@@ -198,19 +250,23 @@ class Adadelta(Optimizer):
grads = self.get_gradients(loss, params)
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
delta_accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.weights = accumulators + delta_accumulators
self.updates = []
for p, g, a, d_a, c in zip(params, grads, accumulators,
delta_accumulators, constraints):
for p, g, a, d_a in zip(params, grads, accumulators, delta_accumulators):
# update accumulator
new_a = self.rho * a + (1 - self.rho) * K.square(g)
new_a = self.rho * a + (1. - self.rho) * K.square(g)
self.updates.append((a, new_a))
# use the new accumulator and the *old* delta_accumulator
update = g * K.sqrt(d_a + self.epsilon) / K.sqrt(new_a + self.epsilon)
new_p = p - self.lr * update
self.updates.append((p, c(new_p))) # apply constraints
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
# update delta_accumulator
new_d_a = self.rho * d_a + (1 - self.rho) * K.square(update)
@@ -248,24 +304,29 @@ class Adam(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations+1.)]
self.updates = [(self.iterations, self.iterations + 1)]
t = self.iterations + 1
lr_t = self.lr * K.sqrt(1 - K.pow(self.beta_2, t)) / (1 - K.pow(self.beta_1, t))
lr_t = self.lr * K.sqrt(1. - K.pow(self.beta_2, t)) / (1. - K.pow(self.beta_1, t))
for p, g, c in zip(params, grads, constraints):
# zero init of moment
m = K.variable(np.zeros(K.get_value(p).shape))
# zero init of velocity
v = K.variable(np.zeros(K.get_value(p).shape))
ms = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
vs = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.weights = ms + vs
m_t = (self.beta_1 * m) + (1 - self.beta_1) * g
v_t = (self.beta_2 * v) + (1 - self.beta_2) * K.square(g)
for p, g, m, v in zip(params, grads, ms, vs):
m_t = (self.beta_1 * m) + (1. - self.beta_1) * g
v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g)
p_t = p - lr_t * m_t / (K.sqrt(v_t) + self.epsilon)
self.updates.append((m, m_t))
self.updates.append((v, v_t))
self.updates.append((p, c(p_t))) # apply constraints
new_p = p_t
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
return self.updates
def get_config(self):
@@ -294,31 +355,39 @@ class Adamax(Optimizer):
*args, **kwargs):
super(Adamax, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0)
self.iterations = K.variable(0.)
self.lr = K.variable(lr)
self.beta_1 = K.variable(beta_1)
self.beta_2 = K.variable(beta_2)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations+1.)]
self.updates = [(self.iterations, self.iterations + 1)]
t = self.iterations + 1
lr_t = self.lr / (1 - K.pow(self.beta_1, t))
lr_t = self.lr / (1. - K.pow(self.beta_1, t))
for p, g, c in zip(params, grads, constraints):
# zero init of 1st moment
m = K.variable(np.zeros(K.get_value(p).shape))
# zero init of exponentially weighted infinity norm
u = K.variable(np.zeros(K.get_value(p).shape))
# zero init of 1st moment
ms = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
# zero init of exponentially weighted infinity norm
us = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.weights = ms + us
m_t = (self.beta_1 * m) + (1 - self.beta_1) * g
for p, g, m, u in zip(params, grads, ms, us):
m_t = (self.beta_1 * m) + (1. - self.beta_1) * g
u_t = K.maximum(self.beta_2 * u, K.abs(g))
p_t = p - lr_t * m_t / (u_t + self.epsilon)
self.updates.append((m, m_t))
self.updates.append((u, u_t))
self.updates.append((p, c(p_t))) # apply constraints
new_p = p_t
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
return self.updates
def get_config(self):
+8 -9
Ver Arquivo
@@ -11,14 +11,13 @@ from scipy import linalg
from os import listdir
from os.path import isfile, join
import random
import math
from six.moves import range
import threading
def random_rotation(x, rg, fill_mode='nearest', cval=0.):
angle = random.uniform(-rg, rg)
angle = np.random.uniform(-rg, rg)
x = ndimage.interpolation.rotate(x, angle,
axes=(1, 2),
reshape=False,
@@ -31,9 +30,9 @@ def random_shift(x, wrg, hrg, fill_mode='nearest', cval=0.):
shift_x = shift_y = 0
if wrg:
shift_x = random.uniform(-wrg, wrg) * x.shape[2]
shift_x = np.random.uniform(-wrg, wrg) * x.shape[2]
if hrg:
shift_y = random.uniform(-hrg, hrg) * x.shape[1]
shift_y = np.random.uniform(-hrg, hrg) * x.shape[1]
x = ndimage.interpolation.shift(x, (0, shift_y, shift_x),
order=0,
mode=fill_mode,
@@ -59,7 +58,7 @@ def random_barrel_transform(x, intensity):
def random_shear(x, intensity, fill_mode='nearest', cval=0.):
shear = random.uniform(-intensity, intensity)
shear = np.random.uniform(-intensity, intensity)
shear_matrix = np.array([[1.0, -math.sin(shear), 0.0],
[0.0, math.cos(shear), 0.0],
[0.0, 0.0, 1.0]])
@@ -76,8 +75,8 @@ def random_channel_shift(x, rg):
def random_zoom(x, rg, fill_mode='nearest', cval=0.):
zoom_w = random.uniform(1.-rg, 1.)
zoom_h = random.uniform(1.-rg, 1.)
zoom_w = np.random.uniform(1.-rg, 1.)
zoom_h = np.random.uniform(1.-rg, 1.)
x = ndimage.interpolation.zoom(x, zoom=(1., zoom_w, zoom_h),
mode=fill_mode,
cval=cval)
@@ -253,10 +252,10 @@ class ImageDataGenerator(object):
if self.width_shift_range or self.height_shift_range:
x = random_shift(x, self.width_shift_range, self.height_shift_range)
if self.horizontal_flip:
if random.random() < 0.5:
if np.random.random() < 0.5:
x = horizontal_flip(x)
if self.vertical_flip:
if random.random() < 0.5:
if np.random.random() < 0.5:
x = vertical_flip(x)
if self.shear_range:
x = random_shear(x, self.shear_range)
+33 -19
Ver Arquivo
@@ -13,46 +13,61 @@ class Regularizer(object):
return loss
def get_config(self):
return {"name": self.__class__.__name__}
return {'name': self.__class__.__name__}
class WeightRegularizer(Regularizer):
def __init__(self, l1=0., l2=0.):
self.l1 = l1
self.l2 = l2
self.l1 = K.cast_to_floatx(l1)
self.l2 = K.cast_to_floatx(l2)
self.uses_learning_phase = True
def set_param(self, p):
self.p = p
def __call__(self, loss):
loss += K.sum(K.abs(self.p)) * self.l1
loss += K.sum(K.square(self.p)) * self.l2
return loss
if not hasattr(self, 'p'):
raise Exception('Need to call `set_param` on '
'WeightRegularizer instance '
'before calling the instance. '
'Check that you are not passing '
'a WeightRegularizer instead of an '
'ActivityRegularizer '
'(i.e. activity_regularizer="l2" instead '
'of activity_regularizer="activity_l2".')
regularized_loss = loss + K.sum(K.abs(self.p)) * self.l1
regularized_loss += K.sum(K.square(self.p)) * self.l2
return K.in_train_phase(regularized_loss, loss)
def get_config(self):
return {"name": self.__class__.__name__,
"l1": self.l1,
"l2": self.l2}
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
class ActivityRegularizer(Regularizer):
def __init__(self, l1=0., l2=0.):
self.l1 = l1
self.l2 = l2
self.l1 = K.cast_to_floatx(l1)
self.l2 = K.cast_to_floatx(l2)
self.uses_learning_phase = True
def set_layer(self, layer):
self.layer = layer
def __call__(self, loss):
output = self.layer.get_output(True)
loss += self.l1 * K.sum(K.mean(K.abs(output), axis=0))
loss += self.l2 * K.sum(K.mean(K.square(output), axis=0))
return loss
if not hasattr(self, 'layer'):
raise Exception('Need to call `set_layer` on '
'ActivityRegularizer instance '
'before calling the instance.')
output = self.layer.output
regularized_loss = loss + self.l1 * K.sum(K.mean(K.abs(output), axis=0))
regularized_loss += self.l2 * K.sum(K.mean(K.square(output), axis=0))
return K.in_train_phase(regularized_loss, loss)
def get_config(self):
return {"name": self.__class__.__name__,
"l1": self.l1,
"l2": self.l2}
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
def l1(l=0.01):
@@ -78,7 +93,6 @@ def activity_l2(l=0.01):
def activity_l1l2(l1=0.01, l2=0.01):
return ActivityRegularizer(l1=l1, l2=l2)
identity = Regularizer
from .utils.generic_utils import get_from_module
def get(identifier, kwargs=None):
+22
Ver Arquivo
@@ -18,6 +18,14 @@ def get_from_module(identifier, module_params, module_name,
return res(**kwargs)
else:
return res
elif type(identifier) is dict:
name = identifier.pop('name')
res = module_params.get(name)
if res:
return res(**identifier)
else:
raise Exception('Invalid ' + str(module_name) + ': ' +
str(identifier))
return identifier
@@ -121,3 +129,17 @@ class Progbar(object):
def add(self, n, values=[]):
self.update(self.seen_so_far + n, values)
def display_table(rows, positions):
def display_row(objects, positions):
line = ''
for i in range(len(objects)):
line += str(objects[i])
line = line[:positions[i]]
line += ' ' * (positions[i] - len(line))
print(line)
for objects in rows:
display_row(objects, positions)
+74 -145
Ver Arquivo
@@ -1,168 +1,97 @@
from __future__ import print_function
import inspect
import numpy as np
import copy
from ..layers.advanced_activations import *
from ..layers.core import *
from ..layers.convolutional import *
from ..layers.embeddings import *
from ..layers.noise import *
from ..layers.normalization import *
from ..layers.recurrent import *
from ..layers.wrappers import *
from ..layers import containers
from .. import regularizers
from .. import constraints
from .generic_utils import get_from_module
from ..layers import *
from ..models import Model, Sequential, Graph
from .. import backend as K
def container_from_config(original_layer_dict, custom_objects={}):
layer_dict = copy.deepcopy(original_layer_dict)
name = layer_dict.get('name')
def layer_from_config(config, custom_objects={}):
'''
# 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, Graph, Layer...)
'''
# Insert custom layers into globals so they can
# be accessed by `get_from_module`.
for cls_key in custom_objects:
globals()[cls_key] = custom_objects[cls_key]
if name == 'Merge':
mode = layer_dict.get('mode')
concat_axis = layer_dict.get('concat_axis')
dot_axes = layer_dict.get('dot_axes')
layers = layer_dict.get('layers')
layer_list = []
for layer in layers:
init_layer = container_from_config(layer)
layer_list.append(init_layer)
merge_layer = Merge(layer_list, mode, concat_axis, dot_axes)
return merge_layer
class_name = config['class_name']
elif name == 'Sequential':
layers = layer_dict.get('layers')
layer_list = []
for layer in layers:
init_layer = container_from_config(layer)
layer_list.append(init_layer)
seq_layer = containers.Sequential(layer_list)
return seq_layer
elif name == 'Graph':
graph_layer = containers.Graph()
inputs = layer_dict.get('input_config')
for input in inputs:
graph_layer.add_input(**input)
nodes = layer_dict.get('node_config')
for node in nodes:
layer = container_from_config(layer_dict['nodes'].get(node['name']))
node['layer'] = layer
node['create_output'] = False # outputs will be added below
graph_layer.add_node(**node)
outputs = layer_dict.get('output_config')
for output in outputs:
graph_layer.add_output(**output)
return graph_layer
elif name == 'AutoEncoder':
kwargs = {'encoder': container_from_config(layer_dict.get('encoder_config')),
'decoder': container_from_config(layer_dict.get('decoder_config'))}
for kwarg in ['output_reconstruction', 'weights']:
if kwarg in layer_dict:
kwargs[kwarg] = layer_dict[kwarg]
return AutoEncoder(**kwargs)
elif name == 'TimeDistributed':
child_layer = container_from_config(layer_dict.pop('layer'))
# the "name" keyword argument of layers is saved as "custom_name"
if 'custom_name' in layer_dict:
layer_dict['name'] = layer_dict.pop('custom_name')
return TimeDistributed(child_layer, **layer_dict)
else: # this is a non-topological layer (e.g. Dense, etc.)
layer_dict.pop('name')
for k, v in layer_dict.items():
# a dictionary argument may be a regularizer or constraint
if isinstance(v, dict):
vname = v.pop('name')
if vname in [x for x, y in inspect.getmembers(constraints, predicate=inspect.isclass)]:
layer_dict[k] = constraints.get(vname, v)
elif vname in [x for x, y in inspect.getmembers(regularizers, predicate=inspect.isclass)]:
layer_dict[k] = regularizers.get(vname, v)
else:
# not a regularizer of constraint, don't touch it
v['name'] = vname
# the "name" keyword argument of layers is saved as "custom_name"
if 'custom_name' in layer_dict:
layer_dict['name'] = layer_dict.pop('custom_name')
base_layer = get_layer(name, layer_dict)
return base_layer
if class_name == 'Sequential':
layer_class = Sequential
elif class_name == 'Graph':
layer_class = Graph
elif class_name in ['Model', 'Container']:
layer_class = Model
else:
layer_class = get_from_module(class_name, globals(), 'layer',
instantiate=False)
return layer_class.from_config(config['config'])
def model_summary(model):
param_count = 0 # param count in the model
def print_summary(layers, relevant_nodes=None):
line_length = 100 # total length of printed lines
positions = [35, 55, 67, 100] # absolute positions of log elements in each line
# header names for the different log elements
to_display = ['Layer (type)', 'Output Shape', 'Param #', 'Connected to']
def display(objects, positions):
def print_row(fields, positions):
line = ''
for i in range(len(objects)):
line += str(objects[i])
for i in range(len(fields)):
line += str(fields[i])
line = line[:positions[i]]
line += ' ' * (positions[i] - len(line))
print(line)
def display_layer_info(layer, name, positions):
layer_type = layer.__class__.__name__
output_shape = layer.output_shape
params = layer.count_params()
to_display = ['%s (%s)' % (layer_type, name), output_shape, params]
display(to_display, positions)
print('_' * line_length)
print_row(to_display, positions)
print('=' * line_length)
line_length = 80 # total length of printed lines
positions = [30, 60, 80] # absolute positions of log elements in each line
# header names for the different log elements
to_display = ['Layer (name)', 'Output Shape', 'Param #']
def print_layer_summary(layer):
try:
output_shape = layer.output_shape
except:
output_shape = 'multiple'
connections = []
for node_index, node in enumerate(layer.inbound_nodes):
if relevant_nodes:
node_key = layer.name + '_ib-' + str(node_index)
if node_key not in relevant_nodes:
# node is node part of the current network
continue
for i in range(len(node.inbound_layers)):
inbound_layer = node.inbound_layers[i].name
inbound_node_index = node.node_indices[i]
inbound_tensor_index = node.tensor_indices[i]
connections.append(inbound_layer + '[' + str(inbound_node_index) + '][' + str(inbound_tensor_index) + ']')
# for sequential models, we start by printing
# the expect input shape
if model.__class__.__name__ == 'Sequential':
print('-' * line_length)
print('Initial input shape: ' + str(model.input_shape))
name = layer.name
cls_name = layer.__class__.__name__
if not connections:
first_connection = ''
else:
first_connection = connections[0]
fields = [name + ' (' + cls_name + ')', output_shape, layer.count_params(), first_connection]
print_row(fields, positions)
if len(connections) > 1:
for i in range(1, len(connections)):
fields = ['', '', '', connections[i]]
print_row(fields, positions)
# print header
print('-' * line_length)
display(to_display, positions)
print('-' * line_length)
total_params = 0
for i in range(len(layers)):
print_layer_summary(layers[i])
if i == len(layers) - 1:
print('=' * line_length)
else:
print('_' * line_length)
total_params += layers[i].count_params()
if model.__class__.__name__ == 'Sequential':
for layer in model.layers:
name = getattr(layer, 'name', 'Unnamed')
display_layer_info(layer, name, positions)
param_count += layer.count_params()
elif model.__class__.__name__ == 'Graph':
for name in model.input_order:
layer = model.inputs[name]
display_layer_info(layer, name, positions)
for name in model.nodes:
layer = model.nodes[name]
display_layer_info(layer, name, positions)
param_count += layer.count_params()
for name in model.output_order:
layer = model.outputs[name]
display_layer_info(layer, name, positions)
print('-' * line_length)
print('Total params: %s' % param_count)
print('-' * line_length)
from .generic_utils import get_from_module
def get_layer(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'layer',
instantiate=True, kwargs=kwargs)
print('Total params: %s' % total_params)
print('_' * line_length)
+78 -1
Ver Arquivo
@@ -1,7 +1,14 @@
import numpy as np
from numpy.testing import assert_allclose
import inspect
from ..engine import Model, Input
from ..models import Sequential, model_from_json
from .. import backend as K
def get_test_data(nb_train=1000, nb_test=500, input_shape=(10,), output_shape=(2,),
def get_test_data(nb_train=1000, nb_test=500, input_shape=(10,),
output_shape=(2,),
classification=True, nb_class=2):
'''
classification=True overrides output_shape
@@ -25,3 +32,73 @@ def get_test_data(nb_train=1000, nb_test=500, input_shape=(10,), output_shape=(2
y[i] = np.random.normal(loc=y_loc[i], scale=0.7, size=output_shape)
return (X[:nb_train], y[:nb_train]), (X[nb_train:], y[nb_train:])
def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
input_data=None, expected_output=None, expected_output_dtype=None):
'''Test routine for a layer with a single input tensor
and single output tensor.
'''
if input_data is None:
assert input_shape
if not input_dtype:
input_dtype = K.floatx()
input_data = (10 * np.random.random(input_shape)).astype(input_dtype)
elif input_shape is None:
input_shape = input_data.shape
if expected_output_dtype is None:
expected_output_dtype = input_dtype
# instantiation
layer = layer_cls(**kwargs)
# test get_weights , set_weights
weights = layer.get_weights()
layer.set_weights(weights)
# test and instantiation from weights
if 'weights' in inspect.getargspec(layer_cls.__init__):
kwargs['weights'] = weights
layer = layer_cls(**kwargs)
# test in functional API
x = Input(shape=input_shape[1:], dtype=input_dtype)
y = layer(x)
assert K.dtype(y) == expected_output_dtype
model = Model(input=x, output=y)
model.compile('rmsprop', 'mse')
expected_output_shape = layer.get_output_shape_for(input_shape)
actual_output = model.predict(input_data)
actual_output_shape = actual_output.shape
assert expected_output_shape == actual_output_shape
if expected_output is not None:
assert_allclose(actual_output, expected_output, rtol=1e-3)
# test serialization
model_config = model.get_config()
model = Model.from_config(model_config)
model.compile('rmsprop', 'mse')
# test as first layer in Sequential API
layer_config = layer.get_config()
layer_config['batch_input_shape'] = input_shape
layer = layer.__class__.from_config(layer_config)
model = Sequential()
model.add(layer)
model.compile('rmsprop', 'mse')
actual_output = model.predict(input_data)
actual_output_shape = actual_output.shape
assert expected_output_shape == actual_output_shape
if expected_output is not None:
assert_allclose(actual_output, expected_output, rtol=1e-3)
# test JSON serialization
json_model = model.to_json()
model = model_from_json(json_model)
# for further checks in the caller function
return actual_output
+44 -137
Ver Arquivo
@@ -1,7 +1,3 @@
import itertools
from keras.layers.containers import Graph, Sequential
from keras.layers.core import Merge
try:
# pydot-ng is a fork of pydot that is better maintained
import pydot_ng as pydot
@@ -9,146 +5,57 @@ except ImportError:
# fall back on pydot if necessary
import pydot
if not pydot.find_graphviz():
raise RuntimeError("Failed to import pydot. You must install pydot"
" and graphviz for `pydotprint` to work.")
raise RuntimeError('Failed to import pydot. You must install pydot'
' and graphviz for `pydotprint` to work.')
def layer_typename(layer):
return type(layer).__module__ + "." + type(layer).__name__
def model_to_dot(model, show_shapes=False):
dot = pydot.Dot()
dot.set('rankdir', 'TB')
dot.set('concentrate', True)
dot.set_node_defaults(shape='record')
if model.__class__.__name__ == 'Sequential':
if not model.built:
model.build()
model = model.model
layers = model.layers
def get_layer_to_name(model):
"""Returns a dict mapping layer to their name in the model"""
if not isinstance(model, Graph):
return {}
else:
node_to_name = itertools.chain(
model.nodes.items(), model.inputs.items(), model.outputs.items()
)
return {v: k for k, v in node_to_name}
# first, populate the nodes of the graph
for layer in layers:
layer_id = str(id(layer))
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
class ModelToDot(object):
"""
This is a helper class which visits a keras model (Sequential or Graph) and
returns a pydot.Graph representation.
This is implemented as a class because we need to maintain various states.
Use it as ```ModelToDot()(model)```
Keras models can have an arbitrary number of inputs and outputs. A given
layer can have multiple inputs but has a single output. We therefore
explore the model by starting at its output and crawling "up" the tree.
"""
def _pydot_node_for_layer(self, layer, label):
"""
Returns the pydot.Node corresponding to the given layer.
`label` specify the name of the layer (only used if the layer isn't yet
associated with a pydot.Node)
"""
# Check if this already exists (will be the case for nodes that
# serve as input to more than one layer)
if layer in self.layer_to_pydotnode:
node = self.layer_to_pydotnode[layer]
else:
layer_id = 'layer%d' % self.idgen
self.idgen += 1
label = label + " (" + layer_typename(layer) + ")"
if self.show_shape:
# Build the label that will actually contain a table with the
# input/output
outputlabels = str(layer.output_shape)
if hasattr(layer, 'input_shape'):
inputlabels = str(layer.input_shape)
elif hasattr(layer, 'input_shapes'):
inputlabels = ', '.join(
[str(ishape) for ishape in layer.input_shapes])
else:
inputlabels = ''
label = "%s\n|{input:|output:}|{{%s}|{%s}}" % (
label, inputlabels, outputlabels)
node = pydot.Node(layer_id, label=label)
self.g.add_node(node)
self.layer_to_pydotnode[layer] = node
return node
def _process_layer(self, layer, layer_to_name=None, connect_to=None):
"""
Process a layer, adding its node to the graph and creating edges to its
outputs.
`connect_to` specify where the output of the current layer will be
connected
`layer_to_name` is a dict mapping layer to their name in the Graph
model. Should be {} when processing a Sequential model
"""
# The layer can be a container layer, in which case we can recurse
is_graph = isinstance(layer, Graph)
is_seq = isinstance(layer, Sequential)
if self.recursive and (is_graph or is_seq):
# We got a container layer, recursively transform it
if is_graph:
child_layers = layer.outputs.values()
if show_shapes:
# Build the label that will actually contain a table with the
# input/output
outputlabels = str(layer.output_shape)
if hasattr(layer, 'input_shape'):
inputlabels = str(layer.input_shape)
elif hasattr(layer, 'input_shapes'):
inputlabels = ', '.join(
[str(ishape) for ishape in layer.input_shapes])
else:
child_layers = [layer.layers[-1]]
for l in child_layers:
self._process_layer(l, layer_to_name=get_layer_to_name(layer),
connect_to=connect_to)
else:
# This is a simple layer.
label = layer_to_name.get(layer, '')
layer_node = self._pydot_node_for_layer(layer, label=label)
inputlabels = ''
label = '%s\n|{input:|output:}|{{%s}|{%s}}' % (label, inputlabels, outputlabels)
if connect_to is not None:
self.g.add_edge(pydot.Edge(layer_node, connect_to))
node = pydot.Node(layer_id, label=label)
dot.add_node(node)
# Proceed upwards to the parent(s). Only Merge layers have more
# than one parent
if isinstance(layer, Merge): # Merge layer
for l in layer.layers:
self._process_layer(l, layer_to_name,
connect_to=layer_node)
elif hasattr(layer, 'previous') and layer.previous is not None:
self._process_layer(layer.previous, layer_to_name,
connect_to=layer_node)
def __call__(self, model, recursive=True, show_shape=False,
connect_to=None):
self.idgen = 0
# Maps keras layer to the pydot.Node representing them
self.layer_to_pydotnode = {}
self.recursive = recursive
self.show_shape = show_shape
self.g = pydot.Dot()
self.g.set('rankdir', 'TB')
self.g.set('concentrate', True)
self.g.set_node_defaults(shape='record')
if hasattr(model, 'outputs'):
# Graph
for name, l in model.outputs.items():
self._process_layer(l, get_layer_to_name(model),
connect_to=connect_to)
else:
# Sequential container
self._process_layer(model.layers[-1], {}, connect_to=connect_to)
return self.g
# second, add the edges
for layer in layers:
layer_id = str(id(layer))
for i, node in enumerate(layer.inbound_nodes):
node_key = layer.name + '_ib-' + str(i)
if node_key in model.container_nodes:
# add edges
for inbound_layer in node.inbound_layers:
inbound_layer_id = str(id(inbound_layer))
layer_id = str(id(layer))
dot.add_edge(pydot.Edge(inbound_layer_id, layer_id))
return dot
def to_graph(model, **kwargs):
"""
`recursive` controls whether we recursively explore container layers
`show_shape` controls whether the shape is shown in the graph
"""
return ModelToDot()(model, **kwargs)
def plot(model, to_file='model.png', **kwargs):
graph = to_graph(model, **kwargs)
graph.write_png(to_file)
def plot(model, to_file='model.png', show_shapes=False):
dot = model_to_dot(model, show_shapes)
dot.write_png(to_file)
+16 -6
Ver Arquivo
@@ -136,7 +136,10 @@ class BaseWrapper(object):
else:
self.model = self.build_fn(**self.filter_sk_params(self.build_fn))
if self.model.loss.__name__ == 'categorical_crossentropy' and len(y.shape) != 2:
loss_name = self.model.loss
if hasattr(loss_name, '__name__'):
loss_name = loss_name.__name__
if loss_name == 'categorical_crossentropy' and len(y.shape) != 2:
y = to_categorical(y)
fit_args = copy.deepcopy(self.filter_sk_params(Sequential.fit))
@@ -221,9 +224,15 @@ class KerasClassifier(BaseWrapper):
Mean accuracy of predictions on X wrt. y.
'''
kwargs = self.filter_sk_params(Sequential.evaluate, kwargs)
kwargs.update({'show_accuracy': True})
loss, accuracy = self.model.evaluate(X, y, **kwargs)
return accuracy
outputs = self.model.evaluate(X, y, **kwargs)
if type(outputs) is not list:
outputs = [outputs]
for name, output in zip(self.model.metrics_names, outputs):
if name == 'acc':
return output
raise Exception('The model is not configured to compute accuracy. '
'You should pass `metrics=["accuracy"]` to '
'the `model.compile()` method.')
class KerasRegressor(BaseWrapper):
@@ -247,7 +256,7 @@ class KerasRegressor(BaseWrapper):
return self.model.predict(X, **kwargs)
def score(self, X, y, **kwargs):
'''Returns the mean accuracy on the given test data and labels.
'''Returns the mean loss on the given test data and labels.
# Arguments
X: array-like, shape `(n_samples, n_features)`
@@ -263,6 +272,7 @@ class KerasRegressor(BaseWrapper):
Mean accuracy of predictions on X wrt. y.
'''
kwargs = self.filter_sk_params(Sequential.evaluate, kwargs)
kwargs.update({'show_accuracy': False})
loss = self.model.evaluate(X, y, **kwargs)
if type(loss) is list:
return loss[0]
return loss
+2 -2
Ver Arquivo
@@ -3,12 +3,12 @@ from setuptools import find_packages
setup(name='Keras',
version='0.3.2',
version='1.0.0',
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/0.3.2',
download_url='https://github.com/fchollet/keras/tarball/1.0.0',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
@@ -35,10 +35,12 @@ def test_image_classification():
Activation('relu'),
Dense(y_test.shape[-1], activation='softmax')
])
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
history = model.fit(X_train, y_train, nb_epoch=10, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
verbose=0)
assert(history.history['val_acc'][-1] > 0.85)
@@ -4,17 +4,22 @@ import pytest
import string
from keras.utils.test_utils import get_test_data
from keras.models import Sequential
from keras.layers.core import TimeDistributedDense, Dropout, Dense, Activation
from keras.layers.recurrent import GRU, LSTM
from keras.layers.embeddings import Embedding
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers import TimeDistributedDense
from keras.layers import Dense
from keras.layers import Activation
from keras.layers import GRU
from keras.layers import LSTM
from keras.layers import Embedding
def test_temporal_classification():
'''
Classify temporal sequences of float numbers of length 3 into 2 classes using
single layer of GRU units and softmax applied to the last activations of the units
Classify temporal sequences of float numbers
of length 3 into 2 classes using
single layer of GRU units and softmax applied
to the last activations of the units
'''
np.random.seed(1337)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
@@ -29,10 +34,12 @@ def test_temporal_classification():
model.add(GRU(y_train.shape[-1],
input_shape=(X_train.shape[1], X_train.shape[2]),
activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
history = model.fit(X_train, y_train, nb_epoch=5, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
verbose=0)
assert(history.history['val_acc'][-1] > 0.9)
@@ -142,12 +149,12 @@ def test_masked_temporal():
'''
np.random.seed(55318)
model = Sequential()
model.add(Embedding(10, 20, mask_zero=True))
model.add(Embedding(10, 20, mask_zero=True, input_length=20))
model.add(TimeDistributedDense(10))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adam',
sample_weight_mode="temporal")
sample_weight_mode='temporal')
X = np.random.random_integers(1, 9, (50000, 20))
for rowi in range(X.shape[0]):
@@ -164,15 +171,15 @@ def test_masked_temporal():
# Mask 50% of the outputs via sample weights
sample_weight = np.random.random_integers(0, 1, y.shape)
print("X shape: ", X.shape)
print("Y shape: ", Y.shape)
print("sample_weight shape: ", Y.shape)
print('X shape:', X.shape)
print('Y shape:', Y.shape)
print('sample_weight shape:', Y.shape)
history = model.fit(X, Y, validation_split=0.05,
sample_weight=sample_weight,
sample_weight=None,
verbose=1, nb_epoch=2)
ground_truth = -np.log(0.5)
assert(np.abs(history.history['val_loss'][-1] - ground_truth) < 0.05)
assert(np.abs(history.history['val_loss'][-1] - ground_truth) < 0.06)
if __name__ == '__main__':
pytest.main([__file__])
@@ -28,10 +28,12 @@ def test_vector_classification():
Dense(nb_hidden, input_shape=(X_train.shape[-1],), activation='relu'),
Dense(y_train.shape[-1], activation='softmax')
])
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
history = model.fit(X_train, y_train, nb_epoch=15, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
verbose=0)
assert(history.history['val_acc'][-1] > 0.8)
+87 -8
Ver Arquivo
@@ -40,6 +40,10 @@ class TestBackend(object):
def test_linear_operations(self):
check_two_tensor_operation('dot', (4, 2), (2, 4))
check_two_tensor_operation('dot', (4, 2), (5, 2, 3))
check_two_tensor_operation('batch_dot', (4, 2, 3), (4, 5, 3),
axes=(2, 2))
check_single_tensor_operation('transpose', (4, 2))
def test_shape_operations(self):
@@ -145,6 +149,7 @@ class TestBackend(object):
check_single_tensor_operation('exp', (4, 2))
check_single_tensor_operation('log', (4, 2))
check_single_tensor_operation('round', (4, 2))
check_single_tensor_operation('sign', (4, 2))
check_single_tensor_operation('pow', (4, 2), a=3)
check_single_tensor_operation('clip', (4, 2), min_value=0.4,
max_value=0.6)
@@ -222,10 +227,10 @@ class TestBackend(object):
return step_function
th_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTH)
inputs = KTH.variable(input_val)
initial_states = [KTH.variable(init_state_val)]
last_output, outputs, new_states = KTH.rnn(th_rnn_step_fn, inputs,
initial_states,
th_inputs = KTH.variable(input_val)
th_initial_states = [KTH.variable(init_state_val)]
last_output, outputs, new_states = KTH.rnn(th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=False,
mask=None)
th_last_output = KTH.eval(last_output)
@@ -234,10 +239,10 @@ class TestBackend(object):
th_state = KTH.eval(new_states[0])
tf_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTF)
inputs = KTF.variable(input_val)
initial_states = [KTF.variable(init_state_val)]
last_output, outputs, new_states = KTF.rnn(tf_rnn_step_fn, inputs,
initial_states,
tf_inputs = KTF.variable(input_val)
tf_initial_states = [KTF.variable(init_state_val)]
last_output, outputs, new_states = KTF.rnn(tf_rnn_step_fn, tf_inputs,
tf_initial_states,
go_backwards=False,
mask=None)
tf_last_output = KTF.eval(last_output)
@@ -249,6 +254,80 @@ class TestBackend(object):
assert_allclose(tf_outputs, th_outputs, atol=1e-04)
assert_allclose(tf_state, th_state, atol=1e-04)
# test unroll
unrolled_last_output, unrolled_outputs, unrolled_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=False,
mask=None,
unroll=True,
input_length=timesteps)
unrolled_th_last_output = KTH.eval(unrolled_last_output)
unrolled_th_outputs = KTH.eval(unrolled_outputs)
assert len(unrolled_new_states) == 1
unrolled_th_state = KTH.eval(unrolled_new_states[0])
assert_allclose(th_last_output, unrolled_th_last_output, atol=1e-04)
assert_allclose(th_outputs, unrolled_th_outputs, atol=1e-04)
assert_allclose(th_state, unrolled_th_state, atol=1e-04)
# test unroll with backwards = True
bwd_last_output, bwd_outputs, bwd_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=True,
mask=None)
bwd_th_last_output = KTH.eval(bwd_last_output)
bwd_th_outputs = KTH.eval(bwd_outputs)
assert len(bwd_new_states) == 1
bwd_th_state = KTH.eval(bwd_new_states[0])
bwd_unrolled_last_output, bwd_unrolled_outputs, bwd_unrolled_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=True,
mask=None,
unroll=True,
input_length=timesteps)
bwd_unrolled_th_last_output = KTH.eval(bwd_unrolled_last_output)
bwd_unrolled_th_outputs = KTH.eval(bwd_unrolled_outputs)
assert len(bwd_unrolled_new_states) == 1
bwd_unrolled_th_state = KTH.eval(bwd_unrolled_new_states[0])
assert_allclose(bwd_th_last_output, bwd_unrolled_th_last_output, atol=1e-04)
assert_allclose(bwd_th_outputs, bwd_unrolled_th_outputs, atol=1e-04)
assert_allclose(bwd_th_state, bwd_unrolled_th_state, atol=1e-04)
# test unroll with masking
np_mask = np.random.randint(2, size=(32, timesteps))
th_mask = KTH.variable(np_mask)
masked_last_output, masked_outputs, masked_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=False,
mask=th_mask)
masked_th_last_output = KTH.eval(masked_last_output)
masked_th_outputs = KTH.eval(masked_outputs)
assert len(masked_new_states) == 1
masked_th_state = KTH.eval(masked_new_states[0])
unrolled_masked_last_output, unrolled_masked_outputs, unrolled_masked_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=False,
mask=th_mask,
unroll=True,
input_length=timesteps)
unrolled_masked_th_last_output = KTH.eval(unrolled_masked_last_output)
unrolled_masked_th_outputs = KTH.eval(unrolled_masked_outputs)
assert len(unrolled_masked_new_states) == 1
unrolled_masked_th_state = KTH.eval(unrolled_masked_new_states[0])
assert_allclose(unrolled_masked_th_last_output, masked_th_last_output, atol=1e-04)
assert_allclose(unrolled_masked_th_outputs, masked_th_outputs, atol=1e-04)
assert_allclose(unrolled_masked_th_state, masked_th_state, atol=1e-04)
def test_switch(self):
val = np.random.random()
xth = KTH.variable(val)
+565
Ver Arquivo
@@ -0,0 +1,565 @@
import pytest
import json
import numpy as np
from keras.layers import Dense, Dropout
from keras.engine import merge, Input, get_source_inputs
from keras.models import Model
from keras import backend as K
from keras.models import model_from_json, model_from_yaml
def test_learning_phase():
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
a_2 = Dense(16, name='dense_1')(a)
dp = Dropout(0.5, name='dropout')
b_2 = dp(b)
assert dp.uses_learning_phase
assert not a_2._uses_learning_phase
assert b_2._uses_learning_phase
# test merge
m = merge([a_2, b_2], mode='concat')
assert m._uses_learning_phase
# Test recursion
model = Model([a, b], [a_2, b_2])
print(model.input_spec)
assert model.uses_learning_phase
c = Input(shape=(32,), name='input_c')
d = Input(shape=(32,), name='input_d')
c_2, b_2 = model([c, d])
assert c_2._uses_learning_phase
assert b_2._uses_learning_phase
# try actually running graph
fn = K.function(model.inputs + [K.learning_phase()], model.outputs)
input_a_np = np.random.random((10, 32))
input_b_np = np.random.random((10, 32))
fn_outputs_no_dp = fn([input_a_np, input_b_np, 0])
fn_outputs_dp = fn([input_a_np, input_b_np, 1])
# output a: nothing changes
assert fn_outputs_no_dp[0].sum() == fn_outputs_dp[0].sum()
# output b: dropout applied
assert fn_outputs_no_dp[1].sum() != fn_outputs_dp[1].sum()
def test_node_construction():
####################################################
# test basics
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
assert a._keras_shape == (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
assert a_tensor_index is 0
node = a_layer.inbound_nodes[a_node_index]
assert node.outbound_layer == a_layer
assert type(node.inbound_layers) is list
assert node.inbound_layers == []
assert type(node.input_tensors) is list
assert node.input_tensors == [a]
assert type(node.input_masks) is list
assert node.input_masks == [None]
assert type(node.input_shapes) is list
assert node.input_shapes == [(None, 32)]
assert type(node.output_tensors) is list
assert node.output_tensors == [a]
assert type(node.output_shapes) is list
assert node.output_shapes == [(None, 32)]
assert type(node.output_masks) is list
assert node.output_masks == [None]
dense = Dense(16, name='dense_1')
a_2 = dense(a)
b_2 = dense(b)
assert len(dense.inbound_nodes) == 2
assert len(dense.outbound_nodes) == 0
assert dense.inbound_nodes[0].inbound_layers == [a_layer]
assert dense.inbound_nodes[0].outbound_layer == dense
assert dense.inbound_nodes[1].inbound_layers == [b_layer]
assert dense.inbound_nodes[1].outbound_layer == dense
assert dense.inbound_nodes[0].input_tensors == [a]
assert dense.inbound_nodes[1].input_tensors == [b]
# test layer properties
test_layer = Dense(16, name='test_layer')
a_test = test_layer(a)
assert test_layer.input == a
assert test_layer.output == a_test
assert test_layer.input_mask is None
assert test_layer.output_mask is None
assert test_layer.input_shape == (None, 32)
assert test_layer.output_shape == (None, 16)
with pytest.raises(Exception):
dense.input
with pytest.raises(Exception):
dense.output
with pytest.raises(Exception):
dense.input_mask
with pytest.raises(Exception):
dense.output_mask
assert dense.get_input_at(0) == a
assert dense.get_input_at(1) == b
assert dense.get_output_at(0) == a_2
assert dense.get_output_at(1) == b_2
assert dense.get_input_shape_at(0) == (None, 32)
assert dense.get_input_shape_at(1) == (None, 32)
assert dense.get_output_shape_at(0) == (None, 16)
assert dense.get_output_shape_at(1) == (None, 16)
assert dense.get_input_mask_at(0) is None
assert dense.get_input_mask_at(1) is None
assert dense.get_output_mask_at(0) is None
assert dense.get_output_mask_at(1) is None
def test_multi_input_layer():
####################################################
# test multi-input layer
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
dense = Dense(16, name='dense_1')
a_2 = dense(a)
b_2 = dense(b)
merged = merge([a_2, b_2], mode='concat', name='merge')
assert merged._keras_shape == (None, 16 * 2)
merge_layer, merge_node_index, merge_tensor_index = merged._keras_history
assert merge_node_index == 0
assert merge_tensor_index == 0
assert len(merge_layer.inbound_nodes) == 1
assert len(merge_layer.outbound_nodes) == 0
assert len(merge_layer.inbound_nodes[0].input_tensors) == 2
assert len(merge_layer.inbound_nodes[0].inbound_layers) == 2
c = Dense(64, name='dense_2')(merged)
d = Dense(5, name='dense_3')(c)
model = Model(input=[a, b], output=[c, d], name='model')
assert len(model.layers) == 6
print('model.input_layers:', model.input_layers)
print('model.input_layers_node_indices:', model.input_layers_node_indices)
print('model.input_layers_tensor_indices:', model.input_layers_tensor_indices)
print('model.output_layers', model.output_layers)
print('output_shape:', model.get_output_shape_for([(None, 32), (None, 32)]))
assert model.get_output_shape_for([(None, 32), (None, 32)]) == [(None, 64), (None, 5)]
assert model.compute_mask([a, b], [None, None]) == [None, None]
print('output_shape:', model.get_output_shape_for([(None, 32), (None, 32)]))
assert model.get_output_shape_for([(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])
assert [l.name for l in model.layers][2:] == ['dense_1', 'merge', 'dense_2', 'dense_3']
print('input_layers:', [l.name for l in model.input_layers])
assert [l.name for l in model.input_layers] == ['input_a', 'input_b']
print('output_layers:', [l.name for l in model.output_layers])
assert [l.name for l in model.output_layers] == ['dense_2', 'dense_3']
# actually run model
fn = K.function(model.inputs, model.outputs)
input_a_np = np.random.random((10, 32))
input_b_np = np.random.random((10, 32))
fn_outputs = fn([input_a_np, input_b_np])
assert [x.shape for x in fn_outputs] == [(10, 64), (10, 5)]
# test get_source_inputs
print(get_source_inputs(c))
assert get_source_inputs(c) == [a, b]
# serialization / deserialization
json_config = model.to_json()
recreated_model = model_from_json(json_config)
recreated_model.compile('rmsprop', 'mse')
print('recreated:')
print([layer.name for layer in recreated_model.layers])
print([layer.name for layer in recreated_model.input_layers])
print([layer.name for layer in recreated_model.output_layers])
assert [l.name for l in recreated_model.layers][2:] == ['dense_1', 'merge', 'dense_2', 'dense_3']
assert [l.name for l in recreated_model.input_layers] == ['input_a', 'input_b']
assert [l.name for l in recreated_model.output_layers] == ['dense_2', 'dense_3']
fn = K.function(recreated_model.inputs, recreated_model.outputs)
input_a_np = np.random.random((10, 32))
input_b_np = np.random.random((10, 32))
fn_outputs = fn([input_a_np, input_b_np])
assert [x.shape for x in fn_outputs] == [(10, 64), (10, 5)]
def test_recursion():
####################################################
# test recursion
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
dense = Dense(16, name='dense_1')
a_2 = dense(a)
b_2 = dense(b)
merged = merge([a_2, b_2], mode='concat', name='merge')
c = Dense(64, name='dense_2')(merged)
d = Dense(5, name='dense_3')(c)
model = Model(input=[a, b], output=[c, d], name='model')
e = Input(shape=(32,), name='input_e')
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
# test separate manipulation of different layer outputs
i = Dense(7, name='dense_4')(h)
final_model = Model(input=[e, f], output=[i, g], name='final')
assert len(final_model.inputs) == 2
assert len(final_model.outputs) == 2
assert len(final_model.layers) == 4
# we don't check names of first 2 layers (inputs) because
# ordering of same-level layers is not fixed
print('final_model layers:', [layer.name for layer in final_model.layers])
assert [layer.name for layer in final_model.layers][2:] == ['model', 'dense_4']
print(model.compute_mask([e, f], [None, None]))
assert model.compute_mask([e, f], [None, None]) == [None, None]
print(final_model.get_output_shape_for([(10, 32), (10, 32)]))
assert final_model.get_output_shape_for([(10, 32), (10, 32)]) == [(10, 7), (10, 64)]
# run recursive model
fn = K.function(final_model.inputs, final_model.outputs)
input_a_np = np.random.random((10, 32))
input_b_np = np.random.random((10, 32))
fn_outputs = fn([input_a_np, input_b_np])
assert [x.shape for x in fn_outputs] == [(10, 7), (10, 64)]
# test serialization
model_config = final_model.get_config()
print(json.dumps(model_config, indent=4))
recreated_model = Model.from_config(model_config)
fn = K.function(recreated_model.inputs, recreated_model.outputs)
input_a_np = np.random.random((10, 32))
input_b_np = np.random.random((10, 32))
fn_outputs = fn([input_a_np, input_b_np])
assert [x.shape for x in fn_outputs] == [(10, 7), (10, 64)]
####################################################
# test multi-input multi-output
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
o = Input(shape=(32,), name='input_o')
p = Input(shape=(32,), name='input_p')
q, r = model([o, p])
assert n._keras_shape == (None, 5)
assert q._keras_shape == (None, 64)
s = merge([n, q], mode='concat', name='merge_nq')
assert s._keras_shape == (None, 64 + 5)
# test with single output as 1-elem list
multi_io_model = Model([j, k, o, p], [s])
fn = K.function(multi_io_model.inputs, multi_io_model.outputs)
fn_outputs = fn([np.random.random((10, 32)), np.random.random((10, 32)),
np.random.random((10, 32)), np.random.random((10, 32))])
assert [x.shape for x in fn_outputs] == [(10, 69)]
# test with single output as tensor
multi_io_model = Model([j, k, o, p], s)
fn = K.function(multi_io_model.inputs, multi_io_model.outputs)
fn_outputs = fn([np.random.random((10, 32)), np.random.random((10, 32)),
np.random.random((10, 32)), np.random.random((10, 32))])
# note that the output of the K.function will still be a 1-elem list
assert [x.shape for x in fn_outputs] == [(10, 69)]
# test serialization
print('multi_io_model.layers:', multi_io_model.layers)
print('len(model.inbound_nodes):', len(model.inbound_nodes))
print('len(model.outbound_nodes):', len(model.outbound_nodes))
model_config = multi_io_model.get_config()
print(model_config)
print(json.dumps(model_config, indent=4))
recreated_model = Model.from_config(model_config)
fn = K.function(recreated_model.inputs, recreated_model.outputs)
fn_outputs = fn([np.random.random((10, 32)), np.random.random((10, 32)),
np.random.random((10, 32)), np.random.random((10, 32))])
# note that the output of the K.function will still be a 1-elem list
assert [x.shape for x in fn_outputs] == [(10, 69)]
config = model.get_config()
new_model = Model.from_config(config)
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
####################################################
# test invalid graphs
# input is not an Input tensor
j = Input(shape=(32,), name='input_j')
j = Dense(32)(j)
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
with pytest.raises(Exception):
invalid_model = 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(Exception) as e:
invalid_model = Model([j], [m, n])
# redudant outputs
j = Input(shape=(32,), name='input_j')
k = Input(shape=(32,), name='input_k')
m, n = model([j, k])
# this should work lol
# TODO: raise a warning
invalid_model = 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(Exception):
invalid_model = 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(Exception):
invalid_model = 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])
# magic
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 not hasattr(m_tf, '_keras_shape')
assert not hasattr(n_tf, '_keras_shape')
assert K.int_shape(m_tf) == (None, 64)
assert K.int_shape(n_tf) == (None, 5)
def test_functional_guide():
# MNIST
from keras.layers import Input, Dense, LSTM
from keras.models import Model
from keras.utils import np_utils
# this returns a tensor
inputs = Input(shape=(784,))
# a layer instance is callable on a tensor, and returns a tensor
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
# this creates a model that includes
# the Input layer and three Dense layers
model = Model(input=inputs, output=predictions)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# the data, shuffled and split between tran and test sets
X_train = np.random.random((100, 784))
Y_train = np.random.random((100, 10))
model.fit(X_train, Y_train, nb_epoch=2, batch_size=128)
assert model.inputs == [inputs]
assert model.outputs == [predictions]
assert model.input == inputs
assert model.output == predictions
assert model.input_shape == (None, 784)
assert model.output_shape == (None, 10)
# try calling the sequential model
inputs = Input(shape=(784,))
new_outputs = model(inputs)
new_model = Model(input=inputs, output=new_outputs)
new_model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
##################################################
# multi-io
##################################################
tweet_a = Input(shape=(4, 25))
tweet_b = Input(shape=(4, 25))
# this layer can take as input a matrix
# and will return a vector of size 64
shared_lstm = LSTM(64)
# when we reuse the same layer instance
# multiple times, the weights of the layer
# are also being reused
# (it is effectively *the same* layer)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
# we can then concatenate the two vectors:
merged_vector = merge([encoded_a, encoded_b],
mode='concat', concat_axis=-1)
# and add a logistic regression on top
predictions = Dense(1, activation='sigmoid')(merged_vector)
# we define a trainable model linking the
# tweet inputs to the predictions
model = Model(input=[tweet_a, tweet_b], output=predictions)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
data_a = np.random.random((1000, 4, 25))
data_b = np.random.random((1000, 4, 25))
labels = np.random.random((1000,))
model.fit([data_a, data_b], labels, nb_epoch=1)
model.summary()
assert model.inputs == [tweet_a, tweet_b]
assert model.outputs == [predictions]
assert model.input == [tweet_a, tweet_b]
assert model.output == predictions
assert model.output == predictions
assert model.input_shape == [(None, 4, 25), (None, 4, 25)]
assert model.output_shape == (None, 1)
assert shared_lstm.get_output_at(0) == encoded_a
assert shared_lstm.get_output_at(1) == encoded_b
assert shared_lstm.input_shape == (None, 4, 25)
def test_sequential_regression():
from keras.models import Sequential, Model
from keras.layers import Merge, Embedding, BatchNormalization, LSTM, InputLayer, Input
# start with a basic example of using a Sequential model
# inside the functional API
seq = Sequential()
seq.add(Dense(input_dim=10, output_dim=10))
x = Input(shape=(10,))
y = seq(x)
model = Model(x, y)
model.compile('rmsprop', 'mse')
weights = model.get_weights()
# test serialization
config = model.get_config()
model = Model.from_config(config)
model.compile('rmsprop', 'mse')
model.set_weights(weights)
# more advanced model with multiple branches
branch_1 = Sequential(name='branch_1')
branch_1.add(Embedding(input_dim=100,
output_dim=10,
input_length=2,
name='embed_1'))
branch_1.add(LSTM(32, name='lstm_1'))
branch_1.add(BatchNormalization())
branch_2 = Sequential(name='branch_2')
branch_2.add(Dense(32, input_shape=(8,), name='dense_2'))
branch_3 = Sequential(name='branch_3')
branch_3.add(Dense(32, input_shape=(6,), name='dense_3'))
branch_1_2 = Sequential([Merge([branch_1, branch_2], mode='concat')], name='branch_1_2')
branch_1_2.add(Dense(16, name='dense_1_2-0'))
# test whether impromtu input_shape breaks the model
branch_1_2.add(Dense(16, input_shape=(16,), name='dense_1_2-1'))
model = Sequential([Merge([branch_1_2, branch_3], mode='concat')], name='final')
model.add(Dense(16, name='dense_final'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
model.summary()
x = (100 * np.random.random((100, 2))).astype('int32')
y = np.random.random((100, 8))
z = np.random.random((100, 6))
labels = np.random.random((100, 16))
model.fit([x, y, z], labels, nb_epoch=1)
# test if Sequential can be called in the functional API
a = Input(shape=(2,), dtype='int32')
b = Input(shape=(8,))
c = Input(shape=(6,))
o = model([a, b, c])
outer_model = Model([a, b, c], o)
outer_model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
outer_model.fit([x, y, z], labels, nb_epoch=1)
# test serialization
config = outer_model.get_config()
outer_model = Model.from_config(config)
outer_model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
outer_model.fit([x, y, z], labels, nb_epoch=1)
if __name__ == "__main__":
pytest.main([__file__])
+157
Ver Arquivo
@@ -0,0 +1,157 @@
import pytest
import numpy as np
from keras.layers import Dense, Dropout
from keras.engine.topology import merge, Input
from keras.engine.training import Model
from keras import backend as K
def test_model_methods():
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)
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
output_a_np = np.random.random((10, 4))
output_b_np = np.random.random((10, 3))
# test train_on_batch
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
out = model.train_on_batch({'input_a': input_a_np, 'input_b': input_b_np},
[output_a_np, output_b_np])
out = model.train_on_batch({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np})
# test fit
out = model.fit([input_a_np, input_b_np],
[output_a_np, output_b_np], nb_epoch=1, batch_size=4)
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
[output_a_np, output_b_np], nb_epoch=1, batch_size=4)
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np},
nb_epoch=1, batch_size=4)
# test validation_split
out = model.fit([input_a_np, input_b_np],
[output_a_np, output_b_np],
nb_epoch=1, batch_size=4, validation_split=0.5)
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
[output_a_np, output_b_np],
nb_epoch=1, batch_size=4, validation_split=0.5)
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np},
nb_epoch=1, batch_size=4, validation_split=0.5)
# test validation data
out = model.fit([input_a_np, input_b_np],
[output_a_np, output_b_np],
nb_epoch=1, batch_size=4,
validation_data=([input_a_np, input_b_np], [output_a_np, output_b_np]))
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
[output_a_np, output_b_np],
nb_epoch=1, batch_size=4, validation_split=0.5,
validation_data=({'input_a': input_a_np, 'input_b': input_b_np}, [output_a_np, output_b_np]))
out = model.fit({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np},
nb_epoch=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}))
# test_on_batch
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
out = model.test_on_batch({'input_a': input_a_np, 'input_b': input_b_np},
[output_a_np, output_b_np])
out = model.test_on_batch({'input_a': input_a_np, 'input_b': input_b_np},
{'dense_1': output_a_np, 'dropout': output_b_np})
# predict_on_batch
out = model.predict_on_batch([input_a_np, input_b_np])
out = model.predict_on_batch({'input_a': input_a_np, 'input_b': input_b_np})
# predict, evaluate
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
output_a_np = np.random.random((10, 4))
output_b_np = np.random.random((10, 3))
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)
# with sample_weight
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
output_a_np = np.random.random((10, 4))
output_b_np = np.random.random((10, 3))
sample_weight = [None, np.random.random((10,))]
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=sample_weight)
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np],
sample_weight=sample_weight)
# test accuracy metric
model.compile(optimizer, loss, metrics=['acc'],
sample_weight_mode=None)
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 3
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 3
# this should also work
model.compile(optimizer, loss, metrics={'dense_1': 'acc'},
sample_weight_mode=None)
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
# and this as well
model.compile(optimizer, loss, metrics={'dense_1': ['acc']},
sample_weight_mode=None)
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
output_a_np = np.random.random((10, 4))
output_b_np = np.random.random((10, 3))
out = model.fit([input_a_np, input_b_np], [output_a_np, output_b_np], batch_size=4, nb_epoch=1)
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)
if __name__ == '__main__':
pytest.main([__file__])
+17 -151
Ver Arquivo
@@ -1,180 +1,46 @@
import pytest
from numpy.testing import assert_allclose
import numpy as np
from keras import backend as K
def get_standard_values():
'''
These are just a set of floats used for testing the activation
functions, and are useful in multiple tests.
The values should all be non-negative because they and their negatives
are used to test the ReLU derivates in this file.
'''
return np.array([[0, 0.1, 0.5, 0.9, 1.0, 10, 1e2, 0.01]], dtype=K.floatx())
from keras.utils.test_utils import layer_test
def test_leaky_relu():
np.random.seed(1337)
from keras.layers.advanced_activations import LeakyReLU
inp = get_standard_values()
for alpha in [0., .5, -1.]:
layer = LeakyReLU(alpha=alpha)
layer.input = K.variable(inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, inp)
layer.input = K.variable(-inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, -inp * alpha)
config = layer.get_config()
assert config['alpha'] == alpha
layer_test(LeakyReLU, kwargs={'alpha': alpha},
input_shape=(2, 3, 4))
def test_prelu():
from keras.layers.advanced_activations import PReLU
np.random.seed(1337)
inp = get_standard_values()
for train in [True, False]:
# test with custom weights
alphas = np.random.random(inp.shape)
layer = PReLU(weights=alphas, input_shape=inp.flatten().shape)
# calling build here causes an error, unclear if this is a bug
# layer.build()
layer.input = K.variable(inp)
outp = K.eval(layer.get_output(train))
assert_allclose(inp, outp)
layer.input = K.variable(-inp)
outp = K.eval(layer.get_output(train))
assert_allclose(-alphas * inp, outp)
# test with default weights
layer = PReLU(input_shape=inp.flatten().shape)
# layer.build()
layer.input = K.variable(inp)
outp = K.eval(layer.get_output(train))
assert_allclose(inp, outp)
layer.input = K.variable(-inp)
outp = K.eval(layer.get_output(train))
assert_allclose(0., alphas * outp)
layer.get_config()
layer_test(PReLU, kwargs={},
input_shape=(2, 3, 4))
def test_elu():
from keras.layers.advanced_activations import ELU
np.random.seed(1337)
inp = get_standard_values()
for alpha in [0.1, .5, -1., 1.]:
layer = ELU(alpha=alpha)
layer.input = K.variable(inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, inp, rtol=1e-3)
layer.input = K.variable(-inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, alpha * (np.exp(-inp) - 1.), rtol=1e-3)
config = layer.get_config()
assert config['alpha'] == alpha
for alpha in [0., .5, -1.]:
layer_test(ELU, kwargs={'alpha': alpha},
input_shape=(2, 3, 4))
@pytest.mark.skipif(K._BACKEND == 'tensorflow',
reason='currently not working with TensorFlow')
def test_parametric_softplus():
from keras.layers.advanced_activations import ParametricSoftplus
np.random.seed(1337)
inp = np.vstack((get_standard_values(), -get_standard_values()))
# large values cause overflow in exp
inp = inp[:-2]
for alpha in [.5, -1., 1., 5]:
for beta in [.5, -1., 1., 2]:
layer = ParametricSoftplus(alpha_init=alpha,
beta_init=beta,
input_shape=inp.shape)
layer.input = K.variable(inp)
layer.build()
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, alpha * np.log(1. + np.exp(beta * inp)),
atol=1e-3)
config = layer.get_config()
assert config['alpha_init'] == alpha
assert config['beta_init'] == beta
for alpha in [0., .5, -1.]:
layer_test(ParametricSoftplus,
kwargs={'alpha_init': 1.,
'beta_init': -1},
input_shape=(2, 3, 4))
@pytest.mark.skipif(K._BACKEND == 'tensorflow',
reason='currently not working with TensorFlow')
def test_thresholded_linear():
from keras.layers.advanced_activations import ThresholdedLinear
np.random.seed(1337)
inp = get_standard_values()
for theta in [0., .5, 1.]:
layer = ThresholdedLinear(theta=theta)
layer.input = K.variable(inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, inp * (np.abs(inp) >= theta))
layer.input = K.variable(-inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, -inp * (np.abs(inp) >= theta))
config = layer.get_config()
assert config['theta'] == theta
@pytest.mark.skipif(K._BACKEND == 'tensorflow',
reason='currently not working with TensorFlow')
def test_thresholded_relu():
from keras.layers.advanced_activations import ThresholdedReLU
np.random.seed(1337)
inp = get_standard_values()
for theta in [-1, 0., .5, 1.]:
layer = ThresholdedReLU(theta=theta)
layer.input = K.variable(inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, inp * (inp > theta))
layer.input = K.variable(-inp)
for train in [True, False]:
outp = K.eval(layer.get_output(train))
assert_allclose(outp, -inp * (-inp > theta))
config = layer.get_config()
assert config['theta'] == theta
layer_test(ThresholdedReLU, kwargs={'theta': 0.5},
input_shape=(2, 3, 4))
def test_srelu():
from keras.layers.advanced_activations import SReLU
np.random.seed(1337)
inp = np.array([-2, -1., -0.5, 0., 0.5, 1., 2.])
out = np.array([-1.5, -1., -0.5, 0., 0.5, 1., 3.])
input_size = len(inp)
for train in [True, False]:
layer = SReLU(input_shape=inp.flatten().shape)
ones_proto = np.ones(input_size)
layer.set_weights([ones_proto * -1., ones_proto * 0.5,
ones_proto * 2., ones_proto * 2.])
layer.input = K.variable(inp)
outp = K.eval(layer.get_output(train))
assert_allclose(out, outp)
layer.get_config()
layer_test(SReLU, kwargs={},
input_shape=(2, 3, 4))
if __name__ == '__main__':
-212
Ver Arquivo
@@ -1,212 +0,0 @@
"""Test keras.layers.core.Layer.__call__"""
import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras import backend as K
from keras.layers.core import Dense
from keras.models import Sequential, Graph
def test_layer_call():
"""Test keras.layers.core.Layer.__call__"""
nb_samples, input_dim, output_dim = 3, 10, 5
layer = Dense(output_dim, input_dim=input_dim)
W = np.asarray(K.eval(layer.W)).astype(K.floatx())
X = K.placeholder(ndim=2)
Y = layer(X)
f = K.function([X], [Y])
x = np.ones((nb_samples, input_dim)).astype(K.floatx())
y = f([x])[0].astype(K.floatx())
t = np.dot(x, W).astype(K.floatx())
assert_allclose(t, y, rtol=.2)
def test_sequential_call():
"""Test keras.models.Sequential.__call__"""
nb_samples, input_dim, output_dim = 3, 10, 5
model = Sequential()
model.add(Dense(output_dim=output_dim, input_dim=input_dim))
model.compile('sgd', 'mse')
# test flat model
X = K.placeholder(ndim=2)
Y = model(X)
f = K.function([X], [Y])
x = np.ones((nb_samples, input_dim)).astype(K.floatx())
y1 = f([x])[0].astype(K.floatx())
y2 = model.predict(x)
# results of __call__ should match model.predict
assert_allclose(y1, y2)
# test nested model
model2 = Sequential()
model2.add(model)
model2.compile('sgd', 'mse')
Y2 = model2(X)
f = K.function([X], [Y2])
y1 = f([x])[0].astype(K.floatx())
y2 = model2.predict(x)
# results of __call__ should match model.predict
assert_allclose(y1, y2)
def test_graph_call():
"""Test keras.models.Graph.__call__"""
nb_samples, input_dim, output_dim = 3, 10, 5
model = Graph()
model.add_input('input', input_shape=(input_dim, ))
model.add_node(Dense(output_dim=output_dim, input_dim=input_dim),
input='input', name='output', create_output=True)
model.compile('sgd', {'output': 'mse'})
# test flat model
X = K.placeholder(ndim=2)
Y = model(X)
f = K.function([X], [Y])
x = np.ones((nb_samples, input_dim)).astype(K.floatx())
y1 = f([x])[0].astype(K.floatx())
y2 = model.predict({'input': x})['output']
# results of __call__ should match model.predict
assert_allclose(y1, y2)
# test nested Graph models
model2 = Graph()
model2.add_input('input', input_shape=(input_dim, ))
model2.add_node(model, input='input', name='output', create_output=True)
# need to turn off cache because we're reusing model
model2.cache_enabled = False
model2.compile('sgd', {'output': 'mse'})
Y2 = model2(X)
f = K.function([X], [Y2])
y1 = f([x])[0].astype(K.floatx())
y2 = model2.predict({'input': x})['output']
# results of __call__ should match model.predict
assert_allclose(y1, y2)
def test_graph_multiple_in_out_call():
"""Test keras.models.Graph.__call__ with multiple inputs"""
nb_samples, input_dim, output_dim = 3, 10, 5
model = Graph()
model.add_input('input1', input_shape=(input_dim, ))
model.add_input('input2', input_shape=(input_dim, ))
model.add_node(Dense(output_dim=output_dim, input_dim=input_dim),
inputs=['input1', 'input2'], merge_mode='sum', name='output', create_output=True)
model.compile('sgd', {'output': 'mse'})
# test flat model
X1 = K.placeholder(ndim=2)
X2 = K.placeholder(ndim=2)
Y = model({'input1': X1, 'input2': X2})['output']
f = K.function([X1, X2], [Y])
x1 = np.ones((nb_samples, input_dim)).astype(K.floatx())
x2 = np.ones((nb_samples, input_dim)).astype(K.floatx()) * -2
y1 = f([x1, x2])[0].astype(K.floatx())
y2 = model.predict({'input1': x1, 'input2': x2})['output']
# results of __call__ should match model.predict
assert_allclose(y1, y2)
# test with single input, multiple outputs
model2 = Graph()
model2.add_input('input', input_shape=(input_dim, ))
model2.add_node(Dense(output_dim=output_dim, input_dim=input_dim),
input='input', name='output1', create_output=True)
model2.add_node(Dense(output_dim=output_dim, input_dim=input_dim),
input='input', name='output2', create_output=True)
model2.compile('sgd', {'output1': 'mse', 'output2': 'mse'})
# test flat model
X = K.placeholder(ndim=2)
Y = model2(X)
f = K.function([X], [Y['output1'], Y['output2']])
x = np.ones((nb_samples, input_dim)).astype(K.floatx())
out = f([x])
y1a = out[0].astype(K.floatx())
y1b = out[1].astype(K.floatx())
y2 = model2.predict({'input': x})
# results of __call__ should match model.predict
assert_allclose(y1a, y2['output1'])
assert_allclose(y1b, y2['output2'])
# test with multiple inputs, multiple outputs
model3 = Graph()
model3.add_input('input1', input_shape=(input_dim, ))
model3.add_input('input2', input_shape=(input_dim, ))
model3.add_shared_node(Dense(output_dim=output_dim, input_dim=input_dim),
inputs=['input1', 'input2'], name='output',
outputs=['output1', 'output2'], create_output=True)
model3.compile('sgd', {'output1': 'mse', 'output2': 'mse'})
# test flat model
Y = model3({'input1': X1, 'input2': X2})
f = K.function([X1, X2], [Y['output1'], Y['output2']])
x1 = np.ones((nb_samples, input_dim)).astype(K.floatx())
x2 = np.ones((nb_samples, input_dim)).astype(K.floatx()) * -2
out = f([x1, x2])
y1a = out[0].astype(K.floatx())
y1b = out[1].astype(K.floatx())
y2 = model3.predict({'input1': x1, 'input2': x2})
# results of __call__ should match model.predict
assert_allclose(y1a, y2['output1'])
assert_allclose(y1b, y2['output2'])
def test_nested_call():
"""Test nested Sequential and Graph models"""
nb_samples, input_dim, output_dim = 3, 10, 5
X = K.placeholder(ndim=2)
x = np.ones((nb_samples, input_dim)).astype(K.floatx())
# test Graph model nested inside Sequential model
model = Graph()
model.add_input('input', input_shape=(input_dim, ))
model.add_node(Dense(output_dim=output_dim, input_dim=input_dim),
input='input', name='output', create_output=True)
model2 = Sequential()
model2.add(model)
model2.compile('sgd', 'mse')
Y2 = model2(X)
f = K.function([X], [Y2])
y1 = f([x])[0].astype(K.floatx())
y2 = model2.predict(x)
# results of __call__ should match model.predict
assert_allclose(y1, y2)
# test Sequential model inside Graph model
model3 = Sequential()
model3.add(Dense(output_dim=output_dim, input_dim=input_dim))
model4 = Graph()
model4.add_input('input', input_shape=(input_dim, ))
model4.add_node(model3, input='input', name='output', create_output=True)
model4.compile('sgd', {'output': 'mse'})
Y2 = model4(X)
f = K.function([X], [Y2])
y1 = f([x])[0].astype(K.floatx())
y2 = model4.predict({'input': x})['output']
# results of __call__ should match model.predict
assert_allclose(y1, y2)
if __name__ == '__main__':
pytest.main([__file__])
+177 -297
Ver Arquivo
@@ -2,295 +2,176 @@ import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.utils.test_utils import layer_test
from keras import backend as K
from keras.layers import convolutional
def test_convolution_1d():
nb_samples = 9
nb_steps = 7
input_dim = 10
filter_length = 6
nb_filter = 5
nb_samples = 2
nb_steps = 8
input_dim = 5
filter_length = 3
nb_filter = 4
weights_in = [np.ones((nb_filter, input_dim, filter_length, 1)),
np.ones(nb_filter)]
for border_mode in ['valid', 'same']:
for subsample_length in [1]:
if border_mode == 'same' and subsample_length != 1:
continue
layer_test(convolutional.Convolution1D,
kwargs={'nb_filter': nb_filter,
'filter_length': filter_length,
'border_mode': border_mode,
'subsample_length': subsample_length},
input_shape=(nb_samples, nb_steps, input_dim))
input = np.ones((nb_samples, nb_steps, input_dim))
for weight in [None, weights_in]:
for border_mode in ['valid', 'same']:
for subsample_length in [1]:
if border_mode == 'same' and subsample_length != 1:
continue
for W_regularizer in [None, 'l2']:
for b_regularizer in [None, 'l2']:
for act_regularizer in [None, 'l2']:
layer = convolutional.Convolution1D(
nb_filter, filter_length,
weights=weight,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
activity_regularizer=act_regularizer,
subsample_length=subsample_length,
input_shape=(None, input_dim))
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
assert input.shape[0] == out.shape[0]
if border_mode == 'same' and subsample_length == 1:
assert input.shape[1] == out.shape[1]
layer.get_config()
layer_test(convolutional.Convolution1D,
kwargs={'nb_filter': nb_filter,
'filter_length': filter_length,
'border_mode': border_mode,
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample_length': subsample_length},
input_shape=(nb_samples, nb_steps, input_dim))
def test_maxpooling_1d():
nb_samples = 9
nb_steps = 7
input_dim = 10
input = np.ones((nb_samples, nb_steps, input_dim))
for stride in [1, 2]:
layer = convolutional.MaxPooling1D(stride=stride,
border_mode='valid')
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
layer_test(convolutional.MaxPooling1D,
kwargs={'stride': stride,
'border_mode': 'valid'},
input_shape=(3, 5, 4))
def test_averagepooling_1d():
nb_samples = 9
nb_steps = 7
input_dim = 10
input = np.ones((nb_samples, nb_steps, input_dim))
for stride in [1, 2]:
layer = convolutional.AveragePooling1D(stride=stride,
border_mode='valid')
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
layer_test(convolutional.AveragePooling1D,
kwargs={'stride': stride,
'border_mode': 'valid'},
input_shape=(3, 5, 4))
def test_convolution_2d():
nb_samples = 8
nb_filter = 9
stack_size = 7
nb_filter = 3
stack_size = 4
nb_row = 10
nb_col = 6
input_nb_row = 11
input_nb_col = 12
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
if border_mode == 'same' and subsample != (1, 1):
continue
weights_in = [np.ones((nb_filter, stack_size, nb_row, nb_col)), np.ones(nb_filter)]
layer_test(convolutional.Convolution2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'subsample': subsample},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
for weight in [None, weights_in]:
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
if border_mode == 'same' and subsample != (1, 1):
continue
for W_regularizer in [None, 'l2']:
for b_regularizer in [None, 'l2']:
for act_regularizer in [None, 'l2']:
layer = convolutional.Convolution2D(
nb_filter, nb_row, nb_col,
weights=weight,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
activity_regularizer=act_regularizer,
subsample=subsample,
input_shape=(stack_size, None, None))
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
if border_mode == 'same' and subsample == (1, 1):
assert out.shape[2:] == input.shape[2:]
layer.get_config()
def test_convolution_2d_dim_ordering():
nb_filter = 4
nb_row = 3
nb_col = 2
stack_size = 3
np.random.seed(1337)
weights = [np.random.random((nb_filter, stack_size, nb_row, nb_col)),
np.random.random(nb_filter)]
input = np.random.random((1, stack_size, 10, 10))
layer = convolutional.Convolution2D(
nb_filter, nb_row, nb_col,
weights=weights,
input_shape=input.shape[1:],
dim_ordering='th')
layer.input = K.variable(input)
out_th = K.eval(layer.get_output(False))
input = np.transpose(input, (0, 2, 3, 1))
weights[0] = np.transpose(weights[0], (2, 3, 1, 0))
layer = convolutional.Convolution2D(
nb_filter, nb_row, nb_col,
weights=weights,
input_shape=input.shape[1:],
dim_ordering='tf')
layer.input = K.variable(input)
out_tf = K.eval(layer.get_output(False))
assert_allclose(out_tf, np.transpose(out_th, (0, 2, 3, 1)), atol=1e-05)
layer_test(convolutional.Convolution2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
def test_maxpooling_2d():
nb_samples = 9
stack_size = 7
input_nb_row = 11
input_nb_col = 12
pool_size = (3, 3)
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
for strides in [(1, 1), (2, 2)]:
layer = convolutional.MaxPooling2D(strides=strides,
border_mode='valid',
pool_size=pool_size)
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
def test_maxpooling_2d_dim_ordering():
stack_size = 3
input = np.random.random((1, stack_size, 10, 10))
layer = convolutional.MaxPooling2D(
(2, 2),
input_shape=input.shape[1:],
dim_ordering='th')
layer.input = K.variable(input)
out_th = K.eval(layer.get_output(False))
input = np.transpose(input, (0, 2, 3, 1))
layer = convolutional.MaxPooling2D(
(2, 2),
input_shape=input.shape[1:],
dim_ordering='tf')
layer.input = K.variable(input)
out_tf = K.eval(layer.get_output(False))
assert_allclose(out_tf, np.transpose(out_th, (0, 2, 3, 1)), atol=1e-05)
layer_test(convolutional.MaxPooling2D,
kwargs={'strides': strides,
'border_mode': 'valid',
'pool_size': pool_size},
input_shape=(3, 4, 11, 12))
def test_averagepooling_2d():
nb_samples = 9
stack_size = 7
input_nb_row = 11
input_nb_col = 12
pool_size = (3, 3)
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
for border_mode in ['valid', 'same']:
for pool_size in [(2, 2), (3, 3), (4, 4), (5, 5)]:
for strides in [(1, 1), (2, 2)]:
layer = convolutional.AveragePooling2D(strides=strides,
border_mode=border_mode,
pool_size=pool_size)
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
if border_mode == 'same' and strides == (1, 1):
assert input.shape == out.shape
layer.get_config()
layer_test(convolutional.MaxPooling2D,
kwargs={'strides': strides,
'border_mode': border_mode,
'pool_size': pool_size},
input_shape=(3, 4, 11, 12))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_convolution_3d():
nb_samples = 8
nb_filter = 9
stack_size = 7
len_conv_dim1 = 2
len_conv_dim2 = 10
len_conv_dim3 = 6
nb_samples = 2
nb_filter = 5
stack_size = 4
kernel_dim1 = 2
kernel_dim2 = 3
kernel_dim3 = 1
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
weights_in = [np.ones((nb_filter, stack_size, len_conv_dim1, len_conv_dim2, len_conv_dim3)),
np.ones(nb_filter)]
for border_mode in ['same', 'valid']:
for subsample in [(1, 1, 1), (2, 2, 2)]:
if border_mode == 'same' and subsample != (1, 1, 1):
continue
input = np.ones((nb_samples, stack_size, input_len_dim1,
input_len_dim2, input_len_dim3))
for weight in [None, weights_in]:
for border_mode in ['same', 'valid']:
for subsample in [(1, 1, 1), (2, 2, 2)]:
if border_mode == 'same' and subsample != (1, 1, 1):
continue
for W_regularizer in [None, 'l2']:
for b_regularizer in [None, 'l2']:
for act_regularizer in [None, 'l2']:
layer = convolutional.Convolution3D(
nb_filter, len_conv_dim1, len_conv_dim2, len_conv_dim3,
weights=weight,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
activity_regularizer=act_regularizer,
subsample=subsample,
input_shape=(stack_size, None, None, None))
layer_test(convolutional.Convolution3D,
kwargs={'nb_filter': nb_filter,
'kernel_dim1': kernel_dim1,
'kernel_dim2': kernel_dim2,
'kernel_dim3': kernel_dim3,
'border_mode': border_mode,
'subsample': subsample},
input_shape=(nb_samples, stack_size,
input_len_dim1, input_len_dim2, input_len_dim3))
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
if border_mode == 'same' and subsample == (1, 1, 1):
assert out.shape[2:] == input.shape[2:]
layer.get_config()
layer_test(convolutional.Convolution3D,
kwargs={'nb_filter': nb_filter,
'kernel_dim1': kernel_dim1,
'kernel_dim2': kernel_dim2,
'kernel_dim3': kernel_dim3,
'border_mode': border_mode,
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample},
input_shape=(nb_samples, stack_size,
input_len_dim1, input_len_dim2, input_len_dim3))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_maxpooling_3d():
nb_samples = 9
stack_size = 7
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
pool_size = (3, 3, 3)
input = np.ones((nb_samples, stack_size, input_len_dim1,
input_len_dim2, input_len_dim3))
for strides in [(1, 1, 1), (2, 2, 2)]:
layer = convolutional.MaxPooling3D(strides=strides,
border_mode='valid',
pool_size=pool_size)
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
layer_test(convolutional.MaxPooling3D,
kwargs={'strides': strides,
'border_mode': 'valid',
'pool_size': pool_size},
input_shape=(3, 4, 11, 12, 10))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_averagepooling_3d():
nb_samples = 9
stack_size = 7
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
pool_size = (3, 3, 3)
input = np.ones((nb_samples, stack_size, input_len_dim1,
input_len_dim2, input_len_dim3))
for strides in [(1, 1, 1), (2, 2, 2)]:
layer = convolutional.AveragePooling3D(strides=strides,
border_mode='valid',
pool_size=pool_size)
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
layer_test(convolutional.AveragePooling3D,
kwargs={'strides': strides,
'border_mode': 'valid',
'pool_size': pool_size},
input_shape=(3, 4, 11, 12, 10))
def test_zero_padding_2d():
@@ -300,14 +181,21 @@ def test_zero_padding_2d():
input_nb_col = 12
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
# basic test
layer_test(convolutional.ZeroPadding2D,
kwargs={'padding': (2, 2)},
input_shape=input.shape)
# correctness test
layer = convolutional.ZeroPadding2D(padding=(2, 2))
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, :, offset, :], 0.)
assert_allclose(out[:, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2], 1.)
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, :, offset, :], 0.)
assert_allclose(out[:, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2], 1.)
layer.get_config()
@@ -321,31 +209,28 @@ def test_zero_padding_3d():
input = np.ones((nb_samples, stack_size, input_len_dim1,
input_len_dim2, input_len_dim3))
# basic test
layer_test(convolutional.ZeroPadding3D,
kwargs={'padding': (2, 2, 2)},
input_shape=input.shape)
# correctness test
layer = convolutional.ZeroPadding3D(padding=(2, 2, 2))
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, :, offset, :, :], 0.)
assert_allclose(out[:, :, :, offset, :], 0.)
assert_allclose(out[:, :, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2, 2:-2], 1.)
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, :, offset, :, :], 0.)
assert_allclose(out[:, :, :, offset, :], 0.)
assert_allclose(out[:, :, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2, 2:-2], 1.)
layer.get_config()
def test_upsampling_1d():
nb_samples = 9
nb_steps = 7
input_dim = 10
input = np.ones((nb_samples, nb_steps, input_dim))
for length in [2, 3, 9]:
layer = convolutional.UpSampling1D(length=length)
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
assert out.shape[1] == length * nb_steps
layer.get_config()
layer_test(convolutional.UpSampling1D,
kwargs={'length': 2},
input_shape=(3, 5, 4))
def test_upsampling_2d():
@@ -366,29 +251,26 @@ def test_upsampling_2d():
for length_col in [2, 3, 9]:
layer = convolutional.UpSampling2D(
size=(length_row, length_col),
input_shape=input.shape[1:],
dim_ordering=dim_ordering)
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
if dim_ordering == 'th':
assert out.shape[2] == length_row * input_nb_row
assert out.shape[3] == length_col * input_nb_col
else: # tf
assert out.shape[1] == length_row * input_nb_row
assert out.shape[2] == length_col * input_nb_col
layer.set_input(K.variable(input), shape=input.shape)
# compare with numpy
if dim_ordering == 'th':
expected_out = np.repeat(input, length_row, axis=2)
expected_out = np.repeat(expected_out, length_col, axis=3)
else: # tf
expected_out = np.repeat(input, length_row, axis=1)
expected_out = np.repeat(expected_out, length_col, axis=2)
out = K.eval(layer.output)
if dim_ordering == 'th':
assert out.shape[2] == length_row * input_nb_row
assert out.shape[3] == length_col * input_nb_col
else: # tf
assert out.shape[1] == length_row * input_nb_row
assert out.shape[2] == length_col * input_nb_col
assert_allclose(out, expected_out)
# compare with numpy
if dim_ordering == 'th':
expected_out = np.repeat(input, length_row, axis=2)
expected_out = np.repeat(expected_out, length_col, axis=3)
else: # tf
expected_out = np.repeat(input, length_row, axis=1)
expected_out = np.repeat(expected_out, length_col, axis=2)
layer.get_config()
assert_allclose(out, expected_out)
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
@@ -411,34 +293,32 @@ def test_upsampling_3d():
for length_dim3 in [2, 3, 9]:
layer = convolutional.UpSampling3D(
size=(length_dim1, length_dim2, length_dim3),
input_shape=input.shape[1:],
dim_ordering=dim_ordering)
layer.input = K.variable(input)
for train in [True, False]:
out = K.eval(layer.get_output(train))
if dim_ordering == 'th':
assert out.shape[2] == length_dim1 * input_len_dim1
assert out.shape[3] == length_dim2 * input_len_dim2
assert out.shape[4] == length_dim3 * input_len_dim3
else: # tf
assert out.shape[1] == length_dim1 * input_len_dim1
assert out.shape[2] == length_dim2 * input_len_dim2
assert out.shape[3] == length_dim3 * input_len_dim3
layer.set_input(K.variable(input), shape=input.shape)
# compare with numpy
if dim_ordering == 'th':
expected_out = np.repeat(input, length_dim1, axis=2)
expected_out = np.repeat(expected_out, length_dim2, axis=3)
expected_out = np.repeat(expected_out, length_dim3, axis=4)
else: # tf
expected_out = np.repeat(input, length_dim1, axis=1)
expected_out = np.repeat(expected_out, length_dim2, axis=2)
expected_out = np.repeat(expected_out, length_dim3, axis=3)
out = K.eval(layer.output)
if dim_ordering == 'th':
assert out.shape[2] == length_dim1 * input_len_dim1
assert out.shape[3] == length_dim2 * input_len_dim2
assert out.shape[4] == length_dim3 * input_len_dim3
else: # tf
assert out.shape[1] == length_dim1 * input_len_dim1
assert out.shape[2] == length_dim2 * input_len_dim2
assert out.shape[3] == length_dim3 * input_len_dim3
assert_allclose(out, expected_out)
# compare with numpy
if dim_ordering == 'th':
expected_out = np.repeat(input, length_dim1, axis=2)
expected_out = np.repeat(expected_out, length_dim2, axis=3)
expected_out = np.repeat(expected_out, length_dim3, axis=4)
else: # tf
expected_out = np.repeat(input, length_dim1, axis=1)
expected_out = np.repeat(expected_out, length_dim2, axis=2)
expected_out = np.repeat(expected_out, length_dim3, axis=3)
layer.get_config()
assert_allclose(out, expected_out)
if __name__ == '__main__':
pytest.main([__file__])
# pytest.main([__file__])
test_convolution_3d()
+195 -208
Ver Arquivo
@@ -1,258 +1,245 @@
import pytest
import numpy as np
from keras.models import Sequential
from numpy.testing import assert_allclose
from keras import backend as K
from keras.layers import core
from keras.layers import containers
from keras.utils.test_utils import layer_test
def test_input_output():
nb_samples = 10
input_dim = 5
layer = core.Layer()
# Once an input is provided, it should be reachable through the
# appropriate getters
input = np.ones((nb_samples, input_dim))
layer.input = K.variable(input)
for train in [True, False]:
assert_allclose(K.eval(layer.get_input(train)), input)
assert_allclose(K.eval(layer.get_output(train)), input)
def test_connections():
nb_samples = 10
input_dim = 5
layer1 = core.Layer()
layer2 = core.Layer()
input = np.ones((nb_samples, input_dim))
layer1.input = K.variable(input)
# After connecting, input of layer1 should be passed through
layer2.set_previous(layer1)
for train in [True, False]:
assert_allclose(K.eval(layer2.get_input(train)), input)
assert_allclose(K.eval(layer2.get_output(train)), input)
def test_base():
layer = core.Layer()
_runner(layer)
def test_masked():
layer = core.MaskedLayer()
_runner(layer)
def test_masking():
layer_test(core.Masking,
kwargs={},
input_shape=(3, 2, 3))
def test_merge():
layer_1 = core.Layer()
layer_2 = core.Layer()
layer_1.set_input_shape((None,))
layer_2.set_input_shape((None,))
layer = core.Merge([layer_1, layer_2])
_runner(layer)
from keras.layers import Input, merge
from keras.models import Model
# test modes: 'sum', 'mul', 'concat', 'ave', 'cos', 'dot'.
input_shapes = [(3, 2), (3, 2)]
inputs = [np.random.random(shape) for shape in input_shapes]
# test graph API
for mode in ['sum', 'mul', 'concat', 'ave', 'cos', 'dot']:
print(mode)
input_a = Input(shape=input_shapes[0][1:])
input_b = Input(shape=input_shapes[1][1:])
merged = merge([input_a, input_b], mode='sum')
model = Model([input_a, input_b], merged)
model.compile('rmsprop', 'mse')
expected_output_shape = model.get_output_shape_for(input_shapes)
actual_output_shape = model.predict(inputs).shape
assert expected_output_shape == actual_output_shape
config = model.get_config()
model = Model.from_config(config)
model.compile('rmsprop', 'mse')
# test lambda with output_shape lambda
input_a = Input(shape=input_shapes[0][1:])
input_b = Input(shape=input_shapes[1][1:])
merged = merge([input_a, input_b],
mode=lambda tup: K.concatenate([tup[0], tup[1]]),
output_shape=lambda tup: (tup[0][:-1],) + (tup[0][-1] + tup[1][-1],))
expected_output_shape = model.get_output_shape_for(input_shapes)
actual_output_shape = model.predict(inputs).shape
assert expected_output_shape == actual_output_shape
config = model.get_config()
model = Model.from_config(config)
model.compile('rmsprop', 'mse')
# test function with output_shape function
def fn_mode(tup):
x, y = tup
return K.concatenate([x, y])
def fn_output_shape(tup):
s1, s2 = tup
return (s1[:-1],) + (s1[-1] + s2[-1],)
input_a = Input(shape=input_shapes[0][1:])
input_b = Input(shape=input_shapes[1][1:])
merged = merge([input_a, input_b],
mode=fn_mode,
output_shape=fn_output_shape)
expected_output_shape = model.get_output_shape_for(input_shapes)
actual_output_shape = model.predict(inputs).shape
assert expected_output_shape == actual_output_shape
config = model.get_config()
model = Model.from_config(config)
model.compile('rmsprop', 'mse')
def test_dropout():
layer = core.Dropout(0.5)
_runner(layer)
layer_test(core.Dropout,
kwargs={'p': 0.5},
input_shape=(3, 2))
def test_activation():
layer = core.Activation('linear')
_runner(layer)
# with string argument
layer_test(core.Activation,
kwargs={'activation': 'relu'},
input_shape=(3, 2))
# with function argument
layer_test(core.Activation,
kwargs={'activation': K.relu},
input_shape=(3, 2))
def test_reshape():
layer = core.Reshape(dims=(10, 10))
_runner(layer)
layer_test(core.Reshape,
kwargs={'target_shape': (8, 1)},
input_shape=(3, 2, 4))
def test_permute():
layer_test(core.Permute,
kwargs={'dims': (2, 1)},
input_shape=(3, 2, 4))
def test_flatten():
layer = core.Flatten()
_runner(layer)
layer_test(core.Flatten,
kwargs={},
input_shape=(3, 2, 4))
def test_repeat_vector():
layer = core.RepeatVector(10)
_runner(layer)
layer_test(core.RepeatVector,
kwargs={'n': 3},
input_shape=(3, 2))
def test_lambda():
from keras.utils.layer_utils import layer_from_config
Lambda = core.Lambda
layer_test(Lambda,
kwargs={'function': lambda x: x + 1},
input_shape=(3, 2))
# test serialization with function
def f(x):
return x + 1
ld = Lambda(f)
config = ld.get_config()
ld = layer_from_config({'class_name': 'Lambda', 'config': config})
ld = Lambda(lambda x: K.concatenate([K.square(x), x]),
output_shape=lambda s: tuple(list(s)[:-1] + [2 * s[-1]]))
config = ld.get_config()
ld = 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 = Lambda(f, output_shape=f_shape)
config = ld.get_config()
ld = layer_from_config({'class_name': 'Lambda', 'config': config})
def test_dense():
layer = core.Dense(10, input_shape=(10,))
_runner(layer)
from keras import regularizers
from keras import constraints
layer_test(core.Dense,
kwargs={'output_dim': 3},
input_shape=(3, 2))
layer_test(core.Dense,
kwargs={'output_dim': 3,
'W_regularizer': regularizers.l2(0.01),
'b_regularizer': regularizers.l1(0.01),
'activity_regularizer': regularizers.activity_l2(0.01),
'W_constraint': constraints.MaxNorm(1),
'b_constraint': constraints.MaxNorm(1)},
input_shape=(3, 2))
def test_act_reg():
layer = core.ActivityRegularization(0.5, 0.5)
_runner(layer)
def test_activity_regularization():
from keras.engine import Input, Model
layer = core.ActivityRegularization(l1=0.01, l2=0.01)
def test_time_dist_dense():
layer = core.TimeDistributedDense(10, input_shape=(None, 10))
_runner(layer)
# test in functional API
x = Input(shape=(3,))
z = core.Dense(2)(x)
y = layer(z)
model = Model(input=x, output=y)
model.compile('rmsprop', 'mse', mode='FAST_COMPILE')
model.predict(np.random.random((2, 3)))
def test_time_dist_merge():
layer = core.TimeDistributedMerge()
_runner(layer)
def test_highway():
layer = core.Highway(input_shape=(10,))
_runner(layer)
def test_autoencoder():
layer_1 = core.Layer()
layer_2 = core.Layer()
layer = core.AutoEncoder(layer_1, layer_2)
_runner(layer)
def test_autoencoder_advanced():
encoder = containers.Sequential([core.Dense(5, input_shape=(10,))])
decoder = containers.Sequential([core.Dense(10, input_shape=(5,))])
X_train = np.random.random((100, 10))
X_test = np.random.random((100, 10))
model = Sequential()
model.add(core.Dense(output_dim=10, input_dim=10))
autoencoder = core.AutoEncoder(encoder=encoder, decoder=decoder,
output_reconstruction=True)
model.add(autoencoder)
# training the autoencoder:
model.compile(optimizer='sgd', loss='mse')
assert autoencoder.output_reconstruction
model.fit(X_train, X_train, nb_epoch=1, batch_size=32)
# predicting compressed representations of inputs:
autoencoder.output_reconstruction = False # the autoencoder has to be recompiled after modifying this property
assert not autoencoder.output_reconstruction
model.compile(optimizer='sgd', loss='mse')
representations = model.predict(X_test)
assert representations.shape == (100, 5)
# the model is still trainable, although it now expects compressed representations as targets:
model.fit(X_test, representations, nb_epoch=1, batch_size=32)
# to keep training against the original inputs, just switch back output_reconstruction to True:
autoencoder.output_reconstruction = True
model.compile(optimizer='sgd', loss='mse')
model.fit(X_train, X_train, nb_epoch=1)
reconstructions = model.predict(X_test)
assert reconstructions.shape == (100, 10)
# test serialization
model_config = model.get_config()
model = Model.from_config(model_config)
model.compile('rmsprop', 'mse')
def test_maxout_dense():
layer = core.MaxoutDense(10, 10, input_shape=(20,))
_runner(layer)
from keras import regularizers
from keras import constraints
layer_test(core.MaxoutDense,
kwargs={'output_dim': 3},
input_shape=(3, 2))
layer_test(core.MaxoutDense,
kwargs={'output_dim': 3,
'W_regularizer': regularizers.l2(0.01),
'b_regularizer': regularizers.l1(0.01),
'activity_regularizer': regularizers.activity_l2(0.01),
'W_constraint': constraints.MaxNorm(1),
'b_constraint': constraints.MaxNorm(1)},
input_shape=(3, 2))
def test_naming():
layer = core.Dense(2, input_dim=2)
assert layer.name == 'dense'
def test_highway():
from keras import regularizers
from keras import constraints
model = Sequential()
model.add(core.Dense(2, input_dim=2, name='my_dense'))
model.add(core.Dense(2, name='my_dense'))
layer_test(core.Highway,
kwargs={},
input_shape=(3, 2))
assert model.layers[0].name == 'my_dense'
assert model.layers[1].name == 'my_dense'
model.compile(optimizer='rmsprop', loss='mse')
model.train_on_batch(np.random.random((2, 2)), np.random.random((2, 2)))
layer_test(core.Highway,
kwargs={'W_regularizer': regularizers.l2(0.01),
'b_regularizer': regularizers.l1(0.01),
'activity_regularizer': regularizers.activity_l2(0.01),
'W_constraint': constraints.MaxNorm(1),
'b_constraint': constraints.MaxNorm(1)},
input_shape=(3, 2))
def test_sequences():
'''Test masking sequences with zeroes as padding'''
# integer inputs, one per timestep, like embeddings
layer = core.Masking(input_shape=(4, 1))
func = K.function([layer.get_input(True)], [layer.get_output_mask()])
input_data = np.array([[[1], [2], [3], [0]],
[[0], [4], [5], [0]]], dtype=np.int32)
def test_timedistributeddense():
from keras import regularizers
from keras import constraints
# This is the expected output mask, one dimension less
expected = np.array([[1, 1, 1, 0], [0, 1, 1, 0]])
layer_test(core.TimeDistributedDense,
kwargs={'output_dim': 2, 'input_length': 2},
input_shape=(3, 2, 3))
# get mask for this input
output = func([input_data])[0]
assert np.all(output == expected), 'Output not as expected'
layer_test(core.TimeDistributedDense,
kwargs={'output_dim': 3,
'W_regularizer': regularizers.l2(0.01),
'b_regularizer': regularizers.l1(0.01),
'activity_regularizer': regularizers.activity_l2(0.01),
'W_constraint': constraints.MaxNorm(1),
'b_constraint': constraints.MaxNorm(1)},
input_shape=(3, 2, 3))
def test_non_zero():
'''Test masking with non-zero mask value'''
layer = core.Masking(5, input_shape=(4, 2))
func = K.function([layer.input], [layer.get_output_mask()])
input_data = np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]],
dtype=np.int32)
output = func([input_data])[0]
expected = np.array([[1, 1, 1, 0], [1, 1, 1, 1]])
assert np.all(output == expected), 'Output not as expected'
def test_non_zero_output():
'''Test output of masking layer with non-zero mask value'''
layer = core.Masking(5, input_shape=(4, 2))
func = K.function([layer.input], [layer.get_output()])
input_data = np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]],
dtype=np.int32)
output = func([input_data])[0]
expected = np.array([[[1, 1], [2, 1], [3, 1], [0, 0]],
[[1, 5], [5, 0], [0, 0], [0, 0]]])
assert np.all(output == expected), 'Output not as expected'
def _runner(layer):
assert isinstance(layer, core.Layer)
layer.build()
conf = layer.get_config()
assert (type(conf) == dict)
param = layer.get_params()
# Typically a list or a tuple, but may be any iterable
assert hasattr(param, '__iter__')
# Test the setter for the trainable attribute
layer.trainable = True
layer.trainable = False
def test_siamese_all():
right_input_layer = core.Dense(7, input_dim=3)
left_input_layer = core.Dense(7, input_dim=3)
shared_layer = core.Dense(5,input_dim=7)
for mode in ['sum', 'mul', 'ave', 'concat']:
siamese_layer = core.Siamese(shared_layer, [left_input_layer, right_input_layer], merge_mode=mode)
siamese_layer.output_shape
siamese_layer.get_output()
@pytest.mark.skipif(K._BACKEND == 'tensorflow',
reason='currently not working with TensorFlow')
def test_siamese_theano_only():
right_input_layer = core.Dense(7, input_dim=3)
left_input_layer = core.Dense(7, input_dim=3)
shared_layer = core.Dense(5,input_dim=7)
for mode in ['dot', 'cos']:
siamese_layer = core.Siamese(shared_layer, [left_input_layer, right_input_layer], merge_mode=mode,
dot_axes=([1], [1]))
siamese_layer.output_shape
siamese_layer.get_output()
if __name__ == '__main__':
pytest.main([__file__])
+8 -23
Ver Arquivo
@@ -1,30 +1,15 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Flatten
from keras.utils.test_utils import layer_test
from keras.layers.embeddings import Embedding
from keras.constraints import unitnorm
from keras import backend as K
import keras.backend as K
X1 = np.array([[1], [2]], dtype='int32')
W1 = np.array([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]], dtype='float32')
def test_unitnorm_constraint():
lookup = Sequential()
lookup.add(Embedding(3, 2, weights=[W1],
W_constraint=unitnorm(),
input_length=1))
lookup.add(Flatten())
lookup.add(Dense(1))
lookup.add(Activation('sigmoid'))
lookup.compile(loss='binary_crossentropy', optimizer='sgd',
class_mode='binary')
lookup.train_on_batch(X1, np.array([[1], [0]], dtype='int32'))
norm = np.linalg.norm(K.get_value(lookup.trainable_weights[0]), axis=0)
assert_allclose(norm, np.ones_like(norm).astype('float32'), rtol=1e-05)
def test_embedding():
layer_test(Embedding,
kwargs={'output_dim': 4., 'input_dim': 10, 'input_length': 2},
input_shape=(3, 2),
input_dtype='int32',
expected_output_dtype=K.floatx())
if __name__ == '__main__':
+7 -29
Ver Arquivo
@@ -1,40 +1,18 @@
import pytest
import numpy as np
from keras import backend as K
from keras.layers import core
from keras.utils.test_utils import layer_test
from keras.layers import noise
input_shape = (10, 10)
batch_input_shape = (10, 10, 10)
def test_GaussianNoise():
layer = noise.GaussianNoise(sigma=1., input_shape=input_shape)
_runner(layer)
layer_test(noise.GaussianNoise,
kwargs={'sigma': 1.},
input_shape=(3, 2, 3))
def test_GaussianDropout():
layer = noise.GaussianDropout(p=0.2, input_shape=input_shape)
_runner(layer)
def _runner(layer):
assert isinstance(layer, core.Layer)
layer.build()
conf = layer.get_config()
assert (type(conf) == dict)
param = layer.get_params()
# Typically a list or a tuple, but may be any iterable
assert hasattr(param, '__iter__')
layer.input = K.variable(np.random.random(batch_input_shape))
output = layer.get_output(train=False)
output_np = K.eval(output)
assert output_np.shape == batch_input_shape
output = layer.get_output(train=True)
output_np = K.eval(output)
assert output_np.shape == batch_input_shape
layer_test(noise.GaussianDropout,
kwargs={'p': 0.5},
input_shape=(3, 2, 3))
if __name__ == '__main__':
+25 -86
Ver Arquivo
@@ -1,8 +1,9 @@
import pytest
import numpy as np
from keras.layers.core import Dense, Activation
from numpy.testing import assert_allclose
from keras.layers.core import Dense, Activation
from keras.utils.test_utils import layer_test
from keras.layers import normalization
from keras.models import Sequential, Graph
from keras import backend as K
@@ -14,8 +15,16 @@ input_3 = np.ones((10))
input_shapes = [np.ones((10, 10)), np.ones((10, 10, 10))]
def basic_batchnorm_test():
layer_test(normalization.BatchNormalization,
kwargs={'mode': 1},
input_shape=(3, 4, 2))
layer_test(normalization.BatchNormalization,
kwargs={'mode': 0},
input_shape=(3, 4, 2))
def test_batchnorm_mode_0():
np.random.seed(1337)
model = Sequential()
norm_m0 = normalization.BatchNormalization(mode=0, input_shape=(10,))
model.add(norm_m0)
@@ -24,11 +33,13 @@ def test_batchnorm_mode_0():
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 10))
model.fit(X, X, nb_epoch=5, verbose=0)
norm_m0.input = K.variable(X)
out = (norm_m0.get_output(train=True) - norm_m0.beta) / norm_m0.gamma
out = norm_m0.call(K.variable(X))
out -= norm_m0.beta
out /= norm_m0.gamma
np_out = K.function([K.learning_phase()], [out])([1.])[0]
assert_allclose(K.eval(K.mean(out)), 0.0, atol=1e-1)
assert_allclose(K.eval(K.std(out)), 1.0, atol=1e-1)
assert_allclose(np_out.mean(), 0.0, atol=1e-1)
assert_allclose(np_out.std(), 1.0, atol=1e-1)
def test_batchnorm_mode_0_convnet():
@@ -40,20 +51,21 @@ def test_batchnorm_mode_0_convnet():
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 3, 4, 4))
model.fit(X, X, nb_epoch=5, verbose=0)
norm_m0.input = K.variable(X)
out = (norm_m0.get_output(train=True) - K.reshape(norm_m0.beta, (1, 3, 1, 1))) / K.reshape(norm_m0.gamma, (1, 3, 1, 1))
out = norm_m0.call(K.variable(X))
out -= K.reshape(norm_m0.beta, (1, 3, 1, 1))
out /= K.reshape(norm_m0.gamma, (1, 3, 1, 1))
np_out = K.function([K.learning_phase()], [out])([1.])[0]
assert_allclose(K.eval(K.mean(out, axis=(0, 2, 3))), 0.0, atol=1e-1)
assert_allclose(K.eval(K.std(out, axis=(0, 2, 3))), 1.0, atol=1e-1)
assert_allclose(np.mean(np_out, axis=(0, 2, 3)), 0.0, atol=1e-1)
assert_allclose(np.std(np_out, axis=(0, 2, 3)), 1.0, atol=1e-1)
def test_batchnorm_mode_1():
np.random.seed(1337)
norm_m1 = normalization.BatchNormalization(input_shape=(10,), mode=1)
norm_m1.build(input_shape=(None, 10))
for inp in [input_1, input_2, input_3]:
norm_m1.input = K.variable(inp)
out = (norm_m1.get_output(train=True) - norm_m1.beta) / norm_m1.gamma
out = (norm_m1.call(K.variable(inp)) - norm_m1.beta) / norm_m1.gamma
assert_allclose(K.eval(K.mean(out)), 0.0, atol=1e-1)
if inp.std() > 0.:
assert_allclose(K.eval(K.std(out)), 1.0, atol=1e-1)
@@ -61,78 +73,5 @@ def test_batchnorm_mode_1():
assert_allclose(K.eval(K.std(out)), 0.0, atol=1e-1)
def test_batchnorm_shapes():
"""
Test batch normalization with various input shapes
"""
for inp in input_shapes:
norm_m0 = normalization.BatchNormalization(batch_input_shape=inp.shape, mode=0)
norm_m0.input = K.variable(inp)
out = norm_m0.get_output(train=True)
K.eval(out)
norm_m1 = normalization.BatchNormalization(batch_input_shape=inp.shape, mode=1)
norm_m1.input = K.variable(inp)
out = norm_m1.get_output(train=True)
K.eval(out)
def test_batchnorm_weight_init():
"""
Test weight initialization
"""
np.random.seed(1337)
norm_m1 = normalization.BatchNormalization(input_shape=(10,), mode=1,
weights=[np.ones(10), np.ones(10), np.zeros(10), np.zeros(10)])
for inp in [input_1, input_2, input_3]:
norm_m1.input = K.variable(inp)
out = (norm_m1.get_output(train=True) - np.ones(10)) / 1.
assert_allclose(K.eval(K.mean(out)), 0.0, atol=1e-1)
if inp.std() > 0.:
assert_allclose(K.eval(K.std(out)), 1.0, atol=1e-1)
else:
assert_allclose(K.eval(K.std(out)), 0.0, atol=1e-1)
assert_allclose(K.eval(norm_m1.gamma), np.ones(10), atol=1e-1)
assert_allclose(K.eval(norm_m1.beta), np.ones(10), atol=1e-1)
def test_batchnorm_config():
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1,
epsilon=0.1, momentum=0.9)
norm.get_config()
def test_batchnorm_save_weights():
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1,
epsilon=0.1)
weights = norm.get_weights()
assert(len(weights) == 4)
norm.set_weights(weights)
def test_batchnorm_nested():
# regression test for issue #1386
g = Graph()
g.add_input("input", input_shape=[20])
g.add_node(Dense(10), "dense", "input")
g.add_node(normalization.BatchNormalization(), "bn", "dense")
g.add_node(Activation('relu'), "activ", "bn")
g.add_output("output", "activ")
g2 = Graph()
g2.add_input("input", input_shape=[10])
g2.add_node(Dense(15), "dense", "input")
g2.add_node(normalization.BatchNormalization(), "bn", "dense")
g2.add_node(Activation('relu'), "activ", "bn")
g2.add_output("output", "activ")
model = Sequential()
model.add(g)
model.add(g2)
model.compile(loss="mse", optimizer="adadelta")
if __name__ == '__main__':
pytest.main([__file__])
+16 -46
Ver Arquivo
@@ -2,13 +2,13 @@ import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.utils.test_utils import layer_test
from keras.layers import recurrent, embeddings
from keras.models import Sequential
from keras.layers.core import Masking
from keras import regularizers
from keras import backend as K
from keras.models import Sequential, model_from_json
nb_samples, timesteps, embedding_dim, output_dim = 3, 5, 10, 5
embedding_num = 12
@@ -19,39 +19,18 @@ def _runner(layer_class):
All the recurrent layers share the same interface,
so we can run through them with a single function.
"""
for ret_seq in [True, False]:
layer = layer_class(output_dim, return_sequences=ret_seq,
weights=None, input_shape=(timesteps, embedding_dim))
layer.input = K.variable(np.ones((nb_samples, timesteps, embedding_dim)))
layer.get_config()
for train in [True, False]:
out = K.eval(layer.get_output(train))
# Make sure the output has the desired shape
if ret_seq:
assert(out.shape == (nb_samples, timesteps, output_dim))
else:
assert(out.shape == (nb_samples, output_dim))
mask = layer.get_output_mask(train)
# check return_sequences
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'return_sequences': True},
input_shape=(3, 2, 3))
# check dropout
for ret_seq in [True, False]:
layer = layer_class(output_dim, return_sequences=ret_seq, weights=None,
batch_input_shape=(nb_samples, timesteps, embedding_dim),
dropout_W=0.5, dropout_U=0.5)
layer.input = K.variable(np.ones((nb_samples, timesteps, embedding_dim)))
layer.get_config()
for train in [True, False]:
out = K.eval(layer.get_output(train))
# Make sure the output has the desired shape
if ret_seq:
assert(out.shape == (nb_samples, timesteps, output_dim))
else:
assert(out.shape == (nb_samples, output_dim))
mask = layer.get_output_mask(train)
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'dropout_U': 0.1,
'dropout_W': 0.1},
input_shape=(3, 2, 3))
# check statefulness
model = Sequential()
@@ -110,13 +89,15 @@ def _runner(layer_class):
assert_allclose(out7, out6, atol=1e-5)
# check regularizers
layer = layer_class(output_dim, return_sequences=ret_seq, weights=None,
layer = layer_class(output_dim, return_sequences=False, weights=None,
batch_input_shape=(nb_samples, timesteps, embedding_dim),
W_regularizer=regularizers.WeightRegularizer(l1=0.01),
U_regularizer=regularizers.WeightRegularizer(l1=0.01),
b_regularizer='l2')
layer.input = K.variable(np.ones((nb_samples, timesteps, embedding_dim)))
out = K.eval(layer.get_output(train=True))
shape = (nb_samples, timesteps, embedding_dim)
layer.set_input(K.variable(np.ones(shape)),
shape=shape)
K.eval(layer.output)
def test_SimpleRNN():
@@ -131,17 +112,6 @@ def test_LSTM():
_runner(recurrent.LSTM)
def test_batch_input_shape_serialization():
model = Sequential()
model.add(embeddings.Embedding(2, 2,
mask_zero=True,
input_length=2,
batch_input_shape=(2, 2)))
json_data = model.to_json()
reconstructed_model = model_from_json(json_data)
assert(reconstructed_model.input_shape == (2, 2))
def test_masking_layer():
''' This test based on a previously failing issue here:
https://github.com/fchollet/keras/issues/1567
+17 -2
Ver Arquivo
@@ -2,9 +2,9 @@ import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.layers import wrappers
from keras.layers import wrappers, Input
from keras.layers import core, convolutional
from keras.models import Sequential, model_from_json
from keras.models import Sequential, Model, model_from_json
def test_TimeDistributed():
@@ -59,6 +59,21 @@ def test_TimeDistributed():
model.fit(np.random.random((10, 3, 4)), np.random.random((10, 3, 3)), nb_epoch=1, batch_size=10)
# test wrapping Sequential model
model = Sequential()
model.add(core.Dense(3, input_dim=2))
outer_model = Sequential()
outer_model.add(wrappers.TimeDistributed(model, input_shape=(3, 2)))
outer_model.compile(optimizer='rmsprop', loss='mse')
outer_model.fit(np.random.random((10, 3, 2)), np.random.random((10, 3, 3)), nb_epoch=1, batch_size=10)
# test with functional API
x = Input(shape=(3, 2))
y = wrappers.TimeDistributed(model)(x)
outer_model = Model(x, y)
outer_model.compile(optimizer='rmsprop', loss='mse')
outer_model.fit(np.random.random((10, 3, 2)), np.random.random((10, 3, 3)), nb_epoch=1, batch_size=10)
if __name__ == '__main__':
pytest.main([__file__])
+26 -19
Ver Arquivo
@@ -36,11 +36,13 @@ def test_ModelCheckpoint():
model = Sequential()
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
model.add(Dense(nb_class, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
cbks = [callbacks.ModelCheckpoint(filepath, monitor=monitor,
save_best_only=save_best_only, mode=mode)]
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
assert os.path.exists(filepath)
os.remove(filepath)
@@ -49,7 +51,7 @@ def test_ModelCheckpoint():
mode = 'min'
cbks = [callbacks.ModelCheckpoint(filepath, monitor=monitor,
save_best_only=save_best_only, mode=mode)]
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
assert os.path.exists(filepath)
os.remove(filepath)
@@ -59,7 +61,7 @@ def test_ModelCheckpoint():
monitor = 'val_acc'
cbks = [callbacks.ModelCheckpoint(filepath, monitor=monitor,
save_best_only=save_best_only, mode=mode)]
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
assert os.path.exists(filepath)
os.remove(filepath)
@@ -68,7 +70,7 @@ def test_ModelCheckpoint():
save_best_only = True
cbks = [callbacks.ModelCheckpoint(filepath, monitor=monitor,
save_best_only=save_best_only, mode=mode)]
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
assert os.path.exists(filepath)
os.remove(filepath)
@@ -85,20 +87,21 @@ def test_EarlyStopping():
model = Sequential()
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
model.add(Dense(nb_class, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
mode = 'max'
monitor = 'val_acc'
patience = 0
cbks = [callbacks.EarlyStopping(patience=patience, monitor=monitor, mode=mode)]
history = model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
history = model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=20)
mode = 'auto'
monitor = 'val_acc'
patience = 2
cbks = [callbacks.EarlyStopping(patience=patience, monitor=monitor, mode=mode)]
history = model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
history = model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=20)
@@ -113,10 +116,12 @@ def test_LearningRateScheduler():
model = Sequential()
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
model.add(Dense(nb_class, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
cbks = [callbacks.LearningRateScheduler(lambda x: 1. / (1. + x))]
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=5)
assert (float(K.get_value(model.optimizer.lr)) - 0.2) < K.epsilon()
@@ -166,39 +171,37 @@ def test_TensorBoard():
model = Sequential()
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
model.add(Dense(nb_class, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
model.compile(loss='categorical_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
tsb = callbacks.TensorBoard(log_dir=filepath, histogram_freq=1)
cbks = [tsb]
# fit with validation data
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=False,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=2)
# fit with validation data and accuracy
model.fit(X_train, y_train, batch_size=batch_size, show_accuracy=True,
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=2)
# fit generator with validation data
model.fit_generator(data_generator(True), len(X_train), nb_epoch=2,
show_accuracy=False,
validation_data=(X_test, y_test),
callbacks=cbks)
# fit generator without validation data
model.fit_generator(data_generator(True), len(X_train), nb_epoch=2,
show_accuracy=False,
callbacks=cbks)
# fit generator with validation data and accuracy
model.fit_generator(data_generator(True), len(X_train), nb_epoch=2,
show_accuracy=True,
validation_data=(X_test, y_test),
callbacks=cbks)
# fit generator without validation data and accuracy
model.fit_generator(data_generator(True), len(X_train), nb_epoch=2,
show_accuracy=True,
callbacks=cbks)
assert os.path.exists(filepath)
@@ -249,4 +252,8 @@ def test_TensorBoard():
KTF.set_session(old_session)
if __name__ == '__main__':
pytest.main([__file__])
# pytest.main([__file__])
# test_ModelCheckpoint()
# test_EarlyStopping()
# test_LearningRateScheduler()
test_TensorBoard()
-17
Ver Arquivo
@@ -34,23 +34,6 @@ def test_nonneg():
assert(np.all(np.min(K.eval(normed), axis=1) == 0.))
def test_identity():
identity_instance = constraints.identity()
normed = identity_instance(example_array)
assert(np.all(normed == example_array))
def test_identity_oddballs():
"""
test the identity constraint on some more exotic input.
this does not need to pass for the desired real life behaviour,
but it should in the current implementation.
"""
identity_instance = constraints.identity()
oddball_examples = ["Hello", [1], -1, None]
assert(oddball_examples == identity_instance(oddball_examples))
def test_unitnorm():
unitnorm_instance = constraints.unitnorm()
normalized = unitnorm_instance(K.variable(example_array))
+122 -98
Ver Arquivo
@@ -6,21 +6,21 @@ import numpy as np
np.random.seed(1337)
from keras import backend as K
from keras.models import Graph, Sequential, model_from_json, model_from_yaml
from keras.layers.core import Dense, Activation, Merge, Lambda, LambdaMerge, Siamese, add_shared_layer
from keras.layers import containers
from keras.models import Graph, Sequential
from keras.layers.core import Dense, Activation, Merge, Lambda
from keras.utils.test_utils import get_test_data
from keras.models import model_from_json, model_from_yaml
batch_size = 32
(X_train_graph, y_train_graph), (X_test_graph, y_test_graph) = get_test_data(nb_train=1000,
nb_test=200,
(X_train_graph, y_train_graph), (X_test_graph, y_test_graph) = get_test_data(nb_train=100,
nb_test=50,
input_shape=(32,),
classification=False,
output_shape=(4,))
(X2_train_graph, y2_train_graph), (X2_test_graph, y2_test_graph) = get_test_data(nb_train=1000,
nb_test=200,
(X2_train_graph, y2_train_graph), (X2_test_graph, y2_test_graph) = get_test_data(nb_train=100,
nb_test=50,
input_shape=(32,),
classification=False,
output_shape=(1,))
@@ -53,21 +53,20 @@ def test_graph_fit_generator():
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3)
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4,
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3)
gen_loss = graph.evaluate_generator(data_generator_graph(True), 128, verbose=0)
assert(gen_loss < 3.)
gen_loss = graph.evaluate_generator(data_generator_graph(True), 128, verbose=0)
loss = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph}, verbose=0)
assert(loss < 3.)
# test show_accuracy
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4, show_accuracy=True)
graph.compile('rmsprop', {'output1': 'mse'}, metrics=['accuracy'])
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4)
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4,
validation_data={'input1': X_test_graph, 'output1': y_test_graph}, show_accuracy=True)
validation_data={'input1': X_test_graph, 'output1': y_test_graph})
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4,
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3, show_accuracy=True)
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3)
graph.fit_generator(data_generator_graph(True), 1000, nb_epoch=4,
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3, show_accuracy=True)
gen_loss = graph.evaluate_generator(data_generator_graph(True), 128, verbose=0, show_accuracy=True)
validation_data=data_generator_graph(False), nb_val_samples=batch_size * 3)
gen_loss = graph.evaluate_generator(data_generator_graph(True), 128, verbose=0)
def test_1o_1i():
@@ -89,19 +88,20 @@ def test_1o_1i():
graph.fit({'input1': X_train_graph, 'output1': y_train_graph},
nb_epoch=10)
out = graph.predict({'input1': X_test_graph})
assert(type(out == dict))
assert(type(out) == dict)
assert(len(out) == 1)
loss = graph.test_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph}, verbose=0)
assert(loss < 2.5)
loss = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph}, verbose=0)
# test show_accuracy:
# test accuracy:
graph.compile('rmsprop', {'output1': 'mse'}, metrics=['accuracy'])
graph.fit({'input1': X_train_graph, 'output1': y_train_graph},
nb_epoch=1, show_accuracy=True)
loss, acc = graph.test_on_batch({'input1': X_test_graph, 'output1': y_test_graph}, accuracy=True)
loss, acc = graph.train_on_batch({'input1': X_test_graph, 'output1': y_test_graph}, accuracy=True)
loss, acc = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph}, verbose=0, show_accuracy=True)
nb_epoch=1)
loss, acc = graph.test_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss, acc = graph.train_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss, acc = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph}, verbose=0)
# test validation split
graph.fit({'input1': X_train_graph, 'output1': y_train_graph},
@@ -117,11 +117,11 @@ def test_1o_1i_2():
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_node(Dense(16), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense2-0', input='input1')
graph.add_node(Activation('relu'), name='dense2', input='dense2-0')
graph.add_node(Dense(16), name='dense3', input='dense2')
graph.add_node(Dense(4), name='dense3', input='dense2')
graph.add_node(Dense(4), name='dense4', inputs=['dense1', 'dense3'],
merge_mode='sum')
@@ -130,7 +130,7 @@ def test_1o_1i_2():
graph.compile('rmsprop', {'output1': 'mse'})
graph.fit({'input1': X_train_graph, 'output1': y_train_graph},
nb_epoch=10)
nb_epoch=2)
out = graph.predict({'input1': X_train_graph})
assert(type(out == dict))
assert(len(out) == 1)
@@ -138,10 +138,17 @@ def test_1o_1i_2():
loss = graph.test_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'output1': y_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph})
assert(loss < 2.5)
graph.get_config(verbose=1)
# test serialization
config = graph.get_config()
new_graph = Graph.from_config(config)
graph.summary()
json_str = graph.to_json()
new_graph = model_from_json(json_str)
yaml_str = graph.to_yaml()
new_graph = model_from_yaml(yaml_str)
def test_1o_2i():
@@ -159,7 +166,7 @@ def test_1o_2i():
graph.compile('rmsprop', {'output1': 'mse'})
graph.fit({'input1': X_train_graph, 'input2': X2_train_graph, 'output1': y_train_graph},
nb_epoch=10)
nb_epoch=2)
out = graph.predict({'input1': X_test_graph, 'input2': X2_test_graph})
assert(type(out == dict))
assert(len(out) == 1)
@@ -167,21 +174,30 @@ def test_1o_2i():
loss = graph.test_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
assert(loss < 3.0)
graph.get_config(verbose=1)
# test serialization
config = graph.get_config()
new_graph = Graph.from_config(config)
graph.summary()
json_str = graph.to_json()
new_graph = model_from_json(json_str)
yaml_str = graph.to_yaml()
new_graph = model_from_yaml(yaml_str)
def test_siamese_3():
def test_siamese_1():
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_input(name='input2', input_shape=(32,))
graph.add_shared_node(Dense(16), name='shared', inputs=['input1', 'input2'], merge_mode='sum')
graph.add_shared_node(Dense(4), name='shared', inputs=['input1', 'input2'], merge_mode='sum')
graph.add_node(Dense(4), name='dense1', input='shared')
graph.add_node(Dense(4), name='dense2', input='dense1')
# graph.add_node(Dense(4), name='output1', input='shared', create_output=True)
graph.add_output(name='output1', input='dense2')
# graph.add_output(name='output1', inputs=['dense1', 'shared'], merge_mode='sum')
graph.add_output(name='output1', input='dense1')
graph.compile('rmsprop', {'output1': 'mse'})
graph.fit({'input1': X_train_graph, 'input2': X2_train_graph, 'output1': y_train_graph},
@@ -195,67 +211,70 @@ def test_siamese_3():
loss = graph.evaluate({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
assert(loss < 3.0)
graph.get_config(verbose=1)
# test serialization
config = graph.get_config()
new_graph = Graph.from_config(config)
graph.summary()
json_str = graph.to_json()
new_graph = model_from_json(json_str)
yaml_str = graph.to_yaml()
new_graph = model_from_yaml(yaml_str)
def test_siamese_4():
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_input(name='input2', input_shape=(32,))
'''Th test below is failing because of a known bug
with the serialization of legacy Graph models
containing shared nodes with named outputs.
This is very low priority (= no plans to fix it),
since the Graph model is deprecated.
'''
# def test_siamese_2():
# graph = Graph()
# graph.add_input(name='input1', input_shape=(32,))
# graph.add_input(name='input2', input_shape=(32,))
graph.add_shared_node(Dense(16), name='shared1', inputs=['input1', 'input2'])
graph.add_shared_node(Dense(4), name='shared2', inputs=['shared1'])
graph.add_shared_node(Dense(4), name='shared3', inputs=['shared2'], merge_mode='sum')
graph.add_node(Dense(4), name='dense', input='shared3')
# graph.add_shared_node(Dense(4), name='shared',
# inputs=['input1', 'input2'],
# outputs=['shared_output1', 'shared_output2'])
# graph.add_node(Dense(4), name='dense1', input='shared_output1')
# graph.add_node(Dense(4), name='dense2', input='shared_output2')
graph.add_output(name='output1', input='dense',
merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
# graph.add_output(name='output1', inputs=['dense1', 'dense2'],
# merge_mode='sum')
# graph.compile('rmsprop', {'output1': 'mse'})
graph.fit({'input1': X_train_graph, 'input2': X2_train_graph, 'output1': y_train_graph},
nb_epoch=10)
out = graph.predict({'input1': X_test_graph, 'input2': X2_test_graph})
assert(type(out == dict))
assert(len(out) == 1)
# graph.fit({'input1': X_train_graph,
# 'input2': X2_train_graph,
# 'output1': y_train_graph},
# nb_epoch=10)
# out = graph.predict({'input1': X_test_graph,
# 'input2': X2_test_graph})
# assert(type(out == dict))
# assert(len(out) == 1)
loss = graph.test_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
assert(loss < 3.0)
# loss = graph.test_on_batch({'input1': X_test_graph,
# 'input2': X2_test_graph,
# 'output1': y_test_graph})
# loss = graph.train_on_batch({'input1': X_test_graph,
# 'input2': X2_test_graph,
# 'output1': y_test_graph})
# loss = graph.evaluate({'input1': X_test_graph,
# 'input2': X2_test_graph,
# 'output1': y_test_graph})
# # test serialization
# config = graph.get_config()
# new_graph = Graph.from_config(config)
graph.get_config(verbose=1)
# graph.summary()
# json_str = graph.to_json()
# new_graph = model_from_json(json_str)
# yaml_str = graph.to_yaml()
# new_graph = model_from_yaml(yaml_str)
def test_siamese_5():
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_input(name='input2', input_shape=(32,))
graph.add_shared_node(Dense(16), name='shared1', inputs=['input1', 'input2'])
graph.add_shared_node(Dense(4), name='shared2', inputs=['shared1'])
graph.add_shared_node(Dense(4), name='shared3', inputs=['shared2'], outputs=['shared_output1','shared_output2'])
graph.add_node(Dense(4), name='dense1', input='shared_output1')
graph.add_node(Dense(4), name='dense2', input='shared_output2')
graph.add_output(name='output1', inputs=['dense1', 'dense2'],
merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
graph.fit({'input1': X_train_graph, 'input2': X2_train_graph, 'output1': y_train_graph},
nb_epoch=10)
out = graph.predict({'input1': X_test_graph, 'input2': X2_test_graph})
assert(type(out == dict))
assert(len(out) == 1)
loss = graph.test_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'input2': X2_test_graph, 'output1': y_test_graph})
assert(loss < 3.0)
graph.get_config(verbose=1)
def test_2o_1i_weights():
def test_2o_1i_save_weights():
# test a non-sequential graph with 1 input and 2 outputs
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
@@ -276,7 +295,6 @@ def test_2o_1i_weights():
loss = graph.test_on_batch({'input1': X_test_graph, 'output1': y_test_graph, 'output2': y2_test_graph})
loss = graph.train_on_batch({'input1': X_test_graph, 'output1': y_test_graph, 'output2': y2_test_graph})
loss = graph.evaluate({'input1': X_test_graph, 'output1': y_test_graph, 'output2': y2_test_graph})
assert(loss < 4.)
# test weight saving
fname = 'test_2o_1i_weights_temp.h5'
@@ -338,8 +356,7 @@ def test_2o_1i_sample_weights():
def test_recursive():
# test layer-like API
graph = containers.Graph()
graph = Graph()
graph.add_input(name='input1', input_shape=(32,))
graph.add_node(Dense(16), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense2', input='input1')
@@ -356,11 +373,17 @@ def test_recursive():
seq.fit(X_train_graph, y_train_graph, batch_size=10, nb_epoch=10)
loss = seq.evaluate(X_test_graph, y_test_graph)
assert(loss < 2.5)
loss = seq.evaluate(X_test_graph, y_test_graph, show_accuracy=True)
seq.predict(X_test_graph)
seq.get_config(verbose=1)
# test serialization
config = seq.get_config()
new_graph = Sequential.from_config(config)
seq.summary()
json_str = seq.to_json()
new_graph = model_from_json(json_str)
yaml_str = seq.to_yaml()
new_graph = model_from_yaml(yaml_str)
def test_create_output():
@@ -387,14 +410,14 @@ def test_create_output():
assert(loss < 2.5)
# test serialization
config = graph.to_json()
del graph
graph = model_from_json(config)
config = graph.get_config()
graph = Graph.from_config(config)
graph.compile('rmsprop', {'output1': 'mse'})
out = graph.predict({'input1': X_test_graph})
def test_count_params():
# test count params
nb_units = 100
nb_classes = 2
@@ -409,6 +432,7 @@ def test_count_params():
name='dense3', input='dense1')
graph.add_output(name='output', inputs=['dense2', 'dense3'],
merge_mode='sum')
graph.build()
n = 32 * nb_units + nb_units
n += 32 * nb_classes + nb_classes
+11
Ver Arquivo
@@ -32,5 +32,16 @@ def test_objective_shapes_2d():
assert K.eval(objective_output).shape == (6,)
def test_cce_one_hot():
y_a = K.variable(np.random.randint(0, 7, (5, 6)))
y_b = K.variable(np.random.random((5, 6, 7)))
objective_output = objectives.sparse_categorical_crossentropy(y_a, y_b)
assert K.eval(objective_output).shape == (5, 6)
y_a = K.variable(np.random.randint(0, 7, (6,)))
y_b = K.variable(np.random.random((6, 7)))
assert K.eval(objectives.sparse_categorical_crossentropy(y_a, y_b)).shape == (6,)
if __name__ == "__main__":
pytest.main([__file__])
+4 -3
Ver Arquivo
@@ -28,10 +28,11 @@ def get_model(input_dim, nb_hidden, output_dim):
def _test_optimizer(optimizer, target=0.9):
model = get_model(X_train.shape[1], 10, y_train.shape[1])
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
model.compile(loss='categorical_crossentropy',
optimizer=optimizer,
metrics=['accuracy'])
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=2)
validation_data=(X_test, y_test), verbose=2)
config = optimizer.get_config()
assert type(config) == dict
assert history.history['val_acc'][-1] > target
+10 -4
Ver Arquivo
@@ -1,10 +1,14 @@
import pytest
import numpy as np
np.random.seed(1337) # for reproducibility
np.random.seed(1337)
from keras.models import Sequential
from keras.layers.core import Merge, Dense, Activation, Flatten, ActivityRegularization
from keras.layers.embeddings import Embedding
from keras.layers import Merge
from keras.layers import Dense
from keras.layers import Activation
from keras.layers import Flatten
from keras.layers import ActivityRegularization
from keras.layers import Embedding
from keras.datasets import mnist
from keras.utils import np_utils
from keras import regularizers
@@ -44,7 +48,9 @@ def create_model(weight_reg=None, activity_reg=None):
def test_W_reg():
for reg in [regularizers.identity(), regularizers.l1(), regularizers.l2(), regularizers.l1l2()]:
for reg in [regularizers.l1(),
regularizers.l2(),
regularizers.l1l2()]:
model = create_model(weight_reg=reg)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit(X_train, Y_train, batch_size=batch_size,
+106 -313
Ver Arquivo
@@ -6,15 +6,17 @@ import numpy as np
np.random.seed(1337)
from keras import backend as K
from keras.models import Graph, Sequential, model_from_json, model_from_yaml
from keras.layers.core import Dense, Activation, Merge, Lambda, LambdaMerge, Siamese, add_shared_layer
from keras.layers import containers
from keras.models import Graph, Sequential
from keras.layers.core import Dense, Activation, Merge, Lambda
from keras.utils import np_utils
from keras.utils.test_utils import get_test_data
from keras.models import model_from_json, model_from_yaml
from keras import objectives
from keras.engine.training import make_batches
input_dim = 32
nb_hidden = 16
input_dim = 16
nb_hidden = 8
nb_class = 4
batch_size = 32
nb_epoch = 1
@@ -23,8 +25,8 @@ nb_epoch = 1
def _get_test_data():
np.random.seed(1234)
train_samples = 2000
test_samples = 500
train_samples = 100
test_samples = 50
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
nb_test=test_samples,
@@ -60,36 +62,27 @@ def test_sequential_fit_generator():
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=False)
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=True)
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=False, validation_data=(X_test, y_test))
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=True, validation_data=(X_test, y_test))
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=False,
validation_data=data_generator(False), nb_val_samples=batch_size * 3)
model.fit_generator(data_generator(True), len(X_train), nb_epoch, show_accuracy=True,
model.fit_generator(data_generator(True), len(X_train), nb_epoch)
model.fit_generator(data_generator(True), len(X_train), nb_epoch, validation_data=(X_test, y_test))
model.fit_generator(data_generator(True), len(X_train), nb_epoch,
validation_data=data_generator(False), nb_val_samples=batch_size * 3)
loss = model.evaluate(X_train, y_train, verbose=0)
assert(loss < 0.9)
loss = model.evaluate(X_train, y_train)
def test_sequential():
(X_train, y_train), (X_test, y_test) = _get_test_data()
# TODO: factor out
def data_generator(train):
if train:
max_batch_index = len(X_train) // batch_size
else:
max_batch_index = len(X_test) // batch_size
i = 0
def data_generator(x, y, batch_size=50):
index_array = np.arange(len(x))
while 1:
if train:
yield (X_train[i * batch_size: (i + 1) * batch_size], y_train[i * batch_size: (i + 1) * batch_size])
else:
yield (X_test[i * batch_size: (i + 1) * batch_size], y_test[i * batch_size: (i + 1) * batch_size])
i += 1
i = i % max_batch_index
batches = make_batches(len(X_test), batch_size)
for batch_index, (batch_start, batch_end) in enumerate(batches):
batch_ids = index_array[batch_start:batch_end]
x_batch = x[batch_ids]
y_batch = y[batch_ids]
yield (x_batch, y_batch)
model = Sequential()
model.add(Dense(nb_hidden, input_shape=(input_dim,)))
@@ -97,27 +90,26 @@ def test_sequential():
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.summary()
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=2, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=1, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, shuffle=False)
model.train_on_batch(X_train[:32], y_train[:32])
gen_loss = model.evaluate_generator(data_generator(True), 256, verbose=0)
assert(gen_loss < 0.8)
loss = model.evaluate(X_test, y_test)
loss = model.evaluate(X_test, y_test, verbose=0)
assert(loss < 0.8)
prediction = model.predict_generator(data_generator(X_test, y_test), X_test.shape[0])
gen_loss = model.evaluate_generator(data_generator(X_test, y_test, 50), X_test.shape[0])
pred_loss = K.eval(K.mean(objectives.get(model.loss)(K.variable(y_test), K.variable(prediction))))
assert(np.isclose(pred_loss, loss))
assert(np.isclose(gen_loss, loss))
model.predict(X_test, verbose=0)
model.predict_classes(X_test, verbose=0)
model.predict_proba(X_test, verbose=0)
model.get_config(verbose=0)
fname = 'test_sequential_temp.h5'
model.save_weights(fname, overwrite=True)
@@ -133,13 +125,16 @@ def test_sequential():
nloss = model.evaluate(X_test, y_test, verbose=0)
assert(loss == nloss)
# test json serialization
json_data = model.to_json()
model = model_from_json(json_data)
# test serialization
config = model.get_config()
new_model = Sequential.from_config(config)
# test yaml serialization
yaml_data = model.to_yaml()
model = model_from_yaml(yaml_data)
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
def test_nested_sequential():
@@ -157,24 +152,19 @@ def test_nested_sequential():
model.add(middle)
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.summary()
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=2, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=1, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, shuffle=False)
model.train_on_batch(X_train[:32], y_train[:32])
loss = model.evaluate(X_test, y_test, verbose=0)
assert(loss < 0.8)
model.predict(X_test, verbose=0)
model.predict_classes(X_test, verbose=0)
model.predict_proba(X_test, verbose=0)
model.get_config(verbose=0)
fname = 'test_nested_sequential_temp.h5'
model.save_weights(fname, overwrite=True)
@@ -197,13 +187,16 @@ def test_nested_sequential():
nloss = model.evaluate(X_test, y_test, verbose=0)
assert(loss == nloss)
# test json serialization
json_data = model.to_json()
model = model_from_json(json_data)
# test serialization
config = model.get_config()
new_model = Sequential.from_config(config)
# test yaml serialization
yaml_data = model.to_yaml()
model = model_from_yaml(yaml_data)
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
def test_merge_sum():
@@ -222,20 +215,16 @@ def test_merge_sum():
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
# test weight saving
fname = 'test_merge_sum_temp.h5'
@@ -257,9 +246,18 @@ def test_merge_sum():
nloss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss == nloss)
# test serialization
config = model.get_config()
new_model = Sequential.from_config(config)
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
@pytest.mark.skipif(K._BACKEND == 'tensorflow',
reason='currently not working with TensorFlow')
def test_merge_dot():
(X_train, y_train), (X_test, y_test) = _get_test_data()
@@ -287,7 +285,7 @@ def test_merge_dot():
right.add(Activation('relu'))
model = Sequential()
model.add(Merge([left, right], mode='dot', dot_axes=([1], [1])))
model.add(Merge([left, right], mode='dot', dot_axes=[1, 1]))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
@@ -297,52 +295,35 @@ def test_merge_dot():
def test_merge_concat():
(X_train, y_train), (X_test, y_test) = _get_test_data()
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
left = Sequential(name='branch_1')
left.add(Dense(nb_hidden, input_shape=(input_dim,), name='dense_1'))
left.add(Activation('relu', name='relu_1'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
right = Sequential(name='branch_2')
right.add(Dense(nb_hidden, input_shape=(input_dim,), name='dense_2'))
right.add(Activation('relu', name='relu_2'))
model = Sequential()
model.add(Merge([left, right], mode='concat'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model = Sequential(name='merged_branches')
model.add(Merge([left, right], mode='concat', name='merge'))
model.add(Dense(nb_class, name='final_dense'))
model.add(Activation('softmax', name='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
model.get_config()
fname = 'test_merge_concat_temp.h5'
model.save_weights(fname, overwrite=True)
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(Merge([left, right], mode='concat'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.load_weights(fname)
os.remove(fname)
@@ -375,20 +356,16 @@ def test_merge_recursivity():
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test, X_test], y_test))
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test, X_test], y_test))
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_data=([X_test, X_test, X_test], y_test))
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, validation_split=0.1)
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test, X_test], verbose=0)
model.get_config(verbose=0)
fname = 'test_merge_recursivity_temp.h5'
model.save_weights(fname, overwrite=True)
@@ -398,6 +375,17 @@ def test_merge_recursivity():
nloss = model.evaluate([X_test, X_test, X_test], y_test, verbose=0)
assert(loss == nloss)
# test serialization
config = model.get_config()
new_model = Sequential.from_config(config)
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
def test_merge_overlap():
(X_train, y_train), (X_test, y_test) = _get_test_data()
@@ -411,112 +399,39 @@ def test_merge_overlap():
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=2, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=1, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, validation_data=(X_test, y_test))
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=2, validation_split=0.1)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, shuffle=False)
model.train_on_batch(X_train[:32], y_train[:32])
loss = model.evaluate(X_test, y_test, verbose=0)
assert(loss < 0.9)
model.predict(X_test, verbose=0)
model.predict_classes(X_test, verbose=0)
model.predict_proba(X_test, verbose=0)
model.get_config(verbose=0)
fname = 'test_merge_overlap_temp.h5'
print(model.layers)
model.save_weights(fname, overwrite=True)
print(model.trainable_weights)
model.load_weights(fname)
os.remove(fname)
nloss = model.evaluate(X_test, y_test, verbose=0)
assert(loss == nloss)
# test serialization
config = model.get_config()
new_model = Sequential.from_config(config)
def test_lambda():
(X_train, y_train), (X_test, y_test) = _get_test_data()
model.summary()
json_str = model.to_json()
new_model = model_from_json(json_str)
def func(X):
s = X[0]
for i in range(1, len(X)):
s += X[i]
return s
def activation(X):
return K.softmax(X)
def output_shape(input_shapes):
return input_shapes[0]
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(LambdaMerge([left, right], function=func,
output_shape=output_shape))
model.add(Dense(nb_class))
model.add(Lambda(activation))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
# test weight saving
fname = 'test_lambda_temp.h5'
model.save_weights(fname, overwrite=True)
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(LambdaMerge([left, right], function=func,
output_shape=output_shape))
model.add(Dense(nb_class))
model.add(Lambda(activation))
model.load_weights(fname)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
os.remove(fname)
nloss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss == nloss)
# test "join" mode in Lambda
def difference(input_dict):
assert(len(input_dict) == 2)
keys = list(input_dict.keys())
return input_dict[keys[0]] - input_dict[keys[1]]
g = Graph()
g.add_input(name='input_a', input_shape=(2,))
g.add_input(name='input_b', input_shape=(2,))
g.add_node(Lambda(difference, output_shape=(2,)),
inputs=['input_a', 'input_b'],
merge_mode='join',
name='d')
g.add_output(name='output', input='d')
g.compile(loss={'output': 'categorical_crossentropy'}, optimizer='rmsprop')
yaml_str = model.to_yaml()
new_model = model_from_yaml(yaml_str)
def test_sequential_count_params():
@@ -533,135 +448,13 @@ def test_sequential_count_params():
model.add(Dense(nb_units))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.build()
assert(n == model.count_params())
model.compile('sgd', 'binary_crossentropy')
assert(n == model.count_params())
def test_siamese_1():
(X_train, y_train), (X_test, y_test) = _get_test_data()
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(Siamese(Dense(nb_hidden), [left, right], merge_mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
# test weight saving
fname = 'test_siamese_1.h5'
model.save_weights(fname, overwrite=True)
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(Siamese(Dense(nb_hidden), [left, right], merge_mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.load_weights(fname)
os.remove(fname)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
nloss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss == nloss)
def test_siamese_2():
(X_train, y_train), (X_test, y_test) = _get_test_data()
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
add_shared_layer(Dense(nb_hidden), [left, right])
left.add(Dense(nb_hidden))
right.add(Dense(nb_hidden))
add_shared_layer(Dense(nb_hidden), [left, right])
model = Sequential()
model.add(Merge([left, right], mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss < 0.8)
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
# test weight saving
fname = 'test_siamese_2.h5'
model.save_weights(fname, overwrite=True)
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
add_shared_layer(Dense(nb_hidden), [left, right])
left.add(Dense(nb_hidden))
right.add(Dense(nb_hidden))
add_shared_layer(Dense(nb_hidden), [left, right])
model = Sequential()
model.add(Merge([left, right], mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.load_weights(fname)
os.remove(fname)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
nloss = model.evaluate([X_test, X_test], y_test, verbose=0)
assert(loss == nloss)
if __name__ == '__main__':
pytest.main([__file__])
+3 -2
Ver Arquivo
@@ -46,7 +46,7 @@ def build_fn_clf(hidden_dims=50):
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(optimizer='sgd', loss='categorical_crossentropy',
class_mode='binary')
metrics=['accuracy'])
return model
@@ -68,7 +68,8 @@ def build_fn_reg(hidden_dims=50):
model.add(Activation('relu'))
model.add(Dense(1))
model.add(Activation('linear'))
model.compile(optimizer='sgd', loss='mean_absolute_error')
model.compile(optimizer='sgd', loss='mean_absolute_error',
metrics=['accuracy'])
return model
+2 -1
Ver Arquivo
@@ -1,7 +1,8 @@
import numpy as np
import pytest
from keras.models import Sequential, weighted_objective
from keras.models import Sequential
from keras.engine.training import weighted_objective
from keras.layers.core import TimeDistributedDense, Masking
from keras import objectives
from keras import backend as K
-224
Ver Arquivo
@@ -1,224 +0,0 @@
import pytest
import numpy as np
from keras import backend as K
from keras.layers.core import *
from keras.layers.convolutional import *
from keras.layers.recurrent import SimpleRNN
def check_layer_output_shape(layer, input_data):
ndim = len(input_data.shape)
layer.input = K.placeholder(ndim=ndim)
layer.set_input_shape(input_data.shape)
expected_output_shape = layer.output_shape[1:]
function = K.function([layer.input], [layer.get_output()])
output = function([input_data])[0]
assert output.shape[1:] == expected_output_shape
########
# Core #
########
def test_Reshape():
input_data = np.random.random((2, 6))
layer = Reshape(dims=(2, 3))
check_layer_output_shape(layer, input_data)
layer = Reshape(dims=(-1,))
check_layer_output_shape(layer, input_data)
layer = Reshape(dims=(-1, 2))
check_layer_output_shape(layer, input_data)
layer = Reshape(dims=(2, -1))
check_layer_output_shape(layer, input_data)
def test_Permute():
layer = Permute(dims=(1, 3, 2))
input_data = np.random.random((2, 2, 4, 3))
check_layer_output_shape(layer, input_data)
def test_Flatten():
layer = Flatten()
input_data = np.random.random((2, 2, 3))
check_layer_output_shape(layer, input_data)
def test_RepeatVector():
layer = RepeatVector(2)
input_data = np.random.random((2, 2))
check_layer_output_shape(layer, input_data)
def test_Dense():
layer = Dense(3)
input_data = np.random.random((2, 2))
check_layer_output_shape(layer, input_data)
def test_TimeDistributedDense():
layer = TimeDistributedDense(2)
input_data = np.random.random((2, 2, 3))
check_layer_output_shape(layer, input_data)
#################
# Convolutional #
#################
def test_Convolution1D():
for border_mode in ['same', 'valid']:
for filter_length in [2, 3]:
for subsample_length in [1]:
if subsample_length > 1 and border_mode == 'same':
continue
for input_data_shape in [(2, 3, 4), (2, 4, 4)]:
layer = Convolution1D(nb_filter=1,
filter_length=filter_length,
border_mode=border_mode,
subsample_length=subsample_length)
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_Convolution2D():
for border_mode in ['same', 'valid']:
for nb_row, nb_col in [(3, 3), (4, 4), (3, 4)]:
for subsample in [(1, 1), (2, 2), (3, 3)]:
if (subsample[0] > nb_row or subsample[1] > nb_col) and border_mode == 'same':
continue
for input_data_shape in [(2, 1, 5, 5), (2, 1, 6, 6)]:
layer = Convolution2D(nb_filter=1, nb_row=nb_row,
nb_col=nb_row,
border_mode=border_mode,
subsample=subsample,
dim_ordering='th')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
for input_data_shape in [(2, 5, 5, 1)]:
layer = Convolution2D(nb_filter=1, nb_row=nb_row,
nb_col=nb_row,
border_mode=border_mode,
subsample=subsample,
dim_ordering='tf')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_MaxPooling1D():
for ignore_border in [True, False]:
for pool_length in [1, 2]:
for stride in [1]:
for input_data_shape in [(2, 3, 4), (2, 4, 4)]:
layer = MaxPooling1D(pool_length=pool_length,
stride=stride,
border_mode='valid')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_AveragePooling1D():
for ignore_border in [True, False]:
for pool_length in [1, 2]:
for stride in [1]:
for input_data_shape in [(2, 3, 4), (2, 4, 4)]:
layer = AveragePooling1D(pool_length=pool_length,
stride=stride,
border_mode='valid')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_MaxPooling2D():
for ignore_border in [True, False]:
for strides in [(1, 1), (2, 2)]:
for pool_size in [(2, 2), (3, 3), (4, 4)]:
for input_data_shape in [(2, 1, 4, 4), (2, 1, 5, 5), (2, 1, 6, 6)]:
layer = MaxPooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='th')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
for input_data_shape in [(2, 4, 4, 1)]:
layer = MaxPooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='tf')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_AveragePooling2D():
for ignore_border in [True, False]:
for strides in [(1, 1), (2, 2)]:
for pool_size in [(2, 2), (3, 3), (4, 4)]:
for input_data_shape in [(2, 1, 4, 4), (2, 1, 5, 5), (2, 1, 6, 6)]:
layer = AveragePooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='th')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
for input_data_shape in [(2, 4, 4, 1)]:
layer = AveragePooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='tf')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_UpSampling1D():
layer = UpSampling1D(length=2)
input_data = np.random.random((2, 2, 3))
check_layer_output_shape(layer, input_data)
def test_UpSampling2D():
layer = UpSampling2D(size=(2, 2), dim_ordering='th')
input_data = np.random.random((2, 1, 2, 3))
check_layer_output_shape(layer, input_data)
layer = UpSampling2D(size=(2, 2), dim_ordering='tf')
input_data = np.random.random((2, 2, 3, 1))
check_layer_output_shape(layer, input_data)
def test_ZeroPadding1D():
layer = ZeroPadding1D(1)
input_data = np.random.random((2, 2, 1))
check_layer_output_shape(layer, input_data)
def test_ZeroPadding2D():
layer = ZeroPadding2D((1, 2), dim_ordering='th')
input_data = np.random.random((2, 1, 2, 3))
check_layer_output_shape(layer, input_data)
layer = ZeroPadding2D((1, 2), dim_ordering='tf')
input_data = np.random.random((2, 2, 3, 1))
check_layer_output_shape(layer, input_data)
# #############
# # Recurrent #
# #############
def test_SimpleRNN():
# all recurrent layers inherit output_shape
# from the same base recurrent layer
layer = SimpleRNN(2)
input_data = np.random.random((2, 2, 3))
check_layer_output_shape(layer, input_data)
if __name__ == "__main__":
pytest.main([__file__])