Comparar commits

..

88 Commits

Autor SHA1 Mensagem Data
Francois Chollet c6d2ccd453 Prepare 1.1.1 release. 2016-10-31 13:12:59 -07:00
Francois Chollet cdab739471 Merge branch 'master' of https://github.com/fchollet/keras 2016-10-31 13:11:49 -07:00
Taras Boiko fee03bd5a6 Use six for wrapping in keras_test (#4235)
This will allow parameterized tests to work correctly in both 2.7 and
3.4
2016-10-31 10:51:32 -07:00
Aloïs Gruson 6fd2d43bfe Fix Theano Cudnn BatchNorm when axis!=1 (#3968)
* fix batch_norm when axis!=1

* fix dimshuffle for all backends

* moving cudnn bn fix to theano backend

* fix pep8

* dont use cudnn when bn axis is non broadcastable, ie dim=1
2016-10-28 10:51:32 -07:00
Laurent Gautier 9c7020f7e7 Only allow the addition to Sequential objects of layers that are instances of Layer (#4184)
* Check that the added object is an instance of class Layer

* Update models.py

* Fix ValueError error message
2016-10-26 11:02:10 -07:00
Sean 556399cc48 Add more util docs (#4154)
* Add more util docs

* Leave out single use utils
2016-10-26 10:40:33 -07:00
Ramanan Balakrishnan bef888c2d8 add new min_delta parameter in EarlyStopping to stop in cases of minimal improvements (#4202) 2016-10-26 10:39:52 -07:00
Stefan Wunsch a89dabe0cd Enhance doc about usage of sample weights in validation data tuple (#4199) 2016-10-26 10:18:59 -07:00
Alexander Rakhlin 80fbbc3a6a Bug fix in zca_whitening (#4181)
When calculating 'sigma' denominator is # of instances (axis=0), not dimensionality (axis=1)

Proof:
http://ufldl.stanford.edu/wiki/index.php/Implementing_PCA/Whitening
http://ufldl.stanford.edu/wiki/index.php/Exercise:PCA_and_Whitening
Ng uses 2nd dim in denominator because his matrix is features x instances
2016-10-25 10:40:03 -07:00
Carl Thomé 7a6ee934e1 Display wrapped layers in graph visualization (#4169)
* Display wrapped layers in graph visualization

* Check parent class instead of class's module

* Check instance instead for brevity

* More consistent naming
2016-10-25 09:40:14 -07:00
Francois Chollet 4401120ca6 Style fixes 2016-10-24 15:49:38 -07:00
Michael Dietz 8dd61c1dc4 Fixed https://github.com/fchollet/keras/issues/4048 : in TensorBoard callback which fails when it is not the only callback (specifically when another cbk is ReduceLROnPlateau). (#4159) 2016-10-24 15:13:39 -07:00
Roberto de Moura Estevão Filho 6849589430 Fix LiL sparse matrix on Tensorflow (#4173)
LiL sparse matrices would not work correctly due to dtype being
different. Using the sparse_coo data fixes it.
2016-10-24 13:33:45 -07:00
Jaye 4cd83631ee Update imdb_cnn.py to use GlobalMaxPooling1D (#4164) 2016-10-24 09:25:08 -07:00
Felix Sonntag 028aae19bf Fixes for Python 3 (#4121)
* Fixed weights.sort for Python 3

In Python 3 weights.sort could throw a TypeError exception, if the
names are all None

* Fixed _flattened_layers under Python 3

If self.layers is empty, an IndexError appears when accessing it. So
it’s necessary to check if it’s non-empty first

* Fixed weight sorting for Theano backend

* Added missing import statement

* Improved backend handling for weight calculation

* Simplified weight sorting and backend check

* Changed behavior of weights sorting

* Removed unnecessary import
2016-10-23 09:01:16 -07:00
jarfo 41741c38e5 Keep shape of the initial (dummy) state (#4146)
tensorflow breaks if the shape of the state changes
https://github.com/fchollet/keras/issues/4008
2016-10-22 20:23:02 -07:00
Thomas Boquet 3feca20c59 + multiprocessing in legacy - unused imports (#4139) 2016-10-21 14:58:28 -07:00
Johan Pauwels f1bc3c03ed Make build_fn argument of sckit-learn wrappers accept class methods (#4107) 2016-10-20 15:33:56 -07:00
Fariz Rahman 66e5944799 Fix Merge layer docstring (#4132) 2016-10-20 15:23:10 -07:00
Francois Chollet 6ffa6f39e6 Fix typo in Merge layer docstring. 2016-10-19 14:10:17 -07:00
Francois Chollet 94ee8e1570 Add Xception model to keras.applications. 2016-10-19 14:06:07 -07:00
happygds 3e95633b1f manually terminate threads process returned by generator_queue() (#4101)
* manually terminate threads process returned by `generator_queue()`

Recently I custum a video sequence DataGenerator (based on ImageDataGenerator) for experiment. When I use model.fit_generator as following:
>history = model.fit_generator(train_data_generator, samples_per_epoch=train_data_generator.nb_sample,
                              nb_epoch=nb_epoch, verbose=1, callbacks=[early_stopping, model_checkpoint],
                              validation_data=test_data_generator, nb_val_samples=test_data_generator.nb_sample,
                              max_q_size=10, nb_worker=8, pickle_safe=True)
I found that the validation process consumes much longer time than training despite it contains less data.
I read the code and changed the `self.evaluate_generator()` (line 1482) in `fit_generator' to use a multiprocessing approach as training process did. However, the memory usage quikly increases and it only last for a few epoches. 
Through analysis, I think it is caused by the processes weren't freed after the `evaluate_generator` accomplished. Thus I suggest returning `generator_threads` from function `generator_queue()` and manually terminate these threads in `fit_generator`, `evaluate_generator`, `predict_generator`.

* stastify the PEP style

* correct the PEP8's E128 error
2016-10-18 20:34:50 -07:00
Ramanan Balakrishnan 70ebb15a33 Add documentation about metrics functions (#4024)
* Add documentation about metrics functions

* Add docstrings to metrics.py and auto-generate the docs from these strings
2016-10-18 19:57:42 -07:00
Gijs van Tulder d745d9ee96 Use Theano's pool_3d function. (#4065) 2016-10-16 22:27:15 -07:00
Abishek Bhat b89a93faae Remove unused imports. (#4083) 2016-10-16 21:58:35 -07:00
Vijay Vasudevan 044071f0d5 Switch use of TF cond function to use public function. (#4064)
* Switch use of TF cond function to use public function.

Prior to newer TFs, cond was unavailable and thus was being
imported via private module namespaces.

Newer TFs expose tf.cond as the public interface.  There
are plans to remove private module namespace access so
this fixes keras to first try accessing through the public
namespace, and then going through the private one for older
versions of TF.

* PEP8 fix
2016-10-14 14:27:15 -07:00
ηzw 79c1331432 Remove unused import statement (#4053) 2016-10-14 09:16:56 -07:00
Jayanth Koushik 86f28494a5 Return decay from get_config of all optimizers (#4052) 2016-10-13 15:25:50 -07:00
Yu Kobayashi d53a1cd0c0 Python 3 support of image_ocr.py (#4049)
I fixed to support Python 3.
2016-10-13 13:53:35 -07:00
fchollet e52740f09a Add Gitter link to README 2016-10-12 20:11:43 -07:00
fchollet 5dd8c5c10c Padding style fixes. 2016-10-12 18:02:39 -07:00
Dmitry Lukovkin 169c0896d6 Make ZeroPadding2D optionally asymmetric (#3595)
* Make ZeroPadding2D and ZeroPadding1D optionally asymmetric

* Make padding argument polymorphic.
Add test case for asymmetric padding.
Remove excessive imports.

* Fix layer config saving.

* Duck typing (as soon as test passes tuple as a list)

* Doc update

* Set padding value for the missing keys to 0.
Raise exception if unexpected keys are found in the padding dict.

* Add test for ZeroPadding1D
2016-10-12 17:48:57 -07:00
ftence 1bc0468ada Applied imagenet mean pixel on BGR instead of RGB. (#4027) 2016-10-12 16:59:56 -07:00
Gijs van Tulder 9a411f367d Use Theano's new theano.nnet.conv3d interface. (#4039) 2016-10-12 16:57:50 -07:00
Jayanth Koushik 6074a18ec4 Fixed typo in Adamax (#4043)
Fixed a typo in Adamax which prevented it from using explicit decay.
2016-10-12 16:57:22 -07:00
Taras Boiko d7d1db5d79 Test AveragePooling2D in test_average_pooling2d (#4034) 2016-10-12 08:21:21 -07:00
Fariz Rahman 9d7a2338b4 imdb fasttext speedup (#4026)
* imdb fasttext speedup

* Lambda -> GlobalAveragePooling1D
2016-10-11 11:01:11 -07:00
Taras Boiko 6e42b0e4a7 Added ability to return more than one metric from a function (#3907) 2016-10-11 10:54:02 -07:00
Gijs van Tulder ef7911310d Use Theano's cuDNN batch normalization for training. (#4023) 2016-10-11 10:52:07 -07:00
Ramanan Balakrishnan 999f402829 add KL divergence to metrics (#4025) 2016-10-11 10:50:44 -07:00
Bas Veeling 85c2d28e99 ReduceLROnPlateau fix for cooldown=0 (Fixes #3991) (#4011) 2016-10-10 13:18:58 -07:00
fchollet 7df184d3aa Style touch-ups 2016-10-08 15:53:24 -07:00
Abishek Bhat 197005a791 Correct metrics usage in getting started guide. (#3993)
As the code
[here](https://github.com/fchollet/keras/blob/master/keras/engine/training.py#L662) suggests whenever a model is compiled with `metrics = [name_of_the_metric_function]` works, however, the documenation suggests that `accuracy` is the only supported string representation.
2016-10-07 23:34:21 -07:00
Ramanan Balakrishnan 52ee2380e4 Add top-k classification accuracy metrics (#3987)
* add categorical accuracy metric which tracks over top-k predictions

* remove top_k_categorical_accuracy from being tested together with other all_metrics

* fix in_top_k to work with batches. correct metrics.py and test_metrics.py appropriately

* style fixes for documentation on in_top_k function

* default to k=5 for top_k_categorical_accuracy metric
2016-10-07 23:32:19 -07:00
Anish Shah 530eff62e5 [issue #3942] Add GlobalMaxPooling3D and GlobalAveragePooling3D (#3983) 2016-10-07 15:06:19 -07:00
Francois Chollet 4de7eaa6a8 Update docs 2016-10-06 15:38:01 -07:00
Francois Chollet 8281988842 Style fixes 2016-10-06 15:01:17 -07:00
Francois Chollet 4ed7138685 Style fixes 2016-10-06 14:55:22 -07:00
Carl Thomé 6689189819 Add F-score metric to metrics.py (#3895)
* Added optional path argument

* Added optional field name argument

* Added LambdaCallback callback

* Fixed on_epoch_begin assignment

* Match default signatures

* Whitespace

* Test LambdaCallback examples

* Only test process termination

* Imports

* Fixed test

* Wait on process to terminate

* Add zero threshold and set F measure to zero if no true samples exist

* Reduce zero threshold

* Flip thresholded non-zero count

* Add F measure test

* Updated test

* Remove lambda, simplify

* Whitespace

* Update docstring

* Update test

* Whitespace
2016-10-06 14:53:53 -07:00
Emad El-Haraty 0ce7e4976a Descriptions of examples as a README.md file, allowing for easier browsing in github (#3982) 2016-10-06 11:17:22 -07:00
Hengkai Guo 6b18a908b8 Fix shape inference error for newly version Tensorflow in ctc_label_dense_to_sparse (#3955) 2016-10-04 11:21:31 -07:00
Gunnar Läthén 570fdf31c5 Python3 fix for deserialization of closures (#3961) 2016-10-04 11:16:44 -07:00
Seonghyeon Nam 929669bd1b Remove a print message when using global pooling (#3963) 2016-10-04 11:15:16 -07:00
Roberto de Moura Estevão Filho 240fd5b68e Fix control_flow_ops import (#3948)
* Fix control_flow_ops import

Old access was not working on new version of tensorflow. This should
work for all versions.

* Fix identation
2016-10-03 09:42:16 -07:00
Andre Simpelo 9194052a94 Fixed dead link in batch norm documentation (#3937)
Fixed dead link for the references in the Batch Normalization documentation
2016-10-01 20:37:42 -07:00
fchollet e0d871b7dc Restructure docs for Applications module 2016-10-01 15:19:12 -07:00
Sean c455a19f8e Change HDF5Matrix so start and end are optional (#3933) 2016-10-01 12:55:31 -07:00
Francois Chollet d864512631 Fix flaky test 2016-10-01 00:37:21 -07:00
Sean 6ee5d61c91 HDF5Matrix documentation (#3931) 2016-10-01 00:14:39 -07:00
fchollet 04df170bea Merge branch 'master' of ssh://github.com/fchollet/keras 2016-10-01 00:11:45 -07:00
fchollet 5f58a6d2ca Support all backends, dim orderings for music CRNN 2016-10-01 00:11:39 -07:00
Yu Yin ffff5e99aa Fix summary param counting problem (#3661) (#3884)
* Fix summary param counting problem (#3661)

* ...recursively

* Fix default parameter
2016-09-30 22:15:10 -07:00
Francois Chollet 8fab33c245 Make deconv VAE compatible with both dim orderings 2016-09-30 16:26:50 -07:00
Eder Santana 3bf8964355 Keras is TF first. Fix TH first example (#3914)
* Keras is TF first. Fix TH first example

* Use K.set_image_dim_ordering('th')
2016-09-29 10:57:08 -07:00
Thomas Boquet 51c85dd8d6 Bypass shape inference in deconv2d and use the output shape provided by the user (#3838)
* bypass shape inference in deconv2d

* * more doc in deconv layer

* more deconv layers in var autoencoder example

* * typo doc

* replicate deconv example with with paper's params

* replicate example with paper's params

* typo doc

* + relus in the deconv

* typo in var autoencodeur example

* + mult by ndim

* style fixes

* pep8
2016-09-28 13:40:44 -07:00
Nithish deva Divakar 31f41b9822 typos (#3869)
Added missing numpy imports in examples
2016-09-28 12:30:36 -07:00
M Clark 458576bbe7 List files in alphabetical order (#3871)
`os.listdir` to `sorted(os.listdir)` for alphabetical order instead of arbitrary order. Following PR#3751 this allows mask and images with the same name to be read together.
2016-09-28 12:30:21 -07:00
Yu Yin e3a64cc8a7 Choose format according to filename when plotting (#3883) 2016-09-28 11:43:23 -07:00
Francois Chollet 9045616bda Revert adadelta lr 2016-09-27 10:50:35 -07:00
Francois Chollet 25dbe8097f Update adadelta default learning rate 2016-09-27 09:56:58 -07:00
fchollet fb6a2941b9 Fix typos 2016-09-24 22:19:32 -07:00
fchollet ed131973ef Fix music tagger application 2016-09-24 22:12:22 -07:00
Keunwoo Choi 43060d8c7d add audio models: audio_convnet and audio_conv_rnn (#3718)
* add audio models: audio_convnet and audio_conv_rnn

* add audio models: audio_convnet and audio_conv_rnn

* remove white spaces at the end of lines

* add audio_conv_utils.py, update applications.md

* remove useless line in example in application.md

* remove useless line in example in application.md

* rename models (MusicTaggerCNN,CRNN), BN mode=0 weights

* pep8

* remove MusicTaggerCNN, add include_top argument

* update to follow pep8
2016-09-24 19:53:47 -07:00
fchollet d5f1250a8b Update imagenet prediction decoding utilities 2016-09-24 11:46:41 -07:00
Bas Veeling 4c01c0c4d7 ReduceLROnPlateau Callback and CSVLogger Callback (#3780)
* ReduceLROnPlateau Callback and CSVLogger Callback

* Added documentation and cleanup.

* Added examples.

* Added test for ReduceLROnPlateau()

* Minor changes to naming.

* Added epsilon for lr comparison.

* Fix sensitivity issue

* PEP8
2016-09-23 21:16:19 -07:00
danstowell af28101af1 Functional API guide: fix variable names "loss"->"output" (#3856)
Some of the variable names in this guide were misleadingly named. The outputs were named as `*_loss` implying that they held loss values, whereas they in fact held the outputs. It rather confused me; I believe my proposed naming is clearer.
2016-09-23 08:59:36 -07:00
Flynn, Michael D 56aa9f364a Add cropping layers to documentation (#3853)
* Correct documentation for Cropping3D layer

* Add Cropping layers to documentation
2016-09-22 20:46:22 -07:00
Taras Boiko f0d9867d09 Changed ELU implementation to use native ops (#3845) 2016-09-22 11:08:21 -07:00
Carl Thomé cfc9b4d41d LambdaCallback (#3760)
* Added optional path argument

* Added optional field name argument

* Added LambdaCallback callback

* Fixed on_epoch_begin assignment

* Match default signatures

* Whitespace

* Test LambdaCallback examples

* Only test process termination

* Imports

* Fixed test

* Wait on process to terminate
2016-09-22 09:19:51 -07:00
Fariz Rahman de66211afb Set theano as default backend for windows users (#3831)
* Set theano as default backend for windows users

* Update __init__.py
2016-09-21 21:12:06 -07:00
M Clark 414d5f0978 make ImageDataGenerator behaviour fully seedable/repeatable (#3751)
* make ImageDataGenerator behaviour fully seedable/repeatable

This makes ImageDataGenerator fully seedable.
- the seed argument in fit is now used
- the seed argument in flow and flow_from_directory now effects
transforms
- added example to docs of transforming images and masks together
- added test of using two seeded streams at once

* implemented requested changes

- PEP8
- explicit names
- classes=None
- remove test
2016-09-21 21:11:39 -07:00
Fariz Rahman 99bd066f38 TimeDistributed : unroll RNN when using TF backend (#3835)
* TimeDistributed : unroll RNN when using TF backend

TF dynamic rnn not working with ndim > 3

* Update wrappers.py

* Update wrappers.py
2016-09-21 17:31:46 -07:00
ηzw 82a22b20fc Update default dim_ordering (#3832)
* Update default dim_ordering

* Update default dim_ordering
2016-09-21 11:32:08 -07:00
Francois Chollet 25ed701dbd Merge branch 'master' of https://github.com/fchollet/keras 2016-09-20 21:40:07 -07:00
Francois Chollet 875c521413 Update deep dream example 2016-09-20 21:39:51 -07:00
kuza55 7b8363632e Attempted fix for #3801 (#3827) 2016-09-20 14:57:08 -07:00
kuza55 06f18fa1b9 Matthews Correlation fix and test (#3822) 2016-09-20 09:19:00 -07:00
Taras Boiko 54fc646537 Split multitest in test_recurrent (#3818) 2016-09-20 08:43:42 -07:00
66 arquivos alterados com 2570 adições e 420 exclusões
+5 -2
Ver Arquivo
@@ -8,7 +8,7 @@
## You have just found Keras.
Keras is a minimalist, highly modular neural networks library, written in Python and capable of running on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Keras is a high-level neural networks library, written in Python and capable of running on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Use Keras if you need a deep learning library that:
@@ -149,7 +149,10 @@ By default, Keras will use TensorFlow as its tensor manipulation library. [Follo
## Support
You can ask questions and join the development discussion on the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
You can ask questions and join the development discussion:
- On the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
- On the [Keras Gitter channel](https://gitter.im/Keras-io/Lobby).
You can also post bug reports and feature requests in [Github issues](https://github.com/fchollet/keras/issues). Make sure to read [our guidelines](https://github.com/fchollet/keras/blob/master/CONTRIBUTING.md) first.
+35 -1
Ver Arquivo
@@ -40,6 +40,7 @@ Index
Sequence preprocessing
Objectives
Metrics
Optimizers
Activations
Callbacks
@@ -79,10 +80,15 @@ from keras import callbacks
from keras import models
from keras.engine import topology
from keras import objectives
from keras import metrics
from keras import backend
from keras import constraints
from keras import activations
from keras import regularizers
from keras.utils import data_utils
from keras.utils import io_utils
from keras.utils import layer_utils
from keras.utils import np_utils
EXCLUDE = {
@@ -158,6 +164,9 @@ PAGES = [
convolutional.SeparableConvolution2D,
convolutional.Deconvolution2D,
convolutional.Convolution3D,
convolutional.Cropping1D,
convolutional.Cropping2D,
convolutional.Cropping3D,
convolutional.UpSampling1D,
convolutional.UpSampling2D,
convolutional.UpSampling3D,
@@ -221,7 +230,10 @@ PAGES = [
'page': 'layers/wrappers.md',
'all_module_classes': [wrappers],
},
{
'page': 'metrics.md',
'all_module_functions': [metrics],
},
{
'page': 'optimizers.md',
'all_module_classes': [optimizers],
@@ -234,6 +246,28 @@ PAGES = [
'page': 'backend.md',
'all_module_functions': [backend],
},
{
'page': 'utils/data_utils.md',
'functions': [
data_utils.get_file,
]
},
{
'page': 'utils/io_utils.md',
'classes': [
io_utils.HDF5Matrix
],
},
{
'page': 'utils/layer_utils.md',
'functions': [
layer_utils.layer_from_config,
]
},
{
'page': 'utils/np_utils.md',
'all_module_functions': [np_utils]
},
]
ROOT = 'http://keras.io/'
+6 -1
Ver Arquivo
@@ -38,6 +38,7 @@ pages:
- Text Preprocessing: preprocessing/text.md
- Image Preprocessing: preprocessing/image.md
- Objectives: objectives.md
- Metrics: metrics.md
- Optimizers: optimizers.md
- Activations: activations.md
- Callbacks: callbacks.md
@@ -49,7 +50,11 @@ pages:
- Constraints: constraints.md
- Visualization: visualization.md
- Scikit-learn API: scikit-learn-api.md
- Utils:
- Data Utils: utils/data_utils.md
- I/O Utils: utils/io_utils.md
- Layer Utils: utils/layer_utils.md
- Numpy Utils: utils/np_utils.md
+164 -7
Ver Arquivo
@@ -7,18 +7,25 @@ Weights are downloaded automatically when instantiating a model. They are stored
## Available models
Models for image classification with weights trained on ImageNet:
### Models for image classification with weights trained on ImageNet:
- [Xception](#xception)
- [VGG16](#vgg16)
- [VGG19](#vgg19)
- [ResNet50](#resnet50)
- [InceptionV3](#inceptionv3)
All of these architectures are compatible with both TensorFlow and Theano, and upon instantiation the models will be built according to the image dimension ordering set in your Keras configuration file at `~/.keras/keras.json`. For instance, if you have set `image_dim_ordering=tf`, then any model loaded from this repository will get built according to the TensorFlow dimension ordering convention, "Width-Height-Depth".
All of these architectures (except Xception) are compatible with both TensorFlow and Theano, and upon instantiation the models will be built according to the image dimension ordering set in your Keras configuration file at `~/.keras/keras.json`. For instance, if you have set `image_dim_ordering=tf`, then any model loaded from this repository will get built according to the TensorFlow dimension ordering convention, "Width-Height-Depth".
The Xception model is only available for TensorFlow, due to its reliance on `SeparableConvolution` layers.
### Model for music audio file auto-tagging (taking as input Mel-spectrograms):
- [MusicTaggerCRNN](#musictaggercrnn)
-----
## Examples
## Usage examples for image classification models
### Classify ImageNet classes with ResNet50
@@ -26,6 +33,7 @@ All of these architectures are compatible with both TensorFlow and Theano, and u
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np
model = ResNet50(weights='imagenet')
@@ -36,8 +44,10 @@ x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
preds = model.predict(x)
print('Predicted:', decode_predictions(preds))
# print: [[u'n02504458', u'African_elephant']]
# decode the results into a list of tuples (class, description, probability)
# (one such list for each sample in the batch)
print('Predicted:', decode_predictions(preds, top=3)[0])
# Predicted: [(u'n02504013', u'Indian_elephant', 0.82658225), (u'n01871265', u'tusker', 0.1122357), (u'n02504458', u'African_elephant', 0.061040461)]
```
### Extract features with VGG16
@@ -46,6 +56,7 @@ print('Predicted:', decode_predictions(preds))
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np
model = VGG16(weights='imagenet', include_top=False)
@@ -65,6 +76,7 @@ from keras.applications.vgg19 import VGG19
from keras.preprocessing import image
from keras.applications.vgg19 import preprocess_input
from keras.models import Model
import numpy as np
base_model = VGG19(weights='imagenet')
model = Model(input=base_model.input, output=base_model.get_layer('block4_pool').output)
@@ -153,12 +165,71 @@ model = InceptionV3(input_tensor=input_tensor, weights='imagenet', include_top=T
-----
# Documentation for individual models
- [Xception](#xception)
- [VGG16](#vgg16)
- [VGG19](#vgg19)
- [ResNet50](#resnet50)
- [InceptionV3](#inceptionv3)
- [MusicTaggerCRNN](#musictaggercrnn)
-----
## Xception
```python
keras.applications.xception.Xception(include_top=True, weights='imagenet', input_tensor=None)
```
Xception V1 model, with weights pre-trained on ImageNet.
On ImageNet, this model gets to a top-1 validation accuracy of 0.790
and a top-5 validation accuracy of 0.945.
Note that this model is only available for the TensorFlow backend,
due to its reliance on `SeparableConvolution` layers. Additionally it only supports
the dimension ordering "tf" (width, height, channels).
The default input size for this model is 299x299.
### Arguments
- include_top: whether to include the fully-connected layer at the top of the network.
- weights: one of `None` (random initialization) or "imagenet" (pre-training on ImageNet).
- input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model.
### Returns
A Keras model instance.
### References
- [Xception: Deep Learning with Depthwise Separable Convolutions](https://arxiv.org/abs/1610.02357)
### License
These weights are trained by ourselves and are released under the MIT license.
-----
## VGG16
```python
keras.applications.vgg16.VGG16(include_top=True, weights='imagenet', input_tensor=None)
```
VGG16 model, with weights pre-trained on ImageNet.
This model is available for both the Theano and TensorFlow backend, and can be built both
with "th" dim ordering (channels, width, height) or "tf" dim ordering (width, height, channels).
The default input size for this model is 224x224.
### Arguments
- include_top: whether to include the 3 fully-connected layers at the top of the network.
@@ -186,6 +257,14 @@ These weights are ported from the ones [released by VGG at Oxford](http://www.ro
keras.applications.vgg19.VGG19(include_top=True, weights='imagenet', input_tensor=None)
```
VGG19 model, with weights pre-trained on ImageNet.
This model is available for both the Theano and TensorFlow backend, and can be built both
with "th" dim ordering (channels, width, height) or "tf" dim ordering (width, height, channels).
The default input size for this model is 224x224.
### Arguments
- include_top: whether to include the 3 fully-connected layers at the top of the network.
@@ -214,9 +293,18 @@ These weights are ported from the ones [released by VGG at Oxford](http://www.ro
keras.applications.resnet50.ResNet50(include_top=True, weights='imagenet', input_tensor=None)
```
ResNet50 model, with weights pre-trained on ImageNet.
This model is available for both the Theano and TensorFlow backend, and can be built both
with "th" dim ordering (channels, width, height) or "tf" dim ordering (width, height, channels).
The default input size for this model is 224x224.
### Arguments
- include_top: whether to include the 3 fully-connected layers at the top of the network.
- include_top: whether to include the fully-connected layer at the top of the network.
- weights: one of `None` (random initialization) or "imagenet" (pre-training on ImageNet).
- input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model.
@@ -241,9 +329,17 @@ These weights are ported from the ones [released by Kaiming He](https://github.c
keras.applications.inception_v3.InceptionV3(include_top=True, weights='imagenet', input_tensor=None)
```
Inception V3 model, with weights pre-trained on ImageNet.
This model is available for both the Theano and TensorFlow backend, and can be built both
with "th" dim ordering (channels, width, height) or "tf" dim ordering (width, height, channels).
The default input size for this model is 299x299.
### Arguments
- include_top: whether to include the 3 fully-connected layers at the top of the network.
- include_top: whether to include the fully-connected layer at the top of the network.
- weights: one of `None` (random initialization) or "imagenet" (pre-training on ImageNet).
- input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model.
@@ -258,3 +354,64 @@ A Keras model instance.
### License
These weights are trained by ourselves and are released under the MIT license.
-----
## MusicTaggerCRNN
```python
keras.applications.music_tagger_crnn.MusicTaggerCRNN(weights='msd', input_tensor=None, include_top=True)
```
A convolutional-recurrent model taking as input a vectorized representation of the MelSpectrogram of a music track and capable of outputting the musical genre of the track. You can use `keras.applications.music_tagger_crnn.preprocess_input` to convert a sound file to a vectorized spectrogram. This requires to have installed the [Librosa](http://librosa.github.io/librosa/) library. See [the usage example](#music-tagging-and-feature-extraction-with-musictaggercrnn).
### Arguments
- weights: one of `None` (random initialization) or "msd" (pre-training on [Million Song Dataset](http://labrosa.ee.columbia.edu/millionsong/)).
- input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) to use as image input for the model.
- include_top: whether to include the 1 fully-connected layer (output layer) at the top of the network. If False, the network outputs 32-dim features.
### Returns
A Keras model instance.
### References
- [Convolutional Recurrent Neural Networks for Music Classification](https://arxiv.org/abs/1609.04243)
### License
These weights are ported from the ones [released by Keunwoo Choi](https://github.com/keunwoochoi/music-auto_tagging-keras) under the [MIT license](https://github.com/keunwoochoi/music-auto_tagging-keras/blob/master/LICENSE.md).
### Examples: music tagging and audio feature extraction
```python
from keras.applications.music_tagger_crnn import MusicTaggerCRNN
from keras.applications.music_tagger_crnn import preprocess_input, decode_predictions
import numpy as np
# 1. Tagging
model = MusicTaggerCRNN(weights='msd')
audio_path = 'audio_file.mp3'
melgram = preprocess_input(audio_path)
melgrams = np.expand_dims(melgram, axis=0)
preds = model.predict(melgrams)
print('Predicted:')
print(decode_predictions(preds))
# print: ('Predicted:', [[('rock', 0.097071797), ('pop', 0.042456303), ('alternative', 0.032439161), ('indie', 0.024491295), ('female vocalists', 0.016455274)]])
#. 2. Feature extraction
model = MusicTaggerCRNN(weights='msd', include_top=False)
audio_path = 'audio_file.mp3'
melgram = preprocess_input(audio_path)
melgrams = np.expand_dims(melgram, axis=0)
feats = model.predict(melgrams)
print('Features:')
print(feats[0, :10])
# print: ('Features:', [-0.19160545 0.94259131 -0.9991011 0.47644514 -0.19089699 0.99033844 0.1103896 -0.00340496 0.14823607 0.59856361])
```
+3 -3
Ver Arquivo
@@ -102,7 +102,7 @@ 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)
auxiliary_output = 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:
@@ -117,13 +117,13 @@ 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)
main_output = 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])
model = Model(input=[main_input, auxiliary_input], output=[main_output, auxiliary_output])
```
We compile the model and assign a weight of 0.2 to the auxiliary loss.
+19 -1
Ver Arquivo
@@ -121,7 +121,7 @@ Before training a model, you need to configure the learning process, which is do
- 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. It 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.
- 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 or a custom metric function. Custom metric function should return either a single tensor value or a dict `metric_name -> metric_value`. See: [metrics](/metrics).
```python
# for a multi-class classification problem
@@ -137,6 +137,24 @@ model.compile(optimizer='rmsprop',
# for a mean squared error regression problem
model.compile(optimizer='rmsprop',
loss='mse')
# for custom metrics
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
def false_rates(y_true, y_pred):
false_neg = ...
false_pos = ...
return {
'false_neg': false_neg,
'false_pos': false_pos,
}
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred, false_rates])
```
----
+5 -2
Ver Arquivo
@@ -2,7 +2,7 @@
## You have just found Keras.
Keras is a minimalist, highly modular neural networks library, written in Python and capable of running on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Keras is a high-level neural networks library, written in Python and capable of running on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. *Being able to go from idea to result with the least possible delay is key to doing good research.*
Use Keras if you need a deep learning library that:
@@ -143,7 +143,10 @@ By default, Keras will use TensorFlow as its tensor manipulation library. [Follo
## Support
You can ask questions and join the development discussion on the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
You can ask questions and join the development discussion:
- On the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
- On the [Keras Gitter channel](https://gitter.im/Keras-io/Lobby).
You can also post bug reports and feature requests in [Github issues](https://github.com/fchollet/keras/issues). Make sure to read [our guidelines](https://github.com/fchollet/keras/blob/master/CONTRIBUTING.md) first.
+51
Ver Arquivo
@@ -0,0 +1,51 @@
## Usage of metrics
A metric is a function that is used to judge the performance of your model. Metric functions are to be supplied in the `metrics` parameter when a model is compiled.
A metric function is similar to an [objective function](/objectives), except that the results from evaluating a metric are not used when training the model.
You can either pass the name of an existing metric, or pass a Theano/TensorFlow symbolic function (see [Custom metrics](#custom-metrics)).
#### Arguments
- __y_true__: True labels. Theano/TensorFlow tensor.
- __y_pred__: Predictions. Theano/TensorFlow tensor of the same shape as y_true.
#### Returns
Single tensor value representing the mean of the output array across all
datapoints.
----
## Available metrics
{{autogenerated}}
----
## Custom metrics
Custom metrics can be defined and passed via the compilation step. The
function would need to take `(y_true, y_pred)` as arguments and return
either a single tensor value or a dict `metric_name -> metric_value`.
```python
# for custom metrics
import keras.backend as K
def mean_pred(y_true, y_pred):
return K.mean(y_pred)
def false_rates(y_true, y_pred):
false_neg = ...
false_pos = ...
return {
'false_neg': false_neg,
'false_pos': false_pos,
}
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy', mean_pred, false_rates])
```
+8
Ver Arquivo
@@ -30,3 +30,11 @@ For a few examples of such functions, check out the [objectives source](https://
- __kullback_leibler_divergence__ / __kld__: Information gain from a predicted probability distribution Q to a true probability distribution P. Gives a measure of difference between both distributions.
- __poisson__: Mean of `(predictions - targets * log(predictions))`
- __cosine_proximity__: The opposite (negative) of the mean cosine proximity between predictions and targets.
**Note**: when using the `categorical_crossentropy` objective, your targets should be in categorical format (e.g. if you have 10 classes, the target for each sample should be a 10-dimensional vector that is all-zeros expect for a 1 at the index corresponding to the class of the sample). In order to convert *integer targets* into *categorical targets*, you can use the Keras utility `to_categorical`:
```python
from keras.utils.np_utils import to_categorical
categorical_labels = to_categorical(int_labels, nb_classes=None)
```
+41 -2
Ver Arquivo
@@ -47,7 +47,7 @@ Generate batches of tensor image data with real-time data augmentation. The data
"th" mode means that the images should have shape `(samples, channels, width, height)`.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
- __Methods__:
- __fit(X)__: Compute the internal data stats related to the data-dependent transformations, based on an array of sample data.
@@ -56,12 +56,14 @@ Generate batches of tensor image data with real-time data augmentation. The data
- __X__: sample data.
- __augment__: Boolean (default: False). Whether to fit on randomly augmented samples.
- __rounds__: int (default: 1). If augment, how many augmentation passes over the data to use.
- __seed__: int (default: None). Random seed.
- __flow(X, y)__: Takes numpy data & label arrays, and generates batches of augmented/normalized data. Yields batches indefinitely, in an infinite loop.
- __Arguments__:
- __X__: data.
- __y__: labels.
- __batch_size__: int (default: 32).
- __shuffle__: boolean (defaut: True).
- __seed__: int (default: None).
- __save_to_dir__: None or str (default: None). This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str (default: `''`). Prefix to use for filenames of saved pictures (only relevant if `save_to_dir` is set).
- __save_format__: one of "png", "jpeg" (only relevant if `save_to_dir` is set). Default: "jpeg".
@@ -77,7 +79,7 @@ Generate batches of tensor image data with real-time data augmentation. The data
- __class_mode__: one of "categorical", "binary", "sparse" or None. Default: "categorical". Determines the type of label arrays that are returned: "categorical" will be 2D one-hot encoded labels, "binary" will be 1D binary labels, "sparse" will be 1D integer labels. If None, no labels are returned (the generator will only yield batches of image data, which is useful to use `model.predict_generator()`, `model.evaluate_generator()`, etc.).
- __batch_size__: size of the batches of data (default: 32).
- __shuffle__: whether to shuffle the data (default: True)
- __seed__: optional random seed for shuffling.
- __seed__: optional random seed for shuffling and transformations.
- __save_to_dir__: None or str (default: None). This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str. Prefix to use for filenames of saved pictures (only relevant if `save_to_dir` is set).
- __save_format__: one of "png", "jpeg" (only relevant if `save_to_dir` is set). Default: "jpeg".
@@ -151,3 +153,40 @@ model.fit_generator(
validation_data=validation_generator,
nb_val_samples=800)
```
Example of transforming images and masks together.
```python
# we create two instances with the same arguments
data_gen_args = dict(featurewise_center=True,
featurewise_std_normalization=True,
rotation_range=90.,
width_shift_range=0.1,
height_shift_range=0.1,
zoom_range=0.2)
image_datagen = ImageDataGenerator(**data_gen_args)
mask_datagen = ImageDataGenerator(**data_gen_args)
# Provide the same seed and keyword arguments to the fit and flow methods
seed = 1
image_datagen.fit(images, augment=True, seed=seed)
mask_datagen.fit(masks, augment=True, seed=seed)
image_generator = image_datagen.flow_from_directory(
'data/images',
class_mode=None,
seed=seed)
mask_generator = mask_datagen.flow_from_directory(
'data/masks',
class_mode=None,
seed=seed)
# combine generators into one which yields image and masks
train_generator = zip(image_generator, mask_generator)
model.fit_generator(
train_generator,
samples_per_epoch=2000,
nb_epoch=50)
```
+94
Ver Arquivo
@@ -0,0 +1,94 @@
# Keras examples directory
[addition_rnn.py](addition_rnn.py)
Implementation of sequence to sequence learning for performing addition of two numbers (as strings).
[antirectifier.py](antirectifier.py)
Demonstrates how to write custom layers for Keras.
[babi_memnn.py](babi_memnn.py)
Trains a memory network on the bAbI dataset for reading comprehension.
[babi_rnn.py](babi_rnn.py)
Trains a two-branch recurrent network on the bAbI dataset for reading comprehension.
[cifar10_cnn.py](cifar10_cnn.py)
Trains a simple deep CNN on the CIFAR10 small images dataset.
[conv_filter_visualization.py](conv_filter_visualization.py)
Visualization of the filters of VGG16, via gradient ascent in input space.
[deep_dream.py](deep_dream.py)
Deep Dreams in Keras.
[image_ocr.py](image_ocr.py)
Trains a convolutional stack followed by a recurrent stack and a CTC logloss function to perform optical character recognition (OCR).
[imdb_bidirectional_lstm.py](imdb_bidirectional_lstm.py)
Trains a Bidirectional LSTM on the IMDB sentiment classification task.
[imdb_cnn.py](imdb_cnn.py)
Demonstrates the use of Convolution1D for text classification.
[imdb_cnn_lstm.py](imdb_cnn_lstm.py)
Trains a convolutional stack followed by a recurrent stack network on the IMDB sentiment classification task.
[imdb_fasttext.py](imdb_fasttext.py)
Trains a FastText model on the IMDB sentiment classification task.
[imdb_lstm.py](imdb_lstm.py)
Trains a LSTM on the IMDB sentiment classification task.
[lstm_benchmark.py](lstm_benchmark.py)
Compares different LSTM implementations on the IMDB sentiment classification task.
[lstm_text_generation.py](lstm_text_generation.py)
Generates text from Nietzsche's writings.
[mnist_cnn.py](mnist_cnn.py)
Trains a simple convnet on the MNIST dataset.
[mnist_hierarchical_rnn.py](mnist_hierarchical_rnn.py)
Trains a Hierarchical RNN (HRNN) to classify MNIST digits.
[mnist_irnn.py](mnist_irnn.py)
Reproduction of the IRNN experiment with pixel-by-pixel sequential MNIST in "A Simple Way to Initialize Recurrent Networks of Rectified Linear Units" by Le et al.
[mnist_mlp.py](mnist_mlp.py)
Trains a simple deep multi-layer perceptron on the MNIST dataset.
[mnist_net2net.py](mnist_net2net.py)
Reproduction of the Net2Net experiment with MNIST in "Net2Net: Accelerating Learning via Knowledge Transfer".
[mnist_siamese_graph.py](mnist_siamese_graph.py)
Trains a Siamese multi-layer perceptron on pairs of digits from the MNIST dataset.
[mnist_sklearn_wrapper.py](mnist_sklearn_wrapper.py)
Demonstrates how to use the sklearn wrapper.
[mnist_swwae.py](mnist_swwae.py)
Trains a Stacked What-Where AutoEncoder built on residual blocks on the MNIST dataset.
[mnist_transfer_cnn.py](mnist_transfer_cnn.py)
Transfer learning toy example.
[neural_doodle.py](neural_doodle.py)
Neural doodle.
[neural_style_transfer.py](neural_style_transfer.py)
Neural style transfer.
[pretrained_word_embeddings.py](pretrained_word_embeddings.py)
Loads pre-trained word embeddings (GloVe embeddings) into a frozen Keras Embedding layer, and uses it to train a text classification model on the 20 Newsgroup dataset.
[reuters_mlp.py](reuters_mlp.py)
Trains and evaluate a simple MLP on the Reuters newswire topic classification task.
[stateful_lstm.py](stateful_lstm.py)
Demonstrates how to use stateful RNNs to model long sequences efficiently.
[variational_autoencoder.py](variational_autoencoder.py)
Demonstrates how to build a variational autoencoder.
[variational_autoencoder_deconv.py](variational_autoencoder_deconv.py)
Demonstrates how to build a variational autoencoder with Keras using deconvolution layers.
+53 -77
Ver Arquivo
@@ -15,17 +15,16 @@ If running on CPU, prefer the TensorFlow backend (much faster).
Example results: http://i.imgur.com/FX6ROg9.jpg
'''
from __future__ import print_function
from scipy.misc import imread, imresize, imsave
from keras.preprocessing.image import load_img, img_to_array
import numpy as np
from scipy.misc import imsave
from scipy.optimize import fmin_l_bfgs_b
import time
import argparse
import h5py
import os
from keras.models import Sequential
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.applications import vgg16
from keras import backend as K
from keras.layers import Input
parser = argparse.ArgumentParser(description='Deep Dreams with Keras.')
parser.add_argument('base_image_path', metavar='base', type=str,
@@ -46,14 +45,14 @@ weights_path = 'vgg16_weights.h5'
# some settings we found interesting
saved_settings = {
'bad_trip': {'features': {'conv4_1': 0.05,
'conv4_2': 0.01,
'conv4_3': 0.01},
'bad_trip': {'features': {'block4_conv1': 0.05,
'block4_conv2': 0.01,
'block4_conv3': 0.01},
'continuity': 0.1,
'dream_l2': 0.8,
'jitter': 5},
'dreamy': {'features': {'conv5_1': 0.05,
'conv5_2': 0.02},
'dreamy': {'features': {'block5_conv1': 0.05,
'block5_conv2': 0.02},
'continuity': 0.1,
'dream_l2': 0.02,
'jitter': 0},
@@ -63,73 +62,39 @@ settings = saved_settings['dreamy']
# util function to open, resize and format pictures into appropriate tensors
def preprocess_image(image_path):
img = imresize(imread(image_path), (img_width, img_height))
img = img.transpose((2, 0, 1)).astype('float64')
img = load_img(image_path, target_size=(img_width, img_height))
img = img_to_array(img)
img = np.expand_dims(img, axis=0)
img = vgg16.preprocess_input(img)
return img
# util function to convert a tensor into a valid image
def deprocess_image(x):
x = x.transpose((1, 2, 0))
if K.image_dim_ordering() == 'th':
x = x.reshape((3, img_width, img_height))
x = x.transpose((1, 2, 0))
else:
x = x.reshape((img_width, img_height, 3))
# Remove zero-center by mean pixel
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
# 'BGR'->'RGB'
x = x[:, :, ::-1]
x = np.clip(x, 0, 255).astype('uint8')
return x
# build the VGG16 network
model = Sequential()
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
if K.image_dim_ordering() == 'th':
img_size = (3, img_width, img_height)
else:
img_size = (img_width, img_height, 3)
# this will contain our generated image
dream = Input(batch_shape=(1,) + img_size)
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'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
# load the weights of the VGG16 networks
# (trained on ImageNet, won the ILSVRC competition in 2014)
# note: when there is a complete match between your model definition
# and your weight savefile, you can simply call model.load_weights(filename)
assert os.path.exists(weights_path), 'Model weights not found (see "weights_path" variable in script).'
f = h5py.File(weights_path)
for k in range(f.attrs['nb_layers']):
if k >= len(model.layers):
# we don't look at the last (fully-connected) layers in the savefile
break
g = f['layer_{}'.format(k)]
weights = [g['param_{}'.format(p)] for p in range(g.attrs['nb_params'])]
model.layers[k].set_weights(weights)
f.close()
# build the VGG16 network with our placeholder
# the model will be loaded with pre-trained ImageNet weights
model = vgg16.VGG16(input_tensor=dream,
weights='imagenet', include_top=False)
print('Model loaded.')
# get the symbolic outputs of each "key" layer (we gave them unique names).
@@ -138,8 +103,16 @@ layer_dict = dict([(layer.name, layer) for layer in model.layers])
# continuity loss util function
def continuity_loss(x):
assert K.ndim(x) == 4
a = K.square(x[:, :, :img_width-1, :img_height-1] - x[:, :, 1:, :img_height-1])
b = K.square(x[:, :, :img_width-1, :img_height-1] - x[:, :, :img_width-1, 1:])
if K.image_dim_ordering() == 'th':
a = K.square(x[:, :, :img_width - 1, :img_height - 1] -
x[:, :, 1:, :img_height - 1])
b = K.square(x[:, :, :img_width - 1, :img_height - 1] -
x[:, :, :img_width - 1, 1:])
else:
a = K.square(x[:, :img_width - 1, :img_height-1, :] -
x[:, 1:, :img_height - 1, :])
b = K.square(x[:, :img_width - 1, :img_height-1, :] -
x[:, :img_width - 1, 1:, :])
return K.sum(K.pow(a + b, 1.25))
# define the loss
@@ -151,12 +124,15 @@ for layer_name in settings['features']:
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:])
if K.image_dim_ordering() == 'th':
loss -= coeff * K.sum(K.square(x[:, :, 2: shape[2] - 2, 2: shape[3] - 2])) / np.prod(shape[1:])
else:
loss -= coeff * K.sum(K.square(x[:, 2: shape[1] - 2, 2: shape[2] - 2, :])) / np.prod(shape[1:])
# add continuity loss (gives image local coherence, can result in an artful blur)
loss += settings['continuity'] * continuity_loss(dream) / (3 * img_width * img_height)
loss += settings['continuity'] * continuity_loss(dream) / np.prod(img_size)
# add image L2 norm to loss (prevents pixels from taking very high values, makes image darker)
loss += settings['dream_l2'] * K.sum(K.square(dream)) / (3 * img_width * img_height)
loss += settings['dream_l2'] * K.sum(K.square(dream)) / np.prod(img_size)
# feel free to further modify the loss as you see fit, to achieve new effects...
@@ -171,7 +147,7 @@ else:
f_outputs = K.function([dream], outputs)
def eval_loss_and_grads(x):
x = x.reshape((1, 3, img_width, img_height))
x = x.reshape((1,) + img_size)
outs = f_outputs([x])
loss_value = outs[0]
if len(outs[1:]) == 1:
@@ -215,7 +191,7 @@ for i in range(5):
start_time = time.time()
# add a random jitter to the initial image. This will be reverted at decoding time
random_jitter = (settings['jitter'] * 2) * (np.random.random((3, img_width, img_height)) - 0.5)
random_jitter = (settings['jitter'] * 2) * (np.random.random(img_size) - 0.5)
x += random_jitter
# run L-BFGS for 7 steps
@@ -223,9 +199,9 @@ for i in range(5):
fprime=evaluator.grads, maxfun=7)
print('Current loss value:', min_val)
# decode the dream and save it
x = x.reshape((3, img_width, img_height))
x = x.reshape(img_size)
x -= random_jitter
img = deprocess_image(x)
img = deprocess_image(np.copy(x))
fname = result_prefix + '_at_iteration_%d.png' % i
imsave(fname, img)
end_time = time.time()
+4 -4
Ver Arquivo
@@ -109,7 +109,7 @@ def paint_text(text, w, h):
a = np.frombuffer(buf, np.uint8)
a.shape = (h, w, 4)
a = a[:, :, 0] # grab single channel
a /= 255
a = a.astype(np.float32) / 255
a = np.expand_dims(a, 0)
a = speckle(a)
a = image.random_rotation(a, 3 * (w - top_left_x) / w + 1)
@@ -396,7 +396,7 @@ pool_size_1 = 4
pool_size_2 = 2
time_dense_size = 32
rnn_size = 512
time_steps = img_w / (pool_size_1 * pool_size_2)
time_steps = img_w // (pool_size_1 * pool_size_2)
if K.image_dim_ordering() == 'th':
input_shape = (1, img_h, img_w)
@@ -411,7 +411,7 @@ img_gen = TextImageGenerator(monogram_file=os.path.join(fdir, 'wordlist_mono_cle
minibatch_size=32,
img_w=img_w,
img_h=img_h,
downsample_width=img_w / (pool_size_1 * pool_size_2) - 2,
downsample_width=img_w // (pool_size_1 * pool_size_2) - 2,
val_split=words_per_epoch - val_words)
act = 'relu'
@@ -423,7 +423,7 @@ inner = Convolution2D(conv_num_filters, filter_size, filter_size, border_mode='s
activation=act, name='conv2')(inner)
inner = MaxPooling2D(pool_size=(pool_size_2, pool_size_2), name='max2')(inner)
conv_to_rnn_dims = ((img_h / (pool_size_1 * pool_size_2)) * conv_num_filters, img_w / (pool_size_1 * pool_size_2))
conv_to_rnn_dims = ((img_h // (pool_size_1 * pool_size_2)) * conv_num_filters, img_w // (pool_size_1 * pool_size_2))
inner = Reshape(target_shape=conv_to_rnn_dims, name='reshape')(inner)
inner = Permute(dims=(2, 1), name='permute')(inner)
+3 -7
Ver Arquivo
@@ -12,9 +12,9 @@ np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import Convolution1D, MaxPooling1D
from keras.layers import Convolution1D, GlobalMaxPooling1D
from keras.datasets import imdb
from keras import backend as K
@@ -58,11 +58,7 @@ model.add(Convolution1D(nb_filter=nb_filter,
activation='relu',
subsample_length=1))
# we use max pooling:
model.add(MaxPooling1D(pool_length=model.output_shape[1]))
# We flatten the output of the conv layer,
# so that we can add a vanilla dense layer:
model.add(Flatten())
model.add(GlobalMaxPooling1D())
# We add a vanilla hidden layer:
model.add(Dense(hidden_dims))
+1 -1
Ver Arquivo
@@ -11,7 +11,7 @@ from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import LSTM, GRU, SimpleRNN
from keras.layers import LSTM
from keras.layers import Convolution1D, MaxPooling1D
from keras.datasets import imdb
+6 -9
Ver Arquivo
@@ -6,8 +6,8 @@ Bags of Tricks for Efficient Text Classification
https://arxiv.org/abs/1607.01759
Results on IMDB datasets with uni and bi-gram embeddings:
Uni-gram: 0.8813 test accuracy after 5 epochs. 15s/epoch on i7 cpu.
Bi-gram : 0.9056 test accuracy after 5 epochs. 5s/epoch on GTX 1080 gpu.
Uni-gram: 0.8813 test accuracy after 5 epochs. 8s/epoch on i7 cpu.
Bi-gram : 0.9056 test accuracy after 5 epochs. 2s/epoch on GTX 980M gpu.
'''
from __future__ import print_function
@@ -16,9 +16,9 @@ np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Flatten
from keras.layers import Dense
from keras.layers import Embedding
from keras.layers import AveragePooling1D
from keras.layers import GlobalAveragePooling1D
from keras.datasets import imdb
@@ -119,12 +119,9 @@ model.add(Embedding(max_features,
embedding_dims,
input_length=maxlen))
# we add a AveragePooling1D, which will average the embeddings
# we add a GlobalAveragePooling1D, which will average the embeddings
# of all words in the document
model.add(AveragePooling1D(pool_length=model.output_shape[1]))
# We flatten the output of the AveragePooling1D layer
model.add(Flatten())
model.add(GlobalAveragePooling1D())
# We project onto a single unit output layer, and squash it with a sigmoid:
model.add(Dense(1, activation='sigmoid'))
+3 -1
Ver Arquivo
@@ -108,10 +108,12 @@ def deprocess_image(x):
x = x.transpose((1, 2, 0))
else:
x = x.reshape((img_nrows, img_ncols, 3))
x = x[:, :, ::-1]
# Remove zero-center by mean pixel
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
# 'BGR'->'RGB'
x = x[:, :, ::-1]
x = np.clip(x, 0, 255).astype('uint8')
return x
+3 -1
Ver Arquivo
@@ -91,10 +91,12 @@ def deprocess_image(x):
x = x.transpose((1, 2, 0))
else:
x = x.reshape((img_nrows, img_ncols, 3))
x = x[:, :, ::-1]
# Remove zero-center by mean pixel
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
# 'BGR'->'RGB'
x = x[:, :, ::-1]
x = np.clip(x, 0, 255).astype('uint8')
return x
+3 -1
Ver Arquivo
@@ -16,6 +16,7 @@ original_dim = 784
latent_dim = 2
intermediate_dim = 256
nb_epoch = 50
epsilon_std = 0.01
x = Input(batch_shape=(batch_size, original_dim))
h = Dense(intermediate_dim, activation='relu')(x)
@@ -25,7 +26,8 @@ z_log_var = Dense(latent_dim)(h)
def sampling(args):
z_mean, z_log_var = args
epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.)
epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.,
std=epsilon_std)
return z_mean + K.exp(z_log_var / 2) * epsilon
# note that "output_shape" isn't necessary with the TensorFlow backend
+82 -35
Ver Arquivo
@@ -1,4 +1,5 @@
'''This script demonstrates how to build a variational autoencoder with Keras and deconvolution layers.
'''This script demonstrates how to build a variational autoencoder
with Keras and deconvolution layers.
Reference: "Auto-Encoding Variational Bayes" https://arxiv.org/abs/1312.6114
'''
@@ -6,7 +7,7 @@ import numpy as np
import matplotlib.pyplot as plt
from keras.layers import Input, Dense, Lambda, Flatten, Reshape
from keras.layers import Convolution2D, Deconvolution2D, MaxPooling2D
from keras.layers import Convolution2D, Deconvolution2D
from keras.models import Model
from keras import backend as K
from keras import objectives
@@ -15,25 +16,36 @@ from keras.datasets import mnist
# input image dimensions
img_rows, img_cols, img_chns = 28, 28, 1
# number of convolutional filters to use
nb_filters = 32
nb_filters = 64
# convolution kernel size
nb_conv = 3
batch_size = 16
original_dim = (img_chns, img_rows, img_cols)
batch_size = 100
if K.image_dim_ordering() == 'th':
original_img_size = (img_chns, img_rows, img_cols)
else:
original_img_size = (img_rows, img_cols, img_chns)
latent_dim = 2
intermediate_dim = 128
epsilon_std = 0.01
nb_epoch = 5
x = Input(batch_shape=(batch_size,) + original_img_size)
conv_1 = Convolution2D(img_chns, 2, 2, border_mode='same', activation='relu')(x)
conv_2 = Convolution2D(nb_filters, 2, 2,
border_mode='same', activation='relu',
subsample=(2, 2))(conv_1)
conv_3 = Convolution2D(nb_filters, nb_conv, nb_conv,
border_mode='same', activation='relu',
subsample=(1, 1))(conv_2)
conv_4 = Convolution2D(nb_filters, nb_conv, nb_conv,
border_mode='same', activation='relu',
subsample=(1, 1))(conv_3)
flat = Flatten()(conv_4)
hidden = Dense(intermediate_dim, activation='relu')(flat)
x = Input(batch_shape=(batch_size,) + original_dim)
c = Convolution2D(nb_filters, nb_conv, nb_conv, border_mode='same', activation='relu')(x)
f = Flatten()(c)
h = Dense(intermediate_dim, activation='relu')(f)
z_mean = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)
z_mean = Dense(latent_dim)(hidden)
z_log_var = Dense(latent_dim)(hidden)
def sampling(args):
@@ -47,36 +59,68 @@ def sampling(args):
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_var])
# we instantiate these layers separately so as to reuse them later
decoder_h = Dense(intermediate_dim, activation='relu')
decoder_f = Dense(nb_filters*img_rows*img_cols, activation='relu')
decoder_c = Reshape((nb_filters, img_rows, img_cols))
decoder_mean = Deconvolution2D(img_chns, nb_conv, nb_conv,
(batch_size, img_chns, img_rows, img_cols),
border_mode='same')
decoder_hid = Dense(intermediate_dim, activation='relu')
decoder_upsample = Dense(nb_filters * 14 * 14, activation='relu')
h_decoded = decoder_h(z)
f_decoded = decoder_f(h_decoded)
c_decoded = decoder_c(f_decoded)
x_decoded_mean = decoder_mean(c_decoded)
if K.image_dim_ordering() == 'th':
output_shape = (batch_size, nb_filters, 14, 14)
else:
output_shape = (batch_size, 14, 14, nb_filters)
decoder_reshape = Reshape(output_shape[1:])
decoder_deconv_1 = Deconvolution2D(nb_filters, nb_conv, nb_conv,
output_shape,
border_mode='same',
subsample=(1, 1),
activation='relu')
decoder_deconv_2 = Deconvolution2D(nb_filters, nb_conv, nb_conv,
output_shape,
border_mode='same',
subsample=(1, 1),
activation='relu')
if K.image_dim_ordering() == 'th':
output_shape = (batch_size, nb_filters, 29, 29)
else:
output_shape = (batch_size, 29, 29, nb_filters)
decoder_deconv_3_upsamp = Deconvolution2D(nb_filters, 2, 2,
output_shape,
border_mode='valid',
subsample=(2, 2),
activation='relu')
decoder_mean_squash = Convolution2D(img_chns, 2, 2,
border_mode='valid',
activation='sigmoid')
hid_decoded = decoder_hid(z)
up_decoded = decoder_upsample(hid_decoded)
reshape_decoded = decoder_reshape(up_decoded)
deconv_1_decoded = decoder_deconv_1(reshape_decoded)
deconv_2_decoded = decoder_deconv_2(deconv_1_decoded)
x_decoded_relu = decoder_deconv_3_upsamp(deconv_2_decoded)
x_decoded_mean_squash = decoder_mean_squash(x_decoded_relu)
def vae_loss(x, x_decoded_mean):
# NOTE: binary_crossentropy expects a batch_size by dim for x and x_decoded_mean, so we MUST flatten these!
# NOTE: binary_crossentropy expects a batch_size by dim
# for x and x_decoded_mean, so we MUST flatten these!
x = K.flatten(x)
x_decoded_mean = K.flatten(x_decoded_mean)
xent_loss = objectives.binary_crossentropy(x, x_decoded_mean)
xent_loss = img_rows * img_cols * objectives.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.mean(1 + z_log_var - K.square(z_mean) - K.exp(z_log_var), axis=-1)
return xent_loss + kl_loss
vae = Model(x, x_decoded_mean)
vae = Model(x, x_decoded_mean_squash)
vae.compile(optimizer='rmsprop', loss=vae_loss)
vae.summary()
# train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()
(x_train, _), (x_test, y_test) = mnist.load_data()
x_train = x_train.astype('float32')[:, None, :, :] / 255.
x_test = x_test.astype('float32')[:, None, :, :] / 255.
x_train = x_train.astype('float32') / 255.
x_train = x_train.reshape((x_train.shape[0],) + original_img_size)
x_test = x_test.astype('float32') / 255.
x_test = x_test.reshape((x_test.shape[0],) + original_img_size)
print('x_train.shape:', x_train.shape)
vae.fit(x_train, x_train,
shuffle=True,
@@ -84,7 +128,6 @@ vae.fit(x_train, x_train,
batch_size=batch_size,
validation_data=(x_test, x_test))
# build a model to project inputs on the latent space
encoder = Model(x, z_mean)
@@ -97,11 +140,14 @@ plt.show()
# build a digit generator that can sample from the learned distribution
decoder_input = Input(shape=(latent_dim,))
_h_decoded = decoder_h(decoder_input)
_f_decoded = decoder_f(_h_decoded)
_c_decoded = decoder_c(_f_decoded)
_x_decoded_mean = decoder_mean(_c_decoded)
generator = Model(decoder_input, _x_decoded_mean)
_hid_decoded = decoder_hid(decoder_input)
_up_decoded = decoder_upsample(_hid_decoded)
_reshape_decoded = decoder_reshape(_up_decoded)
_deconv_1_decoded = decoder_deconv_1(_reshape_decoded)
_deconv_2_decoded = decoder_deconv_2(_deconv_1_decoded)
_x_decoded_relu = decoder_deconv_3_upsamp(_deconv_2_decoded)
_x_decoded_mean_squash = decoder_mean_squash(_x_decoded_relu)
generator = Model(decoder_input, _x_decoded_mean_squash)
# display a 2D manifold of the digits
n = 15 # figure with 15x15 digits
@@ -114,7 +160,8 @@ grid_y = np.linspace(-15, 15, n)
for i, yi in enumerate(grid_x):
for j, xi in enumerate(grid_y):
z_sample = np.array([[xi, yi]])
x_decoded = generator.predict(z_sample)
z_sample = np.tile(z_sample, batch_size).reshape(batch_size, 2)
x_decoded = generator.predict(z_sample, batch_size=batch_size)
digit = x_decoded[0].reshape(digit_size, digit_size)
figure[i * digit_size: (i + 1) * digit_size,
j * digit_size: (j + 1) * digit_size] = digit
+1 -1
Ver Arquivo
@@ -15,4 +15,4 @@ from . import objectives
from . import optimizers
from . import regularizers
__version__ = '1.1.0'
__version__ = '1.1.1'
+3
Ver Arquivo
@@ -15,6 +15,9 @@ def softmax(x):
'Here, ndim=' + str(ndim))
def elu(x, alpha=1.0):
return K.elu(x, alpha)
def softplus(x):
return K.softplus(x)
+1
Ver Arquivo
@@ -2,3 +2,4 @@ from .vgg16 import VGG16
from .vgg19 import VGG19
from .resnet50 import ResNet50
from .inception_v3 import InceptionV3
from .xception import Xception
+86
Ver Arquivo
@@ -0,0 +1,86 @@
import numpy as np
from .. import backend as K
TAGS = ['rock', 'pop', 'alternative', 'indie', 'electronic',
'female vocalists', 'dance', '00s', 'alternative rock', 'jazz',
'beautiful', 'metal', 'chillout', 'male vocalists',
'classic rock', 'soul', 'indie rock', 'Mellow', 'electronica',
'80s', 'folk', '90s', 'chill', 'instrumental', 'punk',
'oldies', 'blues', 'hard rock', 'ambient', 'acoustic',
'experimental', 'female vocalist', 'guitar', 'Hip-Hop',
'70s', 'party', 'country', 'easy listening',
'sexy', 'catchy', 'funk', 'electro', 'heavy metal',
'Progressive rock', '60s', 'rnb', 'indie pop',
'sad', 'House', 'happy']
def librosa_exists():
try:
__import__('librosa')
except ImportError:
return False
else:
return True
def preprocess_input(audio_path, dim_ordering='default'):
'''Reads an audio file and outputs a Mel-spectrogram.
'''
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
assert dim_ordering in {'tf', 'th'}
if librosa_exists():
import librosa
else:
raise RuntimeError('Librosa is required to process audio files.\n' +
'Install it via `pip install librosa` \nor visit ' +
'http://librosa.github.io/librosa/ for details.')
# mel-spectrogram parameters
SR = 12000
N_FFT = 512
N_MELS = 96
HOP_LEN = 256
DURA = 29.12
src, sr = librosa.load(audio_path, sr=SR)
n_sample = src.shape[0]
n_sample_wanted = int(DURA * SR)
# trim the signal at the center
if n_sample < n_sample_wanted: # if too short
src = np.hstack((src, np.zeros((int(DURA * SR) - n_sample,))))
elif n_sample > n_sample_wanted: # if too long
src = src[(n_sample - n_sample_wanted) / 2:
(n_sample + n_sample_wanted) / 2]
logam = librosa.logamplitude
melgram = librosa.feature.melspectrogram
x = logam(melgram(y=src, sr=SR, hop_length=HOP_LEN,
n_fft=N_FFT, n_mels=N_MELS) ** 2,
ref_power=1.0)
if dim_ordering == 'th':
x = np.expand_dims(x, axis=0)
elif dim_ordering == 'tf':
x = np.expand_dims(x, axis=3)
return x
def decode_predictions(preds, top_n=5):
'''Decode the output of a music tagger model.
# Arguments
preds: 2-dimensional numpy array
top_n: integer in [0, 50], number of items to show
'''
assert len(preds.shape) == 2 and preds.shape[1] == 50
results = []
for pred in preds:
result = zip(TAGS, pred)
result = sorted(result, key=lambda x: x[1], reverse=True)
results.append(result[:top_n])
return results
+16 -9
Ver Arquivo
@@ -14,30 +14,37 @@ def preprocess_input(x, dim_ordering='default'):
assert dim_ordering in {'tf', 'th'}
if dim_ordering == 'th':
# 'RGB'->'BGR'
x = x[:, ::-1, :, :]
# Zero-center by mean pixel
x[:, 0, :, :] -= 103.939
x[:, 1, :, :] -= 116.779
x[:, 2, :, :] -= 123.68
# 'RGB'->'BGR'
x = x[:, ::-1, :, :]
else:
# 'RGB'->'BGR'
x = x[:, :, :, ::-1]
# Zero-center by mean pixel
x[:, :, :, 0] -= 103.939
x[:, :, :, 1] -= 116.779
x[:, :, :, 2] -= 123.68
# 'RGB'->'BGR'
x = x[:, :, :, ::-1]
return x
def decode_predictions(preds):
def decode_predictions(preds, top=5):
global CLASS_INDEX
assert len(preds.shape) == 2 and preds.shape[1] == 1000
if len(preds.shape) != 2 or preds.shape[1] != 1000:
raise ValueError('`decode_predictions` expects '
'a batch of predictions '
'(i.e. a 2D array of shape (samples, 1000)). '
'Found array with shape: ' + str(preds.shape))
if CLASS_INDEX is None:
fpath = get_file('imagenet_class_index.json',
CLASS_INDEX_PATH,
cache_subdir='models')
CLASS_INDEX = json.load(open(fpath))
indices = np.argmax(preds, axis=-1)
results = []
for i in indices:
results.append(CLASS_INDEX[str(i)])
for pred in preds:
top_indices = np.argpartition(pred, -top)[-top:][::-1]
result = [tuple(CLASS_INDEX[str(i)]) + (pred[i],) for i in top_indices]
results.append(result)
return results
+4 -4
Ver Arquivo
@@ -7,8 +7,8 @@ only gets to 7.8% (same as a fully-converged ResNet 50).
For comparison, VGG16 only gets to 9.9%, quite a bit worse.
Also, do note that the input image format for this model is different than for
other models (299x299 instead of 224x224), and that the input preprocessing function
is also different.
the VGG16 and ResNet models (299x299 instead of 224x224), and that the input preprocessing function
is also different (same as Xception).
# Reference:
@@ -76,8 +76,8 @@ def InceptionV3(include_top=True, weights='imagenet',
Note that the default input image size for this model is 299x299.
# Arguments
include_top: whether to include the 3 fully-connected
layers at the top of the network.
include_top: whether to include the fully-connected
layer at the top of the network.
weights: one of `None` (random initialization)
or "imagenet" (pre-training on ImageNet).
input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)
+147
Ver Arquivo
@@ -0,0 +1,147 @@
# -*- coding: utf-8 -*-
'''MusicTaggerCRNN model for Keras.
# Reference:
- [Music-auto_tagging-keras](https://github.com/keunwoochoi/music-auto_tagging-keras)
'''
from __future__ import print_function
from __future__ import absolute_import
from .. import backend as K
from ..layers import Input, Dense
from ..models import Model
from ..layers import Dense, Dropout, Reshape, Permute
from ..layers.convolutional import Convolution2D
from ..layers.convolutional import MaxPooling2D, ZeroPadding2D
from ..layers.normalization import BatchNormalization
from ..layers.advanced_activations import ELU
from ..layers.recurrent import GRU
from ..utils.data_utils import get_file
from ..utils.layer_utils import convert_all_kernels_in_model
from .audio_conv_utils import decode_predictions, preprocess_input
TH_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.3/music_tagger_crnn_weights_tf_kernels_th_dim_ordering.h5'
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.3/music_tagger_crnn_weights_tf_kernels_tf_dim_ordering.h5'
def MusicTaggerCRNN(weights='msd', input_tensor=None,
include_top=True):
'''Instantiate the MusicTaggerCRNN architecture,
optionally loading weights pre-trained
on Million Song Dataset. Note that when using TensorFlow,
for best performance you should set
`image_dim_ordering="tf"` in your Keras config
at ~/.keras/keras.json.
The model and the weights are compatible with both
TensorFlow and Theano. The dimension ordering
convention used by the model is the one
specified in your Keras config file.
For preparing mel-spectrogram input, see
`audio_conv_utils.py` in [applications](https://github.com/fchollet/keras/tree/master/keras/applications).
You will need to install [Librosa](http://librosa.github.io/librosa/)
to use it.
# Arguments
weights: one of `None` (random initialization)
or "msd" (pre-training on ImageNet).
input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)
to use as image input for the model.
include_top: whether to include the 1 fully-connected
layer (output layer) at the top of the network.
If False, the network outputs 32-dim features.
# Returns
A Keras model instance.
'''
if weights not in {'msd', None}:
raise ValueError('The `weights` argument should be either '
'`None` (random initialization) or `msd` '
'(pre-training on Million Song Dataset).')
# Determine proper input shape
if K.image_dim_ordering() == 'th':
input_shape = (1, 96, 1366)
else:
input_shape = (96, 1366, 1)
if input_tensor is None:
melgram_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
melgram_input = Input(tensor=input_tensor, shape=input_shape)
else:
melgram_input = input_tensor
# Determine input axis
if K.image_dim_ordering() == 'th':
channel_axis = 1
freq_axis = 2
time_axis = 3
else:
channel_axis = 3
freq_axis = 1
time_axis = 2
# Input block
x = ZeroPadding2D(padding=(0, 37))(melgram_input)
x = BatchNormalization(axis=time_axis, name='bn_0_freq')(x)
# Conv block 1
x = Convolution2D(64, 3, 3, border_mode='same', name='conv1')(x)
x = BatchNormalization(axis=channel_axis, mode=0, name='bn1')(x)
x = ELU()(x)
x = MaxPooling2D(pool_size=(2, 2), strides=(2, 2), name='pool1')(x)
# Conv block 2
x = Convolution2D(128, 3, 3, border_mode='same', name='conv2')(x)
x = BatchNormalization(axis=channel_axis, mode=0, name='bn2')(x)
x = ELU()(x)
x = MaxPooling2D(pool_size=(3, 3), strides=(3, 3), name='pool2')(x)
# Conv block 3
x = Convolution2D(128, 3, 3, border_mode='same', name='conv3')(x)
x = BatchNormalization(axis=channel_axis, mode=0, name='bn3')(x)
x = ELU()(x)
x = MaxPooling2D(pool_size=(4, 4), strides=(4, 4), name='pool3')(x)
# Conv block 4
x = Convolution2D(128, 3, 3, border_mode='same', name='conv4')(x)
x = BatchNormalization(axis=channel_axis, mode=0, name='bn4')(x)
x = ELU()(x)
x = MaxPooling2D(pool_size=(4, 4), strides=(4, 4), name='pool4')(x)
# reshaping
if K.image_dim_ordering() == 'th':
x = Permute((3, 1, 2))(x)
x = Reshape((15, 128))(x)
# GRU block 1, 2, output
x = GRU(32, return_sequences=True, name='gru1')(x)
x = GRU(32, return_sequences=False, name='gru2')(x)
if include_top:
x = Dense(50, activation='sigmoid', name='output')(x)
# Create model
model = Model(melgram_input, x)
if weights is None:
return model
else:
# Load weights
if K.image_dim_ordering() == 'tf':
weights_path = get_file('music_tagger_crnn_weights_tf_kernels_tf_dim_ordering.h5',
TF_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('music_tagger_crnn_weights_tf_kernels_th_dim_ordering.h5',
TH_WEIGHTS_PATH,
cache_subdir='models')
model.load_weights(weights_path, by_name=True)
if K.backend() == 'theano':
convert_all_kernels_in_model(model)
return model
+210
Ver Arquivo
@@ -0,0 +1,210 @@
# -*- coding: utf-8 -*-
'''Xception V1 model for Keras.
On ImageNet, this model gets to a top-1 validation accuracy of 0.790
and a top-5 validation accuracy of 0.945.
Do note that the input image format for this model is different than for
the VGG16 and ResNet models (299x299 instead of 224x224),
and that the input preprocessing function
is also different (same as Inception V3).
Also do note that this model is only available for the TensorFlow backend,
due to its reliance on `SeparableConvolution` layers.
# Reference:
- [Xception: Deep Learning with Depthwise Separable Convolutions](https://arxiv.org/abs/1610.02357)
'''
from __future__ import print_function
from __future__ import absolute_import
import warnings
from ..models import Model
from ..layers import Dense, Input, BatchNormalization, Activation, merge
from ..layers import Conv2D, SeparableConv2D, MaxPooling2D, GlobalAveragePooling2D
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.4/xception_weights_tf_dim_ordering_tf_kernels.h5'
TF_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.4/xception_weights_tf_dim_ordering_tf_kernels_notop.h5'
def Xception(include_top=True, weights='imagenet',
input_tensor=None):
'''Instantiate the Xception architecture,
optionally loading weights pre-trained
on ImageNet. This model is available for TensorFlow only,
and can only be used with inputs following the TensorFlow
dimension ordering `(width, height, channels)`.
You should set `image_dim_ordering="tf"` in your Keras config
located at ~/.keras/keras.json.
Note that the default input image size for this model is 299x299.
# Arguments
include_top: whether to include the fully-connected
layer at the top of the network.
weights: one of `None` (random initialization)
or "imagenet" (pre-training on ImageNet).
input_tensor: optional Keras tensor (i.e. output of `layers.Input()`)
to use as image input for the model.
# Returns
A Keras model instance.
'''
if weights not in {'imagenet', None}:
raise ValueError('The `weights` argument should be either '
'`None` (random initialization) or `imagenet` '
'(pre-training on ImageNet).')
if K.backend() != 'tensorflow':
raise Exception('The Xception model is only available with '
'the TensorFlow backend.')
if K.image_dim_ordering() != 'tf':
warnings.warn('The Xception model is only available for the '
'input dimension ordering "tf" '
'(width, height, channels). '
'However your settings specify the default '
'dimension ordering "th" (channels, width, height). '
'You should set `image_dim_ordering="tf"` in your Keras '
'config located at ~/.keras/keras.json. '
'The model being returned right now will expect inputs '
'to follow the "tf" dimension ordering.')
K.set_image_dim_ordering('tf')
old_dim_ordering = 'th'
else:
old_dim_ordering = None
# Determine proper input shape
if include_top:
input_shape = (299, 299, 3)
else:
input_shape = (None, None, 3)
if input_tensor is None:
img_input = Input(shape=input_shape)
else:
if not K.is_keras_tensor(input_tensor):
img_input = Input(tensor=input_tensor, shape=input_shape)
else:
img_input = input_tensor
x = Conv2D(32, 3, 3, subsample=(2, 2), bias=False, name='block1_conv1')(img_input)
x = BatchNormalization(name='block1_conv1_bn')(x)
x = Activation('relu', name='block1_conv1_act')(x)
x = Conv2D(64, 3, 3, bias=False, name='block1_conv2')(x)
x = BatchNormalization(name='block1_conv2_bn')(x)
x = Activation('relu', name='block1_conv2_act')(x)
residual = Conv2D(128, 1, 1, subsample=(2, 2),
border_mode='same', bias=False)(x)
residual = BatchNormalization()(residual)
x = SeparableConv2D(128, 3, 3, border_mode='same', bias=False, name='block2_sepconv1')(x)
x = BatchNormalization(name='block2_sepconv1_bn')(x)
x = Activation('relu', name='block2_sepconv2_act')(x)
x = SeparableConv2D(128, 3, 3, border_mode='same', bias=False, name='block2_sepconv2')(x)
x = BatchNormalization(name='block2_sepconv2_bn')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), border_mode='same', name='block2_pool')(x)
x = merge([x, residual], mode='sum')
residual = Conv2D(256, 1, 1, subsample=(2, 2),
border_mode='same', bias=False)(x)
residual = BatchNormalization()(residual)
x = Activation('relu', name='block3_sepconv1_act')(x)
x = SeparableConv2D(256, 3, 3, border_mode='same', bias=False, name='block3_sepconv1')(x)
x = BatchNormalization(name='block3_sepconv1_bn')(x)
x = Activation('relu', name='block3_sepconv2_act')(x)
x = SeparableConv2D(256, 3, 3, border_mode='same', bias=False, name='block3_sepconv2')(x)
x = BatchNormalization(name='block3_sepconv2_bn')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), border_mode='same', name='block3_pool')(x)
x = merge([x, residual], mode='sum')
residual = Conv2D(728, 1, 1, subsample=(2, 2),
border_mode='same', bias=False)(x)
residual = BatchNormalization()(residual)
x = Activation('relu', name='block4_sepconv1_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name='block4_sepconv1')(x)
x = BatchNormalization(name='block4_sepconv1_bn')(x)
x = Activation('relu', name='block4_sepconv2_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name='block4_sepconv2')(x)
x = BatchNormalization(name='block4_sepconv2_bn')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), border_mode='same', name='block4_pool')(x)
x = merge([x, residual], mode='sum')
for i in range(8):
residual = x
prefix = 'block' + str(i + 5)
x = Activation('relu', name=prefix + '_sepconv1_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name=prefix + '_sepconv1')(x)
x = BatchNormalization(name=prefix + '_sepconv1_bn')(x)
x = Activation('relu', name=prefix + '_sepconv2_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name=prefix + '_sepconv2')(x)
x = BatchNormalization(name=prefix + '_sepconv2_bn')(x)
x = Activation('relu', name=prefix + '_sepconv3_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name=prefix + '_sepconv3')(x)
x = BatchNormalization(name=prefix + '_sepconv3_bn')(x)
x = merge([x, residual], mode='sum')
residual = Conv2D(1024, 1, 1, subsample=(2, 2),
border_mode='same', bias=False)(x)
residual = BatchNormalization()(residual)
x = Activation('relu', name='block13_sepconv1_act')(x)
x = SeparableConv2D(728, 3, 3, border_mode='same', bias=False, name='block13_sepconv1')(x)
x = BatchNormalization(name='block13_sepconv1_bn')(x)
x = Activation('relu', name='block13_sepconv2_act')(x)
x = SeparableConv2D(1024, 3, 3, border_mode='same', bias=False, name='block13_sepconv2')(x)
x = BatchNormalization(name='block13_sepconv2_bn')(x)
x = MaxPooling2D((3, 3), strides=(2, 2), border_mode='same', name='block13_pool')(x)
x = merge([x, residual], mode='sum')
x = SeparableConv2D(1536, 3, 3, border_mode='same', bias=False, name='block14_sepconv1')(x)
x = BatchNormalization(name='block14_sepconv1_bn')(x)
x = Activation('relu', name='block14_sepconv1_act')(x)
x = SeparableConv2D(2048, 3, 3, border_mode='same', bias=False, name='block14_sepconv2')(x)
x = BatchNormalization(name='block14_sepconv2_bn')(x)
x = Activation('relu', name='block14_sepconv2_act')(x)
if include_top:
x = GlobalAveragePooling2D(name='avg_pool')(x)
x = Dense(1000, activation='softmax', name='predictions')(x)
# Create model
model = Model(img_input, x)
# load weights
if weights == 'imagenet':
if include_top:
weights_path = get_file('xception_weights_tf_dim_ordering_tf_kernels.h5',
TF_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('xception_weights_tf_dim_ordering_tf_kernels_notop.h5',
TF_WEIGHTS_PATH_NO_TOP,
cache_subdir='models')
model.load_weights(weights_path)
if old_dim_ordering:
K.set_image_dim_ordering(old_dim_ordering)
return model
def preprocess_input(x):
x /= 255.
x -= 0.5
x *= 2.
return x
+6 -1
Ver Arquivo
@@ -23,7 +23,12 @@ _keras_dir = os.path.join(_keras_base_dir, '.keras')
if not os.path.exists(_keras_dir):
os.makedirs(_keras_dir)
_BACKEND = 'tensorflow'
# Set theano as default backend for Windows users since tensorflow is not available for Windows yet.
if os.name == 'nt':
_BACKEND = 'theano'
else:
_BACKEND = 'tensorflow'
_config_path = os.path.expanduser(os.path.join(_keras_dir, 'keras.json'))
if os.path.exists(_config_path):
_config = json.load(open(_config_path))
+76 -16
Ver Arquivo
@@ -1,9 +1,11 @@
import tensorflow as tf
from tensorflow.python.training import moving_averages
try:
import tensorflow.contrib.ctc as ctc
except ImportError:
from tensorflow.python.ops import ctc_ops as ctc
except ImportError:
import tensorflow.contrib.ctc as ctc
import numpy as np
import os
import copy
@@ -144,7 +146,7 @@ def variable(value, dtype=_FLOATX, name=None):
sparse_coo = value.tocoo()
indices = np.concatenate((np.expand_dims(sparse_coo.row, 1), np.expand_dims(sparse_coo.col, 1)), 1)
# SparseTensor doesn't need initialization
return tf.SparseTensor(indices=indices, values=value.data, shape=value.shape)
return tf.SparseTensor(indices=indices, values=sparse_coo.data, shape=sparse_coo.shape)
v = tf.Variable(value, dtype=_convert_string_dtype(dtype), name=name)
if _MANUAL_VAR_INIT:
@@ -844,6 +846,14 @@ def temporal_padding(x, padding=1):
return tf.pad(x, pattern)
def asymmetric_temporal_padding(x, left_pad=1, right_pad=1):
'''Pad the middle dimension of a 3D tensor
with "left_pad" zeros left and "right_pad" right.
'''
pattern = [[0, 0], [left_pad, right_pad], [0, 0]]
return tf.pad(x, pattern)
def spatial_2d_padding(x, padding=(1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
'''Pads the 2nd and 3rd dimensions of a 4D tensor
with "padding[0]" and "padding[1]" (resp.) zeros left and right.
@@ -858,6 +868,23 @@ def spatial_2d_padding(x, padding=(1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
return tf.pad(x, pattern)
def asymmetric_spatial_2d_padding(x, top_pad=1, bottom_pad=1, left_pad=1, right_pad=1, dim_ordering=_IMAGE_DIM_ORDERING):
'''Pad the rows and columns of a 4D tensor
with "top_pad", "bottom_pad", "left_pad", "right_pad" (resp.) zeros rows on top, bottom; cols on left, right.
'''
if dim_ordering == 'th':
pattern = [[0, 0],
[0, 0],
[top_pad, bottom_pad],
[left_pad, right_pad]]
else:
pattern = [[0, 0],
[top_pad, bottom_pad],
[left_pad, right_pad],
[0, 0]]
return tf.pad(x, pattern)
def spatial_3d_padding(x, padding=(1, 1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
'''Pads 5D tensor with zeros for the depth, height, width dimension with
"padding[0]", "padding[1]" and "padding[2]" (resp.) zeros left and right
@@ -1007,7 +1034,7 @@ class Function(object):
if is_sparse(tensor):
sparse_coo = value.tocoo()
indices = np.concatenate((np.expand_dims(sparse_coo.row, 1), np.expand_dims(sparse_coo.col, 1)), 1)
value = (indices, value.data, value.shape)
value = (indices, sparse_coo.data, sparse_coo.shape)
feed_dict[tensor] = value
session = get_session()
updated = session.run(self.outputs + [self.updates_op], feed_dict=feed_dict)
@@ -1234,7 +1261,7 @@ def rnn(step_function, inputs, initial_states,
new_state = new_states[0]
else:
# return dummy state, otherwise _dynamic_rnn_loop breaks
new_state = output
new_state = state
return output, new_state
_step.state_size = state_size * nb_states
@@ -1273,6 +1300,16 @@ def rnn(step_function, inputs, initial_states,
return last_output, outputs, new_states
def _cond(condition, then_lambda, else_lambda):
'''Backwards compatible interface to tf.cond prior to public introduction.'''
try:
cond_fn = tf.cond
except AttributeError:
from tensorflow.python.ops import control_flow_ops
cond_fn = control_flow_ops.cond
return cond_fn(condition, then_lambda, else_lambda)
def switch(condition, then_expression, else_expression):
'''Switches between two operations depending on a scalar value (int or bool).
Note that both `then_expression` and `else_expression`
@@ -1284,9 +1321,8 @@ def switch(condition, then_expression, else_expression):
else_expression: TensorFlow operation.
'''
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 = _cond(tf.cast(condition, 'bool'),
lambda: then_expression, lambda: else_expression)
x.set_shape(x_shape)
return x
@@ -1301,9 +1337,7 @@ def in_train_phase(x, alt):
return alt
# else: assume learning phase is a placeholder.
x_shape = copy.copy(x.get_shape())
x = tf.python.control_flow_ops.cond(tf.cast(_LEARNING_PHASE, 'bool'),
lambda: x,
lambda: alt)
x = _cond(tf.cast(_LEARNING_PHASE, 'bool'), lambda: x, lambda: alt)
x._uses_learning_phase = True
x.set_shape(x_shape)
return x
@@ -1318,9 +1352,7 @@ def in_test_phase(x, alt):
elif _LEARNING_PHASE is 0:
return 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 = _cond(tf.cast(_LEARNING_PHASE, 'bool'), lambda: alt, lambda: x)
x._uses_learning_phase = True
x.set_shape(x_shape)
return x
@@ -1348,6 +1380,20 @@ def relu(x, alpha=0., max_value=None):
return x
def elu(x, alpha=1.):
""" Exponential linear unit
# Arguments
x: Tensor to compute the activation function for.
alpha: scalar
"""
res = tf.nn.elu(x)
if alpha == 1:
return res
else:
return tf.select(x > 0, res, alpha*res)
def softmax(x):
'''Softmax of a tensor.
'''
@@ -1470,6 +1516,20 @@ def l2_normalize(x, axis):
axis = axis % len(x.get_shape())
return tf.nn.l2_normalize(x, dim=axis)
def in_top_k(predictions, targets, k):
'''Says whether the `targets` are in the top `k` `predictions`
# Arguments
predictions: A tensor of shape batch_size x classess and type float32.
targets: A tensor of shape batch_size and type int32 or int64.
k: An int, number of top elements to consider.
# Returns
A tensor of shape batch_size and type bool. output_i is True if
targets_i is within top-k values of predictions_i
'''
return tf.nn.in_top_k(predictions, targets, k)
# CONVOLUTIONS
@@ -1774,9 +1834,9 @@ def ctc_label_dense_to_sparse(labels, label_lengths):
max_num_labels_tns = tf.pack([label_shape[1]])
def range_less_than(previous_state, current_input):
return tf.expand_dims(tf.range(label_shape[1]), 0) < current_input
return tf.expand_dims(tf.range(label_shape[1]), 0) < tf.fill(max_num_labels_tns, current_input)
init = tf.cast(tf.fill(max_num_labels_tns, 0), tf.bool)
init = tf.cast(tf.fill([1, label_shape[1]], 0), tf.bool)
dense_mask = functional_ops.scan(range_less_than, label_lengths,
initializer=init, parallel_iterations=1)
dense_mask = dense_mask[:, 0, :]
+284 -12
Ver Arquivo
@@ -395,6 +395,19 @@ def normalize_batch_in_training(x, gamma, beta,
reduction_axes, epsilon=0.0001):
'''Compute mean and std for batch then apply batch_normalization on batch.
'''
dev = theano.config.device
use_cudnn = ndim(x) < 5 and reduction_axes == [0, 2, 3] and (dev.startswith('cuda') or dev.startswith('gpu'))
if use_cudnn:
broadcast_beta = beta.dimshuffle('x', 0, 'x', 'x')
broadcast_gamma = gamma.dimshuffle('x', 0, 'x', 'x')
try:
normed, mean, stdinv = theano.sandbox.cuda.dnn.dnn_batch_normalization_train(
x, broadcast_gamma, broadcast_beta, 'spatial', epsilon)
var = T.inv(stdinv ** 2)
return normed, T.flatten(mean), T.flatten(var)
except AttributeError:
pass
var = x.var(reduction_axes)
mean = x.mean(reduction_axes)
@@ -424,10 +437,25 @@ def batch_normalization(x, mean, var, beta, gamma, epsilon=0.0001):
use_cudnn = ndim < 5 and (dev.startswith('cuda') or dev.startswith('gpu'))
if use_cudnn:
try:
return theano.sandbox.cuda.dnn.dnn_batch_normalization_test(x, gamma, beta, mean, var,
'spatial', epsilon)
axis = mean.broadcastable.index(False)
if axis != 1:
shuffle_pattern = list(range(ndim))
shuffle_pattern[1] = shuffle_pattern[axis]
shuffle_pattern[axis] = 1
x = x.dimshuffle(shuffle_pattern)
mean = mean.dimshuffle(shuffle_pattern)
var = var.dimshuffle(shuffle_pattern)
beta = beta.dimshuffle(shuffle_pattern)
gamma = gamma.dimshuffle(shuffle_pattern)
normed = theano.sandbox.cuda.dnn.dnn_batch_normalization_test(x, gamma, beta, mean, var,
'spatial', epsilon)
if axis != 1:
normed = normed.dimshuffle(shuffle_pattern)
return normed
except AttributeError:
pass
except ValueError:
pass
return T.nnet.bn.batch_normalization(x, gamma, beta, mean, sqrt(var + epsilon),
mode='high_mem')
@@ -573,6 +601,21 @@ def temporal_padding(x, padding=1):
return T.set_subtensor(output[:, padding:x.shape[1] + padding, :], x)
def asymmetric_temporal_padding(x, left_pad=1, right_pad=1):
'''Pad the middle dimension of a 3D tensor
with "left_pad" zeros left and "right_pad" right.
Apologies for the inane API, but Theano makes this
really hard.
'''
input_shape = x.shape
output_shape = (input_shape[0],
input_shape[1] + left_pad + right_pad,
input_shape[2])
output = T.zeros(output_shape)
return T.set_subtensor(output[:, left_pad:x.shape[1] + left_pad, :], x)
def spatial_2d_padding(x, padding=(1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
'''Pad the 2nd and 3rd dimensions of a 4D tensor
with "padding[0]" and "padding[1]" (resp.) zeros left and right.
@@ -604,6 +647,38 @@ def spatial_2d_padding(x, padding=(1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
return T.set_subtensor(output[indices], x)
def asymmetric_spatial_2d_padding(x, top_pad=1, bottom_pad=1, left_pad=1, right_pad=1, dim_ordering=_IMAGE_DIM_ORDERING):
'''Pad the rows and columns of a 4D tensor
with "top_pad", "bottom_pad", "left_pad", "right_pad" (resp.) zeros rows on top, bottom; cols on left, right.
'''
input_shape = x.shape
if dim_ordering == 'th':
output_shape = (input_shape[0],
input_shape[1],
input_shape[2] + top_pad + bottom_pad,
input_shape[3] + left_pad + right_pad)
output = T.zeros(output_shape)
indices = (slice(None),
slice(None),
slice(top_pad, input_shape[2] + top_pad),
slice(left_pad, input_shape[3] + left_pad))
elif dim_ordering == 'tf':
output_shape = (input_shape[0],
input_shape[1] + top_pad + bottom_pad,
input_shape[2] + left_pad + right_pad,
input_shape[3])
print(output_shape)
output = T.zeros(output_shape)
indices = (slice(None),
slice(top_pad, input_shape[1] + top_pad),
slice(left_pad, input_shape[2] + left_pad),
slice(None))
else:
raise Exception('Invalid dim_ordering: ' + dim_ordering)
return T.set_subtensor(output[indices], x)
def spatial_3d_padding(x, padding=(1, 1, 1), dim_ordering=_IMAGE_DIM_ORDERING):
'''Pad the 2nd, 3rd and 4th dimensions of a 5D tensor
with "padding[0]", "padding[1]" and "padding[2]" (resp.) zeros left and right.
@@ -931,11 +1006,26 @@ def in_test_phase(x, alt):
# NN OPERATIONS
def _assert_has_capability(module, func):
assert hasattr(module, func), ('It looks like like your version of '
'Theano is out of date. '
'Install the latest version with:\n'
'pip install git+git://github.com/Theano/Theano.git --upgrade --no-deps')
def elu(x, alpha=1.0):
""" Exponential linear unit
# Arguments
x: Tensor to compute the activation function for.
alpha: scalar
"""
_assert_has_capability(T.nnet, 'elu')
return T.nnet.elu(x, alpha)
def relu(x, alpha=0., max_value=None):
assert hasattr(T.nnet, 'relu'), ('It looks like like your version of '
'Theano is out of date. '
'Install the latest version with:\n'
'pip install git+git://github.com/Theano/Theano.git --upgrade --no-deps')
_assert_has_capability(T.nnet, 'relu')
x = T.nnet.relu(x, alpha)
if max_value is not None:
x = T.minimum(x, max_value)
@@ -1028,6 +1118,23 @@ def l2_normalize(x, axis):
return x / norm
def in_top_k(predictions, targets, k):
'''Says whether the `targets` are in the top `k` `predictions`
# Arguments
predictions: A tensor of shape batch_size x classess and type float32.
targets: A tensor of shape batch_size and type int32 or int64.
k: An int, number of top elements to consider.
# Returns
A tensor of shape batch_size and type int. output_i is 1 if
targets_i is within top-k values of predictions_i
'''
predictions_top_k = T.argsort(predictions)[:, -k:]
result, _ = theano.map(lambda prediction, target: any(equal(prediction, target)), sequences=[predictions_top_k, targets])
return result
# CONVOLUTIONS
def _preprocess_conv2d_input(x, dim_ordering):
@@ -1040,6 +1147,16 @@ def _preprocess_conv2d_input(x, dim_ordering):
return x
def _preprocess_conv3d_input(x, dim_ordering):
if dim_ordering == 'tf':
# TF uses the last dimension as channel dimension,
# instead of the 2nd one.
# TH input shape: (samples, input_depth, rows, cols, slices)
# TF input shape: (samples, rows, cols, slices, input_depth)
x = x.dimshuffle((0, 4, 1, 2, 3))
return x
def _preprocess_conv2d_kernel(kernel, dim_ordering):
if dim_ordering == 'tf':
# TF uses the last dimension as channel dimension,
@@ -1050,6 +1167,16 @@ def _preprocess_conv2d_kernel(kernel, dim_ordering):
return kernel
def _preprocess_conv3d_kernel(kernel, dim_ordering):
if dim_ordering == 'tf':
# TF uses the last dimension as channel dimension,
# instead of the 2nd one.
# TH kernel shape: (depth, input_depth, rows, cols, slices)
# TF kernel shape: (rows, cols, slices, input_depth, depth)
kernel = kernel.dimshuffle((4, 3, 0, 1, 2))
return kernel
def _preprocess_border_mode(border_mode):
if border_mode == 'same':
th_border_mode = 'half'
@@ -1060,7 +1187,7 @@ def _preprocess_border_mode(border_mode):
return th_border_mode
def _preprocess_image_shape(dim_ordering, image_shape):
def _preprocess_conv2d_image_shape(dim_ordering, image_shape):
# Theano might not accept long type
def int_or_none(value):
try:
@@ -1076,7 +1203,23 @@ def _preprocess_image_shape(dim_ordering, image_shape):
return image_shape
def _preprocess_filter_shape(dim_ordering, filter_shape):
def _preprocess_conv3d_volume_shape(dim_ordering, volume_shape):
# Theano might not accept long type
def int_or_none(value):
try:
return int(value)
except TypeError:
return None
if dim_ordering == 'tf':
if volume_shape:
volume_shape = (volume_shape[0], volume_shape[4],
volume_shape[1], volume_shape[2], volume_shape[3])
if volume_shape is not None:
volume_shape = tuple(int_or_none(v) for v in volume_shape)
return volume_shape
def _preprocess_conv2d_filter_shape(dim_ordering, filter_shape):
# Theano might not accept long type
def int_or_none(value):
try:
@@ -1092,6 +1235,22 @@ def _preprocess_filter_shape(dim_ordering, filter_shape):
return filter_shape
def _preprocess_conv3d_filter_shape(dim_ordering, filter_shape):
# Theano might not accept long type
def int_or_none(value):
try:
return int(value)
except TypeError:
return None
if dim_ordering == 'tf':
if filter_shape:
filter_shape = (filter_shape[4], filter_shape[3],
filter_shape[0], filter_shape[1], filter_shape[2])
if filter_shape is not None:
filter_shape = tuple(int_or_none(v) for v in filter_shape)
return filter_shape
def _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel, strides, dim_ordering):
if border_mode == 'same':
if np_kernel.shape[2] % 2 == 0:
@@ -1103,6 +1262,19 @@ def _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel, strides, dim
return conv_out
def _postprocess_conv3d_output(conv_out, x, border_mode, np_kernel, strides, dim_ordering):
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], :]
if np_kernel.shape[4] % 2 == 0:
conv_out = conv_out[:, :, :, :, :(x.shape[4] + strides[2] - 1) // strides[2]]
if dim_ordering == 'tf':
conv_out = conv_out.dimshuffle((0, 2, 3, 4, 1))
return conv_out
def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING, image_shape=None,
filter_shape=None, filter_dilation=(1, 1)):
@@ -1123,8 +1295,8 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
kernel = _preprocess_conv2d_kernel(kernel, dim_ordering)
th_border_mode = _preprocess_border_mode(border_mode)
np_kernel = kernel.eval()
image_shape = _preprocess_image_shape(dim_ordering, image_shape)
filter_shape = _preprocess_filter_shape(dim_ordering, filter_shape)
image_shape = _preprocess_conv2d_image_shape(dim_ordering, image_shape)
filter_shape = _preprocess_conv2d_filter_shape(dim_ordering, filter_shape)
# TODO: remove the if statement when theano with no filter dilation is deprecated.
if filter_dilation == (1, 1):
@@ -1170,7 +1342,7 @@ def deconv2d(x, kernel, output_shape, strides=(1, 1),
kernel = kernel.dimshuffle((1, 0, 2, 3))
th_border_mode = _preprocess_border_mode(border_mode)
np_kernel = kernel.eval()
filter_shape = _preprocess_filter_shape(dim_ordering, filter_shape)
filter_shape = _preprocess_conv2d_filter_shape(dim_ordering, filter_shape)
op = T.nnet.abstract_conv.AbstractConv2d_gradInputs(imshp=output_shape,
kshp=filter_shape,
@@ -1198,7 +1370,53 @@ def separable_conv2d(x, depthwise_kernel, pointwise_kernel, strides=(1, 1),
def conv3d(x, kernel, strides=(1, 1, 1),
border_mode='valid', dim_ordering=_IMAGE_DIM_ORDERING,
volume_shape=None, filter_shape=None):
volume_shape=None, filter_shape=None,
filter_dilation=(1, 1, 1)):
'''3D convolution.
# Arguments
kernel: kernel tensor.
strides: strides tuple.
border_mode: string, "same" or "valid".
dim_ordering: "tf" or "th".
Whether to use Theano or TensorFlow dimension ordering
in inputs/kernels/ouputs.
'''
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
# TODO: remove this if statement when Theano without AbstractConv3d is deprecated
if not hasattr(T.nnet, 'conv3d'):
if filter_dilation != (1, 1, 1):
raise Exception('conv3d with filter dilation requires Theano '
'0.9.0dev3 or newer.')
return _old_theano_conv3d(x, kernel, strides, border_mode,
dim_ordering, volume_shape, filter_shape)
x = _preprocess_conv3d_input(x, dim_ordering)
kernel = _preprocess_conv3d_kernel(kernel, dim_ordering)
th_border_mode = _preprocess_border_mode(border_mode)
np_kernel = kernel.eval()
volume_shape = _preprocess_conv3d_volume_shape(dim_ordering, volume_shape)
filter_shape = _preprocess_conv3d_filter_shape(dim_ordering, filter_shape)
conv_out = T.nnet.conv3d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
input_shape=volume_shape,
filter_shape=filter_shape,
filter_dilation=filter_dilation)
conv_out = _postprocess_conv3d_output(conv_out, x, border_mode, np_kernel,
strides, dim_ordering)
return conv_out
# TODO: remove this function when theano without AbstractConv3d is deprecated
def _old_theano_conv3d(x, kernel, strides=(1, 1, 1),
border_mode='valid', dim_ordering=_IMAGE_DIM_ORDERING,
volume_shape=None, filter_shape=None):
'''
Run on cuDNN if available.
border_mode: string, "same" or "valid".
@@ -1303,6 +1521,60 @@ def pool2d(x, pool_size, strides=(1, 1), border_mode='valid',
def pool3d(x, pool_size, strides=(1, 1, 1), border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING, pool_mode='max'):
# TODO: remove this if statement when Theano without pool_3d is deprecated
# (pool_3d was introduced after 0.9.0dev3)
if not hasattr(T.signal.pool, 'pool_3d'):
return _old_theano_pool3d(x, pool_size, strides, border_mode,
dim_ordering, pool_mode)
if border_mode == 'same':
w_pad = pool_size[0] - 2 if pool_size[0] % 2 == 1 else pool_size[0] - 1
h_pad = pool_size[1] - 2 if pool_size[1] % 2 == 1 else pool_size[1] - 1
d_pad = pool_size[2] - 2 if pool_size[2] % 2 == 1 else pool_size[2] - 1
padding = (w_pad, h_pad, d_pad)
elif border_mode == 'valid':
padding = (0, 0, 0)
else:
raise Exception('Invalid border mode: ' + str(border_mode))
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
if dim_ordering == 'tf':
x = x.dimshuffle((0, 4, 1, 2, 3))
if pool_mode == 'max':
pool_out = pool.pool_3d(x, ds=pool_size, st=strides,
ignore_border=True,
padding=padding,
mode='max')
elif pool_mode == 'avg':
pool_out = pool.pool_3d(x, ds=pool_size, st=strides,
ignore_border=True,
padding=padding,
mode='average_exc_pad')
else:
raise Exception('Invalid pooling mode: ' + str(pool_mode))
if border_mode == 'same':
expected_width = (x.shape[2] + strides[0] - 1) // strides[0]
expected_height = (x.shape[3] + strides[1] - 1) // strides[1]
expected_depth = (x.shape[4] + strides[2] - 1) // strides[2]
pool_out = pool_out[:, :,
: expected_width,
: expected_height,
: expected_depth]
if dim_ordering == 'tf':
pool_out = pool_out.dimshuffle((0, 2, 3, 4, 1))
return pool_out
# TODO: remove this function when Theano without pool_3d is deprecated
# (pool_3d was introduced after 0.9.0dev3)
def _old_theano_pool3d(x, pool_size, strides=(1, 1, 1), border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING, pool_mode='max'):
if border_mode == 'same':
# TODO: add implementation for border_mode="same"
raise Exception('border_mode="same" not supported with Theano.')
+230 -4
Ver Arquivo
@@ -1,12 +1,14 @@
from __future__ import absolute_import
from __future__ import print_function
import csv
import numpy as np
import time
import json
import warnings
from collections import deque
from collections import deque, OrderedDict, Iterable
from .utils.generic_utils import Progbar
from keras import backend as K
from pkg_resources import parse_version
@@ -312,6 +314,10 @@ class EarlyStopping(Callback):
# Arguments
monitor: quantity to be monitored.
min_delta: minimum change in the monitored quantity
to qualify as an improvement, i.e. an absolute
change of less than min_delta, will count as no
improvement.
patience: number of epochs with no improvement
after which training will be stopped.
verbose: verbosity mode.
@@ -323,12 +329,13 @@ class EarlyStopping(Callback):
mode, the direction is automatically inferred
from the name of the monitored quantity.
'''
def __init__(self, monitor='val_loss', patience=0, verbose=0, mode='auto'):
def __init__(self, monitor='val_loss', min_delta=0, patience=0, verbose=0, mode='auto'):
super(EarlyStopping, self).__init__()
self.monitor = monitor
self.patience = patience
self.verbose = verbose
self.min_delta = min_delta
self.wait = 0
if mode not in ['auto', 'min', 'max']:
@@ -347,6 +354,11 @@ class EarlyStopping(Callback):
else:
self.monitor_op = np.less
if self.monitor_op == np.greater:
self.min_delta *= 1
else:
self.min_delta *= -1
def on_train_begin(self, logs={}):
self.wait = 0 # Allow instances to be re-used
self.best = np.Inf if self.monitor_op == np.less else -np.Inf
@@ -357,7 +369,7 @@ class EarlyStopping(Callback):
warnings.warn('Early stopping requires %s available!' %
(self.monitor), RuntimeWarning)
if self.monitor_op(current, self.best):
if self.monitor_op(current - self.min_delta, self.best):
self.best = current
self.wait = 0
else:
@@ -528,7 +540,221 @@ class TensorBoard(Callback):
continue
summary = tf.Summary()
summary_value = summary.value.add()
summary_value.simple_value = value
summary_value.simple_value = value.item()
summary_value.tag = name
self.writer.add_summary(summary, epoch)
self.writer.flush()
class ReduceLROnPlateau(Callback):
'''Reduce learning rate when a metric has stopped improving.
Models often benefit from reducing the learning rate by a factor
of 2-10 once learning stagnates. This callback monitors a
quantity and if no improvement is seen for a 'patience' number
of epochs, the learning rate is reduced.
# Example
```python
reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.2,
patience=5, min_lr=0.001)
model.fit(X_train, Y_train, callbacks=[reduce_lr])
```
# Arguments
monitor: quantity to be monitored.
factor: factor by which the learning rate will
be reduced. new_lr = lr * factor
patience: number of epochs with no improvement
after which learning rate will be reduced.
verbose: int. 0: quiet, 1: update messages.
mode: one of {auto, min, max}. In `min` mode,
lr will be reduced when the quantity
monitored has stopped decreasing; in `max`
mode it will be reduced when the quantity
monitored has stopped increasing; in `auto`
mode, the direction is automatically inferred
from the name of the monitored quantity.
epsilon: threshold for measuring the new optimum,
to only focus on significant changes.
cooldown: number of epochs to wait before resuming
normal operation after lr has been reduced.
min_lr: lower bound on the learning rate.
'''
def __init__(self, monitor='val_loss', factor=0.1, patience=10,
verbose=0, mode='auto', epsilon=1e-4, cooldown=0, min_lr=0):
super(Callback, self).__init__()
self.monitor = monitor
if factor >= 1.0:
raise ValueError('ReduceLROnPlateau does not support a factor >= 1.0.')
self.factor = factor
self.min_lr = min_lr
self.epsilon = epsilon
self.patience = patience
self.verbose = verbose
self.cooldown = cooldown
self.cooldown_counter = 0 # Cooldown counter.
self.wait = 0
self.best = 0
self.mode = mode
self.monitor_op = None
self.reset()
def reset(self):
if self.mode not in ['auto', 'min', 'max']:
warnings.warn('Learning Rate Plateau Reducing mode %s is unknown, '
'fallback to auto mode.' % (self.mode), RuntimeWarning)
self.mode = 'auto'
if self.mode == 'min' or (self.mode == 'auto' and 'acc' not in self.monitor):
self.monitor_op = lambda a, b: np.less(a, b - self.epsilon)
self.best = np.Inf
else:
self.monitor_op = lambda a, b: np.greater(a, b + self.epsilon)
self.best = -np.Inf
self.cooldown_counter = 0
self.wait = 0
self.lr_epsilon = self.min_lr * 1e-4
def on_train_begin(self, logs={}):
self.reset()
def on_epoch_end(self, epoch, logs={}):
logs['lr'] = K.get_value(self.model.optimizer.lr)
current = logs.get(self.monitor)
if current is None:
warnings.warn('Learning Rate Plateau Reducing requires %s available!' %
self.monitor, RuntimeWarning)
else:
if self.in_cooldown():
self.cooldown_counter -= 1
self.wait = 0
if self.monitor_op(current, self.best):
self.best = current
self.wait = 0
elif not self.in_cooldown():
if self.wait >= self.patience:
old_lr = float(K.get_value(self.model.optimizer.lr))
if old_lr > self.min_lr + self.lr_epsilon:
new_lr = old_lr * self.factor
new_lr = max(new_lr, self.min_lr)
K.set_value(self.model.optimizer.lr, new_lr)
if self.verbose > 0:
print('\nEpoch %05d: reducing learning rate to %s.' % (epoch, new_lr))
self.cooldown_counter = self.cooldown
self.wait = 0
self.wait += 1
def in_cooldown(self):
return self.cooldown_counter > 0
class CSVLogger(Callback):
'''Callback that streams epoch results to a csv file.
Supports all values that can be represented as a string,
including 1D iterables such as np.ndarray.
# Example
```python
csv_logger = CSVLogger('training.log')
model.fit(X_train, Y_train, callbacks=[csv_logger])
```
Arguments
filename: filename of the csv file, e.g. 'run/log.csv'.
separator: string used to separate elements in the csv file.
append: True: append if file exists (useful for continuing
training). False: overwrite existing file,
'''
def __init__(self, filename, separator=',', append=False):
self.sep = separator
self.filename = filename
self.append = append
self.writer = None
self.keys = None
super(CSVLogger, self).__init__()
def on_train_begin(self, logs={}):
if self.append:
self.csv_file = open(self.filename, 'a')
else:
self.csv_file = open(self.filename, 'w')
def on_epoch_end(self, epoch, logs={}):
def handle_value(k):
is_zero_dim_ndarray = isinstance(k, np.ndarray) and k.ndim == 0
if isinstance(k, Iterable) and not is_zero_dim_ndarray:
return '"[%s]"' % (', '.join(map(lambda x: str(x), k)))
else:
return k
if not self.writer:
self.keys = sorted(logs.keys())
self.writer = csv.DictWriter(self.csv_file, fieldnames=['epoch'] + self.keys)
self.writer.writeheader()
row_dict = OrderedDict({'epoch': epoch})
row_dict.update((key, handle_value(logs[key])) for key in self.keys)
self.writer.writerow(row_dict)
self.csv_file.flush()
def on_train_end(self, logs={}):
self.csv_file.close()
class LambdaCallback(Callback):
"""Callback for creating simple, custom callbacks on-the-fly.
This callback is constructed with anonymous functions that will be called
at the appropiate time. Note that the callbacks expects positional
arguments, as:
- `on_epoch_begin` and `on_epoch_end` expect two positional arguments: `epoch`, `logs`
- `on_batch_begin` and `on_batch_end` expect two positional arguments: `batch`, `logs`
- `on_train_begin` and `on_train_end` expect one positional argument: `logs`
# Arguments
on_epoch_begin: called at the beginning of every epoch.
on_epoch_end: called at the end of every epoch.
on_batch_begin: called at the beginning of every batch.
on_batch_end: called at the end of every batch.
on_train_begin: called at the beginning of model training.
on_train_end: called at the end of model training.
# Example
```python
# Print the batch number at the beginning of every batch.
batch_print_callback = LambdaCallback(on_batch_begin=lambda batch, logs: print(batch))
# Plot the loss after every epoch.
import numpy as np
import matplotlib.pyplot as plt
plot_loss_callback = LambdaCallback(on_epoch_end=lambda epoch, logs: plt.plot(np.arange(epoch), logs['loss']))
# Terminate some processes after having finished model training.
processes = ...
cleanup_callback = LambdaCallback(on_train_end=lambda logs: [p.terminate() for p in processes if p.is_alive()])
model.fit(..., callbacks=[batch_print_callback, plot_loss_callback, cleanup_callback])
```
"""
def __init__(self,
on_epoch_begin=None,
on_epoch_end=None,
on_batch_begin=None,
on_batch_end=None,
on_train_begin=None,
on_train_end=None,
**kwargs):
super(Callback, self).__init__()
self.__dict__.update(kwargs)
self.on_epoch_begin = on_epoch_begin if on_epoch_begin else lambda epoch, logs: None
self.on_epoch_end = on_epoch_end if on_epoch_end else lambda epoch, logs: None
self.on_batch_begin = on_batch_begin if on_batch_begin else lambda batch, logs: None
self.on_batch_end = on_batch_end if on_batch_end else lambda batch, logs: None
self.on_train_begin = on_train_begin if on_train_begin else lambda logs: None
self.on_train_end = on_train_end if on_train_end else lambda logs: None
+4 -5
Ver Arquivo
@@ -1,14 +1,13 @@
# -*- coding: utf-8 -*-
import gzip
from ..utils.data_utils import get_file
from six.moves import cPickle
import sys
def load_data(path="mnist.pkl.gz"):
path = get_file(path, origin="https://s3.amazonaws.com/img-datasets/mnist.pkl.gz")
def load_data(path='mnist.pkl.gz'):
path = get_file(path, origin='https://s3.amazonaws.com/img-datasets/mnist.pkl.gz')
if path.endswith(".gz"):
if path.endswith('.gz'):
f = gzip.open(path, 'rb')
else:
f = open(path, 'rb')
@@ -16,7 +15,7 @@ def load_data(path="mnist.pkl.gz"):
if sys.version_info < (3,):
data = cPickle.load(f)
else:
data = cPickle.load(f, encoding="bytes")
data = cPickle.load(f, encoding='bytes')
f.close()
return data # (X_train, y_train), (X_test, y_test)
+2 -1
Ver Arquivo
@@ -10,7 +10,8 @@ import sys
def load_data(path='reuters.pkl', nb_words=None, skip_top=0,
maxlen=None, test_split=0.2, seed=113,
start_char=1, oov_char=2, index_from=3):
'''
'''Loads the Reuters newswire classification dataset.
# Arguments
path: where to store the data (in `/.keras/dataset`)
nb_words: max number of words to include. Words are ranked
+2 -2
Ver Arquivo
@@ -1106,10 +1106,10 @@ class Merge(Layer):
```python
model1 = Sequential()
model1.add(Dense(32))
model1.add(Dense(32, input_dim=32))
model2 = Sequential()
model2.add(Dense(32))
model2.add(Dense(32, input_dim=32))
merged_model = Sequential()
merged_model.add(Merge([model1, model2], mode='concat', concat_axis=1)
+56 -24
Ver Arquivo
@@ -7,6 +7,9 @@ import time
import numpy as np
import multiprocessing
import threading
import six
try:
import queue
except ImportError:
@@ -255,7 +258,12 @@ def collect_trainable_weights(layer):
weights += layer.trainable_weights
# dedupe weights
weights = list(set(weights))
weights.sort(key=lambda x: x.name)
# TF variables have auto-generated the name, while Theano has auto-generated the auto_name variable. name in Theano is None
if weights:
if K.backend() == 'theano':
weights.sort(key=lambda x: x.auto_name)
else:
weights.sort(key=lambda x: x.name)
return weights
@@ -450,7 +458,7 @@ def generator_queue(generator, max_q_size=10,
q.close()
raise
return q, _stop
return q, _stop, generator_threads
class Model(Container):
@@ -635,6 +643,15 @@ class Model(Container):
# list of same size as output_names.
# contains tuples (metrics for output, names of metrics)
nested_metrics = collect_metrics(metrics, self.output_names)
def append_metric(layer_num, metric_name, metric_tensor):
"""Helper function, used in loop below"""
if len(self.output_names) > 1:
metric_name = self.output_layers[layer_num].name + '_' + metric_name
self.metrics_names.append(metric_name)
self.metrics_tensors.append(metric_tensor)
for i in range(len(self.outputs)):
y_true = self.targets[i]
y_pred = self.outputs[i]
@@ -644,27 +661,28 @@ class Model(Container):
if metric == 'accuracy' or metric == 'acc':
# custom handling of accuracy (because of class mode duality)
output_shape = self.internal_output_shapes[i]
acc_fn = None
if output_shape[-1] == 1 or self.loss_functions[i] == objectives.binary_crossentropy:
# case: binary accuracy
self.metrics_tensors.append(metrics_module.binary_accuracy(y_true, y_pred))
acc_fn = metrics_module.binary_accuracy
elif self.loss_functions[i] == objectives.sparse_categorical_crossentropy:
# case: categorical accuracy with sparse targets
self.metrics_tensors.append(
metrics_module.sparse_categorical_accuracy(y_true, y_pred))
acc_fn = metrics_module.sparse_categorical_accuracy
else:
# case: categorical accuracy with dense targets
self.metrics_tensors.append(metrics_module.categorical_accuracy(y_true, y_pred))
if len(self.output_names) == 1:
self.metrics_names.append('acc')
else:
self.metrics_names.append(self.output_layers[i].name + '_acc')
acc_fn = metrics_module.categorical_accuracy
append_metric(i, 'acc', acc_fn(y_true, y_pred))
else:
metric_fn = metrics_module.get(metric)
self.metrics_tensors.append(metric_fn(y_true, y_pred))
if len(self.output_names) == 1:
self.metrics_names.append(metric_fn.__name__)
else:
self.metrics_names.append(self.output_layers[i].name + '_' + metric_fn.__name__)
metric_result = metric_fn(y_true, y_pred)
if not isinstance(metric_result, dict):
metric_result = {
metric_fn.__name__: metric_result
}
for name, tensor in six.iteritems(metric_result):
append_metric(i, name, tensor)
# prepare gradient updates and state updates
self.optimizer = optimizers.get(optimizer)
@@ -1007,7 +1025,7 @@ class Model(Container):
on this data at the end of each epoch.
validation_data: data on which to evaluate the loss and any model metrics
at the end of each epoch. The model will not be trained on this data.
This could be a tuple (x_val, y_val) or a tuple (val_x, val_y, val_sample_weights).
This could be a tuple (x_val, y_val) or a tuple (x_val, y_val, val_sample_weights).
shuffle: boolean, whether to shuffle the training data before each epoch.
class_weight: optional dictionary mapping class indices (integers) to
a weight (float) to apply to the model's loss for the samples
@@ -1393,8 +1411,8 @@ class Model(Container):
self.validation_data = None
# start generator thread storing batches into a queue
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
data_gen_queue, _stop, generator_threads = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
callback_model.stop_training = False
while epoch < nb_epoch:
@@ -1468,7 +1486,9 @@ class Model(Container):
if val_gen:
val_outs = self.evaluate_generator(validation_data,
nb_val_samples,
max_q_size=max_q_size)
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
else:
# no need for try/except because
# data has already been validated
@@ -1489,6 +1509,10 @@ class Model(Container):
_stop.set()
if pickle_safe:
# Terminate all daemon processes
for p in generator_threads:
if p.is_alive():
p.terminate()
data_gen_queue.close()
callbacks.on_train_end()
return self.history
@@ -1523,8 +1547,8 @@ class Model(Container):
wait_time = 0.01
all_outs = []
weights = []
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
data_gen_queue, _stop, generator_threads = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
while processed_samples < val_samples:
generator_output = None
@@ -1569,6 +1593,10 @@ class Model(Container):
_stop.set()
if pickle_safe:
# Terminate all daemon processes
for p in generator_threads:
if p.is_alive():
p.terminate()
data_gen_queue.close()
if type(outs) is not list:
return np.average(np.asarray(all_outs),
@@ -1604,8 +1632,8 @@ class Model(Container):
processed_samples = 0
wait_time = 0.01
all_outs = []
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
data_gen_queue, _stop, generator_threads = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
while processed_samples < val_samples:
generator_output = None
@@ -1658,6 +1686,10 @@ class Model(Container):
_stop.set()
if pickle_safe:
# Terminate all daemon processes
for p in generator_threads:
if p.is_alive():
p.terminate()
data_gen_queue.close()
if len(all_outs) == 1:
return all_outs[0]
+1 -3
Ver Arquivo
@@ -107,9 +107,7 @@ class ELU(Layer):
super(ELU, self).__init__(**kwargs)
def call(self, x, mask=None):
pos = K.relu(x)
neg = (x - abs(x)) * 0.5
return pos + self.alpha * (K.exp(neg) - 1.)
return K.elu(x, self.alpha)
def get_config(self):
config = {'alpha': float(self.alpha)}
+138 -43
Ver Arquivo
@@ -348,7 +348,7 @@ class Convolution2D(Layer):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
bias: whether to include a bias
(i.e. make the layer affine rather than linear).
@@ -506,19 +506,39 @@ class Deconvolution2D(Convolution2D):
(tuple of integers, does not include the sample axis),
e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures.
To pass the correct `output_shape` to this layer,
one could use a test model to predict and observe the actual output shape.
# Examples
```python
# apply a 3x3 transposed convolution with stride 1x1 and 3 output filters on a 12x12 image:
model = Sequential()
model.add(Deconvolution2D(3, 3, 3, output_shape=(None, 3, 14, 14), border_mode='valid', input_shape=(3, 12, 12)))
# output_shape will be (None, 3, 14, 14)
# Note that you will have to change the output_shape depending on the backend used.
# we can predict with the model and print the shape of the array.
dummy_input = np.ones((32, 3, 12, 12))
# For TensorFlow dummy_input = np.ones((32, 12, 12, 3))
preds = model.predict(dummy_input)
print(preds.shape)
# Theano GPU: (None, 3, 13, 13)
# Theano CPU: (None, 3, 14, 14)
# TensorFlow: (None, 14, 14, 3)
# apply a 3x3 transposed convolution with stride 2x2 and 3 output filters on a 12x12 image:
model = Sequential()
model.add(Deconvolution2D(3, 3, 3, output_shape=(None, 3, 25, 25), subsample=(2, 2), border_mode='valid', input_shape=(3, 12, 12)))
model.summary()
# output_shape will be (None, 3, 25, 25)
# we can predict with the model and print the shape of the array.
dummy_input = np.ones((32, 3, 12, 12))
# For TensorFlow dummy_input = np.ones((32, 12, 12, 3))
preds = model.predict(dummy_input)
print(preds.shape)
# Theano GPU: (None, 3, 25, 25)
# Theano CPU: (None, 3, 25, 25)
# TensorFlow: (None, 25, 25, 3)
```
# Arguments
@@ -536,6 +556,9 @@ class Deconvolution2D(Convolution2D):
p - padding size,
a - user-specified quantity used to distinguish between
the s different possible output sizes.
Because a is not specified explicitly and Theano and Tensorflow
use different values, it is better to use a dummy input and observe
the actual output shape of a layer as specified in the examples.
init: name of initialization function for the weights of the layer
(see [initializations](../initializations.md)), or alternatively,
Theano function to use for weights initialization.
@@ -564,7 +587,7 @@ class Deconvolution2D(Convolution2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
@@ -610,19 +633,14 @@ class Deconvolution2D(Convolution2D):
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
rows = input_shape[2]
cols = input_shape[3]
rows = self.output_shape_[2]
cols = self.output_shape_[3]
elif self.dim_ordering == 'tf':
rows = input_shape[1]
cols = input_shape[2]
rows = self.output_shape_[1]
cols = self.output_shape_[2]
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
rows = conv_input_length(rows, self.nb_row,
self.border_mode, self.subsample[0])
cols = conv_input_length(cols, self.nb_col,
self.border_mode, self.subsample[1])
if self.dim_ordering == 'th':
return (input_shape[0], self.nb_filter, rows, cols)
elif self.dim_ordering == 'tf':
@@ -704,7 +722,7 @@ class AtrousConvolution2D(Convolution2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
@@ -853,7 +871,7 @@ class SeparableConvolution2D(Layer):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
bias: whether to include a bias
(i.e. make the layer affine rather than linear).
@@ -1068,7 +1086,7 @@ class Convolution3D(Layer):
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
@@ -1271,7 +1289,7 @@ class UpSampling2D(Layer):
is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -1334,7 +1352,7 @@ class UpSampling3D(Layer):
is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
@@ -1394,9 +1412,16 @@ class ZeroPadding1D(Layer):
'''Zero-padding layer for 1D input (e.g. temporal sequence).
# Arguments
padding: int
padding: int, or tuple of int (length 2), or dictionary.
- If int:
How many zeros to add at the beginning and end of
the padding dimension (axis 1).
- If tuple of int (length 2)
How many zeros to add at the beginning and at the end of
the padding dimension, in order '(left_pad, right_pad)'.
- If dictionary: should contain the keys
{'left_pad', 'right_pad'}.
If any key is missing, default value of 0 will be used for the missing key.
# Input shape
3D tensor with shape (samples, axis_to_pad, features)
@@ -1408,16 +1433,37 @@ class ZeroPadding1D(Layer):
def __init__(self, padding=1, **kwargs):
super(ZeroPadding1D, self).__init__(**kwargs)
self.padding = padding
if isinstance(padding, int):
self.left_pad = padding
self.right_pad = padding
elif isinstance(padding, dict):
if set(padding.keys()) <= {'left_pad', 'right_pad'}:
self.left_pad = padding.get('left_pad', 0)
self.right_pad = padding.get('right_pad', 0)
else:
raise ValueError('Unexpected key found in `padding` dictionary. '
'Keys have to be in {"left_pad", "right_pad"}. '
'Found: ' + str(padding.keys()))
else:
padding = tuple(padding)
if len(padding) != 2:
raise ValueError('`padding` should be int, or dict with keys '
'{"left_pad", "right_pad"}, or tuple of length 2. '
'Found: ' + str(padding))
self.left_pad = padding[0]
self.right_pad = padding[1]
self.input_spec = [InputSpec(ndim=3)]
def get_output_shape_for(self, input_shape):
length = input_shape[1] + self.padding * 2 if input_shape[1] is not None else None
length = input_shape[1] + self.left_pad + self.right_pad if input_shape[1] is not None else None
return (input_shape[0],
length,
input_shape[2])
def call(self, x, mask=None):
return K.temporal_padding(x, padding=self.padding)
return K.asymmetric_temporal_padding(x, left_pad=self.left_pad, right_pad=self.right_pad)
def get_config(self):
config = {'padding': self.padding}
@@ -1429,55 +1475,103 @@ class ZeroPadding2D(Layer):
'''Zero-padding layer for 2D input (e.g. picture).
# Arguments
padding: tuple of int (length 2)
padding: tuple of int (length 2), or tuple of int (length 4), or dictionary.
- If tuple of int (length 2):
How many zeros to add at the beginning and end of
the 2 padding dimensions (axis 3 and 4).
the 2 padding dimensions (rows and cols).
- If tuple of int (length 4):
How many zeros to add at the beginning and at the end of
the 2 padding dimensions (rows and cols), in the order
'(top_pad, bottom_pad, left_pad, right_pad)'.
- If dictionary: should contain the keys
{'top_pad', 'bottom_pad', 'left_pad', 'right_pad'}.
If any key is missing, default value of 0 will be used for the missing key.
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.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
(samples, depth, first_axis_to_pad, second_axis_to_pad)
`(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, depth, first_padded_axis, second_padded_axis)
`(samples, channels, padded_rows, padded_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, padded_rows, padded_cols, channels)` if dim_ordering='tf'.
'''
def __init__(self, padding=(1, 1), dim_ordering='default', **kwargs):
def __init__(self,
padding=(1, 1),
dim_ordering='default',
**kwargs):
super(ZeroPadding2D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.padding = tuple(padding)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.padding = padding
if isinstance(padding, dict):
if set(padding.keys()) <= {'top_pad', 'bottom_pad', 'left_pad', 'right_pad'}:
self.top_pad = padding.get('top_pad', 0)
self.bottom_pad = padding.get('bottom_pad', 0)
self.left_pad = padding.get('left_pad', 0)
self.right_pad = padding.get('right_pad', 0)
else:
raise ValueError('Unexpected key found in `padding` dictionary. '
'Keys have to be in {"top_pad", "bottom_pad", '
'"left_pad", "right_pad"}.'
'Found: ' + str(padding.keys()))
else:
padding = tuple(padding)
if len(padding) == 2:
self.top_pad = padding[0]
self.bottom_pad = padding[0]
self.left_pad = padding[1]
self.right_pad = padding[1]
elif len(padding) == 4:
self.top_pad = padding[0]
self.bottom_pad = padding[1]
self.left_pad = padding[2]
self.right_pad = padding[3]
else:
raise TypeError('`padding` should be tuple of int '
'of length 2 or 4, or dict. '
'Found: ' + str(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)]
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
rows = input_shape[2] + self.top_pad + self.bottom_pad if input_shape[2] is not None else None
cols = input_shape[3] + self.left_pad + self.right_pad if input_shape[3] is not None else None
return (input_shape[0],
input_shape[1],
width,
height)
rows,
cols)
elif self.dim_ordering == 'tf':
width = input_shape[1] + 2 * self.padding[0] if input_shape[1] is not None else None
height = input_shape[2] + 2 * self.padding[1] if input_shape[2] is not None else None
rows = input_shape[1] + self.top_pad + self.bottom_pad if input_shape[1] is not None else None
cols = input_shape[2] + self.left_pad + self.right_pad if input_shape[2] is not None else None
return (input_shape[0],
width,
height,
rows,
cols,
input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def call(self, x, mask=None):
return K.spatial_2d_padding(x, padding=self.padding,
dim_ordering=self.dim_ordering)
return K.asymmetric_spatial_2d_padding(x,
top_pad=self.top_pad,
bottom_pad=self.bottom_pad,
left_pad=self.left_pad,
right_pad=self.right_pad,
dim_ordering=self.dim_ordering)
def get_config(self):
config = {'padding': self.padding}
@@ -1492,12 +1586,13 @@ class ZeroPadding3D(Layer):
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).
Currentl only symmetric padding is supported.
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.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
@@ -1601,7 +1696,7 @@ class Cropping2D(Layer):
is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -1674,7 +1769,7 @@ class Cropping2D(Layer):
return dict(list(base_config.items()) + list(config.items()))
class Cropping3D(Layer):
'''Cropping layer for 2D input (e.g. picture).
'''Cropping layer for 3D data (e.g. spatial or saptio-temporal).
# Arguments
cropping: tuple of tuple of int (length 3)
@@ -1685,7 +1780,7 @@ class Cropping3D(Layer):
is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
+2 -2
Ver Arquivo
@@ -111,7 +111,7 @@ class SpatialDropout2D(Dropout):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -159,7 +159,7 @@ class SpatialDropout3D(Dropout):
is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
+1 -1
Ver Arquivo
@@ -58,7 +58,7 @@ class BatchNormalization(Layer):
Same shape as input.
# References
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](http://jmlr.org/proceedings/papers/v37/ioffe15.html)
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](http://jmlr.org/proceedings/papers/v37/ioffe15.pdf)
'''
def __init__(self, epsilon=1e-5, mode=0, axis=-1, momentum=0.99,
weights=None, beta_init='zero', gamma_init='one',
+86 -7
Ver Arquivo
@@ -186,7 +186,7 @@ class MaxPooling2D(_Pooling2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -228,7 +228,7 @@ class AveragePooling2D(_Pooling2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -333,7 +333,7 @@ class MaxPooling3D(_Pooling3D):
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
@@ -373,7 +373,7 @@ class AveragePooling3D(_Pooling3D):
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
@@ -447,7 +447,6 @@ class _GlobalPooling2D(Layer):
super(_GlobalPooling2D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
print(dim_ordering)
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=4)]
@@ -474,7 +473,7 @@ class GlobalAveragePooling2D(_GlobalPooling2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -502,7 +501,7 @@ class GlobalMaxPooling2D(_GlobalPooling2D):
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
If you never set it, then it will be "tf".
# Input shape
4D tensor with shape:
@@ -520,3 +519,83 @@ class GlobalMaxPooling2D(_GlobalPooling2D):
return K.max(x, axis=[1, 2])
else:
return K.max(x, axis=[2, 3])
class _GlobalPooling3D(Layer):
def __init__(self, dim_ordering='default', **kwargs):
super(_GlobalPooling3D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'tf':
return (input_shape[0], input_shape[4])
else:
return (input_shape[0], input_shape[1])
def call(self, x, mask=None):
raise NotImplementedError
def get_config(self):
config = {'dim_ordering': self.dim_ordering}
base_config = super(_GlobalPooling3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class GlobalAveragePooling3D(_GlobalPooling3D):
'''Global Average pooling operation for 3D data.
# Arguments
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.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
`(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)` if dim_ordering='tf'.
# Output shape
2D tensor with shape:
`(nb_samples, channels)`
'''
def call(self, x, mask=None):
if self.dim_ordering == 'tf':
return K.mean(x, axis=[1, 2, 3])
else:
return K.mean(x, axis=[2, 3, 4])
class GlobalMaxPooling3D(_GlobalPooling3D):
'''Global Max pooling operation for 3D data.
# Arguments
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.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "tf".
# Input shape
5D tensor with shape:
`(samples, channels, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)` if dim_ordering='tf'.
# Output shape
2D tensor with shape:
`(nb_samples, channels)`
'''
def call(self, x, mask=None):
if self.dim_ordering == 'tf':
return K.max(x, axis=[1, 2, 3])
else:
return K.max(x, axis=[2, 3, 4])
+16 -2
Ver Arquivo
@@ -112,9 +112,23 @@ class TimeDistributed(Wrapper):
def step(x, states):
output = self.layer.call(x)
return output, []
input_length = input_shape[1]
if K.backend() == 'tensorflow' and len(input_shape) > 3:
if input_length is None:
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.')
unroll = True
else:
unroll = False
last_output, outputs, states = K.rnn(step, X,
initial_states=[])
initial_states=[], input_length=input_length, unroll=unroll)
y = outputs
else:
# no batch size specified, therefore the layer will be able
+10 -8
Ver Arquivo
@@ -538,7 +538,8 @@ class Graph(Model):
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight={},
max_q_size=10, **kwargs):
max_q_size=10, nb_worker=1,
pickle_safe=False, **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
@@ -599,10 +600,6 @@ class Graph(Model):
'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, '
@@ -647,13 +644,16 @@ class Graph(Model):
validation_data=validation_data,
nb_val_samples=nb_val_samples,
class_weight=class_weight,
max_q_size=max_q_size)
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
self.train_on_batch = self._train_on_batch
self.evaluate = self._evaluate
return history
def evaluate_generator(self, generator, val_samples,
verbose=1, max_q_size=10, **kwargs):
verbose=1, max_q_size=10, nb_worker=1,
pickle_safe=False, **kwargs):
'''Evaluates the model on a generator. The generator should
return the same kind of data with every yield as accepted
by `evaluate`.
@@ -707,7 +707,9 @@ class Graph(Model):
generator = fixed_generator()
history = super(Graph, self).evaluate_generator(generator,
val_samples,
max_q_size=max_q_size)
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
self.test_on_batch = self._test_on_batch
return history
+109 -13
Ver Arquivo
@@ -1,78 +1,134 @@
import numpy as np
from . import backend as K
from .utils.generic_utils import get_from_module
def binary_accuracy(y_true, y_pred):
'''Calculates the mean accuracy rate across all predictions for binary
classification problems
'''
return K.mean(K.equal(y_true, K.round(y_pred)))
def categorical_accuracy(y_true, y_pred):
'''Calculates the mean accuracy rate across all predictions for
multiclass classification problems
'''
return K.mean(K.equal(K.argmax(y_true, axis=-1),
K.argmax(y_pred, axis=-1)))
def sparse_categorical_accuracy(y_true, y_pred):
'''Same as categorical_accuracy, but useful when the predictions are for
sparse targets
'''
return K.mean(K.equal(K.max(y_true, axis=-1),
K.cast(K.argmax(y_pred, axis=-1), K.floatx())))
def top_k_categorical_accuracy(y_true, y_pred, k=5):
'''Calculates the top-k categorical accuracy rate, i.e. success when the
target class is within the top-k predictions provided
'''
return K.mean(K.in_top_k(y_pred, K.argmax(y_true, axis=-1), k))
def mean_squared_error(y_true, y_pred):
'''Calculates the mean squared error (mse) rate between predicted and target
values
'''
return K.mean(K.square(y_pred - y_true))
def mean_absolute_error(y_true, y_pred):
'''Calculates the mean absolute error (mae) rate between predicted and target
values
'''
return K.mean(K.abs(y_pred - y_true))
def mean_absolute_percentage_error(y_true, y_pred):
'''Calculates the mean absolute percentage error (mape) rate between predicted
and target values
'''
diff = K.abs((y_true - y_pred) / K.clip(K.abs(y_true), K.epsilon(), np.inf))
return 100. * K.mean(diff)
def mean_squared_logarithmic_error(y_true, y_pred):
'''Calculates the mean squared logarithmic error (msle) rate between predicted
and target values
'''
first_log = K.log(K.clip(y_pred, K.epsilon(), np.inf) + 1.)
second_log = K.log(K.clip(y_true, K.epsilon(), np.inf) + 1.)
return K.mean(K.square(first_log - second_log))
def squared_hinge(y_true, y_pred):
return K.mean(K.square(K.maximum(1. - y_true * y_pred, 0.)))
def hinge(y_true, y_pred):
'''Calculates the hinge loss, which is defined as
`max(1 - y_true * y_pred, 0)`
'''
return K.mean(K.maximum(1. - y_true * y_pred, 0.))
def squared_hinge(y_true, y_pred):
'''Calculates the squared value of the hinge loss
'''
return K.mean(K.square(K.maximum(1. - y_true * y_pred, 0.)))
def categorical_crossentropy(y_true, y_pred):
'''Expects a binary class matrix instead of a vector of scalar classes.
'''Calculates the cross-entropy value for multiclass classification
problems. Note: Expects a binary class matrix instead of a vector
of scalar classes.
'''
return K.mean(K.categorical_crossentropy(y_pred, y_true))
def sparse_categorical_crossentropy(y_true, y_pred):
'''expects an array of integer classes.
Note: labels shape must have the same number of dimensions as output shape.
If you get a shape error, add a length-1 dimension to labels.
'''Calculates the cross-entropy value for multiclass classification
problems with sparse targets. Note: Expects an array of integer
classes. Labels shape must have the same number of dimensions as
output shape. If you get a shape error, add a length-1 dimension
to labels.
'''
return K.mean(K.sparse_categorical_crossentropy(y_pred, y_true))
def binary_crossentropy(y_true, y_pred):
'''Calculates the cross-entropy value for binary classification
problems.
'''
return K.mean(K.binary_crossentropy(y_pred, y_true))
def kullback_leibler_divergence(y_true, y_pred):
'''Calculates the Kullback-Leibler (KL) divergence between prediction
and target values
'''
y_true = K.clip(y_true, K.epsilon(), 1)
y_pred = K.clip(y_pred, K.epsilon(), 1)
return K.sum(y_true * K.log(y_true / y_pred), axis=-1)
def poisson(y_true, y_pred):
'''Calculates the poisson function over prediction and target values.
'''
return K.mean(y_pred - y_true * K.log(y_pred + K.epsilon()))
def cosine_proximity(y_true, y_pred):
'''Calculates the cosine similarity between the prediction and target
values.
'''
y_true = K.l2_normalize(y_true, axis=-1)
y_pred = K.l2_normalize(y_pred, axis=-1)
return -K.mean(y_true * y_pred)
def matthews_correlation(y_true, y_pred):
''' Matthews correlation coefficient
'''Calculates the Matthews correlation coefficient measure for quality
of binary classification problems.
'''
y_pred_pos = K.round(K.clip(y_pred, 0, 1))
y_pred_neg = 1 - y_pred_pos
@@ -83,14 +139,55 @@ def matthews_correlation(y_true, y_pred):
tp = K.sum(y_pos * y_pred_pos)
tn = K.sum(y_neg * y_pred_neg)
fp = K.sum(1 - y_neg * y_pred_pos)
fn = K.sum(1 - y_pos * y_pred_neg)
fp = K.sum(y_neg * y_pred_pos)
fn = K.sum(y_pos * y_pred_neg)
numerator = (tp * tn - fp * fn)
denominator = K.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn))
return numerator / (denominator + K.epsilon())
def fbeta_score(y_true, y_pred, beta=1):
'''Computes the F score, the weighted harmonic mean of precision and recall.
This is useful for multi-label classification where input samples can be
tagged with a set of labels. By only using accuracy (precision) a model
would achieve a perfect score by simply assigning every class to every
input. In order to avoid this, a metric should penalize incorrect class
assignments as well (recall). The F-beta score (ranged from 0.0 to 1.0)
computes this, as a weighted mean of the proportion of correct class
assignments vs. the proportion of incorrect class assignments.
With beta = 1, this is equivalent to a F-measure. With beta < 1, assigning
correct classes becomes more important, and with beta > 1 the metric is
instead weighted towards penalizing incorrect class assignments.
'''
if beta < 0:
raise ValueError('The lowest choosable beta is zero (only precision).')
# Count positive samples.
c1 = K.sum(K.round(K.clip(y_true * y_pred, 0, 1)))
c2 = K.sum(K.round(K.clip(y_pred, 0, 1)))
c3 = K.sum(K.round(K.clip(y_true, 0, 1)))
# If there are no true samples, fix the F score at 0.
if c3 == 0:
return 0
# How many selected items are relevant?
precision = c1 / c2
# How many relevant items are selected?
recall = c1 / c3
# Weight precision and recall together as a single scalar.
beta2 = beta ** 2
f_score = (1 + beta2) * (precision * recall) / (beta2 * precision + recall)
return f_score
# aliases
mse = MSE = mean_squared_error
mae = MAE = mean_absolute_error
@@ -99,6 +196,5 @@ msle = MSLE = mean_squared_logarithmic_error
cosine = cosine_proximity
from .utils.generic_utils import get_from_module
def get(identifier):
return get_from_module(identifier, globals(), 'metric')
+36 -25
Ver Arquivo
@@ -8,7 +8,7 @@ import numpy as np
from . import backend as K
from .utils.io_utils import ask_to_proceed_with_overwrite
from .engine.training import Model
from .engine.topology import get_source_inputs, Node
from .engine.topology import get_source_inputs, Node, Layer
from .optimizers import optimizer_from_config
from .legacy.models import Graph
@@ -260,6 +260,10 @@ class Sequential(Model):
# Arguments
layer: layer instance.
'''
if not isinstance(layer, Layer):
raise ValueError('The added layer must be '
'an instance of class Layer. '
'Found: ' + str(layer))
if not self.outputs:
# first layer in model: check that it is an input layer
if len(layer.inbound_nodes) == 0:
@@ -400,26 +404,27 @@ class Sequential(Model):
if self._flattened_layers is not None:
return self._flattened_layers
layers = []
if self.layers[0].__class__.__name__ == 'Merge':
merge = self.layers[0]
for layer in merge.layers:
if hasattr(layer, 'flattened_layers'):
for sublayer in layer.flattened_layers:
if sublayer not in layers:
layers.append(sublayer)
elif hasattr(layer, 'layers'):
for sublayer in layer.layers:
if sublayer not in layers:
layers.append(sublayer)
else:
if layer not in layers:
layers.append(layer)
else:
if self.layers[0] not in layers:
layers.append(self.layers[0])
for layer in self.layers[1:]:
if layer not in layers:
layers.append(layer)
if self.layers:
if self.layers[0].__class__.__name__ == 'Merge':
merge = self.layers[0]
for layer in merge.layers:
if hasattr(layer, 'flattened_layers'):
for sublayer in layer.flattened_layers:
if sublayer not in layers:
layers.append(sublayer)
elif hasattr(layer, 'layers'):
for sublayer in layer.layers:
if sublayer not in layers:
layers.append(sublayer)
else:
if layer not in layers:
layers.append(layer)
else:
if self.layers[0] not in layers:
layers.append(self.layers[0])
for layer in self.layers[1:]:
if layer not in layers:
layers.append(layer)
self._flattened_layers = layers
return layers
@@ -517,6 +522,7 @@ class Sequential(Model):
metrics: list of metrics to be evaluated by the model
during training and testing.
Typically you will use `metrics=['accuracy']`.
See [metrics](/metrics).
sample_weight_mode: if you need to do timestep-wise
sample weighting (2D weights), set this to "temporal".
"None" defaults to sample-wise weights (1D).
@@ -571,7 +577,8 @@ class Sequential(Model):
See [callbacks](/callbacks).
validation_split: float (0. < x < 1).
Fraction of the data to use as held-out validation data.
validation_data: tuple (X, y) to be used as held-out
validation_data: tuple (x_val, y_val) or tuple
(x_val, y_val, val_sample_weights) to be used as held-out
validation data. Will override validation_split.
shuffle: boolean or str (for 'batch').
Whether to shuffle the samples at each epoch.
@@ -785,7 +792,8 @@ class Sequential(Model):
def fit_generator(self, generator, samples_per_epoch, nb_epoch,
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight=None, max_q_size=10, nb_worker=1, pickle_safe=False, **kwargs):
class_weight=None, max_q_size=10, nb_worker=1,
pickle_safe=False, **kwargs):
'''Fits the model on data generated batch-by-batch by
a Python generator.
The generator is run in parallel to the model, for efficiency.
@@ -873,7 +881,9 @@ class Sequential(Model):
nb_worker=nb_worker,
pickle_safe=pickle_safe)
def evaluate_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False, **kwargs):
def evaluate_generator(self, generator, val_samples,
max_q_size=10, nb_worker=1,
pickle_safe=False, **kwargs):
'''Evaluates the model on a data generator. The generator should
return the same kind of data as accepted by `test_on_batch`.
@@ -915,7 +925,8 @@ class Sequential(Model):
nb_worker=nb_worker,
pickle_safe=pickle_safe)
def predict_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False):
def predict_generator(self, generator, val_samples,
max_q_size=10, nb_worker=1, pickle_safe=False):
'''Generates predictions for the input samples from a data generator.
The generator should return the same kind of data as accepted by
`predict_on_batch`.
+6 -1
Ver Arquivo
@@ -230,6 +230,7 @@ class RMSprop(Optimizer):
def get_config(self):
config = {'lr': float(K.get_value(self.lr)),
'rho': float(K.get_value(self.rho)),
'decay': float(K.get_value(self.decay)),
'epsilon': self.epsilon}
base_config = super(RMSprop, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -281,6 +282,7 @@ class Adagrad(Optimizer):
def get_config(self):
config = {'lr': float(K.get_value(self.lr)),
'decay': float(K.get_value(self.decay)),
'epsilon': self.epsilon}
base_config = super(Adagrad, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -346,6 +348,7 @@ class Adadelta(Optimizer):
def get_config(self):
config = {'lr': float(K.get_value(self.lr)),
'rho': self.rho,
'decay': float(K.get_value(self.decay)),
'epsilon': self.epsilon}
base_config = super(Adadelta, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -411,6 +414,7 @@ class Adam(Optimizer):
config = {'lr': float(K.get_value(self.lr)),
'beta_1': float(K.get_value(self.beta_1)),
'beta_2': float(K.get_value(self.beta_2)),
'decay': float(K.get_value(self.decay)),
'epsilon': self.epsilon}
base_config = super(Adam, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -450,7 +454,7 @@ class Adamax(Optimizer):
lr *= (1. / (1. + self.decay * self.iterations))
t = self.iterations + 1
lr_t = self.lr / (1. - K.pow(self.beta_1, t))
lr_t = lr / (1. - K.pow(self.beta_1, t))
shapes = [K.get_variable_shape(p) for p in params]
# zero init of 1st moment
@@ -480,6 +484,7 @@ class Adamax(Optimizer):
config = {'lr': float(K.get_value(self.lr)),
'beta_1': float(K.get_value(self.beta_1)),
'beta_2': float(K.get_value(self.beta_2)),
'decay': float(K.get_value(self.decay)),
'epsilon': self.epsilon}
base_config = super(Adamax, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+9 -6
Ver Arquivo
@@ -181,7 +181,7 @@ def load_img(path, grayscale=False, target_size=None):
def list_pictures(directory, ext='jpg|jpeg|bmp|png'):
return [os.path.join(directory, f) for f in os.listdir(directory)
return [os.path.join(directory, f) for f in sorted(os.listdir(directory))
if os.path.isfile(os.path.join(directory, f)) and re.match('([\w]+\.(?:' + ext + '))', f)]
@@ -390,6 +390,9 @@ class ImageDataGenerator(object):
how many augmentation passes to do over the data
seed: random seed.
'''
if seed is not None:
np.random.seed(seed)
X = np.copy(X)
if augment:
aX = np.zeros(tuple([rounds * X.shape[0]] + list(X.shape)[1:]))
@@ -408,7 +411,7 @@ class ImageDataGenerator(object):
if self.zca_whitening:
flatX = np.reshape(X, (X.shape[0], X.shape[1] * X.shape[2] * X.shape[3]))
sigma = np.dot(flatX.T, flatX) / flatX.shape[1]
sigma = np.dot(flatX.T, flatX) / flatX.shape[0]
U, S, V = linalg.svd(sigma)
self.principal_components = np.dot(np.dot(U, np.diag(1. / np.sqrt(S + 10e-7))), U.T)
@@ -431,11 +434,11 @@ class Iterator(object):
# ensure self.batch_index is 0
self.reset()
while 1:
if seed is not None:
np.random.seed(seed + self.total_batches_seen)
if self.batch_index == 0:
index_array = np.arange(N)
if shuffle:
if seed is not None:
np.random.seed(seed + self.total_batches_seen)
index_array = np.random.permutation(N)
current_index = (self.batch_index * batch_size) % N
@@ -560,7 +563,7 @@ class DirectoryIterator(Iterator):
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
for fname in sorted(os.listdir(subpath)):
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
@@ -576,7 +579,7 @@ class DirectoryIterator(Iterator):
i = 0
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
for fname in sorted(os.listdir(subpath)):
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
+23
Ver Arquivo
@@ -40,6 +40,20 @@ else:
def get_file(fname, origin, untar=False,
md5_hash=None, cache_subdir='datasets'):
'''Downloads a file from a URL if it not already in the cache.
Passing the MD5 hash will verify the file after download as well as if it is already present in the cache.
# Arguments
fname: name of the file
origin: original URL of the file
untar: boolean, whether the file should be decompressed
md5_hash: MD5 hash of the file for verification
cache_subdir: directory being used as the cache
# Returns
Path to the downloaded file
'''
datadir_base = os.path.expanduser(os.path.join('~', '.keras'))
if not os.access(datadir_base, os.W_OK):
datadir_base = os.path.join('/tmp', '.keras')
@@ -110,6 +124,15 @@ def get_file(fname, origin, untar=False,
def validate_file(fpath, md5_hash):
'''Validates a file against a MD5 hash
# Arguments
fpath: path to the file being validated
md5_hash: the MD5 hash being validated against
# Returns
Whether the file is valid
'''
hasher = hashlib.md5()
with open(fpath, 'rb') as f:
buf = f.read()
+1 -1
Ver Arquivo
@@ -66,7 +66,7 @@ def func_reconstruct_closure(values):
src += [" return lambda:(%s)" % ','.join(["_%d" % n for n in nums]), ""]
src = '\n'.join(src)
try:
exec(src)
exec(src, globals())
except:
raise SyntaxError(src)
return func(values).__closure__
+30 -3
Ver Arquivo
@@ -6,9 +6,33 @@ from collections import defaultdict
class HDF5Matrix():
'''Representation of HDF5 dataset which can be used instead of a
Numpy array.
# Example
```python
X_data = HDF5Matrix('input/file.hdf5', 'data')
model.predict(X_data)
```
Providing start and end allows use of a slice of the dataset.
Optionally, a normalizer function (or lambda) can be given. This will
be called on every slice of data retrieved.
# Arguments
datapath: string, path to a HDF5 file
dataset: string, name of the HDF5 dataset in the file specified
in datapath
start: int, start of desired slice of the specified dataset
end: int, end of desired slice of the specified dataset
normalizer: function to be called on data when retrieved
'''
refs = defaultdict(int)
def __init__(self, datapath, dataset, start, end, normalizer=None):
def __init__(self, datapath, dataset, start=0, end=None, normalizer=None):
import h5py
if datapath not in list(self.refs.keys()):
@@ -16,9 +40,12 @@ class HDF5Matrix():
self.refs[datapath] = f
else:
f = self.refs[datapath]
self.start = start
self.end = end
self.data = f[dataset]
self.start = start
if end is None:
self.end = self.data.shape[0]
else:
self.end = end
self.normalizer = normalizer
def __len__(self):
+23 -5
Ver Arquivo
@@ -37,8 +37,14 @@ def layer_from_config(config, custom_objects={}):
def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33, .55, .67, 1.]):
# line_length: total length of printed lines
# positions: relative or absolute positions of log elements in each line
'''Prints a summary of a layer
# Arguments
layers: list of layers to print summaries of
relevant_nodes: list of relevant nodes
line_length: total length of printed lines
positions: relative or absolute positions of log elements in each line
'''
if positions[-1] <= 1:
positions = [int(line_length * p) for p in positions]
# header names for the different log elements
@@ -87,16 +93,28 @@ def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33,
fields = ['', '', '', connections[i]]
print_row(fields, positions)
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()
print('Total params: %s' % total_params)
def count_total_params(layers, layer_set=None):
if layer_set is None:
layer_set = set()
total_params = 0
for layer in layers:
if layer in layer_set:
continue
layer_set.add(layer)
if type(layer) in (Model, Sequential):
total_params += count_total_params(layer.layers, layer_set)
else:
total_params += layer.count_params()
return total_params
print('Total params: %s' % count_total_params(layers))
print('_' * line_length)
+12 -3
Ver Arquivo
@@ -3,11 +3,18 @@ import numpy as np
import scipy as sp
from six.moves import range
from six.moves import zip
from .. import backend as K
def to_categorical(y, nb_classes=None):
'''Convert class vector (integers from 0 to nb_classes)
to binary class matrix, for use with categorical_crossentropy.
'''Convert class vector (integers from 0 to nb_classes) to binary class matrix, for use with categorical_crossentropy.
# Arguments
y: class vector to be converted into a matrix
nb_classes: total number of classes
# Returns
A binary matrix representation of the input.
'''
if not nb_classes:
nb_classes = np.max(y)+1
@@ -52,12 +59,14 @@ def categorical_probas_to_classes(p):
return np.argmax(p, axis=1)
def convert_kernel(kernel, dim_ordering='th'):
def convert_kernel(kernel, dim_ordering='default'):
'''Converts a kernel matrix (Numpy array)
from Theano format to TensorFlow format
(or reciprocally, since the transformation
is its own inverse).
'''
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
new_kernel = np.copy(kernel)
if kernel.ndim == 4:
# conv 2d
+2 -2
Ver Arquivo
@@ -1,7 +1,7 @@
import numpy as np
from numpy.testing import assert_allclose
import inspect
import functools
import six
from ..engine import Model, Input
from ..models import Sequential, model_from_json
@@ -112,7 +112,7 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
def keras_test(func):
'''Clean up after tensorflow tests.
'''
@functools.wraps(func)
@six.wraps(func)
def wrapper(*args, **kwargs):
output = func(*args, **kwargs)
if K._BACKEND == 'tensorflow':
+26 -10
Ver Arquivo
@@ -1,3 +1,7 @@
import os
from ..layers.wrappers import Wrapper
try:
# pydot-ng is a fork of pydot that is better maintained
import pydot_ng as pydot
@@ -21,17 +25,25 @@ def model_to_dot(model, show_shapes=False, show_layer_names=True):
model = model.model
layers = model.layers
# first, populate the nodes of the graph
# Create graph nodes.
for layer in layers:
layer_id = str(id(layer))
if show_layer_names:
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
else:
label = layer.__class__.__name__
# Append a wrapped layer's label to node's label, if it exists.
layer_name = layer.name
class_name = layer.__class__.__name__
if isinstance(layer, Wrapper):
layer_name = '{}({})'.format(layer_name, layer.layer.name)
class_name = '{}({})'.format(class_name, layer.layer.__class__.__name__)
# Create node's label.
if show_layer_names:
label = '{}: {}'.format(layer_name, class_name)
else:
label = class_name
# Rebuild the label as a table including input/output shapes.
if show_shapes:
# Build the label that will actually contain a table with the
# input/output
try:
outputlabels = str(layer.output_shape)
except:
@@ -48,13 +60,12 @@ def model_to_dot(model, show_shapes=False, show_layer_names=True):
node = pydot.Node(layer_id, label=label)
dot.add_node(node)
# second, add the edges
# Connect nodes with 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))
@@ -64,4 +75,9 @@ def model_to_dot(model, show_shapes=False, show_layer_names=True):
def plot(model, to_file='model.png', show_shapes=False, show_layer_names=True):
dot = model_to_dot(model, show_shapes, show_layer_names)
dot.write_png(to_file)
_, format = os.path.splitext(to_file)
if not format:
format = 'png'
else:
format = format[1:]
dot.write(to_file, format=format)
+2 -2
Ver Arquivo
@@ -66,7 +66,7 @@ class BaseWrapper(object):
Sequential.predict_classes, Sequential.evaluate]
if self.build_fn is None:
legal_params_fns.append(self.__call__)
elif not isinstance(self.build_fn, types.FunctionType):
elif not isinstance(self.build_fn, types.FunctionType) and not isinstance(self.build_fn, types.MethodType):
legal_params_fns.append(self.build_fn.__call__)
else:
legal_params_fns.append(self.build_fn)
@@ -130,7 +130,7 @@ class BaseWrapper(object):
if self.build_fn is None:
self.model = self.__call__(**self.filter_sk_params(self.__call__))
elif not isinstance(self.build_fn, types.FunctionType):
elif not isinstance(self.build_fn, types.FunctionType) and not isinstance(self.build_fn, types.MethodType):
self.model = self.build_fn(
**self.filter_sk_params(self.build_fn.__call__))
else:
+2 -2
Ver Arquivo
@@ -3,12 +3,12 @@ from setuptools import find_packages
setup(name='Keras',
version='1.1.0',
version='1.1.1',
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/1.1.0',
download_url='https://github.com/fchollet/keras/tarball/1.1.1',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
+3 -2
Ver Arquivo
@@ -492,6 +492,7 @@ class TestBackend(object):
check_single_tensor_operation('relu', (4, 2), alpha=0.1, max_value=0.5)
check_single_tensor_operation('softmax', (4, 10))
check_single_tensor_operation('softplus', (4, 10))
check_single_tensor_operation('elu', (4, 10), alpha=0.5)
check_single_tensor_operation('sigmoid', (4, 2))
check_single_tensor_operation('hard_sigmoid', (4, 2))
@@ -528,7 +529,7 @@ class TestBackend(object):
kernel_val = np.random.random(kernel_shape) - 0.5
kernel_th = KTH.variable(convert_kernel(kernel_val))
kernel_th = KTH.variable(convert_kernel(kernel_val, dim_ordering='th'))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv2d(xth, kernel_th, dim_ordering='th'))
@@ -572,7 +573,7 @@ class TestBackend(object):
kernel_val = np.random.random(kernel_shape) - 0.5
kernel_th = KTH.variable(convert_kernel(kernel_val))
kernel_th = KTH.variable(convert_kernel(kernel_val, dim_ordering='th'))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv3d(xth, kernel_th, dim_ordering='th'))
+13 -4
Ver Arquivo
@@ -5,7 +5,7 @@ from numpy.testing import assert_allclose
from keras.layers import Dense, Dropout
from keras.engine.topology import merge, Input
from keras.engine.training import Model
from keras.models import Sequential, Graph
from keras.models import Sequential
from keras import backend as K
from keras.utils.test_utils import keras_test
@@ -148,15 +148,24 @@ def test_model_methods():
# test with a custom metric function
mse = lambda y_true, y_pred: K.mean(K.pow(y_true - y_pred, 2))
model.compile(optimizer, loss, metrics=[mse],
def mse_powers(y_true, y_pred):
m = mse(y_true, y_pred)
return {
'mse_squared': K.pow(m, 2),
'mse_cubed': K.pow(m, 3)
}
model.compile(optimizer, loss, metrics=[mse, mse_powers],
sample_weight_mode=None)
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 5
out_len = 1 + 2 * 4 # total loss, per layer: loss + 3 metrics
assert len(out) == out_len
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 5
assert len(out) == out_len
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
+109 -14
Ver Arquivo
@@ -269,6 +269,22 @@ def test_globalpooling_2d():
input_shape=(3, 5, 6, 4))
@keras_test
def test_globalpooling_3d():
layer_test(pooling.GlobalMaxPooling3D,
kwargs={'dim_ordering': 'th'},
input_shape=(3, 4, 3, 4, 3))
layer_test(pooling.GlobalMaxPooling3D,
kwargs={'dim_ordering': 'tf'},
input_shape=(3, 4, 3, 4, 3))
layer_test(pooling.GlobalAveragePooling3D,
kwargs={'dim_ordering': 'th'},
input_shape=(3, 4, 3, 4, 3))
layer_test(pooling.GlobalAveragePooling3D,
kwargs={'dim_ordering': 'tf'},
input_shape=(3, 4, 3, 4, 3))
@keras_test
def test_maxpooling_2d():
pool_size = (3, 3)
@@ -283,12 +299,10 @@ def test_maxpooling_2d():
@keras_test
def test_averagepooling_2d():
pool_size = (3, 3)
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_test(convolutional.MaxPooling2D,
layer_test(convolutional.AveragePooling2D,
kwargs={'strides': strides,
'border_mode': border_mode,
'pool_size': pool_size},
@@ -363,38 +377,119 @@ def test_averagepooling_3d():
input_shape=(3, 4, 11, 12, 10))
@keras_test
def test_zero_padding_1d():
nb_samples = 2
input_dim = 2
nb_steps = 5
input = np.ones((nb_samples, nb_steps, input_dim))
# basic test
layer_test(convolutional.ZeroPadding1D,
kwargs={'padding': 2},
input_shape=input.shape)
layer_test(convolutional.ZeroPadding1D,
kwargs={'padding': (1, 2)},
input_shape=input.shape)
layer_test(convolutional.ZeroPadding1D,
kwargs={'padding': {'left_pad': 1, 'right_pad': 2}},
input_shape=input.shape)
# correctness test
layer = convolutional.ZeroPadding1D(padding=2)
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[:, 2:-2, :], 1.)
layer = convolutional.ZeroPadding1D(padding=(1, 2))
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
for left_offset in [0]:
assert_allclose(out[:, left_offset, :], 0.)
for right_offset in [-1, -2]:
assert_allclose(out[:, right_offset, :], 0.)
assert_allclose(out[:, 1:-2, :], 1.)
layer.get_config()
@keras_test
def test_zero_padding_2d():
nb_samples = 2
stack_size = 2
input_nb_row = 11
input_nb_col = 12
input_nb_row = 4
input_nb_col = 5
dim_ordering = K.image_dim_ordering()
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
input = np.ones((nb_samples, input_nb_row, input_nb_col, stack_size))
if dim_ordering == 'tf':
input = np.ones((nb_samples, input_nb_row, input_nb_col, stack_size))
elif dim_ordering == 'th':
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)
layer_test(convolutional.ZeroPadding2D,
kwargs={'padding': (1, 2, 3, 4)},
input_shape=input.shape)
layer_test(convolutional.ZeroPadding2D,
kwargs={'padding': {'top_pad': 1, 'bottom_pad': 2, 'left_pad': 3, 'right_pad': 4}},
input_shape=input.shape)
# correctness test
layer = convolutional.ZeroPadding2D(padding=(2, 2))
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.)
if dim_ordering == 'tf':
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.)
elif dim_ordering == 'th':
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 = convolutional.ZeroPadding2D(padding=(1, 2, 3, 4))
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
if dim_ordering == 'tf':
for top_offset in [0]:
assert_allclose(out[:, top_offset, :, :], 0.)
for bottom_offset in [-1, -2]:
assert_allclose(out[:, bottom_offset, :, :], 0.)
for left_offset in [0, 1, 2]:
assert_allclose(out[:, :, left_offset, :], 0.)
for right_offset in [-1, -2, -3, -4]:
assert_allclose(out[:, :, right_offset, :], 0.)
assert_allclose(out[:, 1:-2, 3:-4, :], 1.)
elif dim_ordering == 'th':
for top_offset in [0]:
assert_allclose(out[:, :, top_offset, :], 0.)
for bottom_offset in [-1, -2]:
assert_allclose(out[:, :, bottom_offset, :], 0.)
for left_offset in [0, 1, 2]:
assert_allclose(out[:, :, :, left_offset], 0.)
for right_offset in [-1, -2, -3, -4]:
assert_allclose(out[:, :, :, right_offset], 0.)
assert_allclose(out[:, :, 1:-2, 3:-4], 1.)
layer.get_config()
def test_zero_padding_3d():
nb_samples = 2
stack_size = 2
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
input_len_dim1 = 4
input_len_dim2 = 5
input_len_dim3 = 3
input = np.ones((nb_samples,
input_len_dim1, input_len_dim2, input_len_dim3,
@@ -513,7 +608,7 @@ def test_upsampling_3d():
@keras_test
def test_cropping_1d():
nb_samples = 2
time_length = 10
time_length = 4
input_len_dim1 = 2
input = np.random.rand(nb_samples, time_length, input_len_dim1)
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ from numpy.testing import assert_allclose
from keras.layers.core import Dense, Activation
from keras.utils.test_utils import layer_test, keras_test
from keras.layers import normalization
from keras.models import Sequential, Graph
from keras.models import Sequential
from keras import backend as K
input_1 = np.arange(10)
+26 -22
Ver Arquivo
@@ -15,18 +15,29 @@ nb_samples, timesteps, embedding_dim, output_dim = 2, 5, 4, 3
embedding_num = 12
def _runner(layer_class):
def rnn_test(f):
"""
All the recurrent layers share the same interface,
so we can run through them with a single function.
"""
# check return_sequences
f = keras_test(f)
return pytest.mark.parametrize("layer_class", [
recurrent.SimpleRNN,
recurrent.GRU,
recurrent.LSTM
])(f)
@rnn_test
def test_return_sequences(layer_class):
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'return_sequences': True},
input_shape=(nb_samples, timesteps, embedding_dim))
# check dynamic behavior
@rnn_test
def test_dynamic_behavior(layer_class):
layer = layer_class(output_dim, input_dim=embedding_dim)
model = Sequential()
model.add(layer)
@@ -35,21 +46,27 @@ def _runner(layer_class):
y = np.random.random((nb_samples, output_dim))
model.train_on_batch(x, y)
# check dropout
@rnn_test
def test_dropout(layer_class):
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'dropout_U': 0.1,
'dropout_W': 0.1},
input_shape=(nb_samples, timesteps, embedding_dim))
# check implementation modes
@rnn_test
def test_implementation_mode(layer_class):
for mode in ['cpu', 'mem', 'gpu']:
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'consume_less': mode},
input_shape=(nb_samples, timesteps, embedding_dim))
# check statefulness
@rnn_test
def test_statefulness(layer_class):
model = Sequential()
model.add(embeddings.Embedding(embedding_num, embedding_dim,
mask_zero=True,
@@ -103,7 +120,9 @@ def _runner(layer_class):
assert_allclose(out7, out6, atol=1e-5)
# check regularizers
@rnn_test
def test_regularizer(layer_class):
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),
@@ -115,21 +134,6 @@ def _runner(layer_class):
K.eval(layer.output)
@keras_test
def test_SimpleRNN():
_runner(recurrent.SimpleRNN)
@keras_test
def test_GRU():
_runner(recurrent.GRU)
@keras_test
def test_LSTM():
_runner(recurrent.LSTM)
@keras_test
def test_masking_layer():
''' This test based on a previously failing issue here:
+17
Ver Arquivo
@@ -131,6 +131,23 @@ def test_relu():
assert_allclose(result, test_values, rtol=1e-05)
def test_elu():
x = K.placeholder(ndim=2)
f = K.function([x], [activations.elu(x, 0.5)])
test_values = get_standard_values()
result = f([test_values])[0]
# because no negatives in test values
assert_allclose(result, test_values, rtol=1e-05)
negative_values = np.array([[-1, -2]], dtype=K.floatx())
result = f([negative_values])[0]
true_result = (np.exp(negative_values) - 1) / 2
assert_allclose(result, true_result)
def test_tanh():
test_values = get_standard_values()
+109 -2
Ver Arquivo
@@ -1,7 +1,11 @@
import pytest
import os
import sys
import multiprocessing
import numpy as np
import pytest
from keras import optimizers
np.random.seed(1337)
from keras import callbacks
@@ -147,6 +151,41 @@ def test_LearningRateScheduler():
assert (float(K.get_value(model.optimizer.lr)) - 0.2) < K.epsilon()
def test_ReduceLROnPlateau():
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
nb_test=test_samples,
input_shape=(input_dim,),
classification=True,
nb_class=nb_class)
y_test = np_utils.to_categorical(y_test)
y_train = np_utils.to_categorical(y_train)
def make_model():
np.random.seed(1337)
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=optimizers.SGD(lr=0.1),
metrics=['accuracy'])
return model
model = make_model()
# This should reduce the LR after the first epoch (due to high epsilon).
cbks = [callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, epsilon=10, patience=1, cooldown=5)]
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=5, verbose=2)
assert np.allclose(float(K.get_value(model.optimizer.lr)), 0.01, atol=K.epsilon())
model = make_model()
cbks = [callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, epsilon=0, patience=1, cooldown=5)]
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=5, verbose=2)
assert np.allclose(float(K.get_value(model.optimizer.lr)), 0.1, atol=K.epsilon())
@pytest.mark.skipif((K._BACKEND != 'tensorflow'),
reason="Requires tensorflow backend")
def test_TensorBoard():
@@ -234,7 +273,7 @@ def test_TensorBoard():
session = tf.Session('')
KTF.set_session(session)
model = Graph()
model.add_input(name='X_vars', input_shape=(input_dim, ))
model.add_input(name='X_vars', input_shape=(input_dim,))
model.add_node(Dense(nb_hidden, activation="sigmoid"),
name='Dense1', input='X_vars')
@@ -272,5 +311,73 @@ def test_TensorBoard():
KTF.set_session(old_session)
def test_LambdaCallback():
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
nb_test=test_samples,
input_shape=(input_dim,),
classification=True,
nb_class=nb_class)
y_test = np_utils.to_categorical(y_test)
y_train = np_utils.to_categorical(y_train)
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',
metrics=['accuracy'])
# Start an arbitrary process that should run during model training and be terminated after training has completed.
def f():
while True:
pass
p = multiprocessing.Process(target=f)
p.start()
cleanup_callback = callbacks.LambdaCallback(on_train_end=lambda logs: p.terminate())
cbks = [cleanup_callback]
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=5)
p.join()
assert not p.is_alive()
@pytest.mark.skipif((K._BACKEND != 'tensorflow'),
reason="Requires tensorflow backend")
def test_TensorBoard_with_ReduceLROnPlateau():
import shutil
filepath = './logs'
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
nb_test=test_samples,
input_shape=(input_dim,),
classification=True,
nb_class=nb_class)
y_test = np_utils.to_categorical(y_test)
y_train = np_utils.to_categorical(y_train)
model = Sequential()
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
model.add(Dense(nb_class, activation='softmax'))
model.compile(loss='binary_crossentropy',
optimizer='sgd',
metrics=['accuracy'])
cbks = [
callbacks.ReduceLROnPlateau(
monitor='val_loss',
factor=0.5,
patience=4,
verbose=1),
callbacks.TensorBoard(
log_dir=filepath)]
model.fit(X_train, y_train, batch_size=batch_size,
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=2)
assert os.path.exists(filepath)
shutil.rmtree(filepath)
if __name__ == '__main__':
pytest.main([__file__])
+38
Ver Arquivo
@@ -34,6 +34,30 @@ def test_metrics():
assert K.eval(output).shape == ()
def test_matthews_correlation():
y_true = K.variable(np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0]))
y_pred = K.variable(np.array([1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]))
# Calculated using sklearn.metrics.matthews_corrcoef
expected = -0.14907119849998601
actual = K.eval(metrics.matthews_correlation(y_true, y_pred))
epsilon = 1e-05
assert expected - epsilon <= actual <= expected + epsilon
def test_fbeta_score():
y_true = K.variable(np.array([0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0]))
y_pred = K.variable(np.array([1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0]))
# Calculated using sklearn.metrics.f1_score
expected = 0.33333333333333331
actual = K.eval(metrics.fbeta_score(y_true, y_pred))
epsilon = 1e-05
assert expected - epsilon <= actual <= expected + epsilon
def test_sparse_metrics():
for metric in all_sparse_metrics:
y_a = K.variable(np.random.randint(0, 7, (6,)), dtype=K.floatx())
@@ -41,5 +65,19 @@ def test_sparse_metrics():
assert K.eval(metric(y_a, y_b)).shape == ()
def test_top_k_categorical_accuracy():
y_pred = K.variable(np.array([[0.3, 0.2, 0.1], [0.1, 0.2, 0.7]]))
y_true = K.variable(np.array([[0, 1, 0], [1, 0, 0]]))
success_result = K.eval(metrics.top_k_categorical_accuracy(y_true, y_pred,
k=3))
assert success_result == 1
partial_result = K.eval(metrics.top_k_categorical_accuracy(y_true, y_pred,
k=2))
assert partial_result == 0.5
failure_result = K.eval(metrics.top_k_categorical_accuracy(y_true, y_pred,
k=1))
assert failure_result == 0
if __name__ == "__main__":
pytest.main([__file__])
+1 -1
Ver Arquivo
@@ -6,7 +6,7 @@ import numpy as np
np.random.seed(1337)
from keras import backend as K
from keras.models import Graph, Sequential
from keras.models import 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, keras_test
+1 -1
Ver Arquivo
@@ -5,7 +5,7 @@ import numpy as np
np.random.seed(1337)
from keras.utils.test_utils import get_test_data
from keras.models import Sequential, Graph
from keras.models import Sequential
from keras.layers import Dense, Activation, RepeatVector, TimeDistributedDense, GRU
from keras.utils import np_utils
from keras.utils.test_utils import keras_test