Comparar commits

..

216 Commits

Autor SHA1 Mensagem Data
Francois Chollet b2e3780e8c Prepare PyPI release 2016-09-19 13:18:22 -07:00
Francois Chollet 0b04ac3117 Fix TF RNN dynamic behavior 2016-09-19 11:01:33 -07:00
Francois Chollet 90d0eb9b88 Regularizers style fixes 2016-09-18 15:27:45 -07:00
fchollet f2aa89f443 Freeze list of trainable weights at compile time 2016-09-18 10:41:37 -07:00
kuza55 2a319c7255 Add exception when trying to reuse regularizers (#3803)
My reading of regularizers is that they cannot be reused, but it doesn't actually fail in any way and seems like it results in only regularizing the last layer. Having an exception prevent this would probably improve the ergonomics.
2016-09-17 20:22:26 -07:00
Francois Chollet 4fb3f1b3f3 Make TF dynamic RNN work without states. 2016-09-16 17:15:18 -07:00
Furiously Curious 072d33599b Added Gitter channel badge (#3744)
* Added Gitter channel badge

Assigned @fchollet as channel admin on Gitter

* Link fix
2016-09-15 18:10:06 -07:00
Seonghyeon Nam 56f3c85b87 Fix ValueError(ndim of gamma and beta) of batch normalization when using Theano (#3740)
* Fix ndim mismatch error when using theano

* Change keras backend call
2016-09-15 18:09:02 -07:00
Francois Chollet 8b42fff90e Fix flaky test 2016-09-14 15:15:00 -07:00
Francois Chollet 1dc5d43d32 Remove deprecated resnet50 example 2016-09-14 15:03:26 -07:00
Francois Chollet ee2d08ff79 Fix activity regularization for wrapper layers 2016-09-14 15:02:05 -07:00
Francois Chollet 305b3bed74 Finalize streamlining of conv1d. 2016-09-14 14:39:47 -07:00
Francois Chollet 9f6acd960c Simplify Conv1D ops. 2016-09-14 14:18:15 -07:00
Flynn, Michael D 672890b1c8 Add AtrousConvolution1D to convolutional layers (#3763)
* Add `AtrousConvolution1D` to convolutional layers

* Add test for `AtrousConvolution1D` layer

* Add AtrousConvolution1D to docs
2016-09-14 11:40:04 -07:00
Francois Chollet c58bcc2c02 Fix deconv test 2016-09-13 16:56:39 -07:00
Francois Chollet 82318263a1 Set default backend to TF 2016-09-13 16:24:43 -07:00
Francois Chollet d90e1db50b Revert default backend to TH 2016-09-13 15:37:38 -07:00
Francois Chollet 8af0264a77 Set TensorFlow as default backend for new installs 2016-09-13 15:19:13 -07:00
Junwei Pan 8193287e08 Update docoment for callbacks.py: add the specification of auto mode (#3758) 2016-09-13 08:52:12 -07:00
fchollet 13bd33e73f Merge branch 'master' of ssh://github.com/fchollet/keras 2016-09-10 22:54:51 -07:00
fchollet b2e8d5ab7c Add support for LR decay in all optimizers 2016-09-10 12:34:05 -07:00
Ardalan a375cb322f fastText: adding n-gram embeddings for higher test_set accuracy (#3733)
* adding bi-gram embeddings for better test accuracy

* - add arbitrary n-gram range
- fix typos

* - fixing white spaces

* - add comment
2016-09-10 10:35:15 -07:00
dolaameng d9c4d8a76a update examples/neural_doodle.py based on issues #3731 (#3741) 2016-09-10 10:24:39 -07:00
kuza55 79edae58d5 Initial Sparse Matrix Support (#3695)
* Minimal SparseTensor support for TensorFlow

* Basic Theano support for Sparse dot product

* Sparse Input for Both + Sparse Concat for TF

* Fixed issue with _keras_shape for sparse Inputs

* pep8

* Cleanup + Theano concat (untested)

* Bug fix & pep8

* Fix Theano concat

* Bugfix & simplification

* Next step: Unit tests

* Basic unit test for sparse dot; TF works, TH fails

* Fix KTH is_sparse

* pep8

* more tests, sparse KTH.eval, pep8

* sparse model test

* address code review comments

* make sparse boolean in K.placeholder

* skip sparse tests when TH.sparse import fails

* pep8

* pep8

* fixed flakey test, auto-dense in KTH.eval

* fixed some more len/shape issues for fit_generator

* fixed some more len/shape issues for prediction

* Added better exceptions when theano.sparse fails to import

* betterer

* pep8
2016-09-09 16:26:37 -07:00
iampat 6675776640 Fix a small typo in help files (#3728)
impoprt --> import
2016-09-08 17:35:38 -07:00
dolaameng 40685c3b2a add examples/neural_doodle.py (#3724) 2016-09-08 10:15:57 -07:00
Francois Chollet 25874ceab2 Update TD wrapper 2016-09-07 19:32:26 -07:00
Tim Shi 4b2093ef67 allow output size different from state size (#3709) 2016-09-07 15:52:06 -07:00
kuza55 9bc2e60fd5 TensorBoard callback improvements (#3656)
* TensorBoard callback improvements

* Removed name improvement in TensorBoard callback

* Fix variables broken by removing name fixups

* Update callbacks.py
2016-09-07 12:59:08 -07:00
antonmbk 685ce7573d Added stacked what where autoencoder. (#3616)
* Added stacked what where autoencoder.

SWWAE uses residual blocks. Trains fast. Creates very good reconstructions.

* Added newline at end for PEP8

* Went through PEP8 errors and corrected all (except for the imports which following the numpy seed, but this should be ok).  Also, for the pool_size of 2, we halved the number of features maps and the number of epochs, and it still trains a net that can very nicely reconstruct the input.

* Added spaces arround - and + when they are used as binary operators (more PEP8).

* In decoder, the index of the features and pool size and wheres are all equal to nlayers-1-i, so set ind variable to this value and passed it to them.

* With ind variable in decoder, don't need two lines for the upsampling layer.

* Added title to plot, got rid of ticks on plot.

* PEP8 for * binary operator. Corrected some grammar issues in the docstring.
2016-09-07 11:05:41 -07:00
dolaameng f5ad1c5753 fix bug in neural_style_transfer example for image_dim_ordering=tf (#3715)
* fix bug in neural_style_transfer example for image_dim_ordering=tf

* fix PEP8 mixed space and tab
2016-09-07 10:57:23 -07:00
Francois Chollet cc92025fdc Make examples agnostic to image_dim_ordering 2016-09-06 15:53:56 -07:00
Fariz Rahman f05cd95fad Dot/cos merge : bug fix (#3708) 2016-09-06 15:04:26 -07:00
kuza55 4325843ef0 Add Matthews correlation coefficient to metrics (#3689)
* Add Matthews correlation coefficient to metrics

I needed this for a Kaggle competition and it seemed useful in general so I thought I'd contribute it back.

* Enabled test for matthews metric

* Remove unnecessary cast garbage

* Addresses code review comments

* Renamed to matthews_corrcoef to be consistent with sklearn

* Update test_metrics.py

* pep8

* rename to mathews_correlation

* Update metrics.py

* Fixed typo
2016-09-06 13:42:56 -07:00
Arel Cordero 607635d2ce Optionally load weights by name (#3488)
* Adding feature to load_weights by name

Squashed commit of the following:

commit fd47e763855c34ed78d26ee441d83e0e63f08119
Author: Arel Cordero <arel@ditto.us.com>
Date:   Thu Aug 18 16:02:14 2016 +0000

    typo

commit d0b06c03080131c55ab4777064a196ff339ad7df
Author: Arel Cordero <arel@ditto.us.com>
Date:   Thu Aug 18 15:52:35 2016 +0000

    update documentation for "load_weights"

commit 844cfc2e8c9c6f267799a22ed54ac4d75807c5ab
Author: Arel Cordero <arel@ditto.us.com>
Date:   Thu Aug 18 02:42:10 2016 +0000

    batch updating weights

commit f361a70da4b40b961f1af9c8f1c3cd26273d0cad
Author: Arel Cordero <arel@ditto.us.com>
Date:   Thu Aug 18 02:29:17 2016 +0000

    removing pudb line

commit 738de4c371503626b4c9dbae6428fb279b368a76
Author: Arel Cordero <arel@ditto.us.com>
Date:   Wed Aug 17 19:56:51 2016 +0000

    adding unit tests for loading weights by name

commit cb0971b3cfe62452ab445e4034098cab2be3031b
Author: Arel Cordero <arel@ditto.us.com>
Date:   Tue Aug 16 23:45:32 2016 +0000

    cleaning up code based on comments

commit ef08fd2c9f5d3c65359cbdf5b090e08733a518de
Author: Arel Cordero <arel@ditto.us.com>
Date:   Tue Aug 16 04:50:46 2016 +0000

    debugging

commit 0d74f0e997960886b1044c26001de6cd6ad90bb9
Author: Arel Cordero <arel@ditto.us.com>
Date:   Tue Aug 16 04:15:43 2016 +0000

    optionally load model by name

* changed random file names to use tempfile module

* clean up documentation strings

* clarifying documentation
2016-09-06 11:42:31 -07:00
Abishek Bhat b8fddc862e Add missing Softmax activation memnn. (#3706)
The implementation of bAbi [End to End Memory
Network](https://arxiv.org/pdf/1503.08895v5.pdf) in the example
seems to be missing the Softmax Layer.

Quoting the paper.

> The query q is also embedded (again, in the simplest case via another embedding matrix
B with the same dimensions as A) to obtain an internal state u. In the embedding space, we compute
the match between u and each memory m<sub>i</sub> by taking the inner product followed by a softmax.

Also, the question encoder
[here](https://github.com/fchollet/keras/blob/0df0177437ce672d654db6d7edfdc653aaf67533/examples/babi_memnn.py#L186) seems to sum over the probabilities and the question vector as suggestted in the original paper.

> Output memory representation: Each x<sub>i</sub> has a corresponding output vector c<sub>i</sub> (given in the
simplest case by another embedding matrix C). The response vector from the memory o is then a
sum over the transformed inputs c<sub>i</sub> , weighted by the probability vector from the input.

I tried running the model(with and without the intermediate softmax)
against _Single Supporting Fact_ en-10k dataset and found that the
network the intermediate softmax trained a lot faster(95% at 100epoch) than the former(67% at 100epoch).

Network without the Softmax activation in the Input Memory Representation at epoch=100
======================================================================================
```
Iteration 10
Train on 10000 samples, validate on 1000 samples
Epoch 1/10
10000/10000 [==============================] - 8s - loss: 0.0549 - acc: 0.9819 - val_loss: 1.8088 - val_acc: 0.6470
Epoch 2/10
10000/10000 [==============================] - 6s - loss: 0.0612 - acc: 0.9802 - val_loss: 1.7839 - val_acc: 0.6650
Epoch 3/10
10000/10000 [==============================] - 6s - loss: 0.0542 - acc: 0.9812 - val_loss: 1.7595 - val_acc: 0.6750
Epoch 4/10
10000/10000 [==============================] - 6s - loss: 0.0538 - acc: 0.9826 - val_loss: 1.8198 - val_acc: 0.6670
Epoch 5/10
10000/10000 [==============================] - 6s - loss: 0.0590 - acc: 0.9790 - val_loss: 1.7891 - val_acc: 0.6650
Epoch 6/10
10000/10000 [==============================] - 6s - loss: 0.0548 - acc: 0.9803 - val_loss: 1.7682 - val_acc: 0.6790
Epoch 7/10
10000/10000 [==============================] - 6s - loss: 0.0455 - acc: 0.9841 - val_loss: 1.8394 - val_acc: 0.6730
Epoch 8/10
10000/10000 [==============================] - 6s - loss: 0.0559 - acc: 0.9797 - val_loss: 1.7764 - val_acc: 0.6650
Epoch 9/10
10000/10000 [==============================] - 6s - loss: 0.0488 - acc: 0.9835 - val_loss: 1.7711 - val_acc: 0.6620
Epoch 10/10
10000/10000 [==============================] - 6s - loss: 0.0502 - acc: 0.9834 - val_loss: 1.8225 - val_acc: 0.6700
```

Network with Softmax Activation in the Input Memory Representation at epoch=100
===============================================================================

```
Iteration 10
Train on 10000 samples, validate on 1000 samples
Epoch 1/10
10000/10000 [==============================] - 6s - loss: 0.0084 - acc: 0.9972 - val_loss: 0.2426 - val_acc: 0.9520
Epoch 2/10
10000/10000 [==============================] - 7s - loss: 0.0152 - acc: 0.9946 - val_loss: 0.2063 - val_acc: 0.9560
Epoch 3/10
10000/10000 [==============================] - 6s - loss: 0.0104 - acc: 0.9969 - val_loss: 0.2010 - val_acc: 0.9540
Epoch 4/10
10000/10000 [==============================] - 6s - loss: 0.0163 - acc: 0.9959 - val_loss: 0.2023 - val_acc: 0.9580
Epoch 5/10
10000/10000 [==============================] - 6s - loss: 0.0136 - acc: 0.9962 - val_loss: 0.2007 - val_acc: 0.9560
Epoch 6/10
10000/10000 [==============================] - 6s - loss: 0.0152 - acc: 0.9953 - val_loss: 0.1989 - val_acc: 0.9570
Epoch 7/10
10000/10000 [==============================] - 7s - loss: 0.0085 - acc: 0.9969 - val_loss: 0.2113 - val_acc: 0.9490
Epoch 8/10
10000/10000 [==============================] - 7s - loss: 0.0116 - acc: 0.9972 - val_loss: 0.2346 - val_acc: 0.9500
Epoch 9/10
10000/10000 [==============================] - 7s - loss: 0.0106 - acc: 0.9970 - val_loss: 0.2052 - val_acc: 0.9550
Epoch 10/10
10000/10000 [==============================] - 7s - loss: 0.0132 - acc: 0.9963 - val_loss: 0.2114 - val_acc: 0.9500
```
2016-09-06 11:33:11 -07:00
dolaameng 0df0177437 make image parameters more consistent (#3672)
* change of variable names in examples/neural_transfer_style for consistency

* add docstring to keras.preprocessing.image.load_img()
2016-09-06 10:29:26 -07:00
Pedro S f90cbcd1e3 Added regularization option to BatchNormalization layer (#3671)
* Added regularization option to BatchNormalization layer

* Update normalization.py

* Added regularization to BN test

* Fixed identation

* Removed trailing whitespace and refixed identation
2016-09-02 08:15:51 -07:00
Fariz Rahman 870d7f7f93 Lambda layer : Allow multiple inputs (#3668) 2016-09-01 13:48:21 -07:00
Roberto de Moura Estevão Filho 799bec66a2 CTC import compatibility with tensorflow 0.10 (#3650)
* CTC import compatibility with tensorflow 0.10
Try except clause to import ctc_loss in new path on tensorflow 0.10.

* Fixed ctc_decode and added tests for tensorflow.
ctc_decode when using beam search decoder has been fixed to conform with
tensorflow API. Function documentation has been updated to reflect the
changes. Two tests, for greedy and beam search decoding, have also been
added to test_backends.py.

* Fix pep8 styling.

* Fixed styling on long lines on ctc_decode tests.
2016-09-01 11:33:11 -07:00
Matt 2321fbbc1d Fix Batch Norm compatibility with 3D inputs (#3666)
* Fix Batch Norm compatibility with 3D inputs

the theano backend now uses dnn_batch_normalization which only supports
up to 4-dimensional input. This breaks any 5-d layers such as 3D
convolutions.

* using intermediate variable
2016-09-01 10:22:23 -07:00
gw0 48ae7217e4 Fix TensorFlow RNN backwards support. (#3662) 2016-09-01 05:56:42 -07:00
Francois Chollet 6f54b233f1 Fix Theano input shape inference in InputLayer 2016-08-31 21:49:43 -07:00
ηzw 1bf1055395 Update docs for SpatialDropouts (#3652) 2016-08-31 13:55:21 -07:00
gw0 6417d90d5c Fix #2814 lambda function serialization and deserialization (#3639)
* Remove old-style function attributes.

* Fix lambda function serialization and deserialization.
2016-08-31 10:05:05 -07:00
fchollet c939cebf0d Theano rnn fix when input_dim = 1 2016-08-30 18:35:22 -07:00
kuza55 7ae36d132a Write TensorBoard Histograms with Tensor names (#3635)
Resolves the acute symptoms in https://github.com/fchollet/keras/issues/3357

Doesn't address the question of having a better __repr__ since that is a much wider change.
2016-08-30 16:55:38 -07:00
Francois Chollet c478409dad Fix weight constraint sharing issue 2016-08-30 12:54:42 -07:00
Frédéric Bastien 109441a708 Small speed up by preventing transfer to CPU or copy on the CPU just to get the shape. (#3631) 2016-08-30 12:41:47 -07:00
Fariz Rahman b267e8293d Update sequential-model-guide.md (#3630) 2016-08-30 09:43:41 -07:00
Francois Chollet 3a4c683d5c Update download path for babi dataset 2016-08-29 13:03:36 -07:00
Sean Löfgren d5649da5f8 update pytest config for pep8 tests (#3617) (#3619) 2016-08-29 11:20:39 -07:00
Fariz Rahman 9c28d21b4f Fix lambda layer docstring (#3604) 2016-08-29 10:44:19 -07:00
kuza55 9e58b8237b Enable colocate_gradients_with_ops=True (#3620)
By default TensorFlow allocates all gradient matricies on gpu:0, which makes it pretty much impossible to do parallelize a large model.

colocate_gradients_with_ops puts these matricies next to the operations, allowing you to split your model across multiple GPUs. I ran into this issue myself and this fixed it for me.

I think it's also meant to set gradient computations to be done on the device where the operations are stored, but my belief about that comes from https://github.com/tensorflow/tensorflow/issues/2441

I'm not sure why this isn't the default in TF, so I'm not sure if this should be behind a flag or something, but having to make my own patches to keras to do multi-GPU training seems like the wrong answer.
2016-08-29 10:44:01 -07:00
Francois Chollet b184c76205 Update docs 2016-08-28 14:29:40 -07:00
fchollet 065fb2a74c Add global pooling layers 2016-08-28 14:22:15 -07:00
Francois Chollet a0a0d42630 Fix example in doc 2016-08-28 13:20:51 -07:00
Francois Chollet 756153899a Merge branch 'master' of https://github.com/fchollet/keras 2016-08-28 13:10:47 -07:00
Francois Chollet e02554412f Fix example in doc 2016-08-28 13:09:33 -07:00
ηzw ca37e806b9 Fix docs (#3609)
* Fix typo

* Fix typo

* Fix docstring

* Remove the unnecessary augument in docstring
2016-08-28 11:22:16 -07:00
Francois Chollet fe0347dbf0 Update docs 2016-08-28 02:33:50 -07:00
Francois Chollet 4984c5fc7c Update documentation 2016-08-28 02:03:14 -07:00
Francois Chollet f605769af9 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-28 01:11:08 -07:00
Francois Chollet 534f6b7975 Remove flaky test 2016-08-28 01:10:53 -07:00
ηzw ee8fd78383 Fix docstring in Locally-connected Layers (#3607) 2016-08-28 01:07:58 -07:00
Francois Chollet fbc4f37037 Example touch-up 2016-08-27 20:28:03 -07:00
Francois Chollet f23f2ff2c9 Add keras.applications, refactor 2 convnet scripts 2016-08-27 20:27:49 -07:00
Francois Chollet d0659327bd Prepare 1.0.8 release. 2016-08-27 17:04:58 -07:00
Nithish deva Divakar 88b301f182 Update io_utils.py (#3577)
* Update io_utils.py

Fix for wrong input dimension when using HDF5matrix for loading data

* Update io_utils.py
2016-08-27 09:45:31 -07:00
Yanush Viktor d5e16807d2 Update image.md (#3600)
Information in docs about optional parameter `shuffle` is not correct. In the code
https://github.com/fchollet/keras/blob/master/keras/preprocessing/image.py#L263
it's `True` by default, but `False` in the docs.
2016-08-27 09:45:10 -07:00
Fariz Rahman 79a2bcd05f TF dynamic RNN : Allow sequences of ndim > 3 (#3603)
Docstring says "at least 3D", but current code is hard coded for 3D input.
2016-08-27 09:44:55 -07:00
dibule e582f9dcac Bug fix, batch_size set instead of default one (#3590) 2016-08-26 14:30:57 -07:00
Carl Thomé 4cefd6136b Add pydot-ng dependency (#3593) 2016-08-26 14:30:25 -07:00
Francois Chollet 1cf04b7a10 Update documentation 2016-08-26 14:22:56 -07:00
Francois Chollet ad3db301f2 Update RNN docstring 2016-08-25 12:34:35 -07:00
Francois Chollet e15eb40317 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-25 11:46:41 -07:00
Felix Lau 8459d0403c Fix Cropping3D InputSpec to be dim=5 (#3570) 2016-08-25 10:29:52 -07:00
François Chollet 08014eea36 Add support for dynamic RNNs in TensorFlow. (#3474)
* Add support for dynamic RNNs in TensorFlow.

* Fix return states

* Add support for go_backwards in dynamic TF RNNs

* Currently broken: TF RNN dropout, go_backwards

* Finalize dynamic RNNs in TF

* Remove unnecessary comment

* Comment out added test

* Comment out functional guide test
2016-08-24 20:47:51 -07:00
Francois Chollet c0b27108d0 Whitespace fix 2016-08-24 16:15:38 -07:00
Francois Chollet 40612facf3 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-24 15:16:39 -07:00
Francois Chollet e418fc6937 Add get_variable_shape backend method 2016-08-24 15:16:22 -07:00
cyrusmaher 045d442fcd Update scikit_learn.py (#3567)
Sklearn (e.g. the Bagging estimator) expects a value error if a parameter isn't recognized.
2016-08-24 14:19:25 -07:00
Dmitry Lukovkin 2370f9f1db Docs update for Deconvolution2D layer (#3549)
* Fix exception message for Deconvolution2D

* Docs update for Deconvolution2D layer (#3540)

* Corrections to Deconvolution2D docs

* References formatted as Markdown links
* Blank lines added
2016-08-24 13:16:02 -07:00
Jurim Lee 519d1e7420 bug fix : cnn tensorflow backend error (#3558) 2016-08-24 08:57:31 -07:00
Francois Chollet 82afc713d0 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-24 04:15:34 -07:00
Francois Chollet a1e9a8addd data_utils update 2016-08-24 04:15:20 -07:00
Fariz Rahman f59736a06c Bug fix : RNNs (#3550) 2016-08-23 17:03:17 -07:00
Francois Chollet d187059596 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-23 14:30:21 -07:00
Francois Chollet 7d2f0b1ba8 Fix trainable_weight lists 2016-08-23 14:29:49 -07:00
Francois Chollet 6a6d939dea Style fix 2016-08-23 14:29:27 -07:00
Keunwoo Choi 090b8b7f99 add cropping1d/2d/3d layers (#3509)
* add cropping1d/2d/3d layers

* fix PEP8 issue, fix incorrect doc strings

* add example code on Cropping2D

* fix init/get_config of crop1d/3d, add test codes for cropping1d/2d/3d

* fix test code - PEP8

It doesnt pass test (only in cropping2d and basic_test), but my laptop setting is not correct (it doesnt pass some other existing layes as well), so committing to test it in a correct way.

* change to follow PEP8 again

* update test_convolutonal.py for PEP8, test code to us K.image_dim_ordering()

* PEP8 for test_convolutional.py - indentation

* fix typo. add assert to check cropping lengths
2016-08-22 19:20:47 -07:00
Dominic Breuker e4dda27de1 allow KerasClassifier.score to accept sparse labels (#3534) 2016-08-22 15:19:26 -07:00
EdwardRaff f2786d9d80 Update theano_backend.py (#3532)
fix batch norm causing NaN for many datasets
2016-08-20 12:50:23 -07:00
Katherine Crowson c6daa24e3c Use Theano's CuDNN implementation of batch normalization (#3529) 2016-08-19 20:03:55 -07:00
François Chollet 2f4eed1f0f Remove lock in fit_generator (#3528) 2016-08-19 16:09:20 -07:00
Francois Chollet acc5c45feb Remove lock in fit_generator 2016-08-19 11:21:47 -07:00
Rodrigo Prado 00c3335071 added language sh to install instructions (#3520) 2016-08-19 08:36:51 -07:00
Ardalan 65e4c8e76e Update lstm_text_generation.py (#3516)
updating comment
2016-08-18 14:03:26 -07:00
Francois Chollet d4f5dff8ee Style fixes 2016-08-18 13:51:45 -07:00
dolaameng 8d9cb782fb add example mnist_net2net.py (#3503)
* add example mnist_net2net.py

* change of mnist_net2net.py based on 1st comments

* typo fixed in examples/mnist_net2net.py
2016-08-18 13:07:16 -07:00
fchollet 02ff1d4462 Fix style in example 2016-08-17 20:00:49 -07:00
Francois Chollet 007d2c2e25 Fix theano tests 2016-08-17 17:39:24 -07:00
Francois Chollet 3bf7637986 Style fixes 2016-08-17 16:32:52 -07:00
Francois Chollet 33ff9dbce2 Speed up bidirectional wrapper tests 2016-08-17 16:30:31 -07:00
Fariz Rahman f25e894558 Bidirectional Wrapper (#3495)
* Add Bidirectional Wrapper

* Fix example

* Update wrappers.py

* Add reverse op

* Update tensorflow_backend.py

* Update wrappers.py

* Update test_wrappers.py

* bug fix

* Update test_wrappers.py

* Update test_wrappers.py

* bug fix

* Add test for reverse op

* Enable reverse along multiple axes

* Update theano_backend.py

* Update theano_backend.py

* Update test_wrappers.py

* Speed up tests

* Validate merge_mode arg, Add None mode

* Update test_wrappers.py

* Update test_wrappers.py

* Add properties; reverse -> backward

* Bug fix

* Resolve naming conflict

* Whitespace fix

* Update imdb_bidirectional_lstm.py

* Fix imports
2016-08-17 16:27:06 -07:00
Junwei Pan 52c1a7456f Add a reference paper for Adagrad (#3473)
Add a reference paper for Adagrad
2016-08-17 13:31:24 -07:00
Junwei Pan b2392413fa Fix a issue when only specify one dot_axes for in the Merge layer in the dot mode (#3470)
* Upload examples/imdb_fasttext.py which implement the fasttext model

* Remove Dropout and unnecessary imports

* Remove Dropout and unnecessary imports

* Remove Dropout and unnecessary imports

* Fix a issue when only specify one dot_axes for in the Merge layer

* Fix a issue when only specify one dot_axes for in the Merge layer
2016-08-17 13:30:45 -07:00
Frederico Tommasi Caroli 1941eaabe0 Using locks instead of ignoring ValuErrors in generators (#3501) 2016-08-17 11:20:51 -07:00
ηzw 3d5bf9753f Fix typo (#3505) 2016-08-17 11:18:52 -07:00
fchollet a4d191d4f9 Only write config file if it didn't exist 2016-08-16 20:53:57 -07:00
Reid Sanders dad54ec211 Minor imbd dataset documentation update, added docstring to reuters (#3494)
* Updated dataset documentation to reflect removal of test_split argument
from imbd dataset. Added docstring to reuters dataset load_data.

* Updated imbd and reuters examples in dataset docs to reflect all
available arguments with current default values.
2016-08-16 14:14:32 -07:00
Francois Chollet b525f5f4d7 Make h5py optional again 2016-08-16 13:31:15 -07:00
Mike Henry e8190a8d8d Added support for CTC in both Theano and Tensorflow along with image OCR example. (#3436)
* Added CTC to Theano and Tensorflow backend along with image OCR example

* Fixed python style issues, made data files remote, and made code more idiomatic to Keras

* Fixed a couple more style issues brought up in the original PR

* Reverted wrappers.py

* Fixed potential training-on-validation issue and removed unused imports

* Fixed PEP8 issue

* Remaining PEP8 issues fixed
2016-08-16 13:25:26 -07:00
Francois Chollet 4e155139ca Style fixes. 2016-08-16 11:17:44 -07:00
stas-sl 458edeed9a implement spatial dropout (#3463) 2016-08-16 11:16:18 -07:00
Katherine Crowson 04d785f4bf Allow multiprocessing on OS X (#3389) 2016-08-14 15:43:43 -07:00
fchollet 28d9c0c511 Style fixes in example. 2016-08-14 15:41:04 -07:00
Antonie Lin 91310971b9 mnist hierarchical rnn example (#3460) 2016-08-14 15:40:13 -07:00
Francois Chollet 5d2acf4897 Merge branch 'master' of https://github.com/fchollet/keras 2016-08-13 11:54:04 -07:00
Francois Chollet dc98019d49 Add get_layer to sequential models 2016-08-13 11:53:48 -07:00
ηzw b008bb35cc Style fixes (#3462) 2016-08-13 11:22:01 -07:00
Junwei Pan 46d5b197e0 Implement a fasttext example (#3446)
* Upload examples/imdb_fasttext.py which implement the fasttext model

* Remove Dropout and unnecessary imports

* Remove Dropout and unnecessary imports

* Remove Dropout and unnecessary imports
2016-08-12 14:36:35 -07:00
Francois Chollet 2c510530b1 Update FAQ 2016-08-10 16:44:35 -07:00
Francois Chollet ec6eda77ad Style fixes in tests 2016-08-10 16:44:29 -07:00
Yann Henon 4805e5856b Upsampling layer fix to work when input shape is None (#3429) 2016-08-09 14:47:23 -07:00
Fariz Rahman 55447cbb3d Bug fix : squeeze (#3433) 2016-08-09 13:59:47 -07:00
Francois Chollet 69d5139b8c [breaking change] Weight ordering now topological. 2016-08-09 10:20:00 -07:00
Francois Chollet 89f1e05147 Functional Model weight loading in layer order 2016-08-08 18:53:36 -07:00
Francois Chollet bc779df8b7 Avoid creating new ops in TF to load weights 2016-08-08 16:13:40 -07:00
Francois Chollet e3c260e7d3 Fix test flakes 2016-08-08 13:00:53 -07:00
Francois Chollet 0af7e004c7 Fix test flakiness in TF 2016-08-08 12:28:35 -07:00
Francois Chollet 447445388e Merge branch 'master' of https://github.com/fchollet/keras 2016-08-08 11:23:38 -07:00
Francois Chollet b2c66816d7 Prepare new PyPI release. 2016-08-08 11:23:25 -07:00
Martin Thoma b6f81c6cc3 Fix documentation of the 1D max pooling layer (#3419) 2016-08-08 11:04:54 -07:00
Yad Faeq 98b289630a Word embdedding example updated (#3417)
* Added Convolution1D instead of Conv1D, which is depreceated

* updated rest of the example using Conv1D

* Python3 fails to decode utf-8 data, thus using encoding='latin-1'

* added condition for Encoding line 65-67

* Conv1D reverted back to the way it was
2016-08-08 10:59:31 -07:00
fchollet d68c0bd795 Update optimizers docs 2016-08-07 19:31:25 -07:00
Santiago Castro 5afda71f74 Fix scikit-learn python file name in docs (#3413) 2016-08-06 19:29:27 -07:00
Ramon de Oliveira 1b08a8d675 format Nadam references (#3404) 2016-08-05 16:41:34 -07:00
Moussa Taifi b508ab64bd Fix documentation for ModelCheckpoint callback params (#3408) 2016-08-05 16:41:15 -07:00
Richard Higgins 84f435e24b all zero arrays no longer get divided by zero in the process of being turned into images (#3401)
Update image.py
2016-08-05 09:10:52 -07:00
Fariz Rahman 984ad34a61 One hot op (#3353)
* One hot op

* tf too

* Update theano_backend.py

* Use built-in theano op

* Update theano_backend.py

* Add test

* Update test_backends.py

* Update test_backends.py

* Generalize for nD tensors

* Fix docstring on TF backend

* Update theano_backend.py

* Update theano_backend.py
2016-08-04 14:16:36 -07:00
Ondřej Filip ad3231c29a Docs update for Merge layer (#3392)
In Merge layer dot_axes param affects also 'cos' mode
2016-08-04 08:54:10 -07:00
fchollet c3d20bbc53 Merge branch 'master' of ssh://github.com/fchollet/keras 2016-08-03 22:11:12 -07:00
fchollet f9c03f183f Make trainable_weights dynamic 2016-08-03 22:02:45 -07:00
Tsukasa ŌMOTO 046a3c8a28 Fix YAML serialization for Advanced Activations (#3391)
Fix https://github.com/fchollet/keras/issues/2871#issuecomment-237365465

The problem occurs because PyYAML can't recognize numpy's data types.
2016-08-03 20:41:52 -07:00
Francois Chollet 05883934f1 Unify BN behavior across backends (fix) 2016-08-03 13:22:21 -07:00
Francois Chollet 97d2a73dd3 Unify BN behavior in TF and Theano 2016-08-03 12:39:24 -07:00
Francois Chollet 5367a44acb Further style fixes in example 2016-08-03 11:54:15 -07:00
Francois Chollet 1deaf71388 revert unnecessary changes in example script 2016-08-03 11:11:35 -07:00
Francois Chollet 99f564e972 Style fixes and small bug fixes 2016-08-03 11:08:48 -07:00
Zhengtao Wang c725f8d354 add resnet50 example (#3266)
* add resnet50 example

* fix PEP8 problems

* fix PEP8 problem....again...

This script get 10 points in PEP8 tests on my computer but.....

* add resnet 50

* fix problem caused by interrupted git push

* fix PEP8 problem..again!

* update weights links and remove load_weights

* fix pep8!

* remove skimage dependency, rename the file

* fix pep8...

* update

* support tf dim_ordering

* fix PEP8 problem
2016-08-03 10:51:18 -07:00
Shuhei Iitsuka 257ace722c Correct the reconstruction loss (#3383) 2016-08-02 21:45:31 -07:00
Wei Ouyang 0cd9d46828 remove keyword for cifar10.load_data (#3379) 2016-08-02 08:20:00 -07:00
Chris Caruso cef9e28a6c Added to rnn statefulness doc concerning func api (#3375)
Added correct information for how to enable rnn statefulness on functional models with 1 or more Input layers.
2016-08-01 20:21:42 -07:00
Francois Chollet 6c42da2abf Fix legacy model loading 2016-08-01 16:26:01 -07:00
Francois Chollet a9fc2bed49 Allow to call load_weights on model save file 2016-07-31 22:58:44 -07:00
Francois Chollet 1855c49d1f Merge branch 'master' of https://github.com/fchollet/keras 2016-07-31 17:45:43 -07:00
Francois Chollet cce65ce34d Update docs. 2016-07-31 17:45:32 -07:00
Jan Wilken Dörrie 70866c0154 Compare versions through pkg_resources.parse_version (#3355) 2016-07-31 10:45:03 -07:00
dolaameng d06e3753b0 update examples/neural_style_transfer.py (#3347) 2016-07-29 12:00:37 -07:00
Fariz Rahman cb4de1f859 Embedding layer - cast float to int implicitly (#3342)
* Embedding layer - cast float to int implicitly

* Cast only if not int
2016-07-29 11:11:46 -07:00
Jérémie b6d23b2e2d remove usage of tf.assign() in part of tensorflow backend (#3316) (#3320)
* remove usage of tf.assign() in the tensorflow backend (#3316)

Usage of the tf.assign() function in the set_value() and batch_set_values() functions creates new nodes on the Tensorflow graph which can eventually overflow the memory.
Therefore, the function has been rewritten using placeholders and feed_dict to avoid allocating additional memory.

* Correction to the set_value() function

Change to the set_value() function that had a bug when the variable "value" was a float.
The *1. dummy multiplication was added to avoid having to deal with tf.float32_ref dtypes.

* update set_value() of the tensorflow backend

Removal of the *1. dummy multiplication, replacement with a split() to avoid creating a new operation in the graph.

* fix to have session.run() called once in batch_set_value()

Rewriting of the batch_set_value() to avoid multiple calls to session.run() to improve speed.
2016-07-28 09:29:57 -07:00
Pradeep Dasigi 6a8815de0c Masked and non-masked merge bug fix (#3218)
* Masked and non-masked merge bug fix

* Masked merge concat logic with an expanded loop

* Cast mask of ones for unmasked input in merge to uint8
2016-07-27 17:50:49 -07:00
Francois Chollet e0179bad2f Refresh IMDB dataset 2016-07-27 17:30:04 -07:00
Francois Chollet 8778add0d6 Clean up test files 2016-07-27 12:09:40 -07:00
Francois Chollet facc823612 Update FAQ 2016-07-27 11:15:04 -07:00
Francois Chollet b91854ea9d Fix flaky test 2016-07-27 10:27:47 -07:00
Francois Chollet 05abe814ac Add keras version in model save files 2016-07-27 10:22:49 -07:00
François Chollet ea561ba6d8 Add model saving functionality (#3314)
* Add model saving functionality

* Update model saving functionality

* Fix py3 bytes/str issue

* Fix tests
2016-07-26 20:45:28 -07:00
Mostafa Abdulhamid df84c69676 Docker image for test and experiment Keras (#3035)
* Docker image for test and experiment Keras

 - Docker image with CUDA support on ubuntu 14.04
 - nvidia-docker script to forward the GPU to the container
 - MakeFile to simplify docker commands for build, run, test, ..etc
 - Add useful tools like jupyter notebook, ipdb, sklearn for experiments

* update nvidia-docker plugin

* use .theanorc in Dockerfile

* Add tensorflow to the docker image

* update Docker image to cuDNN v5

* test fixes

* move docker to sub directory

* README for docker

* Fix typos

* Add visualization to Dockerfile
2016-07-26 18:29:56 -07:00
Sadegh 3726aba2ee use of period fixed, default period set to 1000 (#3312) 2016-07-25 20:41:22 -07:00
Francois Chollet f6bcaffe4a Style fixes 2016-07-25 10:42:37 -07:00
yaringal c689b52dd1 Implemented transposed (de-) convolutions into Keras (#3251)
* theano backend now supports transposed convolutions

* working deconv

* new example file with deconv vae

* merged with #3273, fixed based on comments, pep8 tested

* test fix

* passes theano test

* start fixing deconv test

* fix deconv layer tests

* fix the right test

sorry, I "fixed" the wrong test last time

* clean up

* replace with_None with fixed_batch_size

* with_None --> fixed_batch_size

* comment edit

* fixed comments online
2016-07-25 10:33:03 -07:00
fchollet 09d75a4347 Style fixes 2016-07-24 14:20:36 -07:00
Rui Shu 59bd247603 Fix VAE example (#3220)
A number of changes:
1. Switch from Lambda to merge, otherwise code will not run.
2. Rename z_log_std to z_log_var in order for the objective function to make sense
3. Adjust reparameterization trick to reflect use of z_log_var, not z_log_std
4. Remove epsilon_std, since (standard) VAE uses isotropic gaussian prior.
5. Re-balance the weighting of KL and reconstruction terms
6. Use adam instead of rmsprop
7. Increase hidden unit size to improve model
8. Increase batch size to speed up training
2016-07-24 14:09:34 -07:00
dolaameng f221ef952f make examples/pretrained_word_embeddings.py more memory efficient (#3289)
* make examples/pretrained_word_embeddings.py more memory efficient

* make examples/pretrained_word_embeddings.py more memory efficient

* rename NB_WORDS to nb_words as it is not a global constant
2016-07-23 10:14:28 -07:00
Sebastian N. Fernandez d3c75e1d34 adding print_tensor (#3285) 2016-07-22 12:48:44 -07:00
Felix Lau 3aab55d29f Add Tensorflow support for UpSampling3D and ZeroPadding3D (#3274) 2016-07-22 12:47:59 -07:00
Fariz Rahman f9ef72c38a Logical ops (#3272)
* Logical ops

* Update tensorflow_backend.py

* Add tests

* Update tensorflow_backend.py

* lesser->less

* Update test_backends.py

* less->lesser

* less->lesser

* Update test_backends.py
2016-07-21 20:47:02 -07:00
Francois Chollet 108159ed17 Merge branch 'master' of https://github.com/fchollet/keras 2016-07-21 15:10:10 -07:00
Francois Chollet defa1283c4 Include iterations in optimizer weights 2016-07-21 15:04:30 -07:00
Francois Chollet 2788b60fe6 Revert behavior of regularizers 2016-07-21 15:04:09 -07:00
Olivier Grisel 7e70e1768f Small python3 compat fix in backend doc (#3275) 2016-07-21 10:31:52 -07:00
Kai Li 896ba77061 update residual connection example (#3278) 2016-07-21 10:30:19 -07:00
Francois Chollet c034262b78 Removed test for deprecated graph model 2016-07-20 16:12:49 -07:00
Francois Chollet b7edcf6eea Change behavior of regularizers: use mean, not sum 2016-07-20 15:52:47 -07:00
Francois Chollet 23e1ad2df7 Allow overriding learning phase 2016-07-20 15:48:52 -07:00
Francois Chollet 0a3939883a Style fix 2016-07-19 16:29:27 -07:00
Francois Chollet 3c8f91ee3d Style fix 2016-07-19 16:11:33 -07:00
Francois Chollet efa5b04797 Style fix 2016-07-19 16:09:07 -07:00
Francois Chollet 2da66ed009 Py3 fix 2016-07-19 14:56:50 -07:00
Francois Chollet 2ac6811362 Remove deprecated graph model test 2016-07-19 14:53:50 -07:00
Francois Chollet 74c51f213c Fix flaky test 2016-07-19 14:52:56 -07:00
Francois Chollet 4302d8060d Fix image resizing in preprocessing/image 2016-07-19 14:30:43 -07:00
Francois Chollet 576cf8978b Merge branch 'master' of https://github.com/fchollet/keras 2016-07-19 14:22:48 -07:00
Francois Chollet 3533912016 Native initializations, updates 2016-07-19 14:22:34 -07:00
ekerazha cf9922ff1d Fix broken imdb_cnn example (#3244)
* Fix broken imdb_cnn example

* Update imdb_cnn fix
2016-07-19 12:18:59 -07:00
Zhengtao Wang 4fa65fbb2f add doc for layers/normalization/BatchNormalization (#3248)
* add doc for layers/normalization/BatchNormalization

* fix PEP8 problem

* Update normalization.py
2016-07-19 12:18:39 -07:00
Kai Li f502ee2338 Update sequential-model-guide.md (#3257) 2016-07-19 12:18:25 -07:00
Francois Chollet 7a56925176 Even faster tests 2016-07-19 11:57:57 -07:00
Francois Chollet 0a108b3fb2 Fix tests maybe? 2016-07-19 11:31:22 -07:00
Francois Chollet 381a108e6d Revert Travis config 2016-07-19 11:17:32 -07:00
Francois Chollet 726c9fc8a6 Update tests 2016-07-19 10:49:44 -07:00
Francois Chollet 946ccd3228 Speed up tests (especially with TF) 2016-07-19 10:05:30 -07:00
Francois Chollet 8e1ebbfc11 Get rid of coveralls 2016-07-19 00:40:21 -07:00
Francois Chollet cc0e60c101 TF backend performance improvements 2016-07-19 00:30:05 -07:00
Francois Chollet ff3f00d845 Style fix in example 2016-07-18 23:48:56 -07:00
Francois Chollet 40195c2fa2 TF backend: group update ops, add clear_session 2016-07-18 23:48:56 -07:00
Francois Chollet 7f7300b8cb Minor style fixes 2016-07-18 23:48:56 -07:00
Fariz Rahman 1b158ff4ed Bug fix + test - Sequential.pop() (#3252)
* Bug fix - Sequential.pop()

* Add test for Sequential.pop()

* Update test_sequential_model.py
2016-07-18 18:30:13 -07:00
stas-sl b686b85b52 Use symbolic shape in tensorflow version of batch_flatten (#3253) 2016-07-18 15:37:10 -07:00
Francois Chollet 8fa82ae5cb Merge branch 'master' of https://github.com/fchollet/keras 2016-07-16 17:52:56 -07:00
Francois Chollet 0d5289141e Add pre-trained word embeddings example 2016-07-16 17:51:17 -07:00
Francois Chollet 01d5e7bc47 Fix up a few example 2016-07-16 17:47:52 -07:00
Fariz Rahman cfbaec60c7 Simplify output shape inference for dot/cos merge (#3233)
* Simplify output shape inference for dot/cos merge

* Add extra dim if rank is 1

* Explain output shape inference logic in doc string

* Update tensorflow_backend.py

* Update theano_backend.py

* Update tensorflow_backend.py

* Update tensorflow_backend.py

* Update theano_backend.py

* Update topology.py

* example

* Update theano_backend.py

* Update theano_backend.py

* Update tensorflow_backend.py

* Update tensorflow_backend.py

* Update tensorflow_backend.py

* Update tensorflow_backend.py

* Update theano_backend.py

* Update tensorflow_backend.py

* typo fix

* Update theano_backend.py
2016-07-16 16:35:39 -07:00
Francois Chollet f3e7245910 Use native Theano BN 2016-07-16 13:42:41 -07:00
114 arquivos alterados com 8005 adições e 2097 exclusões
+17 -14
Ver Arquivo
@@ -1,19 +1,21 @@
# Keras: Deep Learning library for Theano and TensorFlow
# Keras: Deep Learning library for TensorFlow and Theano
[![Build Status](https://travis-ci.org/fchollet/keras.svg?branch=master)](https://travis-ci.org/fchollet/keras)
[![PyPI version](https://badge.fury.io/py/keras.svg)](https://badge.fury.io/py/keras)
[![license](https://img.shields.io/github/license/mashape/apistatus.svg?maxAge=2592000)](https://github.com/fchollet/keras/blob/master/LICENSE)
[![Join the chat at https://gitter.im/Keras-io/Lobby](https://badges.gitter.im/Keras-io/Lobby.svg)](https://gitter.im/Keras-io/Lobby)
## 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 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.*
Use Keras if you need a deep learning library that:
- allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
- supports both convolutional networks and recurrent networks, as well as combinations of the two.
- supports arbitrary connectivity schemes (including multi-input and multi-output training).
- runs seamlessly on CPU and GPU.
- Allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
- Supports both convolutional networks and recurrent networks, as well as combinations of the two.
- Supports arbitrary connectivity schemes (including multi-input and multi-output training).
- Runs seamlessly on CPU and GPU.
Read the documentation at [Keras.io](http://keras.io).
@@ -114,32 +116,33 @@ Keras uses the following dependencies:
- HDF5 and h5py (optional, required if you use model saving/loading functions)
- Optional but recommended if you use CNNs: cuDNN.
*When using the Theano backend:*
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
*When using the TensorFlow backend:*
- TensorFlow
- [See installation instructions](https://github.com/tensorflow/tensorflow#download-and-setup).
*When using the Theano backend:*
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
To install Keras, `cd` to the Keras folder and run the install command:
```
```sh
sudo python setup.py install
```
You can also install Keras from PyPI:
```
```sh
sudo pip install keras
```
------------------
## Switching from Theano to TensorFlow
## Switching from TensorFlow to Theano
By default, Keras will use Theano as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
By default, Keras will use TensorFlow as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
------------------
+46
Ver Arquivo
@@ -0,0 +1,46 @@
FROM nvidia/cuda:7.5-cudnn5-devel
ENV CONDA_DIR /opt/conda
ENV PATH $CONDA_DIR/bin:$PATH
RUN mkdir -p $CONDA_DIR && \
echo export PATH=$CONDA_DIR/bin:'$PATH' > /etc/profile.d/conda.sh && \
apt-get update && \
apt-get install -y wget git libhdf5-dev g++ graphviz && \
wget --quiet https://repo.continuum.io/miniconda/Miniconda3-3.9.1-Linux-x86_64.sh && \
echo "6c6b44acdd0bc4229377ee10d52c8ac6160c336d9cdd669db7371aa9344e1ac3 *Miniconda3-3.9.1-Linux-x86_64.sh" | sha256sum -c - && \
/bin/bash /Miniconda3-3.9.1-Linux-x86_64.sh -f -b -p $CONDA_DIR && \
rm Miniconda3-3.9.1-Linux-x86_64.sh
ENV NB_USER keras
ENV NB_UID 1000
RUN useradd -m -s /bin/bash -N -u $NB_UID $NB_USER && \
mkdir -p $CONDA_DIR && \
chown keras $CONDA_DIR -R && \
mkdir -p /src && \
chown keras /src
USER keras
# Python
ARG python_version=3.5.1
ARG tensorflow_version=0.9.0rc0-cp35-cp35m
RUN conda install -y python=${python_version} && \
pip install https://storage.googleapis.com/tensorflow/linux/gpu/tensorflow-${tensorflow_version}-linux_x86_64.whl && \
pip install git+git://github.com/Theano/Theano.git && \
pip install ipdb pytest pytest-cov python-coveralls coverage==3.7.1 pytest-xdist pep8 pytest-pep8 pydot_ng && \
conda install Pillow scikit-learn notebook pandas matplotlib nose pyyaml six h5py && \
pip install git+git://github.com/fchollet/keras.git && \
conda clean -yt
ADD theanorc /home/keras/.theanorc
ENV PYTHONPATH='/src/:$PYTHONPATH'
WORKDIR /src
EXPOSE 8888
CMD jupyter notebook --port=8888 --ip=0.0.0.0
+26
Ver Arquivo
@@ -0,0 +1,26 @@
help:
@cat Makefile
DATA?="${HOME}/Data"
GPU?=0
DOCKER_FILE=Dockerfile
DOCKER=GPU=$(GPU) nvidia-docker
BACKEND=tensorflow
TEST=tests/
SRC=$(shell dirname `pwd`)
build:
docker build -t keras --build-arg python_version=3.5 -f $(DOCKER_FILE) .
bash: build
$(DOCKER) run -it -v $(SRC):/src -v $(DATA):/data --env KERAS_BACKEND=$(BACKEND) keras bash
ipython: build
$(DOCKER) run -it -v $(SRC):/src -v $(DATA):/data --env KERAS_BACKEND=$(BACKEND) keras ipython
notebook: build
$(DOCKER) run -it -v $(SRC):/src -v $(DATA):/data --net=host --env KERAS_BACKEND=$(BACKEND) keras
test: build
$(DOCKER) run -it -v $(SRC):/src -v $(DATA):/data --env KERAS_BACKEND=$(BACKEND) keras py.test $(TEST)
+58
Ver Arquivo
@@ -0,0 +1,58 @@
# Using Keras via Docker
This directory contains `Dockerfile` to make it easy to get up and running with
Keras via [Docker](http://www.docker.com/).
## Installing Docker
General installation instructions are
[on the Docker site](https://docs.docker.com/installation/), but we give some
quick links here:
* [OSX](https://docs.docker.com/installation/mac/): [docker toolbox](https://www.docker.com/toolbox)
* [ubuntu](https://docs.docker.com/installation/ubuntulinux/)
## Running the container
We are using `Makefile` to simplify docker commands within make commands.
Build the container and start a jupyter notebook
$ make notebook
Build the container and start an iPython shell
$ make ipython
Build the container and start a bash
$ make bash
For GPU support install NVidia drivers (ideally latest) and
[nvidia-docker](https://github.com/NVIDIA/nvidia-docker). Run using
$ make notebook GPU=0 # or [ipython, bash]
Switch between Theano and TensorFlow
$ make notebook BACKEND=theano
$ make notebook BACKEND=tensorflow
Mount a volume for external data sets
$ make DATA=~/mydata
Prints all make tasks
$ make help
You can change Theano parameters by editing `/docker/theanorc`.
Note: If you would have a problem running nvidia-docker you may try the old way
we have used. But it is not recommended. If you find a bug in the nvidia-docker report
it there please and try using the nvidia-docker as described above.
$ export CUDA_SO=$(\ls /usr/lib/x86_64-linux-gnu/libcuda.* | xargs -I{} echo '-v {}:{}')
$ export DEVICES=$(\ls /dev/nvidia* | xargs -I{} echo '--device {}:{}')
$ docker run -it -p 8888:8888 $CUDA_SO $DEVICES gcr.io/tensorflow/tensorflow:latest-gpu
+5
Ver Arquivo
@@ -0,0 +1,5 @@
[global]
floatX = float32
optimizer=None
device = gpu
+28 -8
Ver Arquivo
@@ -65,6 +65,8 @@ if sys.version[0] == '2':
sys.setdefaultencoding('utf8')
from keras.layers import convolutional
from keras.layers import pooling
from keras.layers import local
from keras.layers import recurrent
from keras.layers import core
from keras.layers import noise
@@ -88,6 +90,7 @@ EXCLUDE = {
'Wrapper',
'get_session',
'set_session',
'CallbackList',
}
PAGES = [
@@ -105,6 +108,7 @@ PAGES = [
models.Sequential.predict_on_batch,
models.Sequential.fit_generator,
models.Sequential.evaluate_generator,
models.Sequential.predict_generator,
],
},
{
@@ -119,6 +123,7 @@ PAGES = [
models.Model.predict_on_batch,
models.Model.fit_generator,
models.Model.evaluate_generator,
models.Model.predict_generator,
models.Model.get_layer,
]
},
@@ -128,6 +133,8 @@ PAGES = [
core.Dense,
core.Activation,
core.Dropout,
core.SpatialDropout2D,
core.SpatialDropout3D,
core.Flatten,
core.Reshape,
core.Permute,
@@ -145,8 +152,11 @@ PAGES = [
'page': 'layers/convolutional.md',
'classes': [
convolutional.Convolution1D,
convolutional.AtrousConvolution1D,
convolutional.Convolution2D,
convolutional.AtrousConv2D,
convolutional.AtrousConvolution2D,
convolutional.SeparableConvolution2D,
convolutional.Deconvolution2D,
convolutional.Convolution3D,
convolutional.UpSampling1D,
convolutional.UpSampling2D,
@@ -159,12 +169,23 @@ PAGES = [
{
'page': 'layers/pooling.md',
'classes': [
convolutional.MaxPooling1D,
convolutional.MaxPooling2D,
convolutional.MaxPooling3D,
convolutional.AveragePooling1D,
convolutional.AveragePooling2D,
convolutional.AveragePooling3D,
pooling.MaxPooling1D,
pooling.MaxPooling2D,
pooling.MaxPooling3D,
pooling.AveragePooling1D,
pooling.AveragePooling2D,
pooling.AveragePooling3D,
pooling.GlobalMaxPooling1D,
pooling.GlobalAveragePooling1D,
pooling.GlobalMaxPooling2D,
pooling.GlobalAveragePooling2D,
],
},
{
'page': 'layers/local.md',
'classes': [
local.LocallyConnected1D,
local.LocallyConnected2D,
],
},
{
@@ -201,7 +222,6 @@ PAGES = [
'all_module_classes': [wrappers],
},
{
'page': 'optimizers.md',
'all_module_classes': [optimizers],
+2
Ver Arquivo
@@ -25,6 +25,7 @@ pages:
- Core Layers: layers/core.md
- Convolutional Layers: layers/convolutional.md
- Pooling Layers: layers/pooling.md
- Locally-connected Layers: layers/local.md
- Recurrent Layers: layers/recurrent.md
- Embedding Layers: layers/embeddings.md
- Advanced Activations Layers: layers/advanced-activations.md
@@ -41,6 +42,7 @@ pages:
- Activations: activations.md
- Callbacks: callbacks.md
- Datasets: datasets.md
- Applications: applications.md
- Backend: backend.md
- Initializations: initializations.md
- Regularizers: regularizers.md
+260
Ver Arquivo
@@ -0,0 +1,260 @@
# Applications
Keras Applications are deep learning models that are made available alongside pre-trained weights.
These models can be used for prediction, feature extraction, and fine-tuning.
Weights are downloaded automatically when instantiating a model. They are stored at `~/.keras/models/`.
## Available models
Models for image classification with weights trained on ImageNet:
- [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".
-----
## Examples
### Classify ImageNet classes with ResNet50
```python
from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
model = ResNet50(weights='imagenet')
img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
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']]
```
### Extract features with VGG16
```python
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
model = VGG16(weights='imagenet', include_top=False)
img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
features = model.predict(x)
```
### Extract features from an arbitrary intermediate layer with VGG19
```python
from keras.applications.vgg19 import VGG19
from keras.preprocessing import image
from keras.applications.vgg19 import preprocess_input
from keras.models import Model
base_model = VGG19(weights='imagenet')
model = Model(input=base_model.input, output=base_model.get_layer('block4_pool').output)
img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)
block4_pool_features = model.predict(x)
```
### Fine-tune InceptionV3 on a new set of classes
```python
from keras.applications.inception_v3 import InceptionV3
from keras.preprocessing import image
from keras.models import Model
from keras.layers import Dense, GlobalAveragePooling2D
from keras import backend as K
# create the base pre-trained model
base_model = InceptionV3(weights='imagenet', include_top=False)
# add a global spatial average pooling layer
x = base_model.output
x = GlobalAveragePooling2D()(x)
# let's add a fully-connected layer
x = Dense(1024, activation='relu')(x)
# and a logistic layer -- let's say we have 200 classes
predictions = Dense(200, activation='softmax')(x)
# this is the model we will train
model = Model(input=base_model.input, output=predictions)
# first: train only the top layers (which were randomly initialized)
# i.e. freeze all convolutional InceptionV3 layers
for layer in base_model.layers:
layer.trainable = False
# compile the model (should be done *after* setting layers to non-trainable)
model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
# train the model on the new data for a few epochs
model.fit_generator(...)
# at this point, the top layers are well trained and we can start fine-tuning
# convolutional layers from inception V3. We will freeze the bottom N layers
# and train the remaining top layers.
# let's visualize layer names and layer indices to see how many layers
# we should freeze:
for i, layer in enumerate(base_model.layers):
print(i, layer.name)
# we chose to train the top 2 inception blocks, i.e. we will freeze
# the first 172 layers and unfreeze the rest:
for layer in model.layers[:172]:
layer.trainable = False
for layer in model.layers[172:]:
layer.trainable = True
# we need to recompile the model for these modifications to take effect
# we use SGD with a low learning rate
from keras.optimizers import SGD
model.compile(optimizer=SGD(lr=0.0001, momentum=0.9), loss='categorical_crossentropy')
# we train our model again (this time fine-tuning the top 2 inception blocks
# alongside the top Dense layers
model.fit_generator(...)
```
### Build InceptionV3 over a custom input tensor
```python
from keras.applications.inception_v3 import InceptionV3
from keras.layers import Input
# this could also be the output a different Keras model or layer
input_tensor = Input(shape=(224, 224, 3)) # this assumes K.image_dim_ordering() == 'tf'
model = InceptionV3(input_tensor=input_tensor, weights='imagenet', include_top=True)
```
-----
## VGG16
```python
keras.applications.vgg16.VGG16(include_top=True, weights='imagenet', input_tensor=None)
```
### Arguments
- include_top: whether to include the 3 fully-connected layers 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
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556): please cite this paper if you use the VGG models in your work.
### License
These weights are ported from the ones [released by VGG at Oxford](http://www.robots.ox.ac.uk/~vgg/research/very_deep/) under the [Creative Commons Attribution License](https://creativecommons.org/licenses/by/4.0/).
-----
## VGG19
```python
keras.applications.vgg19.VGG19(include_top=True, weights='imagenet', input_tensor=None)
```
### Arguments
- include_top: whether to include the 3 fully-connected layers 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
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556)
### License
These weights are ported from the ones [released by VGG at Oxford](http://www.robots.ox.ac.uk/~vgg/research/very_deep/) under the [Creative Commons Attribution License](https://creativecommons.org/licenses/by/4.0/).
-----
## ResNet50
```python
keras.applications.resnet50.ResNet50(include_top=True, weights='imagenet', input_tensor=None)
```
### Arguments
- include_top: whether to include the 3 fully-connected layers 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
- [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385)
### License
These weights are ported from the ones [released by Kaiming He](https://github.com/KaimingHe/deep-residual-networks) under the [MIT license](https://github.com/KaimingHe/deep-residual-networks/blob/master/LICENSE).
-----
## InceptionV3
```python
keras.applications.inception_v3.InceptionV3(include_top=True, weights='imagenet', input_tensor=None)
```
### Arguments
- include_top: whether to include the 3 fully-connected layers 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
- [Rethinking the Inception Architecture for Computer Vision](http://arxiv.org/abs/1512.00567)
### License
These weights are trained by ourselves and are released under the MIT license.
+14 -6
Ver Arquivo
@@ -4,10 +4,12 @@
Keras is a model-level library, providing high-level building blocks for developing deep learning models. It does not handle itself low-level operations such as tensor products, convolutions and so on. Instead, it relies on a specialized, well-optimized tensor manipulation library to do so, serving as the "backend engine" of Keras. Rather than picking one single tensor library and making the implementation of Keras tied to that library, Keras handles the problem in a modular way, and several different backend engines can be plugged seamlessly into Keras.
At this time, Keras has two backend implementations available: the **Theano** backend and the **TensorFlow** backend.
At this time, Keras has two backend implementations available: the **TensorFlow** backend and the **Theano** backend.
- [Theano](http://deeplearning.net/software/theano/) is an open-source symbolic tensor manipulation framework developed by LISA/MILA Lab at Université de Montréal.
- [TensorFlow](http://www.tensorflow.org/) is an open-source symbolic tensor manipulation framework developed by Google, Inc.
- [Theano](http://deeplearning.net/software/theano/) is an open-source symbolic tensor manipulation framework developed by LISA/MILA Lab at Université de Montréal.
In the future, we are likely to add more backend options. If you are interested in developing a new backend, get in touch!
----
@@ -19,9 +21,16 @@ If you have run Keras at least once, you will find the Keras configuration file
If it isn't there, you can create it.
It probably looks like this:
The default configuration file looks like this:
`{"epsilon": 1e-07, "floatx": "float32", "backend": "theano"}`
```
{
"image_dim_ordering": "tf",
"epsilon": 1e-07,
"floatx": "float32",
"backend": "tensorflow"
}
```
Simply change the field `backend` to either `"theano"` or `"tensorflow"`, and Keras will use the new configuration next time you run any Keras code.
@@ -29,9 +38,8 @@ You can also define the environment variable ``KERAS_BACKEND`` and this will
override what is defined in your config file :
```bash
KERAS_BACKEND=tensorflow python -c "from keras import backend; print backend._BACKEND"
KERAS_BACKEND=tensorflow python -c "from keras import backend"
Using TensorFlow backend.
tensorflow
```
----
+18 -5
Ver Arquivo
@@ -53,11 +53,14 @@ As a convention, "0" does not stand for a specific word, but instead is used to
```python
from keras.datasets import imdb
(X_train, y_train), (X_test, y_test) = imdb.load_data(path="imdb.pkl",
(X_train, y_train), (X_test, y_test) = imdb.load_data(path="imdb_full.pkl",
nb_words=None,
skip_top=0,
maxlen=None,
test_split=0.1)
seed=113,
start_char=1,
oov_char=2,
index_from=3)
```
- __Return:__
- 2 tuples:
@@ -70,8 +73,12 @@ from keras.datasets import imdb
- __nb_words__: integer or None. Top most frequent words to consider. Any less frequent word will appear as 0 in the sequence data.
- __skip_top__: integer. Top most frequent words to ignore (they will appear as 0s in the sequence data).
- __maxlen__: int. Maximum sequence length. Any longer sequence will be truncated.
- __test_split__: float. Fraction of the dataset to be used as test data.
- __seed__: int. Seed for reproducible data shuffling.
- __start_char__: char. The start of a sequence will be marked with this character.
Set to 1 because 0 is usually the padding character.
- __oov_char__: char. words that were cut out because of the `nb_words`
or `skip_top` limit will be replaced with this character.
- __index_from__: int. Index actual words with this index and higher.
---
@@ -88,10 +95,16 @@ from keras.datasets import reuters
nb_words=None,
skip_top=0,
maxlen=None,
test_split=0.1)
test_split=0.2,
seed=113,
start_char=1,
oov_char=2,
index_from=3)
```
The specifications are the same as that of the IMDB dataset.
The specifications are the same as that of the IMDB dataset, with the addition of:
- __test_split__: float. Fraction of the dataset to be used as test data.
This dataset also makes available the word index used for encoding the sequences:
+69 -18
Ver Arquivo
@@ -58,7 +58,31 @@ theano.config.floatX = 'float32'
*It is not recommended to use pickle or cPickle to save a Keras model.*
If you only need to save the architecture of a model, and not its weights, you can do:
You can use `model.save(filepath)` to save a Keras model into a single HDF5 file which will contain:
- the architecture of the model, allowing to re-create the model
- the weights of the model
- the training configuration (loss, optimizer)
- the state of the optimizer, allowing to resume training exactly where you left off.
You can then use `keras.models.load_model(filepath)` to reinstantiate your model.
`load_model` will also take care of compiling the model using the saved training configuration
(unless the model was never compiled in the first place).
Example:
```python
from keras.models import load_model
model.save('my_model.h5') # creates a HDF5 file 'my_model.h5'
del model # deletes the existing model
# returns a compiled model
# identical to the previous one
model = load_model('my_model.h5')
```
If you only need to save the **architecture of a model**, and not its weights or its training configuration, you can do:
```python
# save as JSON
@@ -68,6 +92,8 @@ json_string = model.to_json()
yaml_string = model.to_yaml()
```
The generated JSON / YAML files are human-readable and can be manually edited if needed.
You can then build a fresh model from this data:
```python
@@ -79,7 +105,7 @@ model = model_from_json(json_string)
model = model_from_yaml(yaml_string)
```
If you need to save the weights of a model, you can do so in HDF5 with the code below.
If you need to save the **weights of a model**, you can do so in HDF5 with the code below.
Note that you will first need to install HDF5 and the Python library h5py, which do not come bundled with Keras.
@@ -87,26 +113,37 @@ Note that you will first need to install HDF5 and the Python library h5py, which
model.save_weights('my_model_weights.h5')
```
Assuming you have code for instantiating your model, you can then load the weights you saved into a model with the same architecture:
Assuming you have code for instantiating your model, you can then load the weights you saved into a model with the *same* architecture:
```python
model.load_weights('my_model_weights.h5')
```
This leads us to a way to save and reconstruct models from only serialized data:
```python
json_string = model.to_json()
open('my_model_architecture.json', 'w').write(json_string)
model.save_weights('my_model_weights.h5')
If you need to load weights into a *different* architecture (with some layers in common), for instance for fine-tuning or transfer-learning, you can load weights by *layer name*:
# elsewhere...
model = model_from_json(open('my_model_architecture.json').read())
model.load_weights('my_model_weights.h5')
```python
model.load_weights('my_model_weights.h5', by_name=True)
```
Finally, before it can be used, the model shall be compiled.
For example:
```python
model.compile(optimizer='adagrad', loss='mse')
"""
Assume original model looks like this:
model = Sequential()
model.add(Dense(2, input_dim=3, name="dense_1"))
model.add(Dense(3, name="dense_2"))
...
model.save_weights(fname)
"""
# new model
model = Sequential()
model.add(Dense(2, input_dim=3, name="dense_1")) # will be loaded
model.add(Dense(10, name="new_dense")) # will not be loaded
# load weights from first model; will only affect the first layer, dense_1.
model.load_weights(fname, by_name=True)
```
---
@@ -321,13 +358,27 @@ print(len(model.layers)) # "1"
Code and pre-trained weights are available for the following image classification models:
- [VGG-16](https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3)
- [VGG-19](https://gist.github.com/baraldilorenzo/8d096f48a1be4a2d660d)
- [AlexNet](https://github.com/heuritech/convnets-keras)
- VGG16
- VGG19
- ResNet50
- Inception v3
For an example of how to use such a pre-trained model for feature extraction or for fine-tuning, see [this blog post](http://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html).
They can be imported from the module `keras.applications`:
The VGG-16 model is also the basis for several Keras example scripts:
```python
from keras.applications.vgg16 import VGG16
from keras.applications.vgg19 import VGG19
from keras.applications.resnet50 import ResNet50
from keras.applications.inception_v3 import InceptionV3
model = VGG16(weights='imagenet', include_top=True)
```
For a few simple usage examples, see [the documentation for the Applications module](/applications).
For a detailed example of how to use such a pre-trained model for feature extraction or for fine-tuning, see [this blog post](http://blog.keras.io/building-powerful-image-classification-models-using-very-little-data.html).
The VGG16 model is also the basis for several Keras example scripts:
- [Style transfer](https://github.com/fchollet/keras/blob/master/examples/neural_style_transfer.py)
- [Feature visualization](https://github.com/fchollet/keras/blob/master/examples/conv_filter_visualization.py)
+2 -2
Ver Arquivo
@@ -75,7 +75,7 @@ The model will also be supervised via two loss functions. Using the main loss fu
Here's what our model looks like:
<img src="http://s3.amazonaws.com/keras.io/img/multi-input-multi-output-graph.png" alt="multi-input-multi-output-graph" style="width: 400px;"/>
<img src="https://s3.amazonaws.com/keras.io/img/multi-input-multi-output-graph.png" alt="multi-input-multi-output-graph" style="width: 400px;"/>
Let's implement it with the functional API.
@@ -310,7 +310,7 @@ from keras.layers import merge, Convolution2D, Input
# input tensor for a 3-channel 256x256 image
x = Input(shape=(3, 256, 256))
# 3x3 conv with 3 output channels (same as input channels)
y = Convolution2D(3, 3, 3, border_mode='same')
y = Convolution2D(3, 3, 3, border_mode='same')(x)
# this returns x + y.
z = merge([x, y], mode='sum')
```
+5 -5
Ver Arquivo
@@ -86,7 +86,7 @@ final_model.add(merged)
final_model.add(Dense(10, activation='softmax'))
```
<img src="http://s3.amazonaws.com/keras.io/img/two_branches_sequential_model.png" alt="two branch Sequential" style="width: 400px;"/>
<img src="https://s3.amazonaws.com/keras.io/img/two_branches_sequential_model.png" alt="two branch Sequential" style="width: 400px;"/>
Such a two-branch model can then be trained via e.g.:
@@ -107,7 +107,7 @@ The `Merge` layer supports a number of pre-defined modes:
You can also pass a function as the `mode` argument, allowing for arbitrary transformations:
```python
merged = Merge([left_branch, right_branch], mode=lambda x, y: x - y)
merged = Merge([left_branch, right_branch], mode=lambda x: x[0] - x[1])
```
Now you know enough to be able to define *almost* any model with Keras. For complex models that cannot be expressed via `Sequential` and `Merge`, you can use [the functional API](/getting-started/functional-api-guide).
@@ -149,7 +149,7 @@ Keras models are trained on Numpy arrays of input data and labels. For training
# for a single-input model with 2 classes (binary):
model = Sequential()
model.add(Dense(1, input_dim=784, activation='softmax'))
model.add(Dense(1, input_dim=784, activation='sigmoid'))
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
@@ -418,7 +418,7 @@ The first two LSTMs return their full output sequences, but the last one only re
the last step in its output sequence, thus dropping the temporal dimension
(i.e. converting the input sequence into a single vector).
<img src="http://keras.io/img/regular_stacked_lstm.png" alt="stacked LSTM" style="width: 300px;"/>
<img src="https://keras.io/img/regular_stacked_lstm.png" alt="stacked LSTM" style="width: 300px;"/>
```python
from keras.models import Sequential
@@ -507,7 +507,7 @@ In this model, two input sequences are encoded into vectors by two separate LSTM
These two vectors are then concatenated, and a fully connected network is trained on top of the concatenated representations.
<img src="http://keras.io/img/dual_lstm.png" alt="Dual LSTM" style="width: 600px;"/>
<img src="https://keras.io/img/dual_lstm.png" alt="Dual LSTM" style="width: 600px;"/>
```python
from keras.models import Sequential
+15 -14
Ver Arquivo
@@ -2,14 +2,14 @@
## 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 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.*
Use Keras if you need a deep learning library that:
- allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
- supports both convolutional networks and recurrent networks, as well as combinations of the two.
- supports arbitrary connectivity schemes (including multi-input and multi-output training).
- runs seamlessly on CPU and GPU.
- Allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
- Supports both convolutional networks and recurrent networks, as well as combinations of the two.
- Supports arbitrary connectivity schemes (including multi-input and multi-output training).
- Runs seamlessly on CPU and GPU.
Read the documentation at [Keras.io](http://keras.io).
@@ -33,7 +33,6 @@ Keras is compatible with: __Python 2.7-3.5__.
------------------
## Getting started: 30 seconds to Keras
The core data structure of Keras is a __model__, a way to organize layers. The main type of model is the [`Sequential`](http://keras.io/getting-started/sequential-model-guide) model, a linear stack of layers. For more complex architectures, you should use the [Keras functional API](http://keras.io/getting-started/functional-api-guide).
@@ -98,6 +97,7 @@ For a more in-depth tutorial about Keras, you can check out:
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repository, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, etc.
------------------
@@ -110,32 +110,33 @@ Keras uses the following dependencies:
- HDF5 and h5py (optional, required if you use model saving/loading functions)
- Optional but recommended if you use CNNs: cuDNN.
*When using the Theano backend:*
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
*When using the TensorFlow backend:*
- TensorFlow
- [See installation instructions](https://github.com/tensorflow/tensorflow#download-and-setup).
*When using the Theano backend:*
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
To install Keras, `cd` to the Keras folder and run the install command:
```
```sh
sudo python setup.py install
```
You can also install Keras from PyPI:
```
```sh
sudo pip install keras
```
------------------
## Switching from Theano to TensorFlow
## Switching from TensorFlow to Theano
By default, Keras will use Theano as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
By default, Keras will use TensorFlow as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
------------------
+1 -1
Ver Arquivo
@@ -30,4 +30,4 @@ yaml_string = model.to_yaml()
model = model_from_yaml(yaml_string)
```
- `model.save_weights(filepath)`: saves the weights of the model as a HDF5 file.
- `model.load_weights(filepath)`: loads the weights of the model from a HDF5 file (created by `save_weights`).
- `model.load_weights(filepath, by_name=False)`: loads the weights of the model from a HDF5 file (created by `save_weights`). By default, the architecture is expected to be unchanged. To load weights into a different architecture (with some layers in common), use `by_name=True` to load only those layers with the same name.
+20 -1
Ver Arquivo
@@ -9,7 +9,7 @@ model.add(Dense(64, init='uniform', input_dim=10))
model.add(Activation('tanh'))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
```
@@ -22,4 +22,23 @@ model.compile(loss='mean_squared_error', optimizer='sgd')
---
## Parameters common to all Keras optimizers
The parameters `clipnorm` and `clipvalue` can be used with all optimizers to control gradient clipping:
```python
# all parameter gradients will be clipped to
# a maximum norm of 1.
sgd = SGD(lr=0.01, clipnorm=1.)
```
```python
# all parameter gradients will be clipped to
# a maximum value of 0.5 and
# a minimum value of -0.5.
sgd = SGD(lr=0.01, clipvalue=0.5)
```
---
{{autogenerated}}
+4 -4
Ver Arquivo
@@ -61,15 +61,15 @@ Generate batches of tensor image data with real-time data augmentation. The data
- __X__: data.
- __y__: labels.
- __batch_size__: int (default: 32).
- __shuffle__: boolean (defaut: False).
- __shuffle__: boolean (defaut: True).
- __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".
- ___yields__: Tuples of `(x, y)` where `x` is a numpy array of image data and `y` is a numpy array of corresponding labels.
- __yields__: Tuples of `(x, y)` where `x` is a numpy array of image data and `y` is a numpy array of corresponding labels.
The generator loops indefinitely.
- __flow_from_directory(directory)__: Takes the path to a directory, and generates batches of augmented/normalized data. Yields batches indefinitely, in an infinite loop.
- __Arguments__:
- __directory: path to the target directory. It should contain one subdirectory per class,
- __directory__: path to the target directory. It should contain one subdirectory per class,
and the subdirectories should contain PNG or JPG images. See [this script](https://gist.github.com/fchollet/0830affa1f7f19fd47b06d4cf89ed44d) for more details.
- __target_size__: tuple of integers, default: `(256, 256)`. The dimensions to which all images found will be resized.
- __color_mode__: one of "grayscale", "rbg". Default: "rgb". Whether the images will be converted to have 1 or 3 color channels.
@@ -88,7 +88,7 @@ Generate batches of tensor image data with real-time data augmentation. The data
Example of using `.flow(X, y)`:
```python
(X_train, y_train), (X_test, y_test) = cifar10.load_data(test_split=0.1)
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
+3 -3
Ver Arquivo
@@ -1,12 +1,12 @@
# Wrappers for the Scikit-Learn API
You can use `Sequential` Keras models (single-input only) as part of your Scikit-Learn workflow via the wrappers found at `keras.wrappers.sklearn.py`.
You can use `Sequential` Keras models (single-input only) as part of your Scikit-Learn workflow via the wrappers found at `keras.wrappers.scikit_learn.py`.
There are two wrappers available:
`keras.wrappers.sklearn.KerasClassifier(build_fn=None, **sk_params)`, which implements the sklearn classifier interface,
`keras.wrappers.scikit_learn.KerasClassifier(build_fn=None, **sk_params)`, which implements the Scikit-Learn classifier interface,
`keras.wrappers.sklearn.KerasRegressor(build_fn=None, **sk_params)`, which implements the sklearn regressor interface.
`keras.wrappers.scikit_learn.KerasRegressor(build_fn=None, **sk_params)`, which implements the Scikit-Learn regressor interface.
### Arguments
+2 -1
Ver Arquivo
@@ -95,7 +95,7 @@ def vectorize_stories(data, word_idx, story_maxlen, query_maxlen):
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
path = get_file('babi-tasks-v1-2.tar.gz', origin='https://s3.amazonaws.com/text-datasets/babi_tasks_1-20_v1-2.tar.gz')
except:
print('Error downloading dataset, please download it manually:\n'
'$ wget http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz\n'
@@ -173,6 +173,7 @@ match = Sequential()
match.add(Merge([input_encoder_m, question_encoder],
mode='dot',
dot_axes=[2, 2]))
match.add(Activation('softmax'))
# output: (samples, story_maxlen, query_maxlen)
# embed the input into a single vector with size = story_maxlen:
input_encoder_c = Sequential()
+1 -1
Ver Arquivo
@@ -147,7 +147,7 @@ EPOCHS = 40
print('RNN / Embed / Sent / Query = {}, {}, {}, {}'.format(RNN, EMBED_HIDDEN_SIZE, SENT_HIDDEN_SIZE, QUERY_HIDDEN_SIZE))
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
path = get_file('babi-tasks-v1-2.tar.gz', origin='https://s3.amazonaws.com/text-datasets/babi_tasks_1-20_v1-2.tar.gz')
except:
print('Error downloading dataset, please download it manually:\n'
'$ wget http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz\n'
+1 -1
Ver Arquivo
@@ -43,7 +43,7 @@ Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(32, 3, 3, border_mode='same',
input_shape=(img_channels, img_rows, img_cols)))
input_shape=X_train.shape[1:]))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
+23 -75
Ver Arquivo
@@ -3,32 +3,21 @@
This script can run on CPU in a few minutes (with the TensorFlow backend).
Results example: http://i.imgur.com/4nj4KjN.jpg
Before running this script, download the weights for the VGG16 model at:
https://drive.google.com/file/d/0Bz7KyqmuGsilT0J5dmRCM0ROVHc/view?usp=sharing
(source: https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3)
and make sure the variable `weights_path` in this script matches the location of the file.
'''
from __future__ import print_function
from scipy.misc import imsave
import numpy as np
import time
import os
import h5py
from keras.models import Sequential
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.applications import vgg16
from keras import backend as K
# dimensions of the generated pictures for each filter.
img_width = 128
img_height = 128
# path to the model weights file.
weights_path = 'vgg16_weights.h5'
# the name of the layer we want to visualize (see model definition below)
layer_name = 'conv5_1'
# the name of the layer we want to visualize
# (see model definition at keras/applications/vgg16.py)
layer_name = 'block5_conv1'
# util function to convert a tensor into a valid image
def deprocess_image(x):
@@ -43,70 +32,22 @@ def deprocess_image(x):
# convert to RGB array
x *= 255
x = x.transpose((1, 2, 0))
if K.image_dim_ordering() == 'th':
x = x.transpose((1, 2, 0))
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
input_img = first_layer.input
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
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 ImageNet weights
model = vgg16.VGG16(weights='imagenet', include_top=False)
print('Model loaded.')
model.summary()
# this is the placeholder for the input images
input_img = model.input
# get the symbolic outputs of each "key" layer (we gave them unique names).
layer_dict = dict([(layer.name, layer) for layer in model.layers])
layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]])
def normalize(x):
@@ -124,7 +65,10 @@ for filter_index in range(0, 200):
# we build a loss function that maximizes the activation
# of the nth filter of the layer considered
layer_output = layer_dict[layer_name].output
loss = K.mean(layer_output[:, filter_index, :, :])
if K.image_dim_ordering() == 'th':
loss = K.mean(layer_output[:, filter_index, :, :])
else:
loss = K.mean(layer_output[:, :, :, filter_index])
# we compute the gradient of the input picture wrt this loss
grads = K.gradients(loss, input_img)[0]
@@ -139,7 +83,11 @@ for filter_index in range(0, 200):
step = 1.
# we start from a gray image with some random noise
input_img_data = np.random.random((1, 3, img_width, img_height)) * 20 + 128.
if K.image_dim_ordering() == 'th':
input_img_data = np.random.random((1, 3, img_width, img_height))
else:
input_img_data = np.random.random((1, img_width, img_height, 3))
input_img_data = (input_img_data - 0.5) * 20 + 128
# we run gradient ascent for 20 steps
for i in range(20):
+470
Ver Arquivo
@@ -0,0 +1,470 @@
'''This example uses a convolutional stack followed by a recurrent stack
and a CTC logloss function to perform optical character recognition
of generated text images. I have no evidence of whether it actually
learns general shapes of text, or just is able to recognize all
the different fonts thrown at it...the purpose is more to demonstrate CTC
inside of Keras. Note that the font list may need to be updated
for the particular OS in use.
This starts off with 4 letter words. After 10 or so epochs, CTC
learns translational invariance, so longer words and groups of words
with spaces are gradually fed in. This gradual increase in difficulty
is handled using the TextImageGenerator class which is both a generator
class for test/train data and a Keras callback class. Every 10 epochs
the wordlist that the generator draws from increases in difficulty.
The table below shows normalized edit distance values. Theano uses
a slightly different CTC implementation, so some Theano-specific
hyperparameter tuning would be needed to get it to match Tensorflow.
Norm. ED
Epoch | TF | TH
------------------------
10 0.072 0.272
20 0.032 0.115
30 0.024 0.098
40 0.023 0.108
This requires cairo and editdistance packages:
pip install cairocffi
pip install editdistance
Due to the use of a dummy loss function, Theano requires the following flags:
on_unused_input='ignore'
Created by Mike Henry
https://github.com/mbhenry/
'''
import os
import itertools
import re
import datetime
import cairocffi as cairo
import editdistance
import numpy as np
from scipy import ndimage
import pylab
from keras import backend as K
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers import Input, Layer, Dense, Activation, Flatten
from keras.layers import Reshape, Lambda, merge, Permute, TimeDistributed
from keras.models import Model
from keras.layers.recurrent import GRU
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.utils.data_utils import get_file
from keras.preprocessing import image
import keras.callbacks
OUTPUT_DIR = "image_ocr"
np.random.seed(55)
# this creates larger "blotches" of noise which look
# more realistic than just adding gaussian noise
# assumes greyscale with pixels ranging from 0 to 1
def speckle(img):
severity = np.random.uniform(0, 0.6)
blur = ndimage.gaussian_filter(np.random.randn(*img.shape) * severity, 1)
img_speck = (img + blur)
img_speck[img_speck > 1] = 1
img_speck[img_speck <= 0] = 0
return img_speck
# paints the string in a random location the bounding box
# also uses a random font, a slight random rotation,
# and a random amount of speckle noise
def paint_text(text, w, h):
surface = cairo.ImageSurface(cairo.FORMAT_RGB24, w, h)
with cairo.Context(surface) as context:
context.set_source_rgb(1, 1, 1) # White
context.paint()
# this font list works in Centos 7
fonts = ['Century Schoolbook', 'Courier', 'STIX', 'URW Chancery L', 'FreeMono']
context.select_font_face(np.random.choice(fonts), cairo.FONT_SLANT_NORMAL,
np.random.choice([cairo.FONT_WEIGHT_BOLD, cairo.FONT_WEIGHT_NORMAL]))
context.set_font_size(40)
box = context.text_extents(text)
if box[2] > w or box[3] > h:
raise IOError('Could not fit string into image. Max char count is too large for given image width.')
# teach the RNN translational invariance by
# fitting text box randomly on canvas, with some room to rotate
border_w_h = (10, 16)
max_shift_x = w - box[2] - border_w_h[0]
max_shift_y = h - box[3] - border_w_h[1]
top_left_x = np.random.randint(0, int(max_shift_x))
top_left_y = np.random.randint(0, int(max_shift_y))
context.move_to(top_left_x - int(box[0]), top_left_y - int(box[1]))
context.set_source_rgb(0, 0, 0)
context.show_text(text)
buf = surface.get_data()
a = np.frombuffer(buf, np.uint8)
a.shape = (h, w, 4)
a = a[:, :, 0] # grab single channel
a /= 255
a = np.expand_dims(a, 0)
a = speckle(a)
a = image.random_rotation(a, 3 * (w - top_left_x) / w + 1)
return a
def shuffle_mats_or_lists(matrix_list, stop_ind=None):
ret = []
assert all([len(i) == len(matrix_list[0]) for i in matrix_list])
len_val = len(matrix_list[0])
if stop_ind is None:
stop_ind = len_val
assert stop_ind <= len_val
a = range(stop_ind)
np.random.shuffle(a)
a += range(stop_ind, len_val)
for mat in matrix_list:
if isinstance(mat, np.ndarray):
ret.append(mat[a])
elif isinstance(mat, list):
ret.append([mat[i] for i in a])
else:
raise TypeError('shuffle_mats_or_lists only supports '
'numpy.array and list objects')
return ret
def text_to_labels(text, num_classes):
ret = []
for char in text:
if char >= 'a' and char <= 'z':
ret.append(ord(char) - ord('a'))
elif char == ' ':
ret.append(26)
return ret
# only a-z and space..probably not to difficult
# to expand to uppercase and symbols
def is_valid_str(in_str):
search = re.compile(r'[^a-z\ ]').search
return not bool(search(in_str))
# Uses generator functions to supply train/test with
# data. Image renderings are text are created on the fly
# each time with random perturbations
class TextImageGenerator(keras.callbacks.Callback):
def __init__(self, monogram_file, bigram_file, minibatch_size,
img_w, img_h, downsample_width, val_split,
absolute_max_string_len=16):
self.minibatch_size = minibatch_size
self.img_w = img_w
self.img_h = img_h
self.monogram_file = monogram_file
self.bigram_file = bigram_file
self.downsample_width = downsample_width
self.val_split = val_split
self.blank_label = self.get_output_size() - 1
self.absolute_max_string_len = absolute_max_string_len
def get_output_size(self):
return 28
# num_words can be independent of the epoch size due to the use of generators
# as max_string_len grows, num_words can grow
def build_word_list(self, num_words, max_string_len=None, mono_fraction=0.5):
assert max_string_len <= self.absolute_max_string_len
assert num_words % self.minibatch_size == 0
assert (self.val_split * num_words) % self.minibatch_size == 0
self.num_words = num_words
self.string_list = []
self.max_string_len = max_string_len
self.Y_data = np.ones([self.num_words, self.absolute_max_string_len]) * -1
self.X_text = []
self.Y_len = [0] * self.num_words
# monogram file is sorted by frequency in english speech
with open(self.monogram_file, 'rt') as f:
for line in f:
if len(self.string_list) == int(self.num_words * mono_fraction):
break
word = line.rstrip()
if max_string_len == -1 or max_string_len is None or len(word) <= max_string_len:
self.string_list.append(word)
# bigram file contains common word pairings in english speech
with open(self.bigram_file, 'rt') as f:
lines = f.readlines()
for line in lines:
if len(self.string_list) == self.num_words:
break
columns = line.lower().split()
word = columns[0] + ' ' + columns[1]
if is_valid_str(word) and \
(max_string_len == -1 or max_string_len is None or len(word) <= max_string_len):
self.string_list.append(word)
if len(self.string_list) != self.num_words:
raise IOError('Could not pull enough words from supplied monogram and bigram files. ')
for i, word in enumerate(self.string_list):
self.Y_len[i] = len(word)
self.Y_data[i, 0:len(word)] = text_to_labels(word, self.get_output_size())
self.X_text.append(word)
self.Y_len = np.expand_dims(np.array(self.Y_len), 1)
self.cur_val_index = self.val_split
self.cur_train_index = 0
# each time an image is requested from train/val/test, a new random
# painting of the text is performed
def get_batch(self, index, size, train):
if K.image_dim_ordering() == 'th':
X_data = np.ones([size, 1, self.img_h, self.img_w])
else:
X_data = np.ones([size, self.img_h, self.img_w, 1])
labels = np.ones([size, self.absolute_max_string_len])
input_length = np.zeros([size, 1])
label_length = np.zeros([size, 1])
source_str = []
for i in range(0, size):
# Mix in some blank inputs. This seems to be important for
# achieving translational invariance
if train and i > size - 4:
if K.image_dim_ordering() == 'th':
X_data[i, 0, :, :] = paint_text('', self.img_w, self.img_h)
else:
X_data[i, :, :, 0] = paint_text('', self.img_w, self.img_h)
labels[i, 0] = self.blank_label
input_length[i] = self.downsample_width
label_length[i] = 1
source_str.append('')
else:
if K.image_dim_ordering() == 'th':
X_data[i, 0, :, :] = paint_text(self.X_text[index + i], self.img_w, self.img_h)
else:
X_data[i, :, :, 0] = paint_text(self.X_text[index + i], self.img_w, self.img_h)
labels[i, :] = self.Y_data[index + i]
input_length[i] = self.downsample_width
label_length[i] = self.Y_len[index + i]
source_str.append(self.X_text[index + i])
inputs = {'the_input': X_data,
'the_labels': labels,
'input_length': input_length,
'label_length': label_length,
'source_str': source_str # used for visualization only
}
outputs = {'ctc': np.zeros([size])} # dummy data for dummy loss function
return (inputs, outputs)
def next_train(self):
while 1:
ret = self.get_batch(self.cur_train_index, self.minibatch_size, train=True)
self.cur_train_index += self.minibatch_size
if self.cur_train_index >= self.val_split:
self.cur_train_index = self.cur_train_index % 32
(self.X_text, self.Y_data, self.Y_len) = shuffle_mats_or_lists(
[self.X_text, self.Y_data, self.Y_len], self.val_split)
yield ret
def next_val(self):
while 1:
ret = self.get_batch(self.cur_val_index, self.minibatch_size, train=False)
self.cur_val_index += self.minibatch_size
if self.cur_val_index >= self.num_words:
self.cur_val_index = self.val_split + self.cur_val_index % 32
yield ret
def on_train_begin(self, logs={}):
# translational invariance seems to be the hardest thing
# for the RNN to learn, so start with <= 4 letter words.
self.build_word_list(16000, 4, 1)
def on_epoch_begin(self, epoch, logs={}):
# After 10 epochs, translational invariance should be learned
# so start feeding longer words and eventually multiple words with spaces
if epoch == 10:
self.build_word_list(32000, 8, 1)
if epoch == 20:
self.build_word_list(32000, 8, 0.6)
if epoch == 30:
self.build_word_list(64000, 12, 0.5)
# the actual loss calc occurs here despite it not being
# an internal Keras loss function
def ctc_lambda_func(args):
y_pred, labels, input_length, label_length = args
# the 2 is critical here since the first couple outputs of the RNN
# tend to be garbage:
y_pred = y_pred[:, 2:, :]
return K.ctc_batch_cost(labels, y_pred, input_length, label_length)
# For a real OCR application, this should be beam search with a dictionary
# and language model. For this example, best path is sufficient.
def decode_batch(test_func, word_batch):
out = test_func([word_batch])[0]
ret = []
for j in range(out.shape[0]):
out_best = list(np.argmax(out[j, 2:], 1))
out_best = [k for k, g in itertools.groupby(out_best)]
# 26 is space, 27 is CTC blank char
outstr = ''
for c in out_best:
if c >= 0 and c < 26:
outstr += chr(c + ord('a'))
elif c == 26:
outstr += ' '
ret.append(outstr)
return ret
class VizCallback(keras.callbacks.Callback):
def __init__(self, test_func, text_img_gen, num_display_words=6):
self.test_func = test_func
self.output_dir = os.path.join(
OUTPUT_DIR, datetime.datetime.now().strftime('%A, %d. %B %Y %I.%M%p'))
self.text_img_gen = text_img_gen
self.num_display_words = num_display_words
os.makedirs(self.output_dir)
def show_edit_distance(self, num):
num_left = num
mean_norm_ed = 0.0
mean_ed = 0.0
while num_left > 0:
word_batch = next(self.text_img_gen)[0]
num_proc = min(word_batch['the_input'].shape[0], num_left)
decoded_res = decode_batch(self.test_func, word_batch['the_input'][0:num_proc])
for j in range(0, num_proc):
edit_dist = editdistance.eval(decoded_res[j], word_batch['source_str'][j])
mean_ed += float(edit_dist)
mean_norm_ed += float(edit_dist) / len(word_batch['source_str'][j])
num_left -= num_proc
mean_norm_ed = mean_norm_ed / num
mean_ed = mean_ed / num
print('\nOut of %d samples: Mean edit distance: %.3f Mean normalized edit distance: %0.3f'
% (num, mean_ed, mean_norm_ed))
def on_epoch_end(self, epoch, logs={}):
self.model.save_weights(os.path.join(self.output_dir, 'weights%02d.h5' % epoch))
self.show_edit_distance(256)
word_batch = next(self.text_img_gen)[0]
res = decode_batch(self.test_func, word_batch['the_input'][0:self.num_display_words])
for i in range(self.num_display_words):
pylab.subplot(self.num_display_words, 1, i + 1)
if K.image_dim_ordering() == 'th':
the_input = word_batch['the_input'][i, 0, :, :]
else:
the_input = word_batch['the_input'][i, :, :, 0]
pylab.imshow(the_input, cmap='Greys_r')
pylab.xlabel('Truth = \'%s\' Decoded = \'%s\'' % (word_batch['source_str'][i], res[i]))
fig = pylab.gcf()
fig.set_size_inches(10, 12)
pylab.savefig(os.path.join(self.output_dir, 'e%02d.png' % epoch))
pylab.close()
# Input Parameters
img_h = 64
img_w = 512
nb_epoch = 50
minibatch_size = 32
words_per_epoch = 16000
val_split = 0.2
val_words = int(words_per_epoch * (val_split))
# Network parameters
conv_num_filters = 16
filter_size = 3
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)
if K.image_dim_ordering() == 'th':
input_shape = (1, img_h, img_w)
else:
input_shape = (img_h, img_w, 1)
fdir = os.path.dirname(get_file('wordlists.tgz',
origin='http://www.isosemi.com/datasets/wordlists.tgz', untar=True))
img_gen = TextImageGenerator(monogram_file=os.path.join(fdir, 'wordlist_mono_clean.txt'),
bigram_file=os.path.join(fdir, 'wordlist_bi_clean.txt'),
minibatch_size=32,
img_w=img_w,
img_h=img_h,
downsample_width=img_w / (pool_size_1 * pool_size_2) - 2,
val_split=words_per_epoch - val_words)
act = 'relu'
input_data = Input(name='the_input', shape=input_shape, dtype='float32')
inner = Convolution2D(conv_num_filters, filter_size, filter_size, border_mode='same',
activation=act, name='conv1')(input_data)
inner = MaxPooling2D(pool_size=(pool_size_1, pool_size_1), name='max1')(inner)
inner = Convolution2D(conv_num_filters, filter_size, filter_size, border_mode='same',
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))
inner = Reshape(target_shape=conv_to_rnn_dims, name='reshape')(inner)
inner = Permute(dims=(2, 1), name='permute')(inner)
# cuts down input size going into RNN:
inner = TimeDistributed(Dense(time_dense_size, activation=act, name='dense1'))(inner)
# Two layers of bidirecitonal GRUs
# GRU seems to work as well, if not better than LSTM:
gru_1 = GRU(rnn_size, return_sequences=True, name='gru1')(inner)
gru_1b = GRU(rnn_size, return_sequences=True, go_backwards=True, name='gru1_b')(inner)
gru1_merged = merge([gru_1, gru_1b], mode='sum')
gru_2 = GRU(rnn_size, return_sequences=True, name='gru2')(gru1_merged)
gru_2b = GRU(rnn_size, return_sequences=True, go_backwards=True)(gru1_merged)
# transforms RNN output to character activations:
inner = TimeDistributed(Dense(img_gen.get_output_size(), name='dense2'))(merge([gru_2, gru_2b], mode='concat'))
y_pred = Activation('softmax', name='softmax')(inner)
Model(input=[input_data], output=y_pred).summary()
labels = Input(name='the_labels', shape=[img_gen.absolute_max_string_len], dtype='float32')
input_length = Input(name='input_length', shape=[1], dtype='int64')
label_length = Input(name='label_length', shape=[1], dtype='int64')
# Keras doesn't currently support loss funcs with extra parameters
# so CTC loss is implemented in a lambda layer
loss_out = Lambda(ctc_lambda_func, output_shape=(1,), name="ctc")([y_pred, labels, input_length, label_length])
lr = 0.03
# clipnorm seems to speeds up convergence
clipnorm = 5
sgd = SGD(lr=lr, decay=3e-7, momentum=0.9, nesterov=True, clipnorm=clipnorm)
model = Model(input=[input_data, labels, input_length, label_length], output=[loss_out])
# the loss calc occurs elsewhere, so use a dummy lambda func for the loss
model.compile(loss={'ctc': lambda y_true, y_pred: y_pred}, optimizer=sgd)
# captures output of softmax so we can decode the output during visualization
test_func = K.function([input_data], [y_pred])
viz_cb = VizCallback(test_func, img_gen.next_val())
model.fit_generator(generator=img_gen.next_train(), samples_per_epoch=(words_per_epoch - val_words),
nb_epoch=nb_epoch, validation_data=img_gen.next_val(), nb_val_samples=val_words,
callbacks=[viz_cb, img_gen])
+8 -22
Ver Arquivo
@@ -9,8 +9,8 @@ import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.models import Model
from keras.layers import Dense, Dropout, Embedding, LSTM, Input, merge
from keras.models import Sequential
from keras.layers import Dense, Dropout, Embedding, LSTM, Input, Bidirectional
from keras.datasets import imdb
@@ -19,8 +19,7 @@ maxlen = 100 # cut texts after this number of words (among top max_features mos
batch_size = 32
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,
test_split=0.2)
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
@@ -32,24 +31,11 @@ print('X_test shape:', X_test.shape)
y_train = np.array(y_train)
y_test = np.array(y_test)
# this is the placeholder tensor for the input sequences
sequence = Input(shape=(maxlen,), dtype='int32')
# this embedding layer will transform the sequences of integers
# into vectors of size 128
embedded = Embedding(max_features, 128, input_length=maxlen)(sequence)
# apply forwards LSTM
forwards = LSTM(64)(embedded)
# apply backwards LSTM
backwards = LSTM(64, go_backwards=True)(embedded)
# concatenate the outputs of the 2 LSTMs
merged = merge([forwards, backwards], mode='concat', concat_axis=-1)
after_dp = Dropout(0.5)(merged)
output = Dense(1, activation='sigmoid')(after_dp)
model = Model(input=sequence, output=output)
model = Sequential()
model.add(Embedding(max_features, 128, input_length=maxlen))
model.add(Bidirectional(LSTM(64)))
model.add(Dropout(0.5))
model.add(Dense(1, activation='sigmoid'))
# try using different optimizers and different optimizer configs
model.compile('adam', 'binary_crossentropy', metrics=['accuracy'])
+9 -11
Ver Arquivo
@@ -1,6 +1,6 @@
'''This example demonstrates the use of Convolution1D for text classification.
Gets to 0.88 test accuracy after 2 epochs.
Gets to 0.89 test accuracy after 2 epochs.
90s/epoch on Intel i5 2.4Ghz CPU.
10s/epoch on Tesla K40 GPU.
@@ -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, Lambda
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Embedding
from keras.layers import Convolution1D
from keras.layers import Convolution1D, MaxPooling1D
from keras.datasets import imdb
from keras import backend as K
@@ -30,8 +30,7 @@ hidden_dims = 250
nb_epoch = 2
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,
test_split=0.2)
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
@@ -58,13 +57,12 @@ model.add(Convolution1D(nb_filter=nb_filter,
border_mode='valid',
activation='relu',
subsample_length=1))
# we use max pooling:
model.add(MaxPooling1D(pool_length=model.output_shape[1]))
# we use max over time pooling by defining a python function to use
# in a Lambda layer
def max_1d(X):
return K.max(X, axis=1)
model.add(Lambda(max_1d, output_shape=(nb_filter,)))
# We flatten the output of the conv layer,
# so that we can add a vanilla dense layer:
model.add(Flatten())
# We add a vanilla hidden layer:
model.add(Dense(hidden_dims))
+3 -3
Ver Arquivo
@@ -22,9 +22,9 @@ maxlen = 100
embedding_size = 128
# Convolution
filter_length = 3
filter_length = 5
nb_filter = 64
pool_length = 2
pool_length = 4
# LSTM
lstm_output_size = 70
@@ -40,7 +40,7 @@ Only 2 epochs are needed as the dataset is very small.
'''
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features, test_split=0.2)
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
+139
Ver Arquivo
@@ -0,0 +1,139 @@
'''This example demonstrates the use of fasttext for text classification
Based on Joulin et al's paper:
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.
'''
from __future__ import print_function
import numpy as np
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 Embedding
from keras.layers import AveragePooling1D
from keras.datasets import imdb
def create_ngram_set(input_list, ngram_value=2):
"""
Extract a set of n-grams from a list of integers.
>>> create_ngram_set([1, 4, 9, 4, 1, 4], ngram_value=2)
{(4, 9), (4, 1), (1, 4), (9, 4)}
>>> create_ngram_set([1, 4, 9, 4, 1, 4], ngram_value=3)
[(1, 4, 9), (4, 9, 4), (9, 4, 1), (4, 1, 4)]
"""
return set(zip(*[input_list[i:] for i in range(ngram_value)]))
def add_ngram(sequences, token_indice, ngram_range=2):
"""
Augment the input list of list (sequences) by appending n-grams values.
Example: adding bi-gram
>>> sequences = [[1, 3, 4, 5], [1, 3, 7, 9, 2]]
>>> token_indice = {(1, 3): 1337, (9, 2): 42, (4, 5): 2017}
>>> add_ngram(sequences, token_indice, ngram_range=2)
[[1, 3, 4, 5, 1337, 2017], [1, 3, 7, 9, 2, 1337, 42]]
Example: adding tri-gram
>>> sequences = [[1, 3, 4, 5], [1, 3, 7, 9, 2]]
>>> token_indice = {(1, 3): 1337, (9, 2): 42, (4, 5): 2017, (7, 9, 2): 2018}
>>> add_ngram(sequences, token_indice, ngram_range=3)
[[1, 3, 4, 5, 1337], [1, 3, 7, 9, 2, 1337, 2018]]
"""
new_sequences = []
for input_list in sequences:
new_list = input_list[:]
for i in range(len(new_list)-ngram_range+1):
for ngram_value in range(2, ngram_range+1):
ngram = tuple(new_list[i:i+ngram_value])
if ngram in token_indice:
new_list.append(token_indice[ngram])
new_sequences.append(new_list)
return new_sequences
# Set parameters:
# ngram_range = 2 will add bi-grams features
ngram_range = 1
max_features = 20000
maxlen = 400
batch_size = 32
embedding_dims = 50
nb_epoch = 5
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
print('Average train sequence length: {}'.format(np.mean(list(map(len, X_train)), dtype=int)))
print('Average test sequence length: {}'.format(np.mean(list(map(len, X_test)), dtype=int)))
if ngram_range > 1:
print('Adding {}-gram features'.format(ngram_range))
# Create set of unique n-gram from the training set.
ngram_set = set()
for input_list in X_train:
for i in range(2, ngram_range+1):
set_of_ngram = create_ngram_set(input_list, ngram_value=i)
ngram_set.update(set_of_ngram)
# Dictionary mapping n-gram token to a unique integer.
# Integer values are greater than max_features in order
# to avoid collision with existing features.
start_index = max_features + 1
token_indice = {v: k+start_index for k, v in enumerate(ngram_set)}
indice_token = {token_indice[k]: k for k in token_indice}
# max_features is the highest integer that could be found in the dataset.
max_features = np.max(list(indice_token.keys())) + 1
# Augmenting X_train and X_test with n-grams features
X_train = add_ngram(X_train, token_indice, ngram_range)
X_test = add_ngram(X_test, token_indice, ngram_range)
print('Average train sequence length: {}'.format(np.mean(list(map(len, X_train)), dtype=int)))
print('Average test sequence length: {}'.format(np.mean(list(map(len, X_test)), dtype=int)))
print('Pad sequences (samples x time)')
X_train = sequence.pad_sequences(X_train, maxlen=maxlen)
X_test = sequence.pad_sequences(X_test, maxlen=maxlen)
print('X_train shape:', X_train.shape)
print('X_test shape:', X_test.shape)
print('Build model...')
model = Sequential()
# we start off with an efficient embedding layer which maps
# our vocab indices into embedding_dims dimensions
model.add(Embedding(max_features,
embedding_dims,
input_length=maxlen))
# we add a AveragePooling1D, 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())
# We project onto a single unit output layer, and squash it with a sigmoid:
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=nb_epoch,
validation_data=(X_test, y_test))
+3 -8
Ver Arquivo
@@ -1,8 +1,6 @@
'''Trains a LSTM on the IMDB sentiment classification task.
The dataset is actually too small for LSTM to be of any advantage
compared to simpler, much faster methods such as TF-IDF+LogReg.
compared to simpler, much faster methods such as TF-IDF + LogReg.
Notes:
- RNNs are tricky. Choice of batch size is important,
@@ -28,8 +26,7 @@ maxlen = 80 # cut texts after this number of words (among top max_features most
batch_size = 32
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,
test_split=0.2)
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
@@ -41,7 +38,7 @@ print('X_test shape:', X_test.shape)
print('Build model...')
model = Sequential()
model.add(Embedding(max_features, 128, input_length=maxlen, dropout=0.2))
model.add(Embedding(max_features, 128, dropout=0.2))
model.add(LSTM(128, dropout_W=0.2, dropout_U=0.2)) # try using a GRU instead, for fun
model.add(Dense(1))
model.add(Activation('sigmoid'))
@@ -52,8 +49,6 @@ model.compile(loss='binary_crossentropy',
metrics=['accuracy'])
print('Train...')
print(X_train.shape)
print(y_train.shape)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=15,
validation_data=(X_test, y_test))
score, acc = model.evaluate(X_test, y_test,
-290
Ver Arquivo
@@ -1,290 +0,0 @@
'''This script demonstrates how to build the Inception v3 architecture
using the Keras functional API.
We are not actually training it here, for lack of appropriate data.
For more information about this architecture, see:
"Rethinking the Inception Architecture for Computer Vision"
Christian Szegedy, Vincent Vanhoucke, Sergey Ioffe, Jonathon Shlens, Zbigniew Wojna
http://arxiv.org/abs/1512.00567
'''
from keras.layers import Convolution2D, MaxPooling2D, AveragePooling2D
from keras.layers import BatchNormalization, Flatten, Dense, Dropout
from keras.layers import Input, merge
from keras.models import Model
from keras import regularizers
# global constants
NB_CLASS = 1000 # number of classes
DIM_ORDERING = 'th' # 'th' (channels, width, height) or 'tf' (width, height, channels)
WEIGHT_DECAY = 0. # L2 regularization factor
USE_BN = False # whether to use batch normalization
def conv2D_bn(x, nb_filter, nb_row, nb_col,
border_mode='same', subsample=(1, 1),
activation='relu', batch_norm=USE_BN,
weight_decay=WEIGHT_DECAY, dim_ordering=DIM_ORDERING):
'''Utility function to apply to a tensor a module conv + BN
with optional weight decay (L2 weight regularization).
'''
if weight_decay:
W_regularizer = regularizers.l2(weight_decay)
b_regularizer = regularizers.l2(weight_decay)
else:
W_regularizer = None
b_regularizer = None
x = Convolution2D(nb_filter, nb_row, nb_col,
subsample=subsample,
activation=activation,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
dim_ordering=dim_ordering)(x)
if batch_norm:
x = BatchNormalization()(x)
return x
# Define image input layer
if DIM_ORDERING == 'th':
img_input = Input(shape=(3, 299, 299))
CONCAT_AXIS = 1
elif DIM_ORDERING == 'tf':
img_input = Input(shape=(299, 299, 3))
CONCAT_AXIS = 3
else:
raise Exception('Invalid dim ordering: ' + str(DIM_ORDERING))
# Entry module
x = conv2D_bn(img_input, 32, 3, 3, subsample=(2, 2), border_mode='valid')
x = conv2D_bn(x, 32, 3, 3, border_mode='valid')
x = conv2D_bn(x, 64, 3, 3)
x = MaxPooling2D((3, 3), strides=(2, 2), dim_ordering=DIM_ORDERING)(x)
x = conv2D_bn(x, 80, 1, 1, border_mode='valid')
x = conv2D_bn(x, 192, 3, 3, border_mode='valid')
x = MaxPooling2D((3, 3), strides=(2, 2), dim_ordering=DIM_ORDERING)(x)
# mixed: 35 x 35 x 256
branch1x1 = conv2D_bn(x, 64, 1, 1)
branch5x5 = conv2D_bn(x, 48, 1, 1)
branch5x5 = conv2D_bn(branch5x5, 64, 5, 5)
branch3x3dbl = conv2D_bn(x, 64, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 32, 1, 1)
x = merge([branch1x1, branch5x5, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed_1: 35 x 35 x 288
branch1x1 = conv2D_bn(x, 64, 1, 1)
branch5x5 = conv2D_bn(x, 48, 1, 1)
branch5x5 = conv2D_bn(branch5x5, 64, 5, 5)
branch3x3dbl = conv2D_bn(x, 64, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 64, 1, 1)
x = merge([branch1x1, branch5x5, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed2: 35 x 35 x 288
branch1x1 = conv2D_bn(x, 64, 1, 1)
branch5x5 = conv2D_bn(x, 48, 1, 1)
branch5x5 = conv2D_bn(branch5x5, 64, 5, 5)
branch3x3dbl = conv2D_bn(x, 64, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 64, 1, 1)
x = merge([branch1x1, branch5x5, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed3: 17 x 17 x 768
branch3x3 = conv2D_bn(x, 384, 3, 3, subsample=(2, 2), border_mode='valid')
branch3x3dbl = conv2D_bn(x, 64, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2D_bn(branch3x3dbl, 96, 3, 3, subsample=(2, 2), border_mode='valid')
branch_pool = MaxPooling2D((3, 3), strides=(2, 2), dim_ordering=DIM_ORDERING)(x)
x = merge([branch3x3, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed4: 17 x 17 x 768
branch1x1 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(x, 128, 1, 1)
branch7x7 = conv2D_bn(branch7x7, 128, 1, 7)
branch7x7 = conv2D_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2D_bn(x, 128, 1, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 128, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 128, 1, 7)
branch7x7dbl = conv2D_bn(branch7x7dbl, 128, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed5: 17 x 17 x 768
branch1x1 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(x, 160, 1, 1)
branch7x7 = conv2D_bn(branch7x7, 160, 1, 7)
branch7x7 = conv2D_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2D_bn(x, 160, 1, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 1, 7)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed5: 17 x 17 x 768
branch1x1 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(x, 160, 1, 1)
branch7x7 = conv2D_bn(branch7x7, 160, 1, 7)
branch7x7 = conv2D_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2D_bn(x, 160, 1, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 1, 7)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed6: 17 x 17 x 768
branch1x1 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(x, 160, 1, 1)
branch7x7 = conv2D_bn(branch7x7, 160, 1, 7)
branch7x7 = conv2D_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2D_bn(x, 160, 1, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch7x7dbl = conv2D_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed7: 17 x 17 x 768
branch1x1 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(x, 192, 1, 1)
branch7x7 = conv2D_bn(branch7x7, 192, 1, 7)
branch7x7 = conv2D_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2D_bn(x, 160, 1, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 7, 1)
branch7x7dbl = conv2D_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# Auxiliary head
aux_logits = AveragePooling2D((5, 5), strides=(3, 3), dim_ordering=DIM_ORDERING)(x)
aux_logits = conv2D_bn(aux_logits, 128, 1, 1)
aux_logits = conv2D_bn(aux_logits, 728, 5, 5, border_mode='valid')
aux_logits = Flatten()(aux_logits)
aux_preds = Dense(NB_CLASS, activation='softmax')(aux_logits)
# mixed8: 8 x 8 x 1280
branch3x3 = conv2D_bn(x, 192, 1, 1)
branch3x3 = conv2D_bn(branch3x3, 320, 3, 3, subsample=(2, 2), border_mode='valid')
branch7x7x3 = conv2D_bn(x, 192, 1, 1)
branch7x7x3 = conv2D_bn(branch7x7x3, 192, 1, 7)
branch7x7x3 = conv2D_bn(branch7x7x3, 192, 7, 1)
branch7x7x3 = conv2D_bn(branch7x7x3, 192, 3, 3, subsample=(2, 2), border_mode='valid')
branch_pool = AveragePooling2D((3, 3), strides=(2, 2), dim_ordering=DIM_ORDERING)(x)
x = merge([branch3x3, branch7x7x3, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed9: 8 x 8 x 2048
branch1x1 = conv2D_bn(x, 320, 1, 1)
branch3x3 = conv2D_bn(x, 384, 1, 1)
branch3x3_1 = conv2D_bn(branch3x3, 384, 1, 3)
branch3x3_2 = conv2D_bn(branch3x3, 384, 3, 1)
branch3x3 = merge([branch3x3_1, branch3x3_2], mode='concat', concat_axis=CONCAT_AXIS)
branch3x3dbl = conv2D_bn(x, 448, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 384, 3, 3)
branch3x3dbl_1 = conv2D_bn(branch3x3dbl, 384, 1, 3)
branch3x3dbl_2 = conv2D_bn(branch3x3dbl, 384, 3, 1)
branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2], mode='concat', concat_axis=CONCAT_AXIS)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# mixed10: 8 x 8 x 2048
branch1x1 = conv2D_bn(x, 320, 1, 1)
branch3x3 = conv2D_bn(x, 384, 1, 1)
branch3x3_1 = conv2D_bn(branch3x3, 384, 1, 3)
branch3x3_2 = conv2D_bn(branch3x3, 384, 3, 1)
branch3x3 = merge([branch3x3_1, branch3x3_2], mode='concat', concat_axis=CONCAT_AXIS)
branch3x3dbl = conv2D_bn(x, 448, 1, 1)
branch3x3dbl = conv2D_bn(branch3x3dbl, 384, 3, 3)
branch3x3dbl_1 = conv2D_bn(branch3x3dbl, 384, 1, 3)
branch3x3dbl_2 = conv2D_bn(branch3x3dbl, 384, 3, 1)
branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2], mode='concat', concat_axis=CONCAT_AXIS)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same', dim_ordering=DIM_ORDERING)(x)
branch_pool = conv2D_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool], mode='concat', concat_axis=CONCAT_AXIS)
# Final pooling and prediction
x = AveragePooling2D((8, 8), strides=(1, 1), dim_ordering=DIM_ORDERING)(x)
x = Dropout(0.5)(x)
x = Flatten()(x)
preds = Dense(NB_CLASS, activation='softmax')(x)
# Define model
model = Model(input=img_input, output=[preds, aux_preds])
model.compile('rmsprop', 'categorical_crossentropy')
# train via e.g. `model.fit(x_train, [y_train] * 2, batch_size=32, nb_epoch=100)`
# Note that for a large dataset it would be preferable
# to train using `fit_generator` (see Keras docs).
+12 -9
Ver Arquivo
@@ -14,6 +14,7 @@ from __future__ import print_function
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout
from keras.layers import LSTM
from keras.optimizers import RMSprop
from keras.utils.data_utils import get_file
import numpy as np
import random
@@ -47,23 +48,25 @@ for i, sentence in enumerate(sentences):
y[i, char_indices[next_chars[i]]] = 1
# build the model: 2 stacked LSTM
# build the model: a single LSTM
print('Build model...')
model = Sequential()
model.add(LSTM(512, return_sequences=True, input_shape=(maxlen, len(chars))))
model.add(LSTM(512, return_sequences=False))
model.add(Dropout(0.2))
model.add(LSTM(128, input_shape=(maxlen, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
optimizer = RMSprop(lr=0.01)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
def sample(a, temperature=1.0):
def sample(preds, temperature=1.0):
# helper function to sample an index from a probability array
a = np.log(a) / temperature
a = np.exp(a) / np.sum(np.exp(a))
return np.argmax(np.random.multinomial(1, a, 1))
preds = np.asarray(preds).astype('float64')
preds = np.log(preds) / temperature
exp_preds = np.exp(preds)
preds = exp_preds / np.sum(exp_preds)
probas = np.random.multinomial(1, preds, 1)
return np.argmax(probas)
# train the model, output generated text after each iteration
for iteration in range(1, 60):
+16 -8
Ver Arquivo
@@ -14,6 +14,7 @@ from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
batch_size = 128
nb_classes = 10
@@ -24,15 +25,22 @@ img_rows, img_cols = 28, 28
# number of convolutional filters to use
nb_filters = 32
# size of pooling area for max pooling
nb_pool = 2
pool_size = (2, 2)
# convolution kernel size
nb_conv = 3
kernel_size = (3, 3)
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
if K.image_dim_ordering() == 'th':
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
input_shape = (1, img_rows, img_cols)
else:
X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
@@ -47,13 +55,13 @@ Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(nb_filters, nb_conv, nb_conv,
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1],
border_mode='valid',
input_shape=(1, img_rows, img_cols)))
input_shape=input_shape))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, nb_conv, nb_conv))
model.add(Convolution2D(nb_filters, kernel_size[0], kernel_size[1]))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool)))
model.add(MaxPooling2D(pool_size=pool_size))
model.add(Dropout(0.25))
model.add(Flatten())
+87
Ver Arquivo
@@ -0,0 +1,87 @@
"""This is an example of using Hierarchical RNN (HRNN) to classify MNIST digits.
HRNNs can learn across multiple levels of temporal hiearchy over a complex sequence.
Usually, the first recurrent layer of an HRNN encodes a sentence (e.g. of word vectors)
into a sentence vector. The second recurrent layer then encodes a sequence of
such vectors (encoded by the first layer) into a document vector. This
document vector is considered to preserve both the word-level and
sentence-level structure of the context.
# References
- [A Hierarchical Neural Autoencoder for Paragraphs and Documents](https://web.stanford.edu/~jurafsky/pubs/P15-1107.pdf)
Encodes paragraphs and documents with HRNN.
Results have shown that HRNN outperforms standard
RNNs and may play some role in more sophisticated generation tasks like
summarization or question answering.
- [Hierarchical recurrent neural network for skeleton based action recognition](http://ieeexplore.ieee.org/stamp/stamp.jsp?tp=&arnumber=7298714)
Achieved state-of-the-art results on skeleton based action recognition with 3 levels
of bidirectional HRNN combined with fully connected layers.
In the below MNIST example the first LSTM layer first encodes every
column of pixels of shape (28, 1) to a column vector of shape (128,). The second LSTM
layer encodes then these 28 column vectors of shape (28, 128) to a image vector
representing the whole image. A final Dense layer is added for prediction.
After 5 epochs: train acc: 0.9858, val acc: 0.9864
"""
from __future__ import print_function
from keras.datasets import mnist
from keras.models import Sequential, Model
from keras.layers import Input, Dense, TimeDistributed
from keras.layers import LSTM
from keras.utils import np_utils
# Training parameters.
batch_size = 32
nb_classes = 10
nb_epochs = 5
# Embedding dimensions.
row_hidden = 128
col_hidden = 128
# The data, shuffled and split between train and test sets.
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# Reshapes data to 4D for Hierarchical RNN.
X_train = X_train.reshape(X_train.shape[0], 28, 28, 1)
X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
# Converts class vectors to binary class matrices.
Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
row, col, pixel = X_train.shape[1:]
# 4D input.
x = Input(shape=(row, col, pixel))
# Encodes a row of pixels using TimeDistributed Wrapper.
encoded_rows = TimeDistributed(LSTM(output_dim=row_hidden))(x)
# Encodes columns of encoded rows.
encoded_columns = LSTM(col_hidden)(encoded_rows)
# Final predictions and model.
prediction = Dense(nb_classes, activation='softmax')(encoded_columns)
model = Model(input=x, output=prediction)
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# Training.
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epochs,
verbose=1, validation_data=(X_test, Y_test))
# Evaluation.
scores = model.evaluate(X_test, Y_test, verbose=0)
print('Test loss:', scores[0])
print('Test accuracy:', scores[1])
+384
Ver Arquivo
@@ -0,0 +1,384 @@
'''This is an implementation of Net2Net experiment with MNIST in
'Net2Net: Accelerating Learning via Knowledge Transfer'
by Tianqi Chen, Ian Goodfellow, and Jonathon Shlens
arXiv:1511.05641v4 [cs.LG] 23 Apr 2016
http://arxiv.org/abs/1511.05641
Notes
- What:
+ Net2Net is a group of methods to transfer knowledge from a teacher neural
net to a student net,so that the student net can be trained faster than
from scratch.
+ The paper discussed two specific methods of Net2Net, i.e. Net2WiderNet
and Net2DeeperNet.
+ Net2WiderNet replaces a model with an equivalent wider model that has
more units in each hidden layer.
+ Net2DeeperNet replaces a model with an equivalent deeper model.
+ Both are based on the idea of 'function-preserving transformations of
neural nets'.
- Why:
+ Enable fast exploration of multiple neural nets in experimentation and
design process,by creating a series of wider and deeper models with
transferable knowledge.
+ Enable 'lifelong learning system' by gradually adjusting model complexity
to data availability,and reusing transferable knowledge.
Experiments
- Teacher model: a basic CNN model trained on MNIST for 3 epochs.
- Net2WiderNet exepriment:
+ Student model has a wider Conv2D layer and a wider FC layer.
+ Comparison of 'random-padding' vs 'net2wider' weight initialization.
+ With both methods, student model should immediately perform as well as
teacher model, but 'net2wider' is slightly better.
- Net2DeeperNet experiment:
+ Student model has an extra Conv2D layer and an extra FC layer.
+ Comparison of 'random-init' vs 'net2deeper' weight initialization.
+ Starting performance of 'net2deeper' is better than 'random-init'.
- Hyper-parameters:
+ SGD with momentum=0.9 is used for training teacher and student models.
+ Learning rate adjustment: it's suggested to reduce learning rate
to 1/10 for student model.
+ Addition of noise in 'net2wider' is used to break weight symmetry
and thus enable full capacity of student models. It is optional
when a Dropout layer is used.
Results
- Tested with 'Theano' backend and 'th' image_dim_ordering.
- Running on GPU GeForce GTX 980M
- Performance Comparisons - validation loss values during first 3 epochs:
(1) teacher_model: 0.075 0.041 0.041
(2) wider_random_pad: 0.036 0.034 0.032
(3) wider_net2wider: 0.032 0.030 0.030
(4) deeper_random_init: 0.061 0.043 0.041
(5) deeper_net2deeper: 0.032 0.031 0.029
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337)
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten
from keras.optimizers import SGD
from keras.utils import np_utils
from keras.datasets import mnist
input_shape = (1, 28, 28) # image shape
nb_class = 10 # number of class
# load and pre-process data
def preprocess_input(x):
return x.reshape((-1, ) + input_shape) / 255.
def preprocess_output(y):
return np_utils.to_categorical(y)
(train_x, train_y), (validation_x, validation_y) = mnist.load_data()
train_x, validation_x = map(preprocess_input, [train_x, validation_x])
train_y, validation_y = map(preprocess_output, [train_y, validation_y])
print('Loading MNIST data...')
print('train_x shape:', train_x.shape, 'train_y shape:', train_y.shape)
print('validation_x shape:', validation_x.shape,
'validation_y shape', validation_y.shape)
# knowledge transfer algorithms
def wider2net_conv2d(teacher_w1, teacher_b1, teacher_w2, new_width, init):
'''Get initial weights for a wider conv2d layer with a bigger nb_filter,
by 'random-padding' or 'net2wider'.
# Arguments
teacher_w1: `weight` of conv2d layer to become wider,
of shape (nb_filter1, nb_channel1, kh1, kw1)
teacher_b1: `bias` of conv2d layer to become wider,
of shape (nb_filter1, )
teacher_w2: `weight` of next connected conv2d layer,
of shape (nb_filter2, nb_channel2, kh2, kw2)
new_width: new `nb_filter` for the wider conv2d layer
init: initialization algorithm for new weights,
either 'random-pad' or 'net2wider'
'''
assert teacher_w1.shape[0] == teacher_w2.shape[1], (
'successive layers from teacher model should have compatible shapes')
assert teacher_w1.shape[0] == teacher_b1.shape[0], (
'weight and bias from same layer should have compatible shapes')
assert new_width > teacher_w1.shape[0], (
'new width (nb_filter) should be bigger than the existing one')
n = new_width - teacher_w1.shape[0]
if init == 'random-pad':
new_w1 = np.random.normal(0, 0.1, size=(n, ) + teacher_w1.shape[1:])
new_b1 = np.ones(n) * 0.1
new_w2 = np.random.normal(0, 0.1, size=(
teacher_w2.shape[0], n) + teacher_w2.shape[2:])
elif init == 'net2wider':
index = np.random.randint(teacher_w1.shape[0], size=n)
factors = np.bincount(index)[index] + 1.
new_w1 = teacher_w1[index, :, :, :]
new_b1 = teacher_b1[index]
new_w2 = teacher_w2[:, index, :, :] / factors.reshape((1, -1, 1, 1))
else:
raise ValueError('Unsupported weight initializer: %s' % init)
student_w1 = np.concatenate((teacher_w1, new_w1), axis=0)
if init == 'random-pad':
student_w2 = np.concatenate((teacher_w2, new_w2), axis=1)
elif init == 'net2wider':
# add small noise to break symmetry, so that student model will have
# full capacity later
noise = np.random.normal(0, 5e-2 * new_w2.std(), size=new_w2.shape)
student_w2 = np.concatenate((teacher_w2, new_w2 + noise), axis=1)
student_w2[:, index, :, :] = new_w2
student_b1 = np.concatenate((teacher_b1, new_b1), axis=0)
return student_w1, student_b1, student_w2
def wider2net_fc(teacher_w1, teacher_b1, teacher_w2, new_width, init):
'''Get initial weights for a wider fully connected (dense) layer
with a bigger nout, by 'random-padding' or 'net2wider'.
# Arguments
teacher_w1: `weight` of fc layer to become wider,
of shape (nin1, nout1)
teacher_b1: `bias` of fc layer to become wider,
of shape (nout1, )
teacher_w2: `weight` of next connected fc layer,
of shape (nin2, nout2)
new_width: new `nout` for the wider fc layer
init: initialization algorithm for new weights,
either 'random-pad' or 'net2wider'
'''
assert teacher_w1.shape[1] == teacher_w2.shape[0], (
'successive layers from teacher model should have compatible shapes')
assert teacher_w1.shape[1] == teacher_b1.shape[0], (
'weight and bias from same layer should have compatible shapes')
assert new_width > teacher_w1.shape[1], (
'new width (nout) should be bigger than the existing one')
n = new_width - teacher_w1.shape[1]
if init == 'random-pad':
new_w1 = np.random.normal(0, 0.1, size=(teacher_w1.shape[0], n))
new_b1 = np.ones(n) * 0.1
new_w2 = np.random.normal(0, 0.1, size=(n, teacher_w2.shape[1]))
elif init == 'net2wider':
index = np.random.randint(teacher_w1.shape[1], size=n)
factors = np.bincount(index)[index] + 1.
new_w1 = teacher_w1[:, index]
new_b1 = teacher_b1[index]
new_w2 = teacher_w2[index, :] / factors[:, np.newaxis]
else:
raise ValueError('Unsupported weight initializer: %s' % init)
student_w1 = np.concatenate((teacher_w1, new_w1), axis=1)
if init == 'random-pad':
student_w2 = np.concatenate((teacher_w2, new_w2), axis=0)
elif init == 'net2wider':
# add small noise to break symmetry, so that student model will have
# full capacity later
noise = np.random.normal(0, 5e-2 * new_w2.std(), size=new_w2.shape)
student_w2 = np.concatenate((teacher_w2, new_w2 + noise), axis=0)
student_w2[index, :] = new_w2
student_b1 = np.concatenate((teacher_b1, new_b1), axis=0)
return student_w1, student_b1, student_w2
def deeper2net_conv2d(teacher_w):
'''Get initial weights for a deeper conv2d layer by net2deeper'.
# Arguments
teacher_w: `weight` of previous conv2d layer,
of shape (nb_filter, nb_channel, kh, kw)
'''
nb_filter, nb_channel, kh, kw = teacher_w.shape
student_w = np.zeros((nb_filter, nb_filter, kh, kw))
for i in xrange(nb_filter):
student_w[i, i, (kh - 1) / 2, (kw - 1) / 2] = 1.
student_b = np.zeros(nb_filter)
return student_w, student_b
def copy_weights(teacher_model, student_model, layer_names):
'''Copy weights from teacher_model to student_model,
for layers with names listed in layer_names
'''
for name in layer_names:
weights = teacher_model.get_layer(name=name).get_weights()
student_model.get_layer(name=name).set_weights(weights)
# methods to construct teacher_model and student_models
def make_teacher_model(train_data, validation_data, nb_epoch=3):
'''Train a simple CNN as teacher model.
'''
model = Sequential()
model.add(Conv2D(64, 3, 3, input_shape=input_shape,
border_mode='same', name='conv1'))
model.add(MaxPooling2D(name='pool1'))
model.add(Conv2D(64, 3, 3, border_mode='same', name='conv2'))
model.add(MaxPooling2D(name='pool2'))
model.add(Flatten(name='flatten'))
model.add(Dense(64, activation='relu', name='fc1'))
model.add(Dense(nb_class, activation='softmax', name='fc2'))
model.compile(loss='categorical_crossentropy',
optimizer=SGD(lr=0.01, momentum=0.9),
metrics=['accuracy'])
train_x, train_y = train_data
history = model.fit(train_x, train_y, nb_epoch=nb_epoch,
validation_data=validation_data)
return model, history
def make_wider_student_model(teacher_model, train_data,
validation_data, init, nb_epoch=3):
'''Train a wider student model based on teacher_model,
with either 'random-pad' (baseline) or 'net2wider'
'''
new_conv1_width = 128
new_fc1_width = 128
model = Sequential()
# a wider conv1 compared to teacher_model
model.add(Conv2D(new_conv1_width, 3, 3, input_shape=input_shape,
border_mode='same', name='conv1'))
model.add(MaxPooling2D(name='pool1'))
model.add(Conv2D(64, 3, 3, border_mode='same', name='conv2'))
model.add(MaxPooling2D(name='pool2'))
model.add(Flatten(name='flatten'))
# a wider fc1 compared to teacher model
model.add(Dense(new_fc1_width, activation='relu', name='fc1'))
model.add(Dense(nb_class, activation='softmax', name='fc2'))
# The weights for other layers need to be copied from teacher_model
# to student_model, except for widened layers
# and their immediate downstreams, which will be initialized separately.
# For this example there are no other layers that need to be copied.
w_conv1, b_conv1 = teacher_model.get_layer('conv1').get_weights()
w_conv2, b_conv2 = teacher_model.get_layer('conv2').get_weights()
new_w_conv1, new_b_conv1, new_w_conv2 = wider2net_conv2d(
w_conv1, b_conv1, w_conv2, new_conv1_width, init)
model.get_layer('conv1').set_weights([new_w_conv1, new_b_conv1])
model.get_layer('conv2').set_weights([new_w_conv2, b_conv2])
w_fc1, b_fc1 = teacher_model.get_layer('fc1').get_weights()
w_fc2, b_fc2 = teacher_model.get_layer('fc2').get_weights()
new_w_fc1, new_b_fc1, new_w_fc2 = wider2net_fc(
w_fc1, b_fc1, w_fc2, new_fc1_width, init)
model.get_layer('fc1').set_weights([new_w_fc1, new_b_fc1])
model.get_layer('fc2').set_weights([new_w_fc2, b_fc2])
model.compile(loss='categorical_crossentropy',
optimizer=SGD(lr=0.001, momentum=0.9),
metrics=['accuracy'])
train_x, train_y = train_data
history = model.fit(train_x, train_y, nb_epoch=nb_epoch,
validation_data=validation_data)
return model, history
def make_deeper_student_model(teacher_model, train_data,
validation_data, init, nb_epoch=3):
'''Train a deeper student model based on teacher_model,
with either 'random-init' (baseline) or 'net2deeper'
'''
model = Sequential()
model.add(Conv2D(64, 3, 3, input_shape=input_shape,
border_mode='same', name='conv1'))
model.add(MaxPooling2D(name='pool1'))
model.add(Conv2D(64, 3, 3, border_mode='same', name='conv2'))
# add another conv2d layer to make original conv2 deeper
if init == 'net2deeper':
prev_w, _ = model.get_layer('conv2').get_weights()
new_weights = deeper2net_conv2d(prev_w)
model.add(Conv2D(64, 3, 3, border_mode='same',
name='conv2-deeper', weights=new_weights))
elif init == 'random-init':
model.add(Conv2D(64, 3, 3, border_mode='same', name='conv2-deeper'))
else:
raise ValueError('Unsupported weight initializer: %s' % init)
model.add(MaxPooling2D(name='pool2'))
model.add(Flatten(name='flatten'))
model.add(Dense(64, activation='relu', name='fc1'))
# add another fc layer to make original fc1 deeper
if init == 'net2deeper':
# net2deeper for fc layer with relu, is just an identity initializer
model.add(Dense(64, init='identity',
activation='relu', name='fc1-deeper'))
elif init == 'random-init':
model.add(Dense(64, activation='relu', name='fc1-deeper'))
else:
raise ValueError('Unsupported weight initializer: %s' % init)
model.add(Dense(nb_class, activation='softmax', name='fc2'))
# copy weights for other layers
copy_weights(teacher_model, model, layer_names=[
'conv1', 'conv2', 'fc1', 'fc2'])
model.compile(loss='categorical_crossentropy',
optimizer=SGD(lr=0.001, momentum=0.9),
metrics=['accuracy'])
train_x, train_y = train_data
history = model.fit(train_x, train_y, nb_epoch=nb_epoch,
validation_data=validation_data)
return model, history
# experiments setup
def net2wider_experiment():
'''Benchmark performances of
(1) a teacher model,
(2) a wider student model with `random_pad` initializer
(3) a wider student model with `Net2WiderNet` initializer
'''
train_data = (train_x, train_y)
validation_data = (validation_x, validation_y)
print('\nExperiment of Net2WiderNet ...')
print('\nbuilding teacher model ...')
teacher_model, _ = make_teacher_model(train_data,
validation_data,
nb_epoch=3)
print('\nbuilding wider student model by random padding ...')
make_wider_student_model(teacher_model, train_data,
validation_data, 'random-pad',
nb_epoch=3)
print('\nbuilding wider student model by net2wider ...')
make_wider_student_model(teacher_model, train_data,
validation_data, 'net2wider',
nb_epoch=3)
def net2deeper_experiment():
'''Benchmark performances of
(1) a teacher model,
(2) a deeper student model with `random_init` initializer
(3) a deeper student model with `Net2DeeperNet` initializer
'''
train_data = (train_x, train_y)
validation_data = (validation_x, validation_y)
print('\nExperiment of Net2DeeperNet ...')
print('\nbuilding teacher model ...')
teacher_model, _ = make_teacher_model(train_data,
validation_data,
nb_epoch=3)
print('\nbuilding deeper student model by random init ...')
make_deeper_student_model(teacher_model, train_data,
validation_data, 'random-init',
nb_epoch=3)
print('\nbuilding deeper student model by net2deeper ...')
make_deeper_student_model(teacher_model, train_data,
validation_data, 'net2deeper',
nb_epoch=3)
# run the experiments
net2wider_experiment()
net2deeper_experiment()
+167
Ver Arquivo
@@ -0,0 +1,167 @@
'''Trains a stacked what-where autoencoder built on residual blocks on the
MNIST dataset. It exemplifies two influential methods that have been developed
in the past few years.
The first is the idea of properly "unpooling." During any max pool, the
exact location (the "where") of the maximal value in a pooled receptive field
is lost, however it can be very useful in the overall reconstruction of an
input image. Therefore, if the "where" is handed from the encoder
to the corresponding decoder layer, features being decoded can be "placed" in
the right location, allowing for reconstructions of much higher fidelity.
References:
[1]
"Visualizing and Understanding Convolutional Networks"
Matthew D Zeiler, Rob Fergus
https://arxiv.org/abs/1311.2901v3
[2]
"Stacked What-Where Auto-encoders"
Junbo Zhao, Michael Mathieu, Ross Goroshin, Yann LeCun
https://arxiv.org/abs/1506.02351v8
The second idea exploited here is that of residual learning. Residual blocks
ease the training process by allowing skip connections that give the network
the ability to be as linear (or non-linear) as the data sees fit. This allows
for much deep networks to be easily trained. The residual element seems to
be advantageous in the context of this example as it allows a nice symmetry
between the encoder and decoder. Normally, in the decoder, the final
projection to the space where the image is reconstructed is linear, however
this does not have to be the case for a residual block as the degree to which
its output is linear or non-linear is determined by the data it is fed.
However, in order to cap the reconstruction in this example, a hard softmax is
applied as a bias because we know the MNIST digits are mapped to [0,1].
References:
[3]
"Deep Residual Learning for Image Recognition"
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
https://arxiv.org/abs/1512.03385v1
[4]
"Identity Mappings in Deep Residual Networks"
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
https://arxiv.org/abs/1603.05027v3
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
from keras.datasets import mnist
from keras.models import Model
from keras.layers import Activation, merge
from keras.layers import UpSampling2D, Convolution2D, MaxPooling2D
from keras.layers import Input, BatchNormalization
import matplotlib.pyplot as plt
import keras.backend as K
def convresblock(x, nfeats=8, ksize=3, nskipped=2):
''' The proposed residual block from [4]'''
y0 = Convolution2D(nfeats, ksize, ksize, border_mode='same')(x)
y = y0
for i in range(nskipped):
y = BatchNormalization(mode=0, axis=1)(y)
y = Activation('relu')(y)
y = Convolution2D(nfeats, ksize, ksize, border_mode='same')(y)
return merge([y0, y], mode='sum')
def getwhere(x):
''' Calculate the "where" mask that contains switches indicating which
index contained the max value when MaxPool2D was applied. Using the
gradient of the sum is a nice trick to keep everything high level.'''
y_prepool, y_postpool = x
return K.gradients(K.sum(y_postpool), y_prepool)
# input image dimensions
img_rows, img_cols = 28, 28
# the data, shuffled and split between train and test sets
(X_train, _), (X_test, _) = mnist.load_data()
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
# The size of the kernel used for the MaxPooling2D
pool_size = 2
# The total number of feature maps at each layer
nfeats = [8, 16, 32, 64, 128]
# The sizes of the pooling kernel at each layer
pool_sizes = np.array([1, 1, 1, 1, 1]) * pool_size
# The convolution kernel size
ksize = 3
# Number of epochs to train for
nb_epoch = 5
# Batch size during training
batch_size = 128
if pool_size == 2:
# if using a 5 layer net of pool_size = 2
X_train = np.pad(X_train, [[0, 0], [0, 0], [2, 2], [2, 2]],
mode='constant')
X_test = np.pad(X_test, [[0, 0], [0, 0], [2, 2], [2, 2]], mode='constant')
nlayers = 5
elif pool_size == 3:
# if using a 3 layer net of pool_size = 3
X_train = X_train[:, :, :-1, :-1]
X_test = X_test[:, :, :-1, :-1]
nlayers = 3
else:
import sys
sys.exit("Script supports pool_size of 2 and 3.")
# Shape of input to train on (note that model is fully convolutional however)
input_shape = X_train.shape[1:]
# The final list of the size of axis=1 for all layers, including input
nfeats_all = [input_shape[0]] + nfeats
# First build the encoder, all the while keeping track of the "where" masks
img_input = Input(shape=input_shape)
# We push the "where" masks to the following list
wheres = [None] * nlayers
y = img_input
for i in range(nlayers):
y_prepool = convresblock(y, nfeats=nfeats_all[i + 1], ksize=ksize)
y = MaxPooling2D(pool_size=(pool_sizes[i], pool_sizes[i]))(y_prepool)
wheres[i] = merge([y_prepool, y], mode=getwhere,
output_shape=lambda x: x[0])
# Now build the decoder, and use the stored "where" masks to place the features
for i in range(nlayers):
ind = nlayers - 1 - i
y = UpSampling2D(size=(pool_sizes[ind], pool_sizes[ind]))(y)
y = merge([y, wheres[ind]], mode='mul')
y = convresblock(y, nfeats=nfeats_all[ind], ksize=ksize)
# Use hard_simgoid to clip range of reconstruction
y = Activation('hard_sigmoid')(y)
# Define the model and it's mean square error loss, and compile it with Adam
model = Model(img_input, y)
model.compile('adam', 'mse')
# Fit the model
model.fit(X_train, X_train, validation_data=(X_test, X_test),
batch_size=batch_size, nb_epoch=nb_epoch)
# Plot
X_recon = model.predict(X_test[:25])
X_plot = np.concatenate((X_test[:25], X_recon), axis=1)
X_plot = X_plot.reshape((5, 10, input_shape[-2], input_shape[-1]))
X_plot = np.vstack([np.hstack(x) for x in X_plot])
plt.figure()
plt.axis('off')
plt.title('Test Samples: Originals/Reconstructions')
plt.imshow(X_plot, interpolation='none', cmap='gray')
plt.savefig('reconstructions.png')
+15 -12
Ver Arquivo
@@ -22,7 +22,7 @@ from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras import backend as K
now = datetime.datetime.now
@@ -35,14 +35,19 @@ img_rows, img_cols = 28, 28
# number of convolutional filters to use
nb_filters = 32
# size of pooling area for max pooling
nb_pool = 2
pool_size = 2
# convolution kernel size
nb_conv = 3
kernel_size = 3
if K.image_dim_ordering() == 'th':
input_shape = (1, img_rows, img_cols)
else:
input_shape = (img_rows, img_cols, 1)
def train_model(model, train, test, nb_classes):
X_train = train[0].reshape(train[0].shape[0], 1, img_rows, img_cols)
X_test = test[0].reshape(test[0].shape[0], 1, img_rows, img_cols)
X_train = train[0].reshape((train[0].shape[0],) + input_shape)
X_test = test[0].reshape((test[0].shape[0],) + input_shape)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
@@ -86,13 +91,13 @@ y_test_gte5 = y_test[y_test >= 5] - 5
# define two groups of layers: feature (convolutions) and classification (dense)
feature_layers = [
Convolution2D(nb_filters, nb_conv, nb_conv,
Convolution2D(nb_filters, kernel_size, kernel_size,
border_mode='valid',
input_shape=(1, img_rows, img_cols)),
input_shape=input_shape),
Activation('relu'),
Convolution2D(nb_filters, nb_conv, nb_conv),
Convolution2D(nb_filters, kernel_size, kernel_size),
Activation('relu'),
MaxPooling2D(pool_size=(nb_pool, nb_pool)),
MaxPooling2D(pool_size=(pool_size, pool_size)),
Dropout(0.25),
Flatten(),
]
@@ -105,9 +110,7 @@ classification_layers = [
]
# create complete model
model = Sequential()
for l in feature_layers + classification_layers:
model.add(l)
model = Sequential(feature_layers + classification_layers)
# train model for 5-digit classification [0..4]
train_model(model,
+364
Ver Arquivo
@@ -0,0 +1,364 @@
'''Neural doodle with Keras
Script Usage:
# Arguments:
```
--nlabels: # of regions (colors) in mask images
--style-image: image to learn style from
--style-mask: semantic labels for style image
--target-mask: semantic labels for target image (your doodle)
--content-image: optional image to learn content from
--target-image-prefix: path prefix for generated target images
```
# Example 1: doodle using a style image, style mask
and target mask.
```
python neural_doodle.py --nlabels 4 --style-image Monet/style.png \
--style-mask Monet/style_mask.png --target-mask Monet/target_mask.png \
--target-image-prefix generated/monet
```
# Example 2: doodle using a style image, style mask,
target mask and an optional content image.
```
python neural_doodle.py --nlabels 4 --style-image Renoir/style.png \
--style-mask Renoir/style_mask.png --target-mask Renoir/target_mask.png \
--content-image Renoir/creek.jpg \
--target-image-prefix generated/renoir
```
References:
[Dmitry Ulyanov's blog on fast-neural-doodle](http://dmitryulyanov.github.io/feed-forward-neural-doodle/)
[Torch code for fast-neural-doodle](https://github.com/DmitryUlyanov/fast-neural-doodle)
[Torch code for online-neural-doodle](https://github.com/DmitryUlyanov/online-neural-doodle)
[Paper Texture Networks: Feed-forward Synthesis of Textures and Stylized Images](http://arxiv.org/abs/1603.03417)
[Discussion on parameter tuning](https://github.com/fchollet/keras/issues/3705)
Resources:
Example images can be downloaded from
https://github.com/DmitryUlyanov/fast-neural-doodle/tree/master/data
'''
from __future__ import print_function
import time
import argparse
import numpy as np
from scipy.optimize import fmin_l_bfgs_b
from scipy.misc import imread, imsave
from keras import backend as K
from keras.layers import Input, Convolution2D, MaxPooling2D, AveragePooling2D
from keras.models import Model
from keras.preprocessing.image import load_img, img_to_array
from keras.applications import vgg19
# Command line arguments
parser = argparse.ArgumentParser(description='Keras neural doodle example')
parser.add_argument('--nlabels', type=int,
help='number of semantic labels'
' (regions in differnet colors)'
' in style_mask/target_mask')
parser.add_argument('--style-image', type=str,
help='path to image to learn style from')
parser.add_argument('--style-mask', type=str,
help='path to semantic mask of style image')
parser.add_argument('--target-mask', type=str,
help='path to semantic mask of target image')
parser.add_argument('--content-image', type=str, default=None,
help='path to optional content image')
parser.add_argument('--target-image-prefix', type=str,
help='path prefix for generated results')
args = parser.parse_args()
style_img_path = args.style_image
style_mask_path = args.style_mask
target_mask_path = args.target_mask
content_img_path = args.content_image
target_img_prefix = args.target_image_prefix
use_content_img = content_img_path is not None
nb_labels = args.nlabels
nb_colors = 3 # RGB
# determine image sizes based on target_mask
ref_img = imread(target_mask_path)
img_nrows, img_ncols = ref_img.shape[:2]
total_variation_weight = 50.
style_weight = 1.
content_weight = 0.1 if use_content_img else 0
content_feature_layers = ['block5_conv2']
# To get better generation qualities, use more conv layers for style features
style_feature_layers = ['block1_conv1', 'block2_conv1', 'block3_conv1',
'block4_conv1', 'block5_conv1']
# helper functions for reading/processing images
def preprocess_image(image_path):
img = load_img(image_path, target_size=(img_nrows, img_ncols))
img = img_to_array(img)
img = np.expand_dims(img, axis=0)
img = vgg19.preprocess_input(img)
return img
def deprocess_image(x):
if K.image_dim_ordering() == 'th':
x = x.reshape((3, img_nrows, img_ncols))
x = x.transpose((1, 2, 0))
else:
x = x.reshape((img_nrows, img_ncols, 3))
x = x[:, :, ::-1]
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
x = np.clip(x, 0, 255).astype('uint8')
return x
def kmeans(xs, k):
assert xs.ndim == 2
try:
from sklearn.cluster import k_means
_, labels, _ = k_means(xs.astype("float64"), k)
except ImportError:
from scipy.cluster.vq import kmeans2
_, labels = kmeans2(xs, k, missing='raise')
return labels
def load_mask_labels():
'''Load both target and style masks.
A mask image (nr x nc) with m labels/colors will be loaded
as a 4D boolean tensor: (1, m, nr, nc) for 'th' or (1, nr, nc, m) for 'tf'
'''
target_mask_img = load_img(target_mask_path,
target_size=(img_nrows, img_ncols))
target_mask_img = img_to_array(target_mask_img)
style_mask_img = load_img(style_mask_path,
target_size=(img_nrows, img_ncols))
style_mask_img = img_to_array(style_mask_img)
if K.image_dim_ordering() == 'th':
mask_vecs = np.vstack([style_mask_img.reshape((3, -1)).T,
target_mask_img.reshape((3, -1)).T])
else:
mask_vecs = np.vstack([style_mask_img.reshape((-1, 3)),
target_mask_img.reshape((-1, 3))])
labels = kmeans(mask_vecs, nb_labels)
style_mask_label = labels[:img_nrows *
img_ncols].reshape((img_nrows, img_ncols))
target_mask_label = labels[img_nrows *
img_ncols:].reshape((img_nrows, img_ncols))
stack_axis = 0 if K.image_dim_ordering() == 'th' else -1
style_mask = np.stack([style_mask_label == r for r in xrange(nb_labels)],
axis=stack_axis)
target_mask = np.stack([target_mask_label == r for r in xrange(nb_labels)],
axis=stack_axis)
return (np.expand_dims(style_mask, axis=0),
np.expand_dims(target_mask, axis=0))
# Create tensor variables for images
if K.image_dim_ordering() == 'th':
shape = (1, nb_colors, img_nrows, img_ncols)
else:
shape = (1, img_nrows, img_ncols, nb_colors)
style_image = K.variable(preprocess_image(style_img_path))
target_image = K.placeholder(shape=shape)
if use_content_img:
content_image = K.variable(preprocess_image(content_img_path))
else:
content_image = K.zeros(shape=shape)
images = K.concatenate([style_image, target_image, content_image], axis=0)
# Create tensor variables for masks
raw_style_mask, raw_target_mask = load_mask_labels()
style_mask = K.variable(raw_style_mask.astype("float32"))
target_mask = K.variable(raw_target_mask.astype("float32"))
masks = K.concatenate([style_mask, target_mask], axis=0)
# index constants for images and tasks variables
STYLE, TARGET, CONTENT = 0, 1, 2
# Build image model, mask model and use layer outputs as features
# image model as VGG19
image_model = vgg19.VGG19(include_top=False, input_tensor=images)
# mask model as a series of pooling
mask_input = Input(tensor=masks, shape=(None, None, None), name="mask_input")
x = mask_input
for layer in image_model.layers[1:]:
name = 'mask_%s' % layer.name
if 'conv' in layer.name:
x = AveragePooling2D((3, 3), strides=(
1, 1), name=name, border_mode="same")(x)
elif 'pool' in layer.name:
x = AveragePooling2D((2, 2), name=name)(x)
mask_model = Model(mask_input, x)
# Collect features from image_model and task_model
image_features = {}
mask_features = {}
for img_layer, mask_layer in zip(image_model.layers, mask_model.layers):
if 'conv' in img_layer.name:
assert 'mask_' + img_layer.name == mask_layer.name
layer_name = img_layer.name
img_feat, mask_feat = img_layer.output, mask_layer.output
image_features[layer_name] = img_feat
mask_features[layer_name] = mask_feat
# Define loss functions
def gram_matrix(x):
assert K.ndim(x) == 3
features = K.batch_flatten(x)
gram = K.dot(features, K.transpose(features))
return gram
def region_style_loss(style_image, target_image, style_mask, target_mask):
'''Calculate style loss between style_image and target_image,
for one common region specified by their (boolean) masks
'''
assert 3 == K.ndim(style_image) == K.ndim(target_image)
assert 2 == K.ndim(style_mask) == K.ndim(target_mask)
if K.image_dim_ordering() == 'th':
masked_style = style_image * style_mask
masked_target = target_image * target_mask
nb_channels = K.shape(style_image)[0]
else:
masked_style = K.permute_dimensions(
style_image, (2, 0, 1)) * style_mask
masked_target = K.permute_dimensions(
target_image, (2, 0, 1)) * target_mask
nb_channels = K.shape(style_image)[-1]
s = gram_matrix(masked_style) / K.mean(style_mask) / nb_channels
c = gram_matrix(masked_target) / K.mean(target_mask) / nb_channels
return K.mean(K.square(s - c))
def style_loss(style_image, target_image, style_masks, target_masks):
'''Calculate style loss between style_image and target_image,
in all regions.
'''
assert 3 == K.ndim(style_image) == K.ndim(target_image)
assert 3 == K.ndim(style_masks) == K.ndim(target_masks)
loss = K.variable(0)
for i in xrange(nb_labels):
if K.image_dim_ordering() == 'th':
style_mask = style_masks[i, :, :]
target_mask = target_masks[i, :, :]
else:
style_mask = style_masks[:, :, i]
target_mask = target_masks[:, :, i]
loss += region_style_loss(style_image,
target_image, style_mask, target_mask)
return loss
def content_loss(content_image, target_image):
return K.sum(K.square(target_image - content_image))
def total_variation_loss(x):
assert 4 == K.ndim(x)
if K.image_dim_ordering() == 'th':
a = K.square(x[:, :, :img_nrows - 1, :img_ncols - 1] -
x[:, :, 1:, :img_ncols - 1])
b = K.square(x[:, :, :img_nrows - 1, :img_ncols - 1] -
x[:, :, :img_nrows - 1, 1:])
else:
a = K.square(x[:, :img_nrows - 1, :img_ncols - 1, :] -
x[:, 1:, :img_ncols - 1, :])
b = K.square(x[:, :img_nrows - 1, :img_ncols - 1, :] -
x[:, :img_nrows - 1, 1:, :])
return K.sum(K.pow(a + b, 1.25))
# Overall loss is the weighted sum of content_loss, style_loss and tv_loss
# Each individual loss uses features from image/mask models.
loss = K.variable(0)
for layer in content_feature_layers:
content_feat = image_features[layer][CONTENT, :, :, :]
target_feat = image_features[layer][TARGET, :, :, :]
loss += content_weight * content_loss(content_feat, target_feat)
for layer in style_feature_layers:
style_feat = image_features[layer][STYLE, :, :, :]
target_feat = image_features[layer][TARGET, :, :, :]
style_masks = mask_features[layer][STYLE, :, :, :]
target_masks = mask_features[layer][TARGET, :, :, :]
sl = style_loss(style_feat, target_feat, style_masks, target_masks)
loss += (style_weight / len(style_feature_layers)) * sl
loss += total_variation_weight * total_variation_loss(target_image)
loss_grads = K.gradients(loss, target_image)
# Evaluator class for computing efficiency
outputs = [loss]
if type(loss_grads) in {list, tuple}:
outputs += loss_grads
else:
outputs.append(loss_grads)
f_outputs = K.function([target_image], outputs)
def eval_loss_and_grads(x):
if K.image_dim_ordering() == 'th':
x = x.reshape((1, 3, img_nrows, img_ncols))
else:
x = x.reshape((1, img_nrows, img_ncols, 3))
outs = f_outputs([x])
loss_value = outs[0]
if len(outs[1:]) == 1:
grad_values = outs[1].flatten().astype('float64')
else:
grad_values = np.array(outs[1:]).flatten().astype('float64')
return loss_value, grad_values
class Evaluator(object):
def __init__(self):
self.loss_value = None
self.grads_values = None
def loss(self, x):
assert self.loss_value is None
loss_value, grad_values = eval_loss_and_grads(x)
self.loss_value = loss_value
self.grad_values = grad_values
return self.loss_value
def grads(self, x):
assert self.loss_value is not None
grad_values = np.copy(self.grad_values)
self.loss_value = None
self.grad_values = None
return grad_values
evaluator = Evaluator()
# Generate images by iterative optimization
if K.image_dim_ordering() == 'th':
x = np.random.uniform(0, 255, (1, 3, img_nrows, img_ncols)) - 128.
else:
x = np.random.uniform(0, 255, (1, img_nrows, img_ncols, 3)) - 128.
for i in range(50):
print('Start of iteration', i)
start_time = time.time()
x, min_val, info = fmin_l_bfgs_b(evaluator.loss, x.flatten(),
fprime=evaluator.grads, maxfun=20)
print('Current loss value:', min_val)
# save current generated image
img = deprocess_image(x.copy())
fname = target_img_prefix + '_at_iteration_%d.png' % i
imsave(fname, img)
end_time = time.time()
print('Image saved as', fname)
print('Iteration %d completed in %ds' % (i, end_time - start_time))
+51 -82
Ver Arquivo
@@ -1,10 +1,5 @@
'''Neural style transfer with Keras.
Before running this script, download the weights for the VGG16 model at:
https://drive.google.com/file/d/0Bz7KyqmuGsilT0J5dmRCM0ROVHc/view?usp=sharing
(source: https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3)
and make sure the variable `weights_path` in this script matches the location of the file.
Run the script with:
```
python neural_style_transfer.py path_to_your_base_image.jpg path_to_your_reference.jpg prefix_for_results
@@ -15,7 +10,6 @@ python neural_style_transfer.py img/tuebingen.jpg img/starry_night.jpg results/m
```
It is preferable to run this script on GPU, for speed.
If running on CPU, prefer the TensorFlow backend (much faster).
Example result: https://twitter.com/fchollet/status/686631033085677568
@@ -49,16 +43,14 @@ keeping the generated image close enough to the original one.
'''
from __future__ import print_function
from scipy.misc import imread, imresize, imsave
from keras.preprocessing.image import load_img, img_to_array
from scipy.misc import imsave
import numpy as np
from scipy.optimize import fmin_l_bfgs_b
import time
import os
import argparse
import h5py
from keras.models import Sequential
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.applications import vgg16
from keras import backend as K
parser = argparse.ArgumentParser(description='Neural style transfer with Keras.')
@@ -73,7 +65,6 @@ args = parser.parse_args()
base_image_path = args.base_image_path
style_reference_image_path = args.style_reference_image_path
result_prefix = args.result_prefix
weights_path = 'vgg16_weights.h5'
# these are the weights of the different loss components
total_variation_weight = 1.
@@ -81,20 +72,29 @@ style_weight = 1.
content_weight = 0.025
# dimensions of the generated picture.
img_width = 400
img_height = 400
assert img_height == img_width, 'Due to the use of the Gram matrix, width and height must match.'
img_nrows = 400
img_ncols = 400
assert img_ncols == img_nrows, 'Due to the use of the Gram matrix, width and height must match.'
# 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_nrows, img_ncols))
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_nrows, img_ncols))
x = x.transpose((1, 2, 0))
else:
x = x.reshape((img_nrows, img_ncols, 3))
x = x[:, :, ::-1]
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
x = np.clip(x, 0, 255).astype('uint8')
return x
@@ -103,7 +103,10 @@ base_image = K.variable(preprocess_image(base_image_path))
style_reference_image = K.variable(preprocess_image(style_reference_image_path))
# this will contain our generated image
combination_image = K.placeholder((1, 3, img_width, img_height))
if K.image_dim_ordering() == 'th':
combination_image = K.placeholder((1, 3, img_nrows, img_ncols))
else:
combination_image = K.placeholder((1, img_nrows, img_ncols, 3))
# combine the 3 images into a single Keras tensor
input_tensor = K.concatenate([base_image,
@@ -111,60 +114,9 @@ input_tensor = K.concatenate([base_image,
combination_image], axis=0)
# build the VGG16 network with our 3 images as input
first_layer = ZeroPadding2D((1, 1))
first_layer.set_input(input_tensor, shape=(3, 3, img_width, img_height))
model = Sequential()
model.add(first_layer)
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu'))
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'))
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'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu'))
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'))
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'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu'))
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()
# the model will be loaded with pre-trained ImageNet weights
model = vgg16.VGG16(input_tensor=input_tensor,
weights='imagenet', include_top=False)
print('Model loaded.')
# get the symbolic outputs of each "key" layer (we gave them unique names).
@@ -176,7 +128,10 @@ outputs_dict = dict([(layer.name, layer.output) for layer in model.layers])
# the gram matrix of an image tensor (feature-wise outer product)
def gram_matrix(x):
assert K.ndim(x) == 3
features = K.batch_flatten(x)
if K.image_dim_ordering() == 'th':
features = K.batch_flatten(x)
else:
features = K.batch_flatten(K.permute_dimensions(x, (2, 0, 1)))
gram = K.dot(features, K.transpose(features))
return gram
@@ -191,7 +146,7 @@ def style_loss(style, combination):
S = gram_matrix(style)
C = gram_matrix(combination)
channels = 3
size = img_width * img_height
size = img_nrows * img_ncols
return K.sum(K.square(S - C)) / (4. * (channels ** 2) * (size ** 2))
# an auxiliary loss function
@@ -204,19 +159,25 @@ def content_loss(base, combination):
# designed to keep the generated image locally coherent
def total_variation_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_nrows-1, :img_ncols-1] - x[:, :, 1:, :img_ncols-1])
b = K.square(x[:, :, :img_nrows-1, :img_ncols-1] - x[:, :, :img_nrows-1, 1:])
else:
a = K.square(x[:, :img_nrows-1, :img_ncols-1, :] - x[:, 1:, :img_ncols-1, :])
b = K.square(x[:, :img_nrows-1, :img_ncols-1, :] - x[:, :img_nrows-1, 1:, :])
return K.sum(K.pow(a + b, 1.25))
# combine these loss functions into a single scalar
loss = K.variable(0.)
layer_features = outputs_dict['conv4_2']
layer_features = outputs_dict['block4_conv2']
base_image_features = layer_features[0, :, :, :]
combination_features = layer_features[2, :, :, :]
loss += content_weight * content_loss(base_image_features,
combination_features)
feature_layers = ['conv1_1', 'conv2_1', 'conv3_1', 'conv4_1', 'conv5_1']
feature_layers = ['block1_conv1', 'block2_conv1',
'block3_conv1', 'block4_conv1',
'block5_conv1']
for layer_name in feature_layers:
layer_features = outputs_dict[layer_name]
style_reference_features = layer_features[1, :, :, :]
@@ -235,8 +196,12 @@ else:
outputs.append(grads)
f_outputs = K.function([combination_image], outputs)
def eval_loss_and_grads(x):
x = x.reshape((1, 3, img_width, img_height))
if K.image_dim_ordering() == 'th':
x = x.reshape((1, 3, img_nrows, img_ncols))
else:
x = x.reshape((1, img_nrows, img_ncols, 3))
outs = f_outputs([x])
loss_value = outs[0]
if len(outs[1:]) == 1:
@@ -274,7 +239,11 @@ evaluator = Evaluator()
# run scipy-based optimization (L-BFGS) over the pixels of the generated image
# so as to minimize the neural style loss
x = np.random.uniform(0, 255, (1, 3, img_width, img_height))
if K.image_dim_ordering() == 'th':
x = np.random.uniform(0, 255, (1, 3, img_nrows, img_ncols)) - 128.
else:
x = np.random.uniform(0, 255, (1, img_nrows, img_ncols, 3)) - 128.
for i in range(10):
print('Start of iteration', i)
start_time = time.time()
@@ -282,7 +251,7 @@ for i in range(10):
fprime=evaluator.grads, maxfun=20)
print('Current loss value:', min_val)
# save current generated image
img = deprocess_image(x.reshape((3, img_width, img_height)))
img = deprocess_image(x.copy())
fname = result_prefix + '_at_iteration_%d.png' % i
imsave(fname, img)
end_time = time.time()
+144
Ver Arquivo
@@ -0,0 +1,144 @@
'''This script 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
(classication of newsgroup messages into 20 different categories).
GloVe embedding data can be found at:
http://nlp.stanford.edu/data/glove.6B.zip
(source page: http://nlp.stanford.edu/projects/glove/)
20 Newsgroup data can be found at:
http://www.cs.cmu.edu/afs/cs.cmu.edu/project/theo-20/www/data/news20.html
'''
from __future__ import print_function
import os
import numpy as np
np.random.seed(1337)
from keras.preprocessing.text import Tokenizer
from keras.preprocessing.sequence import pad_sequences
from keras.utils.np_utils import to_categorical
from keras.layers import Dense, Input, Flatten
from keras.layers import Conv1D, MaxPooling1D, Embedding
from keras.models import Model
import sys
BASE_DIR = ''
GLOVE_DIR = BASE_DIR + '/glove.6B/'
TEXT_DATA_DIR = BASE_DIR + '/20_newsgroup/'
MAX_SEQUENCE_LENGTH = 1000
MAX_NB_WORDS = 20000
EMBEDDING_DIM = 100
VALIDATION_SPLIT = 0.2
# first, build index mapping words in the embeddings set
# to their embedding vector
print('Indexing word vectors.')
embeddings_index = {}
f = open(os.path.join(GLOVE_DIR, 'glove.6B.100d.txt'))
for line in f:
values = line.split()
word = values[0]
coefs = np.asarray(values[1:], dtype='float32')
embeddings_index[word] = coefs
f.close()
print('Found %s word vectors.' % len(embeddings_index))
# second, prepare text samples and their labels
print('Processing text dataset')
texts = [] # list of text samples
labels_index = {} # dictionary mapping label name to numeric id
labels = [] # list of label ids
for name in sorted(os.listdir(TEXT_DATA_DIR)):
path = os.path.join(TEXT_DATA_DIR, name)
if os.path.isdir(path):
label_id = len(labels_index)
labels_index[name] = label_id
for fname in sorted(os.listdir(path)):
if fname.isdigit():
fpath = os.path.join(path, fname)
if sys.version_info < (3,):
f = open(fpath)
else:
f = open(fpath, encoding='latin-1')
texts.append(f.read())
f.close()
labels.append(label_id)
print('Found %s texts.' % len(texts))
# finally, vectorize the text samples into a 2D integer tensor
tokenizer = Tokenizer(nb_words=MAX_NB_WORDS)
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)
word_index = tokenizer.word_index
print('Found %s unique tokens.' % len(word_index))
data = pad_sequences(sequences, maxlen=MAX_SEQUENCE_LENGTH)
labels = to_categorical(np.asarray(labels))
print('Shape of data tensor:', data.shape)
print('Shape of label tensor:', labels.shape)
# split the data into a training set and a validation set
indices = np.arange(data.shape[0])
np.random.shuffle(indices)
data = data[indices]
labels = labels[indices]
nb_validation_samples = int(VALIDATION_SPLIT * data.shape[0])
x_train = data[:-nb_validation_samples]
y_train = labels[:-nb_validation_samples]
x_val = data[-nb_validation_samples:]
y_val = labels[-nb_validation_samples:]
print('Preparing embedding matrix.')
# prepare embedding matrix
nb_words = min(MAX_NB_WORDS, len(word_index))
embedding_matrix = np.zeros((nb_words + 1, EMBEDDING_DIM))
for word, i in word_index.items():
if i > MAX_NB_WORDS:
continue
embedding_vector = embeddings_index.get(word)
if embedding_vector is not None:
# words not found in embedding index will be all-zeros.
embedding_matrix[i] = embedding_vector
# load pre-trained word embeddings into an Embedding layer
# note that we set trainable = False so as to keep the embeddings fixed
embedding_layer = Embedding(nb_words + 1,
EMBEDDING_DIM,
weights=[embedding_matrix],
input_length=MAX_SEQUENCE_LENGTH,
trainable=False)
print('Training model.')
# train a 1D convnet with global maxpooling
sequence_input = Input(shape=(MAX_SEQUENCE_LENGTH,), dtype='int32')
embedded_sequences = embedding_layer(sequence_input)
x = Conv1D(128, 5, activation='relu')(embedded_sequences)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(5)(x)
x = Conv1D(128, 5, activation='relu')(x)
x = MaxPooling1D(35)(x)
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
preds = Dense(len(labels_index), activation='softmax')(x)
model = Model(sequence_input, preds)
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop',
metrics=['acc'])
# happy learning!
model.fit(x_train, y_train, validation_data=(x_val, y_val),
nb_epoch=2, batch_size=128)
+2 -2
Ver Arquivo
@@ -16,7 +16,7 @@ epochs = 25
lahead = 1
def gen_cosine_amp(amp=100, period=25, x0=0, xn=50000, step=1, k=0.0001):
def gen_cosine_amp(amp=100, period=1000, x0=0, xn=50000, step=1, k=0.0001):
"""Generates an absolute cosine time series with the amplitude
exponentially decreasing
@@ -31,7 +31,7 @@ def gen_cosine_amp(amp=100, period=25, x0=0, xn=50000, step=1, k=0.0001):
cos = np.zeros(((xn - x0) * step, 1, 1))
for i in range(len(cos)):
idx = x0 + i * step
cos[i, 0, 0] = amp * np.cos(idx / (2 * np.pi * period))
cos[i, 0, 0] = amp * np.cos(2 * np.pi * idx / period)
cos[i, 0, 0] = cos[i, 0, 0] * np.exp(-k * idx)
return cos
+13 -14
Ver Arquivo
@@ -11,27 +11,25 @@ from keras import backend as K
from keras import objectives
from keras.datasets import mnist
batch_size = 16
batch_size = 100
original_dim = 784
latent_dim = 2
intermediate_dim = 128
epsilon_std = 0.01
nb_epoch = 40
intermediate_dim = 256
nb_epoch = 50
x = Input(batch_shape=(batch_size, original_dim))
h = Dense(intermediate_dim, activation='relu')(x)
z_mean = Dense(latent_dim)(h)
z_log_std = Dense(latent_dim)(h)
z_log_var = Dense(latent_dim)(h)
def sampling(args):
z_mean, z_log_std = args
epsilon = K.random_normal(shape=(batch_size, latent_dim),
mean=0., std=epsilon_std)
return z_mean + K.exp(z_log_std) * epsilon
z_mean, z_log_var = args
epsilon = K.random_normal(shape=(batch_size, latent_dim), mean=0.)
return z_mean + K.exp(z_log_var / 2) * epsilon
# note that "output_shape" isn't necessary with the TensorFlow backend
# so you could write `Lambda(sampling)([z_mean, z_log_std])`
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_std])
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')
@@ -39,9 +37,10 @@ decoder_mean = Dense(original_dim, activation='sigmoid')
h_decoded = decoder_h(z)
x_decoded_mean = decoder_mean(h_decoded)
def vae_loss(x, x_decoded_mean):
xent_loss = objectives.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.mean(1 + z_log_std - K.square(z_mean) - K.exp(z_log_std), axis=-1)
xent_loss = original_dim * objectives.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.sum(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)
@@ -87,7 +86,7 @@ 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]]) * epsilon_std
z_sample = np.array([[xi, yi]])
x_decoded = generator.predict(z_sample)
digit = x_decoded[0].reshape(digit_size, digit_size)
figure[i * digit_size: (i + 1) * digit_size,
+124
Ver Arquivo
@@ -0,0 +1,124 @@
'''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
'''
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.models import Model
from keras import backend as K
from keras import objectives
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
# convolution kernel size
nb_conv = 3
batch_size = 16
original_dim = (img_chns, img_rows, img_cols)
latent_dim = 2
intermediate_dim = 128
epsilon_std = 0.01
nb_epoch = 5
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)
def sampling(args):
z_mean, z_log_var = args
epsilon = K.random_normal(shape=(batch_size, latent_dim),
mean=0., std=epsilon_std)
return z_mean + K.exp(z_log_var) * epsilon
# note that "output_shape" isn't necessary with the TensorFlow backend
# so you could write `Lambda(sampling)([z_mean, z_log_var])`
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')
h_decoded = decoder_h(z)
f_decoded = decoder_f(h_decoded)
c_decoded = decoder_c(f_decoded)
x_decoded_mean = decoder_mean(c_decoded)
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!
x = K.flatten(x)
x_decoded_mean = K.flatten(x_decoded_mean)
xent_loss = 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.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_train.astype('float32')[:, None, :, :] / 255.
x_test = x_test.astype('float32')[:, None, :, :] / 255.
vae.fit(x_train, x_train,
shuffle=True,
nb_epoch=nb_epoch,
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)
# display a 2D plot of the digit classes in the latent space
x_test_encoded = encoder.predict(x_test, batch_size=batch_size)
plt.figure(figsize=(6, 6))
plt.scatter(x_test_encoded[:, 0], x_test_encoded[:, 1], c=y_test)
plt.colorbar()
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)
# display a 2D manifold of the digits
n = 15 # figure with 15x15 digits
digit_size = 28
figure = np.zeros((digit_size * n, digit_size * n))
# we will sample n points within [-15, 15] standard deviations
grid_x = np.linspace(-15, 15, n)
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)
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
plt.figure(figsize=(10, 10))
plt.imshow(figure)
plt.show()
+1 -1
Ver Arquivo
@@ -15,4 +15,4 @@ from . import objectives
from . import optimizers
from . import regularizers
__version__ = '1.0.6'
__version__ = '1.1.0'
+4
Ver Arquivo
@@ -0,0 +1,4 @@
from .vgg16 import VGG16
from .vgg19 import VGG19
from .resnet50 import ResNet50
from .inception_v3 import InceptionV3
+43
Ver Arquivo
@@ -0,0 +1,43 @@
import numpy as np
import json
from ..utils.data_utils import get_file
from .. import backend as K
CLASS_INDEX = None
CLASS_INDEX_PATH = 'https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json'
def preprocess_input(x, dim_ordering='default'):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
assert dim_ordering in {'tf', 'th'}
if dim_ordering == 'th':
x[:, 0, :, :] -= 103.939
x[:, 1, :, :] -= 116.779
x[:, 2, :, :] -= 123.68
# 'RGB'->'BGR'
x = x[:, ::-1, :, :]
else:
x[:, :, :, 0] -= 103.939
x[:, :, :, 1] -= 116.779
x[:, :, :, 2] -= 123.68
# 'RGB'->'BGR'
x = x[:, :, :, ::-1]
return x
def decode_predictions(preds):
global CLASS_INDEX
assert len(preds.shape) == 2 and preds.shape[1] == 1000
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)])
return results
+312
Ver Arquivo
@@ -0,0 +1,312 @@
# -*- coding: utf-8 -*-
'''Inception V3 model for Keras.
Note that the ImageNet weights provided are from a model that had not fully converged.
Inception v3 should be able to reach 6.9% top-5 error, but our model
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.
# Reference:
- [Rethinking the Inception Architecture for Computer Vision](http://arxiv.org/abs/1512.00567)
'''
from __future__ import print_function
from __future__ import absolute_import
import warnings
from ..models import Model
from ..layers import Flatten, Dense, Input, BatchNormalization, merge
from ..layers import Convolution2D, MaxPooling2D, AveragePooling2D
from ..utils.layer_utils import convert_all_kernels_in_model
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions
TH_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/inception_v3_weights_th_dim_ordering_th_kernels.h5'
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/inception_v3_weights_tf_dim_ordering_tf_kernels.h5'
TH_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/inception_v3_weights_th_dim_ordering_th_kernels_notop.h5'
TF_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5'
def conv2d_bn(x, nb_filter, nb_row, nb_col,
border_mode='same', subsample=(1, 1),
name=None):
'''Utility function to apply conv + BN.
'''
if name is not None:
bn_name = name + '_bn'
conv_name = name + '_conv'
else:
bn_name = None
conv_name = None
if K.image_dim_ordering() == 'th':
bn_axis = 1
else:
bn_axis = 3
x = Convolution2D(nb_filter, nb_row, nb_col,
subsample=subsample,
activation='relu',
border_mode=border_mode,
name=conv_name)(x)
x = BatchNormalization(axis=bn_axis, name=bn_name)(x)
return x
def InceptionV3(include_top=True, weights='imagenet',
input_tensor=None):
'''Instantiate the Inception v3 architecture,
optionally loading weights pre-trained
on ImageNet. 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.
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.
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).')
# Determine proper input shape
if K.image_dim_ordering() == 'th':
if include_top:
input_shape = (3, 299, 299)
else:
input_shape = (3, None, None)
else:
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
if K.image_dim_ordering() == 'th':
channel_axis = 1
else:
channel_axis = 3
x = conv2d_bn(img_input, 32, 3, 3, subsample=(2, 2), border_mode='valid')
x = conv2d_bn(x, 32, 3, 3, border_mode='valid')
x = conv2d_bn(x, 64, 3, 3)
x = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = conv2d_bn(x, 80, 1, 1, border_mode='valid')
x = conv2d_bn(x, 192, 3, 3, border_mode='valid')
x = MaxPooling2D((3, 3), strides=(2, 2))(x)
# mixed 0, 1, 2: 35 x 35 x 256
for i in range(3):
branch1x1 = conv2d_bn(x, 64, 1, 1)
branch5x5 = conv2d_bn(x, 48, 1, 1)
branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)
branch3x3dbl = conv2d_bn(x, 64, 1, 1)
branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
branch_pool = AveragePooling2D(
(3, 3), strides=(1, 1), border_mode='same')(x)
branch_pool = conv2d_bn(branch_pool, 32, 1, 1)
x = merge([branch1x1, branch5x5, branch3x3dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed' + str(i))
# mixed 3: 17 x 17 x 768
branch3x3 = conv2d_bn(x, 384, 3, 3, subsample=(2, 2), border_mode='valid')
branch3x3dbl = conv2d_bn(x, 64, 1, 1)
branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3,
subsample=(2, 2), border_mode='valid')
branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = merge([branch3x3, branch3x3dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed3')
# mixed 4: 17 x 17 x 768
branch1x1 = conv2d_bn(x, 192, 1, 1)
branch7x7 = conv2d_bn(x, 128, 1, 1)
branch7x7 = conv2d_bn(branch7x7, 128, 1, 7)
branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2d_bn(x, 128, 1, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 1, 7)
branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same')(x)
branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed4')
# mixed 5, 6: 17 x 17 x 768
for i in range(2):
branch1x1 = conv2d_bn(x, 192, 1, 1)
branch7x7 = conv2d_bn(x, 160, 1, 1)
branch7x7 = conv2d_bn(branch7x7, 160, 1, 7)
branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2d_bn(x, 160, 1, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 1, 7)
branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D(
(3, 3), strides=(1, 1), border_mode='same')(x)
branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed' + str(5 + i))
# mixed 7: 17 x 17 x 768
branch1x1 = conv2d_bn(x, 192, 1, 1)
branch7x7 = conv2d_bn(x, 192, 1, 1)
branch7x7 = conv2d_bn(branch7x7, 192, 1, 7)
branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)
branch7x7dbl = conv2d_bn(x, 160, 1, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)
branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)
branch_pool = AveragePooling2D((3, 3), strides=(1, 1), border_mode='same')(x)
branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch7x7, branch7x7dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed7')
# mixed 8: 8 x 8 x 1280
branch3x3 = conv2d_bn(x, 192, 1, 1)
branch3x3 = conv2d_bn(branch3x3, 320, 3, 3,
subsample=(2, 2), border_mode='valid')
branch7x7x3 = conv2d_bn(x, 192, 1, 1)
branch7x7x3 = conv2d_bn(branch7x7x3, 192, 1, 7)
branch7x7x3 = conv2d_bn(branch7x7x3, 192, 7, 1)
branch7x7x3 = conv2d_bn(branch7x7x3, 192, 3, 3,
subsample=(2, 2), border_mode='valid')
branch_pool = AveragePooling2D((3, 3), strides=(2, 2))(x)
x = merge([branch3x3, branch7x7x3, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed8')
# mixed 9: 8 x 8 x 2048
for i in range(2):
branch1x1 = conv2d_bn(x, 320, 1, 1)
branch3x3 = conv2d_bn(x, 384, 1, 1)
branch3x3_1 = conv2d_bn(branch3x3, 384, 1, 3)
branch3x3_2 = conv2d_bn(branch3x3, 384, 3, 1)
branch3x3 = merge([branch3x3_1, branch3x3_2],
mode='concat', concat_axis=channel_axis,
name='mixed9_' + str(i))
branch3x3dbl = conv2d_bn(x, 448, 1, 1)
branch3x3dbl = conv2d_bn(branch3x3dbl, 384, 3, 3)
branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 384, 1, 3)
branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 384, 3, 1)
branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2],
mode='concat', concat_axis=channel_axis)
branch_pool = AveragePooling2D(
(3, 3), strides=(1, 1), border_mode='same')(x)
branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
x = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool],
mode='concat', concat_axis=channel_axis,
name='mixed' + str(9 + i))
if include_top:
# Classification block
x = AveragePooling2D((8, 8), strides=(8, 8), name='avg_pool')(x)
x = Flatten(name='flatten')(x)
x = Dense(1000, activation='softmax', name='predictions')(x)
# Create model
model = Model(img_input, x)
# load weights
if weights == 'imagenet':
if K.image_dim_ordering() == 'th':
if include_top:
weights_path = get_file('inception_v3_weights_th_dim_ordering_th_kernels.h5',
TH_WEIGHTS_PATH,
cache_subdir='models',
md5_hash='b3baf3070cc4bf476d43a2ea61b0ca5f')
else:
weights_path = get_file('inception_v3_weights_th_dim_ordering_th_kernels_notop.h5',
TH_WEIGHTS_PATH_NO_TOP,
cache_subdir='models',
md5_hash='79aaa90ab4372b4593ba3df64e142f05')
model.load_weights(weights_path)
if K.backend() == 'tensorflow':
warnings.warn('You are using the TensorFlow backend, yet you '
'are using the Theano '
'image dimension ordering convention '
'(`image_dim_ordering="th"`). '
'For best performance, set '
'`image_dim_ordering="tf"` in '
'your Keras config '
'at ~/.keras/keras.json.')
convert_all_kernels_in_model(model)
else:
if include_top:
weights_path = get_file('inception_v3_weights_tf_dim_ordering_tf_kernels.h5',
TF_WEIGHTS_PATH,
cache_subdir='models',
md5_hash='fe114b3ff2ea4bf891e9353d1bbfb32f')
else:
weights_path = get_file('inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5',
TF_WEIGHTS_PATH_NO_TOP,
cache_subdir='models',
md5_hash='2f3609166de1d967d1a481094754f691')
model.load_weights(weights_path)
if K.backend() == 'theano':
convert_all_kernels_in_model(model)
return model
def preprocess_input(x):
x /= 255.
x -= 0.5
x *= 2.
return x
+235
Ver Arquivo
@@ -0,0 +1,235 @@
# -*- coding: utf-8 -*-
'''ResNet50 model for Keras.
# Reference:
- [Deep Residual Learning for Image Recognition](https://arxiv.org/abs/1512.03385)
Adapted from code contributed by BigMoyan.
'''
from __future__ import print_function
from __future__ import absolute_import
import warnings
from ..layers import merge, Input
from ..layers import Dense, Activation, Flatten
from ..layers import Convolution2D, MaxPooling2D, ZeroPadding2D, AveragePooling2D
from ..layers import BatchNormalization
from ..models import Model
from .. import backend as K
from ..utils.layer_utils import convert_all_kernels_in_model
from ..utils.data_utils import get_file
from .imagenet_utils import decode_predictions, preprocess_input
TH_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_th_dim_ordering_th_kernels.h5'
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels.h5'
TH_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_th_dim_ordering_th_kernels_notop.h5'
TF_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.2/resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5'
def identity_block(input_tensor, kernel_size, filters, stage, block):
'''The identity_block is the block that has no conv layer at shortcut
# Arguments
input_tensor: input tensor
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the nb_filters of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
'''
nb_filter1, nb_filter2, nb_filter3 = filters
if K.image_dim_ordering() == 'tf':
bn_axis = 3
else:
bn_axis = 1
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = Convolution2D(nb_filter1, 1, 1, name=conv_name_base + '2a')(input_tensor)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
x = Activation('relu')(x)
x = Convolution2D(nb_filter2, kernel_size, kernel_size,
border_mode='same', name=conv_name_base + '2b')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
x = Activation('relu')(x)
x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
x = merge([x, input_tensor], mode='sum')
x = Activation('relu')(x)
return x
def conv_block(input_tensor, kernel_size, filters, stage, block, strides=(2, 2)):
'''conv_block is the block that has a conv layer at shortcut
# Arguments
input_tensor: input tensor
kernel_size: defualt 3, the kernel size of middle conv layer at main path
filters: list of integers, the nb_filters of 3 conv layer at main path
stage: integer, current stage label, used for generating layer names
block: 'a','b'..., current block label, used for generating layer names
Note that from stage 3, the first conv layer at main path is with subsample=(2,2)
And the shortcut should have subsample=(2,2) as well
'''
nb_filter1, nb_filter2, nb_filter3 = filters
if K.image_dim_ordering() == 'tf':
bn_axis = 3
else:
bn_axis = 1
conv_name_base = 'res' + str(stage) + block + '_branch'
bn_name_base = 'bn' + str(stage) + block + '_branch'
x = Convolution2D(nb_filter1, 1, 1, subsample=strides,
name=conv_name_base + '2a')(input_tensor)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(x)
x = Activation('relu')(x)
x = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same',
name=conv_name_base + '2b')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(x)
x = Activation('relu')(x)
x = Convolution2D(nb_filter3, 1, 1, name=conv_name_base + '2c')(x)
x = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(x)
shortcut = Convolution2D(nb_filter3, 1, 1, subsample=strides,
name=conv_name_base + '1')(input_tensor)
shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)
x = merge([x, shortcut], mode='sum')
x = Activation('relu')(x)
return x
def ResNet50(include_top=True, weights='imagenet',
input_tensor=None):
'''Instantiate the ResNet50 architecture,
optionally loading weights pre-trained
on ImageNet. 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.
# Arguments
include_top: whether to include the 3 fully-connected
layers 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. xput 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).')
# Determine proper input shape
if K.image_dim_ordering() == 'th':
if include_top:
input_shape = (3, 224, 224)
else:
input_shape = (3, None, None)
else:
if include_top:
input_shape = (224, 224, 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
if K.image_dim_ordering() == 'tf':
bn_axis = 3
else:
bn_axis = 1
x = ZeroPadding2D((3, 3))(img_input)
x = Convolution2D(64, 7, 7, subsample=(2, 2), name='conv1')(x)
x = BatchNormalization(axis=bn_axis, name='bn_conv1')(x)
x = Activation('relu')(x)
x = MaxPooling2D((3, 3), strides=(2, 2))(x)
x = conv_block(x, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
x = identity_block(x, 3, [64, 64, 256], stage=2, block='b')
x = identity_block(x, 3, [64, 64, 256], stage=2, block='c')
x = conv_block(x, 3, [128, 128, 512], stage=3, block='a')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='b')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='c')
x = identity_block(x, 3, [128, 128, 512], stage=3, block='d')
x = conv_block(x, 3, [256, 256, 1024], stage=4, block='a')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='b')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='c')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='d')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='e')
x = identity_block(x, 3, [256, 256, 1024], stage=4, block='f')
x = conv_block(x, 3, [512, 512, 2048], stage=5, block='a')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='b')
x = identity_block(x, 3, [512, 512, 2048], stage=5, block='c')
x = AveragePooling2D((7, 7), name='avg_pool')(x)
if include_top:
x = Flatten()(x)
x = Dense(1000, activation='softmax', name='fc1000')(x)
model = Model(img_input, x)
# load weights
if weights == 'imagenet':
if K.image_dim_ordering() == 'th':
if include_top:
weights_path = get_file('resnet50_weights_th_dim_ordering_th_kernels.h5',
TH_WEIGHTS_PATH,
cache_subdir='models',
md5_hash='1c1f8f5b0c8ee28fe9d950625a230e1c')
else:
weights_path = get_file('resnet50_weights_th_dim_ordering_th_kernels_notop.h5',
TH_WEIGHTS_PATH_NO_TOP,
cache_subdir='models',
md5_hash='f64f049c92468c9affcd44b0976cdafe')
model.load_weights(weights_path)
if K.backend() == 'tensorflow':
warnings.warn('You are using the TensorFlow backend, yet you '
'are using the Theano '
'image dimension ordering convention '
'(`image_dim_ordering="th"`). '
'For best performance, set '
'`image_dim_ordering="tf"` in '
'your Keras config '
'at ~/.keras/keras.json.')
convert_all_kernels_in_model(model)
else:
if include_top:
weights_path = get_file('resnet50_weights_tf_dim_ordering_tf_kernels.h5',
TF_WEIGHTS_PATH,
cache_subdir='models',
md5_hash='a7b3fe01876f51b976af0dea6bc144eb')
else:
weights_path = get_file('resnet50_weights_tf_dim_ordering_tf_kernels_notop.h5',
TF_WEIGHTS_PATH_NO_TOP,
cache_subdir='models',
md5_hash='a268eb855778b3df3c7506639542a6af')
model.load_weights(weights_path)
if K.backend() == 'theano':
convert_all_kernels_in_model(model)
return model
+149
Ver Arquivo
@@ -0,0 +1,149 @@
# -*- coding: utf-8 -*-
'''VGG16 model for Keras.
# Reference:
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556)
'''
from __future__ import print_function
from __future__ import absolute_import
import warnings
from ..models import Model
from ..layers import Flatten, Dense, Input
from ..layers import Convolution2D, MaxPooling2D
from ..utils.layer_utils import convert_all_kernels_in_model
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions, preprocess_input
TH_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_th_dim_ordering_th_kernels.h5'
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels.h5'
TH_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_th_dim_ordering_th_kernels_notop.h5'
TF_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
def VGG16(include_top=True, weights='imagenet',
input_tensor=None):
'''Instantiate the VGG16 architecture,
optionally loading weights pre-trained
on ImageNet. 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.
# Arguments
include_top: whether to include the 3 fully-connected
layers 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).')
# Determine proper input shape
if K.image_dim_ordering() == 'th':
if include_top:
input_shape = (3, 224, 224)
else:
input_shape = (3, None, None)
else:
if include_top:
input_shape = (224, 224, 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
# Block 1
x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name='block1_conv1')(img_input)
x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name='block1_conv2')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
# Block 2
x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name='block2_conv1')(x)
x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name='block2_conv2')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
# Block 3
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv1')(x)
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv2')(x)
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv3')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
# Block 4
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv1')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv2')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv3')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
# Block 5
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv1')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv2')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv3')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
if include_top:
# Classification block
x = Flatten(name='flatten')(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dense(1000, activation='softmax', name='predictions')(x)
# Create model
model = Model(img_input, x)
# load weights
if weights == 'imagenet':
if K.image_dim_ordering() == 'th':
if include_top:
weights_path = get_file('vgg16_weights_th_dim_ordering_th_kernels.h5',
TH_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('vgg16_weights_th_dim_ordering_th_kernels_notop.h5',
TH_WEIGHTS_PATH_NO_TOP,
cache_subdir='models')
model.load_weights(weights_path)
if K.backend() == 'tensorflow':
warnings.warn('You are using the TensorFlow backend, yet you '
'are using the Theano '
'image dimension ordering convention '
'(`image_dim_ordering="th"`). '
'For best performance, set '
'`image_dim_ordering="tf"` in '
'your Keras config '
'at ~/.keras/keras.json.')
convert_all_kernels_in_model(model)
else:
if include_top:
weights_path = get_file('vgg16_weights_tf_dim_ordering_tf_kernels.h5',
TF_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5',
TF_WEIGHTS_PATH_NO_TOP,
cache_subdir='models')
model.load_weights(weights_path)
if K.backend() == 'theano':
convert_all_kernels_in_model(model)
return model
+152
Ver Arquivo
@@ -0,0 +1,152 @@
# -*- coding: utf-8 -*-
'''VGG19 model for Keras.
# Reference:
- [Very Deep Convolutional Networks for Large-Scale Image Recognition](https://arxiv.org/abs/1409.1556)
'''
from __future__ import print_function
from __future__ import absolute_import
import warnings
from ..models import Model
from ..layers import Flatten, Dense, Input
from ..layers import Convolution2D, MaxPooling2D
from ..utils.layer_utils import convert_all_kernels_in_model
from ..utils.data_utils import get_file
from .. import backend as K
from .imagenet_utils import decode_predictions, preprocess_input
TH_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_th_dim_ordering_th_kernels.h5'
TF_WEIGHTS_PATH = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels.h5'
TH_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_th_dim_ordering_th_kernels_notop.h5'
TF_WEIGHTS_PATH_NO_TOP = 'https://github.com/fchollet/deep-learning-models/releases/download/v0.1/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5'
def VGG19(include_top=True, weights='imagenet',
input_tensor=None):
'''Instantiate the VGG19 architecture,
optionally loading weights pre-trained
on ImageNet. 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.
# Arguments
include_top: whether to include the 3 fully-connected
layers 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).')
# Determine proper input shape
if K.image_dim_ordering() == 'th':
if include_top:
input_shape = (3, 224, 224)
else:
input_shape = (3, None, None)
else:
if include_top:
input_shape = (224, 224, 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
# Block 1
x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name='block1_conv1')(img_input)
x = Convolution2D(64, 3, 3, activation='relu', border_mode='same', name='block1_conv2')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
# Block 2
x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name='block2_conv1')(x)
x = Convolution2D(128, 3, 3, activation='relu', border_mode='same', name='block2_conv2')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
# Block 3
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv1')(x)
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv2')(x)
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv3')(x)
x = Convolution2D(256, 3, 3, activation='relu', border_mode='same', name='block3_conv4')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
# Block 4
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv1')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv2')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv3')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block4_conv4')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
# Block 5
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv1')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv2')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv3')(x)
x = Convolution2D(512, 3, 3, activation='relu', border_mode='same', name='block5_conv4')(x)
x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
if include_top:
# Classification block
x = Flatten(name='flatten')(x)
x = Dense(4096, activation='relu', name='fc1')(x)
x = Dense(4096, activation='relu', name='fc2')(x)
x = Dense(1000, activation='softmax', name='predictions')(x)
# Create model
model = Model(img_input, x)
# load weights
if weights == 'imagenet':
if K.image_dim_ordering() == 'th':
if include_top:
weights_path = get_file('vgg19_weights_th_dim_ordering_th_kernels.h5',
TH_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('vgg19_weights_th_dim_ordering_th_kernels_notop.h5',
TH_WEIGHTS_PATH_NO_TOP,
cache_subdir='models')
model.load_weights(weights_path)
if K.backend() == 'tensorflow':
warnings.warn('You are using the TensorFlow backend, yet you '
'are using the Theano '
'image dimension ordering convention '
'(`image_dim_ordering="th"`). '
'For best performance, set '
'`image_dim_ordering="tf"` in '
'your Keras config '
'at ~/.keras/keras.json.')
convert_all_kernels_in_model(model)
else:
if include_top:
weights_path = get_file('vgg19_weights_tf_dim_ordering_tf_kernels.h5',
TF_WEIGHTS_PATH,
cache_subdir='models')
else:
weights_path = get_file('vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5',
TF_WEIGHTS_PATH_NO_TOP,
cache_subdir='models')
model.load_weights(weights_path)
if K.backend() == 'theano':
convert_all_kernels_in_model(model)
return model
+18 -7
Ver Arquivo
@@ -11,6 +11,9 @@ from .common import get_uid
from .common import cast_to_floatx
from .common import image_dim_ordering
from .common import set_image_dim_ordering
from .common import is_keras_tensor
from .common import legacy_weight_ordering
from .common import set_legacy_weight_ordering
_keras_base_dir = os.path.expanduser('~')
if not os.access(_keras_base_dir, os.W_OK):
@@ -20,7 +23,7 @@ _keras_dir = os.path.join(_keras_base_dir, '.keras')
if not os.path.exists(_keras_dir):
os.makedirs(_keras_dir)
_BACKEND = 'theano'
_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))
@@ -39,12 +42,13 @@ if os.path.exists(_config_path):
_BACKEND = _backend
# save config file
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND,
'image_dim_ordering': image_dim_ordering()}
with open(_config_path, 'w') as f:
f.write(json.dumps(_config, indent=4))
if not os.path.exists(_config_path):
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND,
'image_dim_ordering': image_dim_ordering()}
with open(_config_path, 'w') as f:
f.write(json.dumps(_config, indent=4))
if 'KERAS_BACKEND' in os.environ:
_backend = os.environ['KERAS_BACKEND']
@@ -60,3 +64,10 @@ elif _BACKEND == 'tensorflow':
from .tensorflow_backend import *
else:
raise Exception('Unknown backend: ' + str(_BACKEND))
def backend():
'''Publicly accessible method
for determining the current backend.
'''
return _BACKEND
+24 -1
Ver Arquivo
@@ -6,7 +6,8 @@ from collections import defaultdict
_FLOATX = 'float32'
_EPSILON = 10e-8
_UID_PREFIXES = defaultdict(int)
_IMAGE_DIM_ORDERING = 'th'
_IMAGE_DIM_ORDERING = 'tf'
_LEGACY_WEIGHT_ORDERING = False
def epsilon():
@@ -64,3 +65,25 @@ def set_image_dim_ordering(dim_ordering):
def get_uid(prefix=''):
_UID_PREFIXES[prefix] += 1
return _UID_PREFIXES[prefix]
def reset_uids():
global _UID_PREFIXES
_UID_PREFIXES = defaultdict(int)
def is_keras_tensor(x):
if hasattr(x, '_keras_shape'):
return True
else:
return False
def set_legacy_weight_ordering(value):
global _LEGACY_WEIGHT_ORDERING
assert value in {True, False}
_LEGACY_WEIGHT_ORDERING = value
def legacy_weight_ordering():
return _LEGACY_WEIGHT_ORDERING
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+434 -82
Ver Arquivo
@@ -3,6 +3,11 @@ from theano import tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
from theano.tensor.signal import pool
from theano.tensor.nnet import conv3d2d
from theano.printing import Print
try:
import theano.sparse as th_sparse_module
except ImportError:
th_sparse_module = None
try:
from theano.tensor.nnet.nnet import softsign as T_softsign
except ImportError:
@@ -10,6 +15,7 @@ except ImportError:
import inspect
import numpy as np
from .common import _FLOATX, _EPSILON, _IMAGE_DIM_ORDERING
py_all = all
# INTERNAL UTILS
@@ -22,16 +28,45 @@ def learning_phase():
return _LEARNING_PHASE
def set_learning_phase(value):
global _LEARNING_PHASE
if value not in {0, 1}:
raise ValueError('Expected learning phase to be '
'0 or 1.')
_LEARNING_PHASE = value
# VARIABLE MANIPULATION
def _assert_sparse_module():
if not th_sparse_module:
raise ImportError("Failed to import theano.sparse\n"
"You probably need to pip install nose-parameterized")
def is_sparse(tensor):
return th_sparse_module and isinstance(tensor.type, th_sparse_module.SparseType)
def to_dense(tensor):
if is_sparse(tensor):
return th_sparse_module.dense_from_sparse(tensor)
else:
return tensor
def variable(value, dtype=_FLOATX, name=None):
'''Instantiate a tensor variable.
'''
value = np.asarray(value, dtype=dtype)
return theano.shared(value=value, name=name, strict=False)
if hasattr(value, 'tocoo'):
_assert_sparse_module()
return th_sparse_module.as_sparse_variable(value)
else:
value = np.asarray(value, dtype=dtype)
return theano.shared(value=value, name=name, strict=False)
def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
def placeholder(shape=None, ndim=None, dtype=_FLOATX, sparse=False, name=None):
'''Instantiate an input data placeholder variable.
'''
if shape is None and ndim is None:
@@ -42,7 +77,11 @@ def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
shape = tuple([None for _ in range(ndim)])
broadcast = (False,) * ndim
x = T.TensorType(dtype, broadcast)(name)
if sparse:
_assert_sparse_module()
x = th_sparse_module.csr_matrix(name=name, dtype=dtype)
else:
x = T.TensorType(dtype, broadcast)(name)
x._keras_shape = shape
x._uses_learning_phase = False
return x
@@ -68,7 +107,7 @@ def dtype(x):
def eval(x):
'''Run a graph.
'''
return x.eval()
return to_dense(x).eval()
def zeros(shape, dtype=_FLOATX, name=None):
@@ -97,6 +136,16 @@ def zeros_like(x):
return T.zeros_like(x)
def random_uniform_variable(shape, low, high, dtype=_FLOATX, name=None):
return variable(np.random.uniform(low=low, high=high, size=shape),
dtype=dtype, name=name)
def random_normal_variable(shape, mean, scale, dtype=_FLOATX, name=None):
return variable(np.random.normal(loc=0.0, scale=scale, size=shape),
dtype=dtype, name=name)
def count_params(x):
'''Return number of scalars in a tensor.
@@ -109,6 +158,25 @@ def cast(x, dtype):
return T.cast(x, dtype)
# UPDATES OPS
def update(x, new_x):
return (x, new_x)
def update_add(x, increment):
return (x, x + increment)
def update_sub(x, decrement):
return (x, x - decrement)
def moving_average_update(variable, value, momentum):
return (variable, variable * momentum + value * (1. - momentum))
# LINEAR ALGEBRA
'''
@@ -118,28 +186,49 @@ Assumed overridden:
def dot(x, y):
return T.dot(x, y)
if is_sparse(x):
return th_sparse_module.basic.structured_dot(x, y)
else:
return T.dot(x, y)
def batch_dot(x, y, axes=None):
'''batchwise dot product
'''Batchwise dot product.
batch_dot results in a tensor with less dimensions than the input.
If the number of dimensions is reduced to 1, we use `expand_dims` to
make sure that ndim is at least 2.
# Example
Assume x = [[1, 2], [3, 4]] and y = [[5, 6], [7, 8]]
batch_dot(x, y, axes=1) = [[17, 53]] which is the main diagonal
of x.dot(y.T), although we never have to calculate the off-diagonal
elements.
# Arguments
x, y: tensors with ndim >= 2
axes: list (or single) int with target dimensions
# Returns
Tensor with ndim >= 2
A tensor with shape equal to the concatenation of x's shape
(less the dimension that was summed over) and y's shape
(less the batch dimension and the dimension that was summed over).
If the final rank is 1, we reshape it to (batch_size, 1).
# Examples
Assume x = [[1, 2], [3, 4]] and y = [[5, 6], [7, 8]]
batch_dot(x, y, axes=1) = [[17, 53]] which is the main diagonal
of x.dot(y.T), although we never have to calculate the off-diagonal
elements.
Shape inference:
Let x's shape be (100, 20) and y's shape be (100, 30, 20).
If dot_axes is (1, 2), to find the output shape of resultant tensor,
loop through each dimension in x's shape and y's shape:
x.shape[0] : 100 : append to output shape
x.shape[1] : 20 : do not append to output shape,
dimension 1 of x has been summed over. (dot_axes[0] = 1)
y.shape[0] : 100 : do not append to output shape,
always ignore first dimension of y
y.shape[1] : 30 : append to output shape
y.shape[2] : 20 : do not append to output shape,
dimension 2 of y has been summed over. (dot_axes[1] = 2)
output_shape = (100, 30)
'''
if type(axes) == int:
axes = (axes, axes)
@@ -270,6 +359,22 @@ def not_equal(x, y):
return T.neq(x, y)
def greater(x, y):
return T.gt(x, y)
def greater_equal(x, y):
return T.ge(x, y)
def lesser(x, y):
return T.lt(x, y)
def lesser_equal(x, y):
return T.le(x, y)
def maximum(x, y):
return T.maximum(x, y)
@@ -290,7 +395,7 @@ 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.
'''
std = T.sqrt(x.var(reduction_axes) + epsilon)
var = x.var(reduction_axes)
mean = x.mean(reduction_axes)
target_shape = []
@@ -302,26 +407,44 @@ def normalize_batch_in_training(x, gamma, beta,
target_shape = T.stack(*target_shape)
broadcast_mean = T.reshape(mean, target_shape)
broadcast_std = T.reshape(std, target_shape)
broadcast_var = T.reshape(var, target_shape)
broadcast_beta = T.reshape(beta, target_shape)
broadcast_gamma = T.reshape(gamma, target_shape)
normed = batch_normalization(x, broadcast_mean, broadcast_std,
normed = batch_normalization(x, broadcast_mean, broadcast_var,
broadcast_beta, broadcast_gamma,
epsilon)
return normed, mean, std
return normed, mean, var
def batch_normalization(x, mean, std, beta, gamma, epsilon=0.0001):
'''Apply batch normalization on x given mean, std, beta and gamma.
def batch_normalization(x, mean, var, beta, gamma, epsilon=0.0001):
'''Apply batch normalization on x given mean, var, beta and gamma.
'''
normed = (x - mean) * (gamma * T.inv(std + epsilon)) + beta
return normed
ndim = x.ndim
dev = theano.config.device
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)
except AttributeError:
pass
return T.nnet.bn.batch_normalization(x, gamma, beta, mean, sqrt(var + epsilon),
mode='high_mem')
# SHAPE OPERATIONS
def concatenate(tensors, axis=-1):
return T.concatenate(tensors, axis=axis)
if py_all([is_sparse(x) for x in tensors]):
axis = axis % ndim(tensors[0])
if axis == 0:
return th_sparse_module.basic.vstack(tensors, format='csr')
elif axis == 1:
return th_sparse_module.basic.hstack(tensors, format='csr')
else:
raise Exception('Invalid concat axis for sparse matrix: ' + axis)
else:
return T.concatenate([to_dense(x) for x in tensors], axis=axis)
def reshape(x, shape):
@@ -430,11 +553,9 @@ def expand_dims(x, dim=-1):
def squeeze(x, axis):
'''Remove a 1-dimension from the tensor at index "axis".
'''
broadcastable = x.broadcastable[:axis] + x.broadcastable[axis+1:]
x = T.patternbroadcast(x, [i == axis for i in range(x.type.ndim)])
x = T.squeeze(x)
x = T.patternbroadcast(x, broadcastable)
return x
shape = list(x.shape)
shape.pop(axis)
return T.reshape(x, tuple(shape))
def temporal_padding(x, padding=1):
@@ -452,7 +573,7 @@ def temporal_padding(x, padding=1):
return T.set_subtensor(output[:, padding:x.shape[1] + padding, :], x)
def spatial_2d_padding(x, padding=(1, 1), dim_ordering='th'):
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.
'''
@@ -483,7 +604,7 @@ def spatial_2d_padding(x, padding=(1, 1), dim_ordering='th'):
return T.set_subtensor(output[indices], x)
def spatial_3d_padding(x, padding=(1, 1, 1), dim_ordering='th'):
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.
'''
@@ -521,6 +642,28 @@ def spatial_3d_padding(x, padding=(1, 1, 1), dim_ordering='th'):
def pack(x):
return T.stack(*x)
def one_hot(indices, nb_classes):
'''Input: nD integer tensor of shape (batch_size, dim1, dim2, ... dim(n-1))
Output: (n + 1)D one hot representation of the input
with shape (batch_size, dim1, dim2, ... dim(n-1), nb_classes)
'''
input_shape = tuple((indices.shape[i] for i in range(indices.ndim)))
indices = T.flatten(indices)
oh = T.extra_ops.to_one_hot(indices, nb_classes)
oh = T.reshape(oh, input_shape + (nb_classes,))
return oh
def reverse(x, axes):
'''Reverse a tensor along the the specified axes
'''
if type(axes) == int:
axes = [axes]
slices = [slice(None, None, -1) if i in axes else slice(None, None, None) for i in range(x.ndim)]
return x[slices]
# VALUE MANIPULATION
@@ -547,6 +690,18 @@ def batch_set_value(tuples):
x.set_value(np.asarray(value, dtype=x.dtype))
def get_variable_shape(x):
return x.get_value(borrow=True, return_internal_type=True).shape
def print_tensor(x, message=''):
'''Print the message and the tensor when evaluated and return the same
tensor.
'''
p_op = Print(message)
return p_op(x)
# GRAPH MANIPULATION
class Function(object):
@@ -554,7 +709,7 @@ class Function(object):
def __init__(self, inputs, outputs, updates=[], **kwargs):
self.function = theano.function(inputs, outputs, updates=updates,
allow_input_downcast=True,
on_unused_input='warn',
on_unused_input='ignore',
**kwargs)
def __call__(self, inputs):
@@ -755,12 +910,20 @@ def switch(condition, then_expression, else_expression):
def in_train_phase(x, alt):
if _LEARNING_PHASE is 1:
return x
elif _LEARNING_PHASE is 0:
return alt
x = T.switch(_LEARNING_PHASE, x, alt)
x._uses_learning_phase = True
return x
def in_test_phase(x, alt):
if _LEARNING_PHASE is 1:
return alt
elif _LEARNING_PHASE is 0:
return x
x = T.switch(_LEARNING_PHASE, alt, x)
x._uses_learning_phase = True
return x
@@ -829,14 +992,33 @@ def tanh(x):
return T.tanh(x)
def dropout(x, level, seed=None):
def dropout(x, level, noise_shape=None, seed=None):
'''Sets entries in `x` to zero at random,
while scaling the entire tensor.
# Arguments
x: tensor
level: fraction of the entries in the tensor
that will be set to 0.
noise_shape: shape for randomly generated keep/drop flags,
must be broadcastable to the shape of `x`
seed: random seed to ensure determinism.
'''
if level < 0. or level >= 1:
raise Exception('Dropout level must be in interval [0, 1[.')
if seed is None:
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
retain_prob = 1. - level
x *= rng.binomial(x.shape, p=retain_prob, dtype=x.dtype)
if noise_shape is None:
random_tensor = rng.binomial(x.shape, p=retain_prob, dtype=x.dtype)
else:
random_tensor = rng.binomial(noise_shape, p=retain_prob, dtype=x.dtype)
random_tensor = T.patternbroadcast(random_tensor, [dim == 1 for dim in noise_shape])
x *= random_tensor
x /= retain_prob
return x
@@ -848,6 +1030,79 @@ def l2_normalize(x, axis):
# CONVOLUTIONS
def _preprocess_conv2d_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)
# TF input shape: (samples, rows, cols, input_depth)
x = x.dimshuffle((0, 3, 1, 2))
return x
def _preprocess_conv2d_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)
# TF kernel shape: (rows, cols, input_depth, depth)
kernel = kernel.dimshuffle((3, 2, 0, 1))
return kernel
def _preprocess_border_mode(border_mode):
if border_mode == 'same':
th_border_mode = 'half'
elif border_mode == 'valid':
th_border_mode = 'valid'
else:
raise Exception('Border mode not supported: ' + str(border_mode))
return th_border_mode
def _preprocess_image_shape(dim_ordering, image_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 image_shape:
image_shape = (image_shape[0], image_shape[3],
image_shape[1], image_shape[2])
if image_shape is not None:
image_shape = tuple(int_or_none(v) for v in image_shape)
return image_shape
def _preprocess_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[3], filter_shape[2],
filter_shape[0], filter_shape[1])
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:
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 dim_ordering == 'tf':
conv_out = conv_out.dimshuffle((0, 2, 3, 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)):
@@ -864,42 +1119,12 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(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)
# TF input shape: (samples, rows, cols, input_depth)
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
x = x.dimshuffle((0, 3, 1, 2))
kernel = kernel.dimshuffle((3, 2, 0, 1))
if image_shape:
image_shape = (image_shape[0], image_shape[3],
image_shape[1], image_shape[2])
if filter_shape:
filter_shape = (filter_shape[3], filter_shape[2],
filter_shape[0], filter_shape[1])
if border_mode == 'same':
th_border_mode = 'half'
np_kernel = kernel.eval()
elif border_mode == 'valid':
th_border_mode = 'valid'
else:
raise Exception('Border mode not supported: ' + str(border_mode))
# Theano might not accept long type
def int_or_none(value):
try:
return int(value)
except TypeError:
return None
if image_shape is not None:
image_shape = tuple(int_or_none(v) for v in image_shape)
if filter_shape is not None:
filter_shape = tuple(int_or_none(v) for v in filter_shape)
x = _preprocess_conv2d_input(x, dim_ordering)
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)
# TODO: remove the if statement when theano with no filter dilation is deprecated.
if filter_dilation == (1, 1):
@@ -916,14 +1141,8 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
filter_shape=filter_shape,
filter_dilation=filter_dilation)
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 dim_ordering == 'tf':
conv_out = conv_out.dimshuffle((0, 2, 3, 1))
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel,
strides, dim_ordering)
return conv_out
@@ -931,7 +1150,38 @@ def deconv2d(x, kernel, output_shape, strides=(1, 1),
border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING,
image_shape=None, filter_shape=None):
raise NotImplementedError
'''2D deconvolution (transposed convolution).
# Arguments
kernel: kernel tensor.
output_shape: desired dimensions of output.
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.
'''
flip_filters = False
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
x = _preprocess_conv2d_input(x, dim_ordering)
kernel = _preprocess_conv2d_kernel(kernel, dim_ordering)
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)
op = T.nnet.abstract_conv.AbstractConv2d_gradInputs(imshp=output_shape,
kshp=filter_shape,
subsample=strides,
border_mode=th_border_mode,
filter_flip=not flip_filters)
conv_out = op(kernel, x, output_shape[2:])
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel,
strides, dim_ordering)
return conv_out
def atrous_conv2d(x, kernel, rate=1,
@@ -947,7 +1197,7 @@ def separable_conv2d(x, depthwise_kernel, pointwise_kernel, strides=(1, 1),
def conv3d(x, kernel, strides=(1, 1, 1),
border_mode='valid', dim_ordering='th',
border_mode='valid', dim_ordering=_IMAGE_DIM_ORDERING,
volume_shape=None, filter_shape=None):
'''
Run on cuDNN if available.
@@ -1009,7 +1259,7 @@ def conv3d(x, kernel, strides=(1, 1, 1),
def pool2d(x, pool_size, strides=(1, 1), border_mode='valid',
dim_ordering='th', pool_mode='max'):
dim_ordering=_IMAGE_DIM_ORDERING, pool_mode='max'):
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
@@ -1052,7 +1302,7 @@ 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='th', pool_mode='max'):
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.')
@@ -1131,3 +1381,105 @@ def random_binomial(shape, p=0.0, dtype=_FLOATX, seed=None):
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.binomial(shape, p=p, dtype=dtype)
# Theano implementation of CTC
# Used with permission from Shawn Tan
# https://github.com/shawntan/
# Note that tensorflow's native CTC code is significantly
# faster than this
def ctc_interleave_blanks(Y):
Y_ = T.alloc(-1, Y.shape[0] * 2 + 1)
Y_ = T.set_subtensor(Y_[T.arange(Y.shape[0]) * 2 + 1], Y)
return Y_
def ctc_create_skip_idxs(Y):
skip_idxs = T.arange((Y.shape[0] - 3) // 2) * 2 + 1
non_repeats = T.neq(Y[skip_idxs], Y[skip_idxs + 2])
return skip_idxs[non_repeats.nonzero()]
def ctc_update_log_p(skip_idxs, zeros, active, log_p_curr, log_p_prev):
active_skip_idxs = skip_idxs[(skip_idxs < active).nonzero()]
active_next = T.cast(T.minimum(
T.maximum(
active + 1,
T.max(T.concatenate([active_skip_idxs, [-1]])) + 2 + 1
), log_p_curr.shape[0]), 'int32')
common_factor = T.max(log_p_prev[:active])
p_prev = T.exp(log_p_prev[:active] - common_factor)
_p_prev = zeros[:active_next]
# copy over
_p_prev = T.set_subtensor(_p_prev[:active], p_prev)
# previous transitions
_p_prev = T.inc_subtensor(_p_prev[1:], _p_prev[:-1])
# skip transitions
_p_prev = T.inc_subtensor(_p_prev[active_skip_idxs + 2], p_prev[active_skip_idxs])
updated_log_p_prev = T.log(_p_prev) + common_factor
log_p_next = T.set_subtensor(
zeros[:active_next],
log_p_curr[:active_next] + updated_log_p_prev
)
return active_next, log_p_next
def ctc_path_probs(predict, Y, alpha=1e-4):
smoothed_predict = (1 - alpha) * predict[:, Y] + alpha * np.float32(1.) / Y.shape[0]
L = T.log(smoothed_predict)
zeros = T.zeros_like(L[0])
base = T.set_subtensor(zeros[:1], np.float32(1))
log_first = zeros
f_skip_idxs = ctc_create_skip_idxs(Y)
b_skip_idxs = ctc_create_skip_idxs(Y[::-1]) # there should be a shortcut to calculating this
def step(log_f_curr, log_b_curr, f_active, log_f_prev, b_active, log_b_prev):
f_active_next, log_f_next = ctc_update_log_p(f_skip_idxs, zeros, f_active, log_f_curr, log_f_prev)
b_active_next, log_b_next = ctc_update_log_p(b_skip_idxs, zeros, b_active, log_b_curr, log_b_prev)
return f_active_next, log_f_next, b_active_next, log_b_next
[f_active, log_f_probs, b_active, log_b_probs], _ = theano.scan(
step, sequences=[L, L[::-1, ::-1]], outputs_info=[np.int32(1), log_first, np.int32(1), log_first])
idxs = T.arange(L.shape[1]).dimshuffle('x', 0)
mask = (idxs < f_active.dimshuffle(0, 'x')) & (idxs < b_active.dimshuffle(0, 'x'))[::-1, ::-1]
log_probs = log_f_probs + log_b_probs[::-1, ::-1] - L
return log_probs, mask
def ctc_cost(predict, Y):
log_probs, mask = ctc_path_probs(predict, ctc_interleave_blanks(Y))
common_factor = T.max(log_probs)
total_log_prob = T.log(T.sum(T.exp(log_probs - common_factor)[mask.nonzero()])) + common_factor
return -total_log_prob
# batchifies original CTC code
def ctc_batch_cost(y_true, y_pred, input_length, label_length):
'''Runs CTC loss algorithm on each batch element.
# Arguments
y_true: tensor (samples, max_string_length) containing the truth labels
y_pred: tensor (samples, time_steps, num_categories) containing the prediction,
or output of the softmax
input_length: tensor (samples,1) containing the sequence length for
each batch item in y_pred
label_length: tensor (samples,1) containing the sequence length for
each batch item in y_true
# Returns
Tensor with shape (samples,1) containing the
CTC loss of each element
'''
def ctc_step(y_true_step, y_pred_step, input_length_step, label_length_step):
y_pred_step = y_pred_step[0: input_length_step[0]]
y_true_step = y_true_step[0:label_length_step[0]]
return ctc_cost(y_pred_step, y_true_step)
ret, _ = theano.scan(
fn = ctc_step,
outputs_info=None,
sequences=[y_true, y_pred, input_length, label_length]
)
ret = ret.dimshuffle('x', 0)
return ret
+53 -23
Ver Arquivo
@@ -9,6 +9,7 @@ import warnings
from collections import deque
from .utils.generic_utils import Progbar
from keras import backend as K
from pkg_resources import parse_version
class CallbackList(object):
@@ -212,6 +213,7 @@ class History(Callback):
for k, v in logs.items():
self.history.setdefault(k, []).append(v)
class ModelCheckpoint(Callback):
'''Save the model after every epoch.
@@ -229,25 +231,29 @@ class ModelCheckpoint(Callback):
verbose: verbosity mode, 0 or 1.
save_best_only: if `save_best_only=True`,
the latest best model according to
the validation loss will not be overwritten.
the quantity monitored will not be overwritten.
mode: one of {auto, min, max}.
If `save_best_only=True`, the decision
to overwrite the current save file is made
based on either the maximization or the
minization of the monitored. For `val_acc`,
minimization of the monitored quantity. For `val_acc`,
this should be `max`, for `val_loss` this should
be `min`, etc. In `auto` mode, the direction is
automatically inferred from the name of the monitored quantity.
save_weights_only: if True, then only the model's weights will be
saved (`model.save_weights(filepath)`), else the full model
is saved (`model.save(filepath)`).
'''
def __init__(self, filepath, monitor='val_loss', verbose=0,
save_best_only=False, mode='auto'):
save_best_only=False, save_weights_only=False,
mode='auto'):
super(ModelCheckpoint, self).__init__()
self.monitor = monitor
self.verbose = verbose
self.filepath = filepath
self.save_best_only = save_best_only
self.save_weights_only = save_weights_only
if mode not in ['auto', 'min', 'max']:
warnings.warn('ModelCheckpoint mode %s is unknown, '
@@ -284,7 +290,10 @@ class ModelCheckpoint(Callback):
% (epoch, self.monitor, self.best,
current, filepath))
self.best = current
self.model.save_weights(filepath, overwrite=True)
if self.save_weights_only:
self.model.save_weights(filepath, overwrite=True)
else:
self.model.save(filepath, overwrite=True)
else:
if self.verbose > 0:
print('Epoch %05d: %s did not improve' %
@@ -292,7 +301,10 @@ class ModelCheckpoint(Callback):
else:
if self.verbose > 0:
print('Epoch %05d: saving model to %s' % (epoch, filepath))
self.model.save_weights(filepath, overwrite=True)
if self.save_weights_only:
self.model.save_weights(filepath, overwrite=True)
else:
self.model.save(filepath, overwrite=True)
class EarlyStopping(Callback):
@@ -303,11 +315,13 @@ class EarlyStopping(Callback):
patience: number of epochs with no improvement
after which training will be stopped.
verbose: verbosity mode.
mode: one of {auto, min, max}. In 'min' mode,
mode: one of {auto, min, max}. In `min` mode,
training will stop when the quantity
monitored has stopped decreasing; in 'max'
monitored has stopped decreasing; in `max`
mode it will stop when the quantity
monitored has stopped increasing.
monitored has stopped increasing; in `auto`
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'):
super(EarlyStopping, self).__init__()
@@ -319,7 +333,8 @@ class EarlyStopping(Callback):
if mode not in ['auto', 'min', 'max']:
warnings.warn('EarlyStopping mode %s is unknown, '
'fallback to auto mode.' % (self.mode), RuntimeWarning)
'fallback to auto mode.' % (self.mode),
RuntimeWarning)
mode = 'auto'
if mode == 'min':
@@ -361,8 +376,8 @@ class RemoteMonitor(Callback):
# Arguments
root: root url to which the events will be sent (at the end
of every epoch). Events are sent to
`root + '/publish/epoch/end/'` by default. Calls are
HTTP POST, with a `data` argument which is a
`root + '/publish/epoch/end/'` by default. Calls are
HTTP POST, with a `data` argument which is a
JSON-encoded dictionary of event data.
'''
@@ -433,11 +448,12 @@ class TensorBoard(Callback):
histogram_freq: frequency (in epochs) at which to compute activation
histograms for the layers of the model. If set to 0,
histograms won't be computed.
write_graph: whether to visualize the graph in Tensorboard. The log file can
become quite large when write_graph is set to True.
write_graph: whether to visualize the graph in Tensorboard.
The log file can become quite large when
write_graph is set to True.
'''
def __init__(self, log_dir='./logs', histogram_freq=0, write_graph=True):
def __init__(self, log_dir='./logs', histogram_freq=0, write_graph=True, write_images=False):
super(TensorBoard, self).__init__()
if K._BACKEND != 'tensorflow':
raise Exception('TensorBoard callback only works '
@@ -446,6 +462,7 @@ class TensorBoard(Callback):
self.histogram_freq = histogram_freq
self.merged = None
self.write_graph = write_graph
self.write_images = write_images
def _set_model(self, model):
import tensorflow as tf
@@ -454,18 +471,31 @@ class TensorBoard(Callback):
self.model = model
self.sess = KTF.get_session()
if self.histogram_freq and self.merged is None:
layers = self.model.layers
for layer in layers:
if hasattr(layer, 'W'):
tf.histogram_summary('{}_W'.format(layer), layer.W)
if hasattr(layer, 'b'):
tf.histogram_summary('{}_b'.format(layer), layer.b)
for layer in self.model.layers:
for weight in layer.weights:
tf.histogram_summary(weight.name, weight)
if self.write_images:
w_img = tf.squeeze(weight)
shape = w_img.get_shape()
if len(shape) > 1 and shape[0] > shape[1]:
w_img = tf.transpose(w_img)
if len(shape) == 1:
w_img = tf.expand_dims(w_img, 0)
w_img = tf.expand_dims(tf.expand_dims(w_img, 0), -1)
tf.image_summary(weight.name, w_img)
if hasattr(layer, 'output'):
tf.histogram_summary('{}_out'.format(layer),
tf.histogram_summary('{}_out'.format(layer.name),
layer.output)
self.merged = tf.merge_all_summaries()
if self.write_graph:
if tf.__version__ >= '0.8.0':
if parse_version(tf.__version__) >= parse_version('0.8.0'):
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph)
else:
+7 -2
Ver Arquivo
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from .cifar import load_batch
from ..utils.data_utils import get_file
from .. import backend as K
import numpy as np
import os
@@ -18,8 +19,8 @@ def load_data():
for i in range(1, 6):
fpath = os.path.join(path, 'data_batch_' + str(i))
data, labels = load_batch(fpath)
X_train[(i-1)*10000:i*10000, :, :, :] = data
y_train[(i-1)*10000:i*10000] = labels
X_train[(i - 1) * 10000: i * 10000, :, :, :] = data
y_train[(i - 1) * 10000: i * 10000] = labels
fpath = os.path.join(path, 'test_batch')
X_test, y_test = load_batch(fpath)
@@ -27,4 +28,8 @@ def load_data():
y_train = np.reshape(y_train, (len(y_train), 1))
y_test = np.reshape(y_test, (len(y_test), 1))
if K.image_dim_ordering() == 'tf':
X_train = X_train.transpose(0, 2, 3, 1)
X_test = X_test.transpose(0, 2, 3, 1)
return (X_train, y_train), (X_test, y_test)
+5 -3
Ver Arquivo
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from .cifar import load_batch
from ..utils.data_utils import get_file
from .. import backend as K
import numpy as np
import os
@@ -13,9 +14,6 @@ def load_data(label_mode='fine'):
origin = "http://www.cs.toronto.edu/~kriz/cifar-100-python.tar.gz"
path = get_file(dirname, origin=origin, untar=True)
nb_test_samples = 10000
nb_train_samples = 50000
fpath = os.path.join(path, 'train')
X_train, y_train = load_batch(fpath, label_key=label_mode+'_labels')
@@ -25,4 +23,8 @@ def load_data(label_mode='fine'):
y_train = np.reshape(y_train, (len(y_train), 1))
y_test = np.reshape(y_test, (len(y_test), 1))
if K.image_dim_ordering() == 'tf':
X_train = X_train.transpose(0, 2, 3, 1)
X_test = X_test.transpose(0, 2, 3, 1)
return (X_train, y_train), (X_test, y_test)
+58 -11
Ver Arquivo
@@ -4,26 +4,58 @@ import gzip
from ..utils.data_utils import get_file
from six.moves import zip
import numpy as np
import sys
def load_data(path="imdb.pkl", nb_words=None, skip_top=0,
maxlen=None, test_split=0.2, seed=113,
def load_data(path='imdb_full.pkl', nb_words=None, skip_top=0,
maxlen=None, seed=113,
start_char=1, oov_char=2, index_from=3):
'''
# Arguments
path: where to store the data (in `/.keras/dataset`)
nb_words: max number of words to include. Words are ranked
by how often they occur (in the training set) and only
the most frequent words are kept
skip_top: skip the top N most frequently occuring words
(which may not be informative).
maxlen: truncate sequences after this length.
seed: random seed for sample shuffling.
start_char: The start of a sequence will be marked with this character.
Set to 1 because 0 is usually the padding character.
oov_char: words that were cut out because of the `nb_words`
or `skip_top` limit will be replaced with this character.
index_from: index actual words with this index and higher.
path = get_file(path, origin="https://s3.amazonaws.com/text-datasets/imdb.pkl")
Note that the 'out of vocabulary' character is only used for
words that were present in the training set but are not included
because they're not making the `nb_words` cut here.
Words that were not seen in the trining set but are in the test set
have simply been skipped.
'''
path = get_file(path,
origin='https://s3.amazonaws.com/text-datasets/imdb_full.pkl',
md5_hash='d091312047c43cf9e4e38fef92437263')
if path.endswith(".gz"):
if path.endswith('.gz'):
f = gzip.open(path, 'rb')
else:
f = open(path, 'rb')
X, labels = cPickle.load(f)
(x_train, labels_train), (x_test, labels_test) = cPickle.load(f)
f.close()
np.random.seed(seed)
np.random.shuffle(X)
np.random.shuffle(x_train)
np.random.seed(seed)
np.random.shuffle(labels)
np.random.shuffle(labels_train)
np.random.seed(seed * 2)
np.random.shuffle(x_test)
np.random.seed(seed * 2)
np.random.shuffle(labels_test)
X = x_train + x_test
labels = labels_train + labels_test
if start_char is not None:
X = [[start_char] + [w + index_from for w in x] for x in X]
@@ -60,10 +92,25 @@ def load_data(path="imdb.pkl", nb_words=None, skip_top=0,
nX.append(nx)
X = nX
X_train = np.array(X[:int(len(X) * (1 - test_split))])
y_train = np.array(labels[:int(len(X) * (1 - test_split))])
X_train = np.array(X[:len(x_train)])
y_train = np.array(labels[:len(x_train)])
X_test = np.array(X[int(len(X) * (1 - test_split)):])
y_test = np.array(labels[int(len(X) * (1 - test_split)):])
X_test = np.array(X[len(x_train):])
y_test = np.array(labels[len(x_train):])
return (X_train, y_train), (X_test, y_test)
def get_word_index(path='imdb_word_index.pkl'):
path = get_file(path,
origin='https://s3.amazonaws.com/text-datasets/imdb_word_index.pkl',
md5_hash='72d94b01291be4ff843198d3b0e1e4d7')
f = open(path, 'rb')
if sys.version_info < (3,):
data = cPickle.load(f)
else:
data = cPickle.load(f, encoding='latin1')
f.close()
return data
+28 -5
Ver Arquivo
@@ -7,11 +7,34 @@ import numpy as np
import sys
def load_data(path="reuters.pkl", nb_words=None, skip_top=0,
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):
'''
# Arguments
path: where to store the data (in `/.keras/dataset`)
nb_words: max number of words to include. Words are ranked
by how often they occur (in the training set) and only
the most frequent words are kept
skip_top: skip the top N most frequently occuring words
(which may not be informative).
maxlen: truncate sequences after this length.
test_split: Fraction of the dataset to be used as test data.
seed: random seed for sample shuffling.
start_char: The start of a sequence will be marked with this character.
Set to 1 because 0 is usually the padding character.
oov_char: words that were cut out because of the `nb_words`
or `skip_top` limit will be replaced with this character.
index_from: index actual words with this index and higher.
path = get_file(path, origin="https://s3.amazonaws.com/text-datasets/reuters.pkl")
Note that the 'out of vocabulary' character is only used for
words that were present in the training set but are not included
because they're not making the `nb_words` cut here.
Words that were not seen in the trining set but are in the test set
have simply been skipped.
'''
path = get_file(path, origin='https://s3.amazonaws.com/text-datasets/reuters.pkl')
f = open(path, 'rb')
X, labels = cPickle.load(f)
f.close()
@@ -62,14 +85,14 @@ def load_data(path="reuters.pkl", nb_words=None, skip_top=0,
return (X_train, y_train), (X_test, y_test)
def get_word_index(path="reuters_word_index.pkl"):
path = get_file(path, origin="https://s3.amazonaws.com/text-datasets/reuters_word_index.pkl")
def get_word_index(path='reuters_word_index.pkl'):
path = get_file(path, origin='https://s3.amazonaws.com/text-datasets/reuters_word_index.pkl')
f = open(path, 'rb')
if sys.version_info < (3,):
data = cPickle.load(f)
else:
data = cPickle.load(f, encoding="latin1")
data = cPickle.load(f, encoding='latin1')
f.close()
return data
+305 -108
Ver Arquivo
@@ -5,14 +5,15 @@ from __future__ import division
import numpy as np
import sys
import marshal
import types as python_types
import warnings
import copy
import os
from six.moves import zip
from keras import backend as K
from .. import backend as K
from ..utils.io_utils import ask_to_proceed_with_overwrite
from ..utils.generic_utils import func_dump, func_load
def to_list(x):
@@ -282,10 +283,14 @@ class Layer(object):
# these properties will be set upon call of self.build(),
# which itself will be called upon self.add_inbound_node if necessary.
self.trainable_weights = []
self.non_trainable_weights = []
self.regularizers = []
self.constraints = {} # dict {tensor: constraint instance}
if not hasattr(self, 'trainable_weights'):
self.trainable_weights = []
if not hasattr(self, 'non_trainable_weights'):
self.non_trainable_weights = []
if not hasattr(self, 'regularizers'):
self.regularizers = []
if not hasattr(self, 'constraints'):
self.constraints = {} # dict {tensor: constraint instance}
self.built = False
# these properties should be set by the user via keyword arguments.
@@ -321,6 +326,30 @@ class Layer(object):
if 'create_input_layer' in kwargs:
self.create_input_layer(batch_input_shape, input_dtype)
@property
def trainable_weights(self):
trainable = getattr(self, 'trainable', True)
if trainable:
return self._trainable_weights
else:
return []
@trainable_weights.setter
def trainable_weights(self, weights):
self._trainable_weights = weights
@property
def non_trainable_weights(self):
trainable = getattr(self, 'trainable', True)
if not trainable:
return self._trainable_weights + self._non_trainable_weights
else:
return self._non_trainable_weights
@non_trainable_weights.setter
def non_trainable_weights(self, weights):
self._non_trainable_weights = weights
def create_input_layer(self, batch_input_shape,
input_dtype=None, name=None):
if not name:
@@ -694,15 +723,15 @@ class Layer(object):
' outbound layers. '
'This will cause part of your model '
'to be disconnected.')
if not shape:
if hasattr(K, 'int_shape'):
shape = K.int_shape(input_tensor)
else:
raise Exception('`set_input` needs to know the shape '
'of the `input_tensor` it receives, but '
'Keras was not able to infer it automatically.'
' Specify it via: '
'`model.set_input(input_tensor, shape)`')
if hasattr(K, 'int_shape'):
# auto-infered shape takes priority
shape = K.int_shape(input_tensor)
elif not shape:
raise Exception('`set_input` needs to know the shape '
'of the `input_tensor` it receives, but '
'Keras was not able to infer it automatically.'
' Specify it via: '
'`model.set_input(input_tensor, shape)`')
# reset layer connections
self.inbound_nodes = []
self.outbound_nodes = []
@@ -828,6 +857,10 @@ class Layer(object):
'ill-defined for the layer. ' +
'Use `get_output_shape_at(node_index)` instead.')
@property
def weights(self):
return self.trainable_weights + self.non_trainable_weights
def set_weights(self, weights):
'''Sets the weights of the layer, from Numpy arrays.
@@ -838,12 +871,12 @@ class Layer(object):
of the layer (i.e. it should match the
output of `get_weights`).
'''
params = self.trainable_weights + self.non_trainable_weights
params = self.weights
if len(params) != len(weights):
raise Exception('You called `set_weights(weights)` on layer "' + self.name +
'" with a weight list of length ' + str(len(weights)) +
', but the layer was expecting ' + str(len(params)) +
' weights. Provided weights: ' + str(weights))
' weights. Provided weights: ' + str(weights)[:50] + '...')
if not params:
return
weight_value_tuples = []
@@ -861,7 +894,7 @@ class Layer(object):
'''Returns the current weights of the layer,
as a list of numpy arrays.
'''
params = self.trainable_weights + self.non_trainable_weights
params = self.weights
return K.batch_get_value(params)
def get_config(self):
@@ -914,12 +947,14 @@ class InputLayer(Layer):
'''TODO: dosctring
'''
def __init__(self, input_shape=None, batch_input_shape=None,
input_dtype=None, input_tensor=None, name=None):
input_dtype=None, input_tensor=None, sparse=False, name=None):
self.input_spec = None
self.supports_masking = False
self.uses_learning_phase = False
self.trainable = False
self.built = True
self.trainable_weights = []
self.non_trainable_weights = []
self.inbound_nodes = []
self.outbound_nodes = []
@@ -929,6 +964,8 @@ class InputLayer(Layer):
self.regularizers = []
self.constraints = {}
self.sparse = sparse
if not name:
prefix = 'input'
name = prefix + '_' + str(K.get_uid(prefix))
@@ -939,11 +976,11 @@ class InputLayer(Layer):
'batch_input_shape argument to '
'InputLayer, not both at the same time.')
if input_tensor is not None:
if not input_shape and not batch_input_shape:
# attempt automatic input shape inference
try:
batch_input_shape = K.int_shape(input_tensor)
except:
# attempt automatic input shape inference
try:
batch_input_shape = K.int_shape(input_tensor)
except:
if not input_shape and not batch_input_shape:
raise ValueError('InputLayer was provided an input_tensor argument, '
'but its input shape cannot be automatically inferred. '
'You should pass an input_shape or batch_input_shape '
@@ -969,6 +1006,7 @@ class InputLayer(Layer):
if input_tensor is None:
input_tensor = K.placeholder(shape=batch_input_shape,
dtype=input_dtype,
sparse=self.sparse,
name=self.name)
else:
input_tensor._keras_shape = batch_input_shape
@@ -990,12 +1028,13 @@ class InputLayer(Layer):
def get_config(self):
config = {'batch_input_shape': self.batch_input_shape,
'input_dtype': self.input_dtype,
'sparse': self.sparse,
'name': self.name}
return config
def Input(shape=None, batch_shape=None,
name=None, dtype=K.floatx(),
name=None, dtype=K.floatx(), sparse=False,
tensor=None):
'''`Input()` is used to instantiate a Keras tensor.
A Keras tensor is a tensor object from the underlying backend
@@ -1028,6 +1067,7 @@ def Input(shape=None, batch_shape=None,
It will be autogenerated if it isn't provided.
dtype: The data type expected by the input, as a string
(`float32`, `float64`, `int32`...)
sparse: a boolean specifying whether this will be a sparse tensor
# Example usage
@@ -1043,9 +1083,11 @@ def Input(shape=None, batch_shape=None,
' or a `batch_shape` argument. Note that ' +
'`shape` does not include the batch '
'dimension.')
if shape and not batch_shape:
batch_shape = (None,) + tuple(shape)
input_layer = InputLayer(batch_input_shape=batch_shape,
name=name, input_dtype=dtype,
sparse=sparse,
input_tensor=tensor)
# return tensor including _keras_shape and _keras_history
# note that in this case train_output and test_output are the same pointer.
@@ -1084,7 +1126,7 @@ class Merge(Layer):
If lambda/function, it should take as input a list of tensors
and return a single tensor.
concat_axis: integer, axis to use in mode `concat`.
dot_axes: integer or tuple of integers, axes to use in mode `dot`.
dot_axes: integer or tuple of integers, axes to use in mode `dot` or `cos`.
output_shape: either a shape tuple (tuple of integers), or a lambda/function
to compute `output_shape` (only if merge mode is a lambda/function).
If the argument is a tuple,
@@ -1111,8 +1153,6 @@ class Merge(Layer):
self.mode = mode
self.concat_axis = concat_axis
self.dot_axes = dot_axes
if type(self.dot_axes) == int:
self.dot_axes = [self.dot_axes, ] * 2
self._output_shape = output_shape
self.node_indices = node_indices
self._output_mask = output_mask
@@ -1188,18 +1228,18 @@ class Merge(Layer):
n2 = len(shape2)
if type(dot_axes) == int:
if dot_axes < 0:
dot_axes = [dot_axes % n1, dot_axes % n2]
self.dot_axes = [dot_axes % n1, dot_axes % n2]
else:
dot_axes = [n1 - dot_axes, n2-dot_axes]
if type(dot_axes) not in [list, tuple]:
self.dot_axes = [dot_axes, ] * 2
if type(self.dot_axes) not in [list, tuple]:
raise Exception('Invalid type for dot_axes - should be a list.')
if len(dot_axes) != 2:
if len(self.dot_axes) != 2:
raise Exception('Invalid format for dot_axes - should contain two elements.')
if type(dot_axes[0]) is not int or type(dot_axes[1]) is not int:
if type(self.dot_axes[0]) is not int or type(self.dot_axes[1]) is not int:
raise Exception('Invalid format for dot_axes - list elements should be "int".')
if shape1[dot_axes[0]] != shape2[dot_axes[1]]:
if shape1[self.dot_axes[0]] != shape2[self.dot_axes[1]]:
raise Exception('Dimension incompatibility using dot mode: ' +
'%s != %s. ' % (shape1[dot_axes[0]], shape2[dot_axes[1]]) +
'%s != %s. ' % (shape1[self.dot_axes[0]], shape2[self.dot_axes[1]]) +
'Layer shapes: %s, %s' % (shape1, shape2))
elif mode == 'concat':
reduced_inputs_shapes = [list(shape) for shape in input_shapes]
@@ -1336,15 +1376,13 @@ class Merge(Layer):
elif self.mode in ['dot', 'cos']:
shape1 = list(input_shapes[0])
shape2 = list(input_shapes[1])
dot_axes = [a - 1 for a in self.dot_axes]
tensordot_output = np.tensordot(np.zeros(tuple(shape1[1:])),
np.zeros(tuple(shape2[1:])),
axes=dot_axes)
if len(tensordot_output.shape) == 0:
shape = (1,)
else:
shape = tensordot_output.shape
return (shape1[0],) + shape
shape1.pop(self.dot_axes[0])
shape2.pop(self.dot_axes[1])
shape2.pop(0)
output_shape = shape1 + shape2
if len(output_shape) == 1:
output_shape += [1]
return tuple(output_shape)
def compute_mask(self, inputs, mask=None):
if mask is None or all([m is None for m in mask]):
@@ -1356,9 +1394,19 @@ class Merge(Layer):
masks = [K.expand_dims(m, 0) for m in mask if m is not None]
return K.all(K.concatenate(masks, axis=0), axis=0, keepdims=False)
elif self.mode == 'concat':
masks = [K.ones_like(inputs[i][:-1]) if m is None else m for i, m in zip(inputs, mask)]
expanded_dims = [K.expand_dims(m) for m in masks]
concatenated = K.concatenate(expanded_dims, axis=self.concat_axis)
# Make a list of masks while making sure the dimensionality of each mask
# is the same as the corresponding input.
masks = []
for input_i, mask_i in zip(inputs, mask):
if mask_i is None:
# Input is unmasked. Append all 1s to masks, but cast it to uint8 first
masks.append(K.cast(K.ones_like(input_i), 'uint8'))
elif K.ndim(mask_i) < K.ndim(input_i):
# Mask is smaller than the input, expand it
masks.append(K.expand_dims(mask_i))
else:
masks.append(mask_i)
concatenated = K.concatenate(masks, axis=self.concat_axis)
return K.all(concatenated, axis=-1, keepdims=False)
elif self.mode in ['cos', 'dot']:
return None
@@ -1372,13 +1420,8 @@ class Merge(Layer):
raise Exception('Invalid merge mode: {}'.format(self.mode))
def get_config(self):
py3 = sys.version_info[0] == 3
if isinstance(self.mode, python_types.LambdaType):
if py3:
mode = marshal.dumps(self.mode.__code__).decode('raw_unicode_escape')
else:
mode = marshal.dumps(self.mode.func_code).decode('raw_unicode_escape')
mode = func_dump(self.mode)
mode_type = 'lambda'
elif callable(self.mode):
mode = self.mode.__name__
@@ -1388,10 +1431,7 @@ class Merge(Layer):
mode_type = 'raw'
if isinstance(self._output_shape, python_types.LambdaType):
if py3:
output_shape = marshal.dumps(self._output_shape.__code__).decode('raw_unicode_escape')
else:
output_shape = marshal.dumps(self._output_shape.func_code).decode('raw_unicode_escape')
output_shape = func_dump(self._output_shape)
output_shape_type = 'lambda'
elif callable(self._output_shape):
output_shape = self._output_shape.__name__
@@ -1414,8 +1454,7 @@ class Merge(Layer):
if mode_type == 'function':
mode = globals()[config['mode']]
elif mode_type == 'lambda':
mode = marshal.loads(config['mode'].encode('raw_unicode_escape'))
mode = python_types.FunctionType(mode, globals())
mode = func_load(config['mode'], globs=globals())
else:
mode = config['mode']
@@ -1423,8 +1462,7 @@ class Merge(Layer):
if output_shape_type == 'function':
output_shape = globals()[config['output_shape']]
elif output_shape_type == 'lambda':
output_shape = marshal.loads(config['output_shape'].encode('raw_unicode_escape'))
output_shape = python_types.FunctionType(output_shape, globals())
output_shape = func_load(config['output_shape'], globs=globals())
else:
output_shape = config['output_shape']
@@ -1452,7 +1490,7 @@ def merge(inputs, mode='sum', concat_axis=-1,
If lambda/function, it should take as input a list of tensors
and return a single tensor.
concat_axis: integer, axis to use in mode `concat`.
dot_axes: integer or tuple of integers, axes to use in mode `dot`.
dot_axes: integer or tuple of integers, axes to use in mode `dot` or `cos`.
output_shape: shape tuple (tuple of integers), or lambda/function
to compute output_shape (only if merge mode is a lambda/function).
If the latter case, it should take as input a list of shape tuples
@@ -1544,6 +1582,9 @@ class Container(Layer):
name = prefix + '_' + str(K.get_uid(prefix))
self.name = name
# whether container weights are trainable
self.trainable = True
# Container-specific properties
if type(input) in {list, tuple}:
self.inputs = list(input) # tensor or list of tensors
@@ -1673,6 +1714,7 @@ class Container(Layer):
container_nodes = set() # ids of all nodes relevant to the Container
nodes_depths = {} # map {node: depth value}
layers_depths = {} # map {layer: depth value}
layer_indices = {} # map {layer: index in traversal}
def make_node_marker(node, depth):
return str(id(node)) + '-' + str(depth)
@@ -1716,6 +1758,8 @@ class Container(Layer):
else:
current_depth = max(depth, previously_seen_depth)
layers_depths[layer] = current_depth
if layer not in layer_indices:
layer_indices[layer] = len(layer_indices)
# propagate to all previous tensors connected to this node
for i in range(len(node.inbound_layers)):
@@ -1756,8 +1800,12 @@ class Container(Layer):
layers = []
for depth in depth_keys:
layers_for_depth = layers_by_depth[depth]
# container.layers needs to have a deterministic order
layers_for_depth.sort(key=lambda x: x.name)
# container.layers needs to have a deterministic order:
# here we order them by traversal order
if K.legacy_weight_ordering():
layers_for_depth.sort(key=lambda x: x.name)
else:
layers_for_depth.sort(key=lambda x: layer_indices[x])
for layer in layers_for_depth:
layers.append(layer)
self.layers = layers
@@ -1898,7 +1946,7 @@ class Container(Layer):
cons = {}
for layer in self.layers:
for key, value in layer.constraints.items():
if key in cons:
if key in cons and cons[key] != value:
raise Exception('Received multiple constraints '
'for one weight tensor: ' + str(key))
cons[key] = value
@@ -1913,6 +1961,8 @@ class Container(Layer):
@property
def trainable_weights(self):
if not self.trainable:
return []
weights = []
for layer in self.layers:
weights += layer.trainable_weights
@@ -1923,8 +1973,37 @@ class Container(Layer):
weights = []
for layer in self.layers:
weights += layer.non_trainable_weights
if not self.trainable:
trainable_weights = []
for layer in self.layers:
trainable_weights += layer.trainable_weights
return trainable_weights + weights
return weights
def get_weights(self):
'''Returns the weights of the model,
as a flat list of Numpy arrays.
'''
weights = []
for layer in self.layers:
weights += layer.weights
return K.batch_get_value(weights)
def set_weights(self, weights):
'''Sets the weights of the model.
The `weights` argument should be a list
of Numpy arrays with shapes and types matching
the output of `model.get_weights()`.
'''
tuples = []
for layer in self.layers:
nb_param = len(layer.weights)
layer_weights = weights[:nb_param]
for sw, w in zip(layer.weights, layer_weights):
tuples.append((sw, w))
weights = weights[nb_param:]
K.batch_set_value(tuples)
@property
def input_spec(self):
specs = []
@@ -2312,7 +2391,38 @@ class Container(Layer):
output_tensors.append(layer_output_tensors[tensor_index])
return cls(input=input_tensors, output=output_tensors, name=name)
def save_weights(self, filepath, overwrite=False):
def save(self, filepath, overwrite=True):
'''Save into a single HDF5 file:
- the model architecture, allowing to re-instantiate the model
- the model weights
- the state of the optimizer, allowing to resume training
exactly where you left off.
This allows you to save the entirety of the state of a model
in a single file.
Saved models can be reinstantiated via `keras.models.load_model`.
The model returned by `load_model`
is a compiled model ready to be used (unless the saved model
was never compiled in the first place).
# Example usage
```python
from keras.models import load_model
model.save('my_model.h5') # creates a HDF5 file 'my_model.h5'
del model # deletes the existing model
# returns a compiled model
# identical to the previous one
model = load_model('my_model.h5')
```
'''
from ..models import save_model
save_model(self, filepath, overwrite)
def save_weights(self, filepath, overwrite=True):
'''Dumps all layer weights to a HDF5 file.
The weight file has:
@@ -2325,33 +2435,28 @@ class Container(Layer):
storing the weight value, named after the weight tensor
'''
import h5py
import os.path
# if file exists and should not be overwritten
if not overwrite and os.path.isfile(filepath):
import sys
get_input = input
if sys.version_info[:2] <= (2, 7):
get_input = raw_input
overwrite = get_input('[WARNING] %s already exists - overwrite? '
'[y/n]' % (filepath))
while overwrite not in ['y', 'n']:
overwrite = get_input('Enter "y" (overwrite) or "n" (cancel).')
if overwrite == 'n':
proceed = ask_to_proceed_with_overwrite(filepath)
if not proceed:
return
print('[TIP] Next time specify overwrite=True in save_weights!')
f = h5py.File(filepath, 'w')
self.save_weights_to_hdf5_group(f)
f.flush()
f.close()
def save_weights_to_hdf5_group(self, f):
if hasattr(self, 'flattened_layers'):
# support for legacy Sequential/Merge behavior
flattened_layers = self.flattened_layers
else:
flattened_layers = self.layers
f = h5py.File(filepath, 'w')
f.attrs['layer_names'] = [layer.name.encode('utf8') for layer in flattened_layers]
for layer in flattened_layers:
g = f.create_group(layer.name)
symbolic_weights = layer.trainable_weights + layer.non_trainable_weights
symbolic_weights = layer.weights
weight_values = K.batch_get_value(symbolic_weights)
weight_names = []
for i, (w, val) in enumerate(zip(symbolic_weights, weight_values)):
@@ -2364,16 +2469,46 @@ class Container(Layer):
for name, val in zip(weight_names, weight_values):
param_dset = g.create_dataset(name, val.shape,
dtype=val.dtype)
param_dset[:] = val
f.flush()
f.close()
if not val.shape:
# scalar
param_dset[()] = val
else:
param_dset[:] = val
def load_weights(self, filepath):
def load_weights(self, filepath, by_name=False):
'''Load all layer weights from a HDF5 save file.
If `by_name` is False (default) weights are loaded
based on the network's topology, meaning the architecture
should be the same as when the weights were saved.
Note that layers that don't have weights are not taken
into account in the topological ordering, so adding or
removing layers is fine as long as they don't have weights.
If `by_name` is True, weights are loaded into layers
only if they share the same name. This is useful
for fine-tuning or transfer-learning models where
some of the layers have changed.
'''
import h5py
f = h5py.File(filepath, mode='r')
if 'layer_names' not in f.attrs and 'model_weights' in f:
f = f['model_weights']
if by_name:
self.load_weights_from_hdf5_group_by_name(f)
else:
self.load_weights_from_hdf5_group(f)
if hasattr(f, 'close'):
f.close()
def load_weights_from_hdf5_group(self, f):
'''Weight loading is based on layer order in a list
(matching model.flattened_layers for Sequential models,
and model.layers for Model class instances), not
on layer names.
Layers that have no weights are skipped.
'''
if hasattr(self, 'flattened_layers'):
# support for legacy Sequential/Merge behavior
flattened_layers = self.flattened_layers
@@ -2387,7 +2522,7 @@ class Container(Layer):
raise Exception('You are trying to load a weight file '
'containing ' + str(nb_layers) +
' layers into a model with ' +
str(len(flattened_layers)) + '.')
str(len(flattened_layers)) + ' layers.')
for k in range(nb_layers):
g = f['layer_{}'.format(k)]
@@ -2395,7 +2530,21 @@ class Container(Layer):
flattened_layers[k].set_weights(weights)
else:
# new file format
filtered_layers = []
for layer in flattened_layers:
weights = layer.weights
if weights:
filtered_layers.append(layer)
flattened_layers = filtered_layers
layer_names = [n.decode('utf8') for n in f.attrs['layer_names']]
filtered_layer_names = []
for name in layer_names:
g = f[name]
weight_names = [n.decode('utf8') for n in g.attrs['weight_names']]
if len(weight_names):
filtered_layer_names.append(name)
layer_names = filtered_layer_names
if len(layer_names) != len(flattened_layers):
raise Exception('You are trying to load a weight file '
'containing ' + str(len(layer_names)) +
@@ -2408,24 +2557,80 @@ class Container(Layer):
for k, name in enumerate(layer_names):
g = f[name]
weight_names = [n.decode('utf8') for n in g.attrs['weight_names']]
if len(weight_names):
weight_values = [g[weight_name] for weight_name in weight_names]
layer = flattened_layers[k]
symbolic_weights = layer.trainable_weights + layer.non_trainable_weights
weight_values = [g[weight_name] for weight_name in weight_names]
layer = flattened_layers[k]
symbolic_weights = layer.weights
if len(weight_values) != len(symbolic_weights):
raise Exception('Layer #' + str(k) +
' (named "' + layer.name +
'" in the current model) was found to '
'correspond to layer ' + name +
' in the save file. '
'However the new layer ' + layer.name +
' expects ' + str(len(symbolic_weights)) +
' weights, but the saved weights have ' +
str(len(weight_values)) +
' elements.')
if layer.__class__.__name__ == 'Convolution1D':
# this is for backwards compatibility with
# the old Conv1D weights format.
w = weight_values[0]
shape = w.shape
if shape[:2] != (layer.filter_length, 1) or shape[3] != layer.nb_filter:
# legacy shape: (self.nb_filter, input_dim, self.filter_length, 1)
assert shape[0] == layer.nb_filter and shape[2:] == (layer.filter_length, 1)
w = np.transpose(w, (2, 3, 1, 0))
weight_values[0] = w
weight_value_tuples += zip(symbolic_weights, weight_values)
K.batch_set_value(weight_value_tuples)
def load_weights_from_hdf5_group_by_name(self, f):
''' Name-based weight loading
(instead of topological weight loading).
Layers that have no matching name are skipped.
'''
if hasattr(self, 'flattened_layers'):
# support for legacy Sequential/Merge behavior
flattened_layers = self.flattened_layers
else:
flattened_layers = self.layers
if 'nb_layers' in f.attrs:
raise Exception('The weight file you are trying to load is' +
' in a legacy format that does not support' +
' name-based weight loading.')
else:
# new file format
layer_names = [n.decode('utf8') for n in f.attrs['layer_names']]
# Reverse index of layer name to list of layers with name.
index = {}
for layer in flattened_layers:
if layer.name:
index.setdefault(layer.name, []).append(layer)
# we batch weight value assignments in a single backend call
# which provides a speedup in TensorFlow.
weight_value_tuples = []
for k, name in enumerate(layer_names):
g = f[name]
weight_names = [n.decode('utf8') for n in g.attrs['weight_names']]
weight_values = [g[weight_name] for weight_name in weight_names]
for layer in index.get(name, []):
symbolic_weights = layer.weights
if len(weight_values) != len(symbolic_weights):
raise Exception('Layer #' + str(k) +
' (named "' + layer.name +
'" in the current model) was found to '
'correspond to layer ' + name +
' in the save file. '
'However the new layer ' + layer.name +
' expects ' + str(len(symbolic_weights)) +
' weights, but the saved weights have ' +
str(len(weight_values)) +
' elements.')
weight_value_tuples += zip(symbolic_weights, weight_values)
'") expects ' +
str(len(symbolic_weights)) +
' weight(s), but the saved weights' +
' have ' + str(len(weight_values)) +
' element(s).')
# set values
for i in range(len(weight_values)):
weight_value_tuples.append((symbolic_weights[i], weight_values[i]))
K.batch_set_value(weight_value_tuples)
f.close()
def _updated_config(self):
'''shared between different serialization methods'''
@@ -2437,14 +2642,6 @@ class Container(Layer):
'config': config,
'keras_version': keras_version
}
if hasattr(self, 'optimizer'):
model_config['optimizer'] = self.optimizer.get_config()
model_config['loss'] = getattr(self.loss, '__name__', self.loss)
model_config['sample_weight_mode'] = self.sample_weight_mode
if hasattr(self, 'loss_weights'):
model_config['loss_weights'] = self.loss_weights
return model_config
def to_json(self, **kwargs):
@@ -2464,7 +2661,7 @@ class Container(Layer):
if type(obj).__name__ == type.__name__:
return obj.__name__
raise TypeError('Not JSON Serializable')
raise TypeError('Not JSON Serializable:', obj)
model_config = self._updated_config()
return json.dumps(model_config, default=get_json_type, **kwargs)
+38 -39
Ver Arquivo
@@ -418,15 +418,11 @@ def generator_queue(generator, max_q_size=10,
_stop = threading.Event()
try:
def data_generator_task():
while not _stop.is_set():
try:
if q.qsize() < max_q_size:
try:
generator_output = next(generator)
except ValueError:
continue
if pickle_safe or q.qsize() < max_q_size:
generator_output = next(generator)
q.put(generator_output)
else:
time.sleep(wait_time)
@@ -444,7 +440,6 @@ def generator_queue(generator, max_q_size=10,
generator_threads.append(thread)
thread.daemon = True
thread.start()
except:
_stop.set()
if pickle_safe:
@@ -610,8 +605,9 @@ class Model(Container):
self.targets.append(K.placeholder(ndim=len(shape), name=name + '_target'))
# prepare metrics
self.metrics = metrics
self.metrics_names = ['loss']
self.metrics = []
self.metrics_tensors = []
# compute total loss
total_loss = None
@@ -625,7 +621,7 @@ class Model(Container):
output_loss = weighted_loss(y_true, y_pred,
sample_weight, mask)
if len(self.outputs) > 1:
self.metrics.append(output_loss)
self.metrics_tensors.append(output_loss)
self.metrics_names.append(self.output_names[i] + '_loss')
if total_loss is None:
total_loss = loss_weight * output_loss
@@ -650,21 +646,21 @@ class Model(Container):
output_shape = self.internal_output_shapes[i]
if output_shape[-1] == 1 or self.loss_functions[i] == objectives.binary_crossentropy:
# case: binary accuracy
self.metrics.append(metrics_module.binary_accuracy(y_true, y_pred))
self.metrics_tensors.append(metrics_module.binary_accuracy(y_true, y_pred))
elif self.loss_functions[i] == objectives.sparse_categorical_crossentropy:
# case: categorical accuracy with sparse targets
self.metrics.append(
self.metrics_tensors.append(
metrics_module.sparse_categorical_accuracy(y_true, y_pred))
else:
# case: categorical accuracy with dense targets
self.metrics.append(metrics_module.categorical_accuracy(y_true, y_pred))
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')
else:
metric_fn = metrics_module.get(metric)
self.metrics.append(metric_fn(y_true, y_pred))
self.metrics_tensors.append(metric_fn(y_true, y_pred))
if len(self.output_names) == 1:
self.metrics_names.append(metric_fn.__name__)
else:
@@ -684,23 +680,25 @@ class Model(Container):
self.test_function = None
self.predict_function = None
self._collected_trainable_weights = collect_trainable_weights(self)
def _make_train_function(self):
if not hasattr(self, 'train_function'):
raise Exception('You must compile your model before using it.')
if self.train_function is None:
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
inputs = self.inputs + self.targets + self.sample_weights + [K.learning_phase()]
else:
inputs = self.inputs + self.targets + self.sample_weights
# get trainable weights
trainable_weights = collect_trainable_weights(self)
training_updates = self.optimizer.get_updates(trainable_weights, self.constraints, self.total_loss)
training_updates = self.optimizer.get_updates(self._collected_trainable_weights,
self.constraints,
self.total_loss)
updates = self.updates + training_updates
# returns loss and metrics. Updates weights at each call.
self.train_function = K.function(inputs,
[self.total_loss] + self.metrics,
[self.total_loss] + self.metrics_tensors,
updates=updates,
**self._function_kwargs)
@@ -708,14 +706,14 @@ class Model(Container):
if not hasattr(self, 'test_function'):
raise Exception('You must compile your model before using it.')
if self.test_function is None:
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
inputs = self.inputs + self.targets + self.sample_weights + [K.learning_phase()]
else:
inputs = self.inputs + self.targets + self.sample_weights
# return loss and metrics, no gradient updates.
# Does update the network states.
self.test_function = K.function(inputs,
[self.total_loss] + self.metrics,
[self.total_loss] + self.metrics_tensors,
updates=self.state_updates,
**self._function_kwargs)
@@ -723,7 +721,7 @@ class Model(Container):
if not hasattr(self, 'predict_function'):
self.predict_function = None
if self.predict_function is None:
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
inputs = self.inputs + [K.learning_phase()]
else:
inputs = self.inputs
@@ -767,9 +765,9 @@ class Model(Container):
do_validation = True
if verbose:
print('Train on %d samples, validate on %d samples' %
(len(ins[0]), len(val_ins[0])))
(ins[0].shape[0], val_ins[0].shape[0]))
nb_train_sample = len(ins[0])
nb_train_sample = ins[0].shape[0]
index_array = np.arange(nb_train_sample)
self.history = cbks.History()
@@ -863,7 +861,7 @@ class Model(Container):
or list of arrays of predictions
(if the model has multiple outputs).
'''
nb_sample = len(ins[0])
nb_sample = ins[0].shape[0]
outs = []
if verbose == 1:
progbar = Progbar(target=nb_sample)
@@ -908,7 +906,7 @@ class Model(Container):
and/or metrics). The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
nb_sample = len(ins[0])
nb_sample = ins[0].shape[0]
outs = []
if verbose == 1:
progbar = Progbar(target=nb_sample)
@@ -1050,7 +1048,7 @@ class Model(Container):
batch_size=batch_size)
self._make_test_function()
val_f = self.test_function
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
val_ins = val_x + val_y + val_sample_weights + [0.]
else:
val_ins = val_x + val_y + val_sample_weights
@@ -1064,7 +1062,7 @@ class Model(Container):
slice_X(sample_weights, 0, split_at), slice_X(sample_weights, split_at))
self._make_test_function()
val_f = self.test_function
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
val_ins = val_x + val_y + val_sample_weights + [0.]
else:
val_ins = val_x + val_y + val_sample_weights
@@ -1074,7 +1072,7 @@ class Model(Container):
val_ins = None
# prepare input arrays and training function
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + y + sample_weights + [1.]
else:
ins = x + y + sample_weights
@@ -1134,7 +1132,7 @@ class Model(Container):
check_batch_dim=False,
batch_size=batch_size)
# prepare inputs, delegate logic to _test_loop
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + y + sample_weights + [0.]
else:
ins = x + y + sample_weights
@@ -1171,7 +1169,7 @@ class Model(Container):
'Batch size: ' + str(batch_size) + '.')
# prepare inputs, delegate logic to _predict_loop
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + [0.]
else:
ins = x
@@ -1215,7 +1213,7 @@ class Model(Container):
sample_weight=sample_weight,
class_weight=class_weight,
check_batch_dim=True)
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + y + sample_weights + [1.]
else:
ins = x + y + sample_weights
@@ -1253,7 +1251,7 @@ class Model(Container):
x, y, sample_weights = self._standardize_user_data(x, y,
sample_weight=sample_weight,
check_batch_dim=True)
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + y + sample_weights + [0.]
else:
ins = x + y + sample_weights
@@ -1268,7 +1266,7 @@ class Model(Container):
'''
x = standardize_input_data(x, self.input_names,
self.internal_input_shapes)
if self.uses_learning_phase:
if self.uses_learning_phase and type(K.learning_phase()) is not int:
ins = x + [0.]
else:
ins = x
@@ -1314,7 +1312,7 @@ class Model(Container):
max_q_size: maximum size for the generator queue
nb_worker: maximum number of processes to spin up when using process based threading
pickle_safe: if True, use process based threading. Note that because
this implementation relies on multiprocessing, you should not pass non
this implementation relies on multiprocessing, you should not pass
non picklable arguments to the generator as they can't be passed
easily to children processes.
@@ -1430,11 +1428,11 @@ class Model(Container):
# build batch logs
batch_logs = {}
if type(x) is list:
batch_size = len(x[0])
batch_size = x[0].shape[0]
elif type(x) is dict:
batch_size = len(list(x.values())[0])
batch_size = list(x.values())[0].shape[0]
else:
batch_size = len(x)
batch_size = x.shape[0]
batch_logs['batch'] = batch_index
batch_logs['size'] = batch_size
callbacks.on_batch_begin(batch_index, batch_logs)
@@ -1475,6 +1473,7 @@ class Model(Container):
# no need for try/except because
# data has already been validated
val_outs = self.evaluate(val_x, val_y,
batch_size=batch_size,
sample_weight=val_sample_weights,
verbose=0)
if type(val_outs) is not list:
@@ -1508,7 +1507,7 @@ class Model(Container):
max_q_size: maximum size for the generator queue
nb_worker: maximum number of processes to spin up when using process based threading
pickle_safe: if True, use process based threading. Note that because
this implementation relies on multiprocessing, you should not pass non
this implementation relies on multiprocessing, you should not pass
non picklable arguments to the generator as they can't be passed
easily to children processes.
@@ -1593,7 +1592,7 @@ class Model(Container):
max_q_size: maximum size for the generator queue
nb_worker: maximum number of processes to spin up when using process based threading
pickle_safe: if True, use process based threading. Note that because
this implementation relies on multiprocessing, you should not pass non
this implementation relies on multiprocessing, you should not pass
non picklable arguments to the generator as they can't be passed
easily to children processes.
+2 -4
Ver Arquivo
@@ -29,13 +29,11 @@ def get_fans(shape, dim_ordering='th'):
def uniform(shape, scale=0.05, name=None):
return K.variable(np.random.uniform(low=-scale, high=scale, size=shape),
name=name)
return K.random_uniform_variable(shape, -scale, scale, name=name)
def normal(shape, scale=0.05, name=None):
return K.variable(np.random.normal(loc=0.0, scale=scale, size=shape),
name=name)
return K.random_normal_variable(shape, 0.0, scale, name=name)
def lecun_uniform(shape, name=None, dim_ordering='th'):
+4 -4
Ver Arquivo
@@ -112,7 +112,7 @@ class ELU(Layer):
return pos + self.alpha * (K.exp(neg) - 1.)
def get_config(self):
config = {'alpha': self.alpha}
config = {'alpha': float(self.alpha)}
base_config = super(ELU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -161,8 +161,8 @@ class ParametricSoftplus(Layer):
return K.softplus(self.betas * x) * self.alphas
def get_config(self):
config = {'alpha_init': self.alpha_init,
'beta_init': self.beta_init}
config = {'alpha_init': float(self.alpha_init),
'beta_init': float(self.beta_init)}
base_config = super(ParametricSoftplus, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -195,7 +195,7 @@ class ThresholdedReLU(Layer):
return x * K.cast(x > self.theta, K.floatx())
def get_config(self):
config = {'theta': self.theta}
config = {'theta': float(self.theta)}
base_config = super(ThresholdedReLU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+542 -40
Ver Arquivo
@@ -4,7 +4,7 @@ from __future__ import absolute_import
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..engine import Layer, InputSpec
from ..utils.np_utils import conv_output_length
from ..utils.np_utils import conv_output_length, conv_input_length
# imports for backwards namespace compatibility
from .pooling import AveragePooling1D, AveragePooling2D, AveragePooling3D
@@ -113,7 +113,7 @@ class Convolution1D(Layer):
def build(self, input_shape):
input_dim = input_shape[2]
self.W_shape = (self.nb_filter, input_dim, self.filter_length, 1)
self.W_shape = (self.filter_length, 1, input_dim, self.nb_filter)
self.W = self.init(self.W_shape, name='{}_W'.format(self.name))
if self.bias:
self.b = K.zeros((self.nb_filter,), name='{}_b'.format(self.name))
@@ -152,15 +152,13 @@ class Convolution1D(Layer):
return (input_shape[0], length, self.nb_filter)
def call(self, x, mask=None):
x = K.expand_dims(x, -1) # add a dimension of the right
x = K.permute_dimensions(x, (0, 2, 1, 3))
x = K.expand_dims(x, 2) # add a dummy dimension
output = K.conv2d(x, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering='th')
dim_ordering='tf')
output = K.squeeze(output, 2) # remove the dummy dimension
if self.bias:
output += K.reshape(self.b, (1, self.nb_filter, 1, 1))
output = K.squeeze(output, 3) # remove the dummy 3rd dimension
output = K.permute_dimensions(output, (0, 2, 1))
output += K.reshape(self.b, (1, 1, self.nb_filter))
output = self.activation(output)
return output
@@ -183,6 +181,121 @@ class Convolution1D(Layer):
return dict(list(base_config.items()) + list(config.items()))
class AtrousConvolution1D(Convolution1D):
'''Atrous Convolution operator for filtering neighborhoods of one-dimensional inputs.
A.k.a dilated convolution or convolution with holes.
When using this layer as the first layer in a model,
either provide the keyword argument `input_dim`
(int, e.g. 128 for sequences of 128-dimensional vectors),
or `input_shape` (tuples of integers, e.g. (10, 128) for sequences
of 10 vectors of 128-dimensional vectors).
# Example
```python
# apply an atrous convolution 1d with atrous rate 2 of length 3 to a sequence with 10 timesteps,
# with 64 output filters
model = Sequential()
model.add(AtrousConvolution1D(64, 3, atrous_rate=2, border_mode='same', input_shape=(10, 32)))
# now model.output_shape == (None, 10, 64)
# add a new atrous conv1d on top
model.add(AtrousConvolution1D(32, 3, atrous_rate=2, border_mode='same'))
# now model.output_shape == (None, 10, 32)
```
# Arguments
nb_filter: Number of convolution kernels to use
(dimensionality of the output).
filter_length: The extension (spatial or temporal) of each filter.
init: name of initialization function for the weights of the layer
(see [initializations](../initializations.md)),
or alternatively, Theano function to use for weights initialization.
This parameter is only relevant if you don't pass a `weights` argument.
activation: name of activation function to use
(see [activations](../activations.md)),
or alternatively, elementwise Theano function.
If you don't specify anything, no activation is applied
(ie. "linear" activation: a(x) = x).
weights: list of numpy arrays to set as initial weights.
border_mode: 'valid' or 'same'.
subsample_length: factor by which to subsample output.
atrous_rate: Factor for kernel dilation. Also called filter_dilation
elsewhere.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
(eg. L1 or L2 regularization), applied to the main weights matrix.
b_regularizer: instance of [WeightRegularizer](../regularizers.md),
applied to the bias.
activity_regularizer: instance of [ActivityRegularizer](../regularizers.md),
applied to the network output.
W_constraint: instance of the [constraints](../constraints.md) module
(eg. maxnorm, nonneg), applied to the main weights matrix.
b_constraint: instance of the [constraints](../constraints.md) module,
applied to the bias.
bias: whether to include a bias
(i.e. make the layer affine rather than linear).
input_dim: Number of channels/dimensions in the input.
Either this argument or the keyword argument `input_shape`must be
provided when using this layer as the first layer in a model.
input_length: Length of input sequences, when it is constant.
This argument is required if you are going to connect
`Flatten` then `Dense` layers upstream
(without it, the shape of the dense outputs cannot be computed).
# Input shape
3D tensor with shape: `(samples, steps, input_dim)`.
# Output shape
3D tensor with shape: `(samples, new_steps, nb_filter)`.
`steps` value might have changed due to padding.
'''
def __init__(self, nb_filter, filter_length,
init='uniform', activation='linear', weights=None,
border_mode='valid', subsample_length=1, atrous_rate=1,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for AtrousConv1D:', border_mode)
self.atrous_rate = int(atrous_rate)
super(AtrousConvolution1D, self).__init__(nb_filter, filter_length,
init=init, activation=activation,
weights=weights, border_mode=border_mode,
subsample_length=subsample_length,
W_regularizer=W_regularizer, b_regularizer=b_regularizer,
activity_regularizer=activity_regularizer,
W_constraint=W_constraint, b_constraint=b_constraint,
bias=bias, **kwargs)
def get_output_shape_for(self, input_shape):
length = conv_output_length(input_shape[1],
self.filter_length,
self.border_mode,
self.subsample[0],
dilation=self.atrous_rate)
return (input_shape[0], length, self.nb_filter)
def call(self, x, mask=None):
x = K.expand_dims(x, 2) # add a dummy dimension
output = K.conv2d(x, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering='tf',
filter_dilation=(self.atrous_rate, self.atrous_rate))
output = K.squeeze(output, 2) # remove the dummy dimension
if self.bias:
output += K.reshape(self.b, (1, 1, self.nb_filter))
output = self.activation(output)
return output
def get_config(self):
config = {'atrous_rate': self.atrous_rate}
base_config = super(AtrousConvolution1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Convolution2D(Layer):
'''Convolution operator for filtering windows of two-dimensional inputs.
When using this layer as the first layer in a model,
@@ -254,11 +367,12 @@ class Convolution2D(Layer):
'''
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1), dim_ordering=K.image_dim_ordering(),
border_mode='valid', subsample=(1, 1), dim_ordering='default',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for Convolution2D:', border_mode)
self.nb_filter = nb_filter
@@ -379,6 +493,165 @@ class Convolution2D(Layer):
return dict(list(base_config.items()) + list(config.items()))
class Deconvolution2D(Convolution2D):
'''Transposed convolution operator for filtering windows of two-dimensional inputs.
The need for transposed convolutions generally arises from the desire
to use a transformation going in the opposite direction of a normal convolution,
i.e., from something that has the shape of the output of some convolution
to something that has the shape of its input
while maintaining a connectivity pattern that is compatible with said convolution. [1]
When using this layer as the first layer in a model,
provide the keyword argument `input_shape`
(tuple of integers, does not include the sample axis),
e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures.
# 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)
# 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)
```
# Arguments
nb_filter: Number of transposed convolution filters to use.
nb_row: Number of rows in the transposed convolution kernel.
nb_col: Number of columns in the transposed convolution kernel.
output_shape: Output shape of the transposed convolution operation.
tuple of integers (nb_samples, nb_filter, nb_output_rows, nb_output_cols)
Formula for calculation of the output shape [1], [2]:
o = s (i - 1) + a + k - 2p, \quad a \in \{0, \ldots, s - 1\}
where:
i - input size (rows or cols),
k - kernel size (nb_filter),
s - stride (subsample for rows or cols respectively),
p - padding size,
a - user-specified quantity used to distinguish between
the s different possible output sizes.
init: name of initialization function for the weights of the layer
(see [initializations](../initializations.md)), or alternatively,
Theano function to use for weights initialization.
This parameter is only relevant if you don't pass
a `weights` argument.
activation: name of activation function to use
(see [activations](../activations.md)),
or alternatively, elementwise Theano/TensorFlow function.
If you don't specify anything, no activation is applied
(ie. "linear" activation: a(x) = x).
weights: list of numpy arrays to set as initial weights.
border_mode: 'valid' or 'same'.
subsample: tuple of length 2. Factor by which to oversample output.
Also called strides elsewhere.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
(eg. L1 or L2 regularization), applied to the main weights matrix.
b_regularizer: instance of [WeightRegularizer](../regularizers.md),
applied to the bias.
activity_regularizer: instance of [ActivityRegularizer](../regularizers.md),
applied to the network output.
W_constraint: instance of the [constraints](../constraints.md) module
(eg. maxnorm, nonneg), applied to the main weights matrix.
b_constraint: instance of the [constraints](../constraints.md) module,
applied to the bias.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
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".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Output shape
4D tensor with shape:
`(samples, nb_filter, new_rows, new_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, new_rows, new_cols, nb_filter)` if dim_ordering='tf'.
`rows` and `cols` values might have changed due to padding.
# References
[1] [A guide to convolution arithmetic for deep learning](https://arxiv.org/abs/1603.07285 "arXiv:1603.07285v1 [stat.ML]")
[2] [Transposed convolution arithmetic](http://deeplearning.net/software/theano_versions/dev/tutorial/conv_arithmetic.html#transposed-convolution-arithmetic)
[3] [Deconvolutional Networks](http://www.matthewzeiler.com/pubs/cvpr2010/cvpr2010.pdf)
'''
def __init__(self, nb_filter, nb_row, nb_col, output_shape,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
dim_ordering='default',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for Deconvolution2D:', border_mode)
self.output_shape_ = output_shape
super(Deconvolution2D, self).__init__(nb_filter, nb_row, nb_col,
init=init, activation=activation,
weights=weights, border_mode=border_mode,
subsample=subsample, dim_ordering=dim_ordering,
W_regularizer=W_regularizer, b_regularizer=b_regularizer,
activity_regularizer=activity_regularizer,
W_constraint=W_constraint, b_constraint=b_constraint,
bias=bias, **kwargs)
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
rows = input_shape[2]
cols = input_shape[3]
elif self.dim_ordering == 'tf':
rows = input_shape[1]
cols = input_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':
return (input_shape[0], rows, cols, self.nb_filter)
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def call(self, x, mask=None):
output = K.deconv2d(x, self.W, self.output_shape_,
strides=self.subsample,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering,
filter_shape=self.W_shape)
if self.bias:
if self.dim_ordering == 'th':
output += K.reshape(self.b, (1, self.nb_filter, 1, 1))
elif self.dim_ordering == 'tf':
output += K.reshape(self.b, (1, 1, 1, self.nb_filter))
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
output = self.activation(output)
return output
def get_config(self):
config = {'output_shape': self.output_shape}
base_config = super(Deconvolution2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class AtrousConvolution2D(Convolution2D):
'''Atrous Convolution operator for filtering windows of two-dimensional inputs.
A.k.a dilated convolution or convolution with holes.
@@ -453,10 +726,12 @@ class AtrousConvolution2D(Convolution2D):
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
atrous_rate=(1, 1), dim_ordering=K.image_dim_ordering(),
atrous_rate=(1, 1), dim_ordering='default',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for AtrousConv2D:', border_mode)
@@ -535,6 +810,11 @@ class SeparableConvolution2D(Layer):
(tuple of integers, does not include the sample axis),
e.g. `input_shape=(3, 128, 128)` for 128x128 RGB pictures.
# Theano warning
This layer is only available with the
TensorFlow backend for the time being.
# Arguments
nb_filter: Number of convolution filters to use.
nb_row: Number of rows in the convolution kernel.
@@ -555,8 +835,6 @@ class SeparableConvolution2D(Layer):
Also called strides elsewhere.
depth_multiplier: how many output channel to use per input channel
for the depthwise convolution step.
atrous_rate: tuple of length 2. Factor for kernel dilation.
Also called filter_dilation elsewhere.
depthwise_regularizer: instance of [WeightRegularizer](../regularizers.md)
(eg. L1 or L2 regularization), applied to the depthwise weights matrix.
pointwise_regularizer: instance of [WeightRegularizer](../regularizers.md)
@@ -595,7 +873,7 @@ class SeparableConvolution2D(Layer):
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
depth_multiplier=1, dim_ordering=K.image_dim_ordering(),
depth_multiplier=1, dim_ordering='default',
depthwise_regularizer=None, pointwise_regularizer=None,
b_regularizer=None, activity_regularizer=None,
depthwise_constraint=None, pointwise_constraint=None,
@@ -606,6 +884,9 @@ class SeparableConvolution2D(Layer):
raise Exception('SeparableConv2D is only available '
'with TensorFlow for the time being.')
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for SeparableConv2D:', border_mode)
@@ -806,10 +1087,13 @@ class Convolution3D(Layer):
def __init__(self, nb_filter, kernel_dim1, kernel_dim2, kernel_dim3,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1, 1), dim_ordering=K.image_dim_ordering(),
border_mode='valid', subsample=(1, 1, 1), dim_ordering='default',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for Convolution3D:', border_mode)
self.nb_filter = nb_filter
@@ -963,7 +1247,8 @@ class UpSampling1D(Layer):
super(UpSampling1D, self).__init__(**kwargs)
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.length * input_shape[1], input_shape[2])
length = self.length * input_shape[1] if input_shape[1] is not None else None
return (input_shape[0], length, input_shape[2])
def call(self, x, mask=None):
output = K.repeat_elements(x, self.length, axis=1)
@@ -1001,7 +1286,9 @@ class UpSampling2D(Layer):
`(samples, upsampled_rows, upsampled_cols, channels)` if dim_ordering='tf'.
'''
def __init__(self, size=(2, 2), dim_ordering=K.image_dim_ordering(), **kwargs):
def __init__(self, size=(2, 2), dim_ordering='default', **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
@@ -1010,14 +1297,18 @@ class UpSampling2D(Layer):
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
width = self.size[0] * input_shape[2] if input_shape[2] is not None else None
height = self.size[1] * input_shape[3] if input_shape[3] is not None else None
return (input_shape[0],
input_shape[1],
self.size[0] * input_shape[2],
self.size[1] * input_shape[3])
width,
height)
elif self.dim_ordering == 'tf':
width = self.size[0] * input_shape[1] if input_shape[1] is not None else None
height = self.size[1] * input_shape[2] if input_shape[2] is not None else None
return (input_shape[0],
self.size[0] * input_shape[1],
self.size[1] * input_shape[2],
width,
height,
input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
@@ -1036,8 +1327,6 @@ class UpSampling3D(Layer):
'''Repeat the first, second and third dimension of the data
by size[0], size[1] and size[2] respectively.
Note: this layer will only work with Theano for the time being.
# Arguments
size: tuple of 3 integers. The upsampling factors for dim1, dim2 and dim3.
dim_ordering: 'th' or 'tf'.
@@ -1060,10 +1349,9 @@ class UpSampling3D(Layer):
`(samples, upsampled_dim1, upsampled_dim2, upsampled_dim3, channels)` if dim_ordering='tf'.
'''
def __init__(self, size=(2, 2, 2), dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
def __init__(self, size=(2, 2, 2), dim_ordering='default', **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
@@ -1072,16 +1360,22 @@ class UpSampling3D(Layer):
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
dim1 = self.size[0] * input_shape[2] if input_shape[2] is not None else None
dim2 = self.size[1] * input_shape[3] if input_shape[3] is not None else None
dim3 = self.size[2] * input_shape[4] if input_shape[4] is not None else None
return (input_shape[0],
input_shape[1],
self.size[0] * input_shape[2],
self.size[1] * input_shape[3],
self.size[2] * input_shape[4])
dim1,
dim2,
dim3)
elif self.dim_ordering == 'tf':
dim1 = self.size[0] * input_shape[1] if input_shape[1] is not None else None
dim2 = self.size[1] * input_shape[2] if input_shape[2] is not None else None
dim3 = self.size[2] * input_shape[3] if input_shape[3] is not None else None
return (input_shape[0],
self.size[0] * input_shape[1],
self.size[1] * input_shape[2],
self.size[2] * input_shape[3],
dim1,
dim2,
dim3,
input_shape[4])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
@@ -1154,8 +1448,10 @@ class ZeroPadding2D(Layer):
(samples, depth, first_padded_axis, second_padded_axis)
'''
def __init__(self, padding=(1, 1), dim_ordering=K.image_dim_ordering(), **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.dim_ordering = dim_ordering
@@ -1192,8 +1488,6 @@ class ZeroPadding2D(Layer):
class ZeroPadding3D(Layer):
'''Zero-padding layer for 3D data (spatial or spatio-temporal).
Note: this layer will only work with Theano for the time being.
# Arguments
padding: tuple of int (length 3)
How many zeros to add at the beginning and end of
@@ -1214,11 +1508,10 @@ class ZeroPadding3D(Layer):
(samples, depth, first_padded_axis, second_padded_axis, third_axis_to_pad)
'''
def __init__(self, padding=(1, 1, 1), dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
def __init__(self, padding=(1, 1, 1), dim_ordering='default', **kwargs):
super(ZeroPadding3D, 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.dim_ordering = dim_ordering
@@ -1255,11 +1548,220 @@ class ZeroPadding3D(Layer):
base_config = super(ZeroPadding3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Cropping1D(Layer):
'''Cropping layer for 1D input (e.g. temporal sequence).
It crops along the time dimension (axis 1).
# Arguments
cropping: tuple of int (length 2)
How many units should be trimmed off at the beginning and end of
the cropping dimension (axis 1).
# Input shape
3D tensor with shape (samples, axis_to_crop, features)
# Output shape
3D tensor with shape (samples, cropped_axis, features)
'''
def __init__(self, cropping=(1, 1), **kwargs):
super(Cropping1D, self).__init__(**kwargs)
self.cropping = tuple(cropping)
assert len(self.cropping) == 2, 'cropping must be a tuple length of 2'
self.input_spec = [InputSpec(ndim=3)]
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
def get_output_shape_for(self, input_shape):
length = input_shape[1] - self.cropping[0] - self.cropping[1] if input_shape[1] is not None else None
return (input_shape[0],
length,
input_shape[2])
def call(self, x, mask=None):
input_shape = self.input_spec[0].shape
return x[:, self.cropping[0]:input_shape[1]-self.cropping[1], :]
def get_config(self):
config = {'cropping': self.cropping}
base_config = super(Cropping1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Cropping2D(Layer):
'''Cropping layer for 2D input (e.g. picture).
It crops along spatial dimensions, i.e. width and height.
# Arguments
cropping: tuple of tuple of int (length 2)
How many units should be trimmed off at the beginning and end of
the 2 cropping dimensions (width, height).
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".
# Input shape
4D tensor with shape:
(samples, depth, first_axis_to_crop, second_axis_to_crop)
# Output shape
4D tensor with shape:
(samples, depth, first_cropped_axis, second_cropped_axis)
# Examples
```python
# Crop the input 2D images or feature maps
model = Sequential()
model.add(Cropping2D(cropping=((2, 2), (4, 4)), input_shape=(3, 28, 28)))
# now model.output_shape == (None, 3, 24, 20)
model.add(Convolution2D(64, 3, 3, border_mode='same))
model.add(Cropping2D(cropping=((2, 2), (2, 2))))
# now model.output_shape == (None, 64, 20, 16)
```
'''
def __init__(self, cropping=((0, 0), (0, 0)), dim_ordering='default', **kwargs):
super(Cropping2D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.cropping = tuple(cropping)
assert len(self.cropping) == 2, 'cropping must be a tuple length of 2'
assert len(self.cropping[0]) == 2, 'cropping[0] must be a tuple length of 2'
assert len(self.cropping[1]) == 2, 'cropping[1] must be a tuple length of 2'
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 build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
return (input_shape[0],
input_shape[1],
input_shape[2] - self.cropping[0][0] - self.cropping[0][1],
input_shape[3] - self.cropping[1][0] - self.cropping[1][1])
elif self.dim_ordering == 'tf':
return (input_shape[0],
input_shape[1] - self.cropping[0][0] - self.cropping[0][1],
input_shape[2] - self.cropping[1][0] - self.cropping[1][1],
input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def call(self, x, mask=None):
input_shape = self.input_spec[0].shape
if self.dim_ordering == 'th':
return x[:,
:,
self.cropping[0][0]:input_shape[2]-self.cropping[0][1],
self.cropping[1][0]:input_shape[3]-self.cropping[1][1]]
elif self.dim_ordering == 'tf':
return x[:,
self.cropping[0][0]:input_shape[1]-self.cropping[0][1],
self.cropping[1][0]:input_shape[2]-self.cropping[1][1],
:]
def get_config(self):
config = {'cropping': self.cropping}
base_config = super(Cropping2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Cropping3D(Layer):
'''Cropping layer for 2D input (e.g. picture).
# Arguments
cropping: tuple of tuple of int (length 3)
How many units should be trimmed off at the beginning and end of
the 3 cropping dimensions (kernel_dim1, kernel_dim2, kernerl_dim3).
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 4.
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".
# Input shape
5D tensor with shape:
(samples, depth, first_axis_to_crop, second_axis_to_crop, third_axis_to_crop)
# Output shape
5D tensor with shape:
(samples, depth, first_cropped_axis, second_cropped_axis, third_cropped_axis)
'''
def __init__(self, cropping=((1, 1), (1, 1), (1, 1)), dim_ordering='default', **kwargs):
super(Cropping3D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.cropping = tuple(cropping)
assert len(self.cropping) == 3, 'cropping must be a tuple length of 3'
assert len(self.cropping[0]) == 2, 'cropping[0] must be a tuple length of 2'
assert len(self.cropping[1]) == 2, 'cropping[1] must be a tuple length of 2'
assert len(self.cropping[2]) == 2, 'cropping[2] must be a tuple length of 2'
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
dim1 = input_shape[2] - self.cropping[0][0] - self.cropping[0][1] if input_shape[2] is not None else None
dim2 = input_shape[3] - self.cropping[1][0] - self.cropping[1][1] if input_shape[3] is not None else None
dim3 = input_shape[4] - self.cropping[2][0] - self.cropping[2][1] if input_shape[4] is not None else None
return (input_shape[0],
input_shape[1],
dim1,
dim2,
dim3)
elif self.dim_ordering == 'tf':
dim1 = input_shape[1] - self.cropping[0][0] - self.cropping[0][1] if input_shape[1] is not None else None
dim2 = input_shape[2] - self.cropping[1][0] - self.cropping[1][1] if input_shape[2] is not None else None
dim3 = input_shape[3] - self.cropping[2][0] - self.cropping[2][1] if input_shape[3] is not None else None
return (input_shape[0],
dim1,
dim2,
dim3,
input_shape[4])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def call(self, x, mask=None):
input_shape = self.input_spec[0].shape
if self.dim_ordering == 'th':
return x[:,
:,
self.cropping[0][0]:input_shape[2]-self.cropping[0][1],
self.cropping[1][0]:input_shape[3]-self.cropping[1][1],
self.cropping[2][0]:input_shape[4]-self.cropping[2][1]]
elif self.dim_ordering == 'tf':
return x[:,
self.cropping[0][0]:input_shape[1]-self.cropping[0][1],
self.cropping[1][0]:input_shape[2]-self.cropping[1][1],
self.cropping[2][0]:input_shape[3]-self.cropping[2][1],
:]
def get_config(self):
config = {'cropping': self.cropping}
base_config = super(Cropping3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
# Aliases
Conv1D = Convolution1D
Conv2D = Convolution2D
Conv3D = Convolution3D
Deconv2D = Deconvolution2D
AtrousConv1D = AtrousConvolution1D
AtrousConv2D = AtrousConvolution2D
SeparableConv2D = SeparableConvolution2D
+113 -22
Ver Arquivo
@@ -7,14 +7,13 @@ import numpy as np
import copy
import inspect
import types as python_types
import marshal
import sys
import warnings
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..engine import InputSpec, Layer, Merge
from ..regularizers import ActivityRegularizer
from ..utils.generic_utils import func_dump, func_load
class Masking(Layer):
@@ -82,9 +81,13 @@ class Dropout(Layer):
self.supports_masking = True
super(Dropout, self).__init__(**kwargs)
def _get_noise_shape(self, x):
return None
def call(self, x, mask=None):
if 0. < self.p < 1.:
x = K.in_train_phase(K.dropout(x, level=self.p), x)
noise_shape = self._get_noise_shape(x)
x = K.in_train_phase(K.dropout(x, self.p, noise_shape), x)
return x
def get_config(self):
@@ -93,6 +96,101 @@ class Dropout(Layer):
return dict(list(base_config.items()) + list(config.items()))
class SpatialDropout2D(Dropout):
'''This version performs the same function as Dropout, however it drops
entire 2D feature maps instead of individual elements. If adjacent pixels
within feature maps are strongly correlated (as is normally the case in
early convolution layers) then regular dropout will not regularize the
activations and will otherwise just result in an effective learning rate
decrease. In this case, SpatialDropout2D will help promote independence
between feature maps and should be used instead.
# Arguments
p: float between 0 and 1. Fraction of the input units to drop.
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".
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Output shape
Same as input
# References
- [Efficient Object Localization Using Convolutional Networks](https://arxiv.org/pdf/1411.4280.pdf)
'''
def __init__(self, p, dim_ordering='default', **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
super(SpatialDropout2D, self).__init__(p, **kwargs)
def _get_noise_shape(self, x):
input_shape = K.shape(x)
if self.dim_ordering == 'th':
noise_shape = (input_shape[0], input_shape[1], 1, 1)
elif self.dim_ordering == 'tf':
noise_shape = (input_shape[0], 1, 1, input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
return noise_shape
class SpatialDropout3D(Dropout):
'''This version performs the same function as Dropout, however it drops
entire 3D feature maps instead of individual elements. If adjacent voxels
within feature maps are strongly correlated (as is normally the case in
early convolution layers) then regular dropout will not regularize the
activations and will otherwise just result in an effective learning rate
decrease. In this case, SpatialDropout3D will help promote independence
between feature maps and should be used instead.
# Arguments
p: float between 0 and 1. Fraction of the input units to drop.
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".
# Input shape
5D tensor with shape:
`(samples, channels, dim1, dim2, dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, dim1, dim2, dim3, channels)` if dim_ordering='tf'.
# Output shape
Same as input
# References
- [Efficient Object Localization Using Convolutional Networks](https://arxiv.org/pdf/1411.4280.pdf)
'''
def __init__(self, p, dim_ordering='default', **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
super(SpatialDropout3D, self).__init__(p, **kwargs)
def _get_noise_shape(self, x):
input_shape = K.shape(x)
if self.dim_ordering == 'th':
noise_shape = (input_shape[0], input_shape[1], 1, 1, 1)
elif self.dim_ordering == 'tf':
noise_shape = (input_shape[0], 1, 1, 1, input_shape[4])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
return noise_shape
class Activation(Layer):
'''Applies an activation function to an output.
@@ -385,16 +483,16 @@ class Lambda(Layer):
# Arguments
function: The function to be evaluated.
Takes one argument: the output of previous layer
Takes input tensor as first argument.
output_shape: Expected output shape from function.
Can be a tuple or function.
If a tuple, it only specifies the first dimension onward;
If a tuple, it only specifies the first dimension onward;
sample dimension is assumed either the same as the input:
`output_shape = (input_shape[0], ) + output_shape`
or, the input is `None` and the sample dimension is also `None`:
`output_shape = (None, ) + output_shape`
If a function, it specifies the entire shape as a function of
the input shape: `output_shape = f(input_shape)`
If a function, it specifies the entire shape as a function of the
input shape: `output_shape = f(input_shape)`
arguments: optional dictionary of keyword arguments to be passed
to the function.
@@ -439,7 +537,10 @@ class Lambda(Layer):
# otherwise, we default to the input shape
return input_shape
elif type(self._output_shape) in {tuple, list}:
nb_samples = input_shape[0] if input_shape else None
if type(input_shape) is list:
nb_samples = input_shape[0][0]
else:
nb_samples = input_shape[0] if input_shape else None
return (nb_samples,) + tuple(self._output_shape)
else:
shape = self._output_shape(input_shape)
@@ -455,23 +556,15 @@ class Lambda(Layer):
return self.function(x, **arguments)
def get_config(self):
py3 = sys.version_info[0] == 3
if isinstance(self.function, python_types.LambdaType):
if py3:
function = marshal.dumps(self.function.__code__).decode('raw_unicode_escape')
else:
function = marshal.dumps(self.function.func_code).decode('raw_unicode_escape')
function = func_dump(self.function)
function_type = 'lambda'
else:
function = self.function.__name__
function_type = 'function'
if isinstance(self._output_shape, python_types.LambdaType):
if py3:
output_shape = marshal.dumps(self._output_shape.__code__).decode('raw_unicode_escape')
else:
output_shape = marshal.dumps(self._output_shape.func_code).decode('raw_unicode_escape')
output_shape = func_dump(self._output_shape)
output_shape_type = 'lambda'
elif callable(self._output_shape):
output_shape = self._output_shape.__name__
@@ -494,8 +587,7 @@ class Lambda(Layer):
if function_type == 'function':
function = globals()[config['function']]
elif function_type == 'lambda':
function = marshal.loads(config['function'].encode('raw_unicode_escape'))
function = python_types.FunctionType(function, globals())
function = func_load(config['function'], globs=globals())
else:
raise Exception('Unknown function type: ' + function_type)
@@ -503,8 +595,7 @@ class Lambda(Layer):
if output_shape_type == 'function':
output_shape = globals()[config['output_shape']]
elif output_shape_type == 'lambda':
output_shape = marshal.loads(config['output_shape'].encode('raw_unicode_escape'))
output_shape = python_types.FunctionType(output_shape, globals())
output_shape = func_load(config['output_shape'], globs=globals())
else:
output_shape = config['output_shape']
+2
Ver Arquivo
@@ -125,6 +125,8 @@ class Embedding(Layer):
return (input_shape[0], input_length, self.output_dim)
def call(self, x, mask=None):
if K.dtype(x) != 'int32':
x = K.cast(x, 'int32')
if 0. < self.dropout < 1.:
retain_p = 1. - self.dropout
B = K.random_binomial((self.input_dim,), p=retain_p) * (1. / retain_p)
+26 -16
Ver Arquivo
@@ -8,14 +8,17 @@ from ..utils.np_utils import conv_output_length
class LocallyConnected1D(Layer):
'''LocallyConnected1D layer works almost the same as Convolution1D layer,
except that weights are unshared, that is, a different set of filters is
applied at each different patch of the input. When using this layer as the
first layer in a model, either provide the keyword argument `input_dim`
'''The `LocallyConnected1D` layer works similarly to
the `Convolution1D` layer, except that weights are unshared,
that is, a different set of filters is applied at each different patch
of the input.
When using this layer as the first layer in a model,
either provide the keyword argument `input_dim`
(int, e.g. 128 for sequences of 128-dimensional vectors), or `input_shape`
(tuple of integers, e.g. (10, 128) for sequences of 10 vectors of
128-dimensional vectors). Also, you will need to fix shape of the previous
layer, since the weights can only be defined with determined output shape.
(tuple of integers, e.g. `input_shape=(10, 128)`
for sequences of 10 vectors of 128-dimensional vectors).
Also, note that this layer can only be used with
a fully-specified input shape (`None` dimensions not allowed).
# Example
```python
@@ -28,6 +31,7 @@ class LocallyConnected1D(Layer):
model.add(LocallyConnected1D(32, 3))
# now model.output_shape == (None, 6, 32)
```
# Arguments
nb_filter: Dimensionality of the output.
filter_length: The extension (spatial or temporal) of each filter.
@@ -62,8 +66,10 @@ class LocallyConnected1D(Layer):
This argument is required if you are going to connect
`Flatten` then `Dense` layers upstream
(without it, the shape of the dense outputs cannot be computed).
# Input shape
3D tensor with shape: `(samples, steps, input_dim)`.
# Output shape
3D tensor with shape: `(samples, new_steps, nb_filter)`.
`steps` value might have changed due to padding.
@@ -75,7 +81,7 @@ class LocallyConnected1D(Layer):
W_constraint=None, b_constraint=None,
bias=True, input_dim=None, input_length=None, **kwargs):
if border_mode != 'valid':
raise Exception('Invalid border mode for Convolution2D '
raise Exception('Invalid border mode for LocallyConnected1D '
'(only "valid" is supported):', border_mode)
self.nb_filter = nb_filter
self.filter_length = filter_length
@@ -180,14 +186,16 @@ class LocallyConnected1D(Layer):
class LocallyConnected2D(Layer):
'''LocallyConnected2D layer works almost the same as Convolution2D layer,
except that weights are unshared, that is, a different set of filters is
applied at each different patch of the input. When using this layer as the
'''The `LocallyConnected2D` layer works similarly
to the `Convolution2D` layer, except that weights are unshared,
that is, a different set of filters is applied at each
different patch of the input.
When using this layer as the
first layer in a model, provide the keyword argument `input_shape` (tuple
of integers, does not include the sample axis), e.g.
`input_shape=(3, 128, 128)` for 128x128 RGB pictures. Also, you will need
to fix shape of the previous layer, since the weights can only be defined
with determined output shape.
`input_shape=(3, 128, 128)` for 128x128 RGB pictures.
Also, note that this layer can only be used with
a fully-specified input shape (`None` dimensions not allowed).
# Examples
```python
@@ -251,12 +259,14 @@ class LocallyConnected2D(Layer):
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
dim_ordering=K.image_dim_ordering(),
dim_ordering='default',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if border_mode != 'valid':
raise Exception('Invalid border mode for Convolution2D '
raise Exception('Invalid border mode for LocallyConnected2D '
'(only "valid" is supported):', border_mode)
self.nb_filter = nb_filter
self.nb_row = nb_row
+2 -1
Ver Arquivo
@@ -1,6 +1,7 @@
from __future__ import absolute_import
from ..engine import Layer
from .. import backend as K
import numpy as np
class GaussianNoise(Layer):
@@ -71,7 +72,7 @@ class GaussianDropout(Layer):
def call(self, x, mask=None):
if 0 < self.p < 1:
noise_x = x * K.random_normal(shape=K.shape(x), mean=1.0,
std=K.sqrt(self.p / (1.0 - self.p)))
std=np.sqrt(self.p / (1.0 - self.p)))
return K.in_train_phase(noise_x, x)
return x
+40 -29
Ver Arquivo
@@ -1,5 +1,5 @@
from ..engine import Layer, InputSpec
from .. import initializations
from .. import initializations, regularizers
from .. import backend as K
@@ -35,6 +35,7 @@ class BatchNormalization(Layer):
weights: Initialization weights.
List of 2 Numpy arrays, with shapes:
`[(input_shape,), (input_shape,)]`
Note that the order of this list is [gamma, beta, mean, std]
beta_init: name of initialization function for shift parameter
(see [initializations](../initializations.md)), or alternatively,
Theano/TensorFlow function to use for weights initialization.
@@ -43,6 +44,10 @@ class BatchNormalization(Layer):
[initializations](../initializations.md)), or alternatively,
Theano/TensorFlow function to use for weights initialization.
This parameter is only relevant if you don't pass a `weights` argument.
gamma_regularizer: instance of [WeightRegularizer](../regularizers.md)
(eg. L1 or L2 regularization), applied to the gamma vector.
beta_regularizer: instance of [WeightRegularizer](../regularizers.md),
applied to the beta vector.
# Input shape
Arbitrary. Use the keyword argument `input_shape`
@@ -55,8 +60,9 @@ class BatchNormalization(Layer):
# References
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](http://jmlr.org/proceedings/papers/v37/ioffe15.html)
'''
def __init__(self, epsilon=1e-6, mode=0, axis=-1, momentum=0.9,
weights=None, beta_init='zero', gamma_init='one', **kwargs):
def __init__(self, epsilon=1e-5, mode=0, axis=-1, momentum=0.99,
weights=None, beta_init='zero', gamma_init='one',
gamma_regularizer=None, beta_regularizer=None, **kwargs):
self.supports_masking = True
self.beta_init = initializations.get(beta_init)
self.gamma_init = initializations.get(gamma_init)
@@ -64,6 +70,8 @@ class BatchNormalization(Layer):
self.mode = mode
self.axis = axis
self.momentum = momentum
self.gamma_regularizer = regularizers.get(gamma_regularizer)
self.beta_regularizer = regularizers.get(beta_regularizer)
self.initial_weights = weights
if self.mode == 0:
self.uses_learning_phase = True
@@ -77,6 +85,15 @@ class BatchNormalization(Layer):
self.beta = self.beta_init(shape, name='{}_beta'.format(self.name))
self.trainable_weights = [self.gamma, self.beta]
self.regularizers = []
if self.gamma_regularizer:
self.gamma_regularizer.set_param(self.gamma)
self.regularizers.append(self.gamma_regularizer)
if self.beta_regularizer:
self.beta_regularizer.set_param(self.beta)
self.regularizers.append(self.beta_regularizer)
self.running_mean = K.zeros(shape,
name='{}_running_mean'.format(self.name))
self.running_std = K.ones(shape,
@@ -99,17 +116,10 @@ class BatchNormalization(Layer):
broadcast_shape = [1] * len(input_shape)
broadcast_shape[self.axis] = input_shape[self.axis]
# # case: train mode (uses stats of the current batch)
# mean = K.mean(x, axis=reduction_axes)
# brodcast_mean = K.reshape(mean, broadcast_shape)
# std = K.mean(K.square(x - brodcast_mean) + self.epsilon, axis=reduction_axes)
# std = K.sqrt(std)
# brodcast_std = K.reshape(std, broadcast_shape)
if self.mode == 2:
x_normed, mean, std = K.normalize_batch_in_training(x, self.gamma, self.beta, reduction_axes, epsilon=self.epsilon)
mean_update = self.momentum * self.running_mean + (1 - self.momentum) * mean
std_update = self.momentum * self.running_std + (1 - self.momentum) * std
x_normed, mean, std = K.normalize_batch_in_training(
x, self.gamma, self.beta, reduction_axes,
epsilon=self.epsilon)
else:
# mode 0
if self.called_with not in {None, x}:
@@ -123,29 +133,28 @@ class BatchNormalization(Layer):
'(see docs for a description of '
'the behavior).')
self.called_with = x
x_normed, mean, std = K.normalize_batch_in_training(x, self.gamma, self.beta, reduction_axes, epsilon=self.epsilon)
mean_update = self.momentum * self.running_mean + (1 - self.momentum) * mean
std_update = self.momentum * self.running_std + (1 - self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
x_normed, mean, std = K.normalize_batch_in_training(
x, self.gamma, self.beta, reduction_axes,
epsilon=self.epsilon)
if sorted(reduction_axes) == range(K.ndim(x))[:-1]:
x_normed_running = K.batch_normalization(x, self.running_mean,
self.running_std,
self.beta,
self.gamma,
epsilon=self.epsilon)
self.updates = [K.moving_average_update(self.running_mean, mean, self.momentum),
K.moving_average_update(self.running_std, std, self.momentum)]
if K.backend() == 'tensorflow' and sorted(reduction_axes) == range(K.ndim(x))[:-1]:
x_normed_running = K.batch_normalization(
x, self.running_mean, self.running_std,
self.beta, self.gamma,
epsilon=self.epsilon)
else:
# need broadcasting
broadcast_running_mean = K.reshape(self.running_mean, broadcast_shape)
broadcast_running_std = K.reshape(self.running_std, broadcast_shape)
broadcast_beta = K.reshape(self.beta, broadcast_shape)
broadcast_gamma = K.reshape(self.gamma, broadcast_shape)
x_normed_running = K.batch_normalization(x, broadcast_running_mean,
broadcast_running_std,
broadcast_beta,
broadcast_gamma,
epsilon=self.epsilon)
x_normed_running = K.batch_normalization(
x, broadcast_running_mean, broadcast_running_std,
broadcast_beta, broadcast_gamma,
epsilon=self.epsilon)
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
@@ -162,6 +171,8 @@ class BatchNormalization(Layer):
config = {"epsilon": self.epsilon,
"mode": self.mode,
"axis": self.axis,
"gamma_regularizer": self.gamma_regularizer.get_config() if self.gamma_regularizer else None,
"beta_regularizer": self.beta_regularizer.get_config() if self.beta_regularizer else None,
"momentum": self.momentum}
base_config = super(BatchNormalization, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+135 -8
Ver Arquivo
@@ -61,8 +61,9 @@ class MaxPooling1D(_Pooling1D):
3D tensor with shape: `(samples, downsampled_steps, features)`.
# Arguments
pool_length: factor by which to downscale. 2 will halve the input.
stride: integer, or None. Stride value.
pool_length: size of the region to which max pooling is applied
stride: integer, or None. factor by which to downscale.
2 will halve the input.
If None, it will default to `pool_length`.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
@@ -114,8 +115,10 @@ class _Pooling2D(Layer):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(_Pooling2D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.pool_size = tuple(pool_size)
if strides is None:
strides = self.pool_size
@@ -199,7 +202,7 @@ class MaxPooling2D(_Pooling2D):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(MaxPooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -241,7 +244,7 @@ class AveragePooling2D(_Pooling2D):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(AveragePooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -257,8 +260,10 @@ class _Pooling3D(Layer):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(_Pooling3D, self).__init__(**kwargs)
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.pool_size = tuple(pool_size)
if strides is None:
strides = self.pool_size
@@ -344,7 +349,7 @@ class MaxPooling3D(_Pooling3D):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(MaxPooling3D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -384,7 +389,7 @@ class AveragePooling3D(_Pooling3D):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering=K.image_dim_ordering(), **kwargs):
dim_ordering='default', **kwargs):
super(AveragePooling3D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -393,3 +398,125 @@ class AveragePooling3D(_Pooling3D):
output = K.pool3d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='avg')
return output
class _GlobalPooling1D(Layer):
def __init__(self, **kwargs):
super(_GlobalPooling1D, self).__init__(**kwargs)
self.input_spec = [InputSpec(ndim=3)]
def get_output_shape_for(self, input_shape):
return (input_shape[0], input_shape[2])
def call(self, x, mask=None):
raise NotImplementedError
class GlobalAveragePooling1D(_GlobalPooling1D):
'''Global average pooling operation for temporal data.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
2D tensor with shape: `(samples, features)`.
'''
def call(self, x, mask=None):
return K.mean(x, axis=1)
class GlobalMaxPooling1D(_GlobalPooling1D):
'''Global max pooling operation for temporal data.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
2D tensor with shape: `(samples, features)`.
'''
def call(self, x, mask=None):
return K.max(x, axis=1)
class _GlobalPooling2D(Layer):
def __init__(self, dim_ordering='default', **kwargs):
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)]
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'tf':
return (input_shape[0], input_shape[3])
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(_GlobalPooling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class GlobalAveragePooling2D(_GlobalPooling2D):
'''Global average pooling operation for spatial 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 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".
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Output shape
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])
else:
return K.mean(x, axis=[2, 3])
class GlobalMaxPooling2D(_GlobalPooling2D):
'''Global max pooling operation for spatial 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 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".
# Input shape
4D tensor with shape:
`(samples, channels, rows, cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, rows, cols, channels)` if dim_ordering='tf'.
# Output shape
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])
else:
return K.max(x, axis=[2, 3])
+19 -37
Ver Arquivo
@@ -12,13 +12,10 @@ def time_distributed_dense(x, w, b=None, dropout=None,
'''Apply y.w + b for every temporal slice y of x.
'''
if not input_dim:
# won't work with TensorFlow
input_dim = K.shape(x)[2]
if not timesteps:
# won't work with TensorFlow
timesteps = K.shape(x)[1]
if not output_dim:
# won't work with TensorFlow
output_dim = K.shape(w)[1]
if dropout is not None and 0. < dropout < 1.:
@@ -30,12 +27,15 @@ def time_distributed_dense(x, w, b=None, dropout=None,
# collapse time dimension and batch dimension together
x = K.reshape(x, (-1, input_dim))
x = K.dot(x, w)
if b:
x = x + b
# reshape to 3D tensor
x = K.reshape(x, (-1, timesteps, output_dim))
if K.backend() == 'tensorflow':
x = K.reshape(x, K.pack([-1, timesteps, output_dim]))
x.set_shape([None, None, output_dim])
else:
x = K.reshape(x, (-1, timesteps, output_dim))
return x
@@ -120,14 +120,10 @@ class Recurrent(Layer):
use an [Embedding](embeddings.md) layer with the `mask_zero` parameter
set to `True`.
# TensorFlow warning
For the time being, when using the TensorFlow backend,
the number of timesteps used must be specified in your model.
Make sure to pass an `input_length` int argument to your
recurrent layer (if it comes first in your model),
or to pass a complete `input_shape` argument to the first layer
in your model otherwise.
# Note on performance
You are likely to see better performance with RNNs in Theano compared
to TensorFlow. Additionally, when using TensorFlow, it is often
preferable to set `unroll=True` for better performance.
# Note on using statefulness in RNNs
You can set RNN layers to be 'stateful', which means that the states
@@ -139,16 +135,15 @@ class Recurrent(Layer):
To enable statefulness:
- specify `stateful=True` in the layer constructor.
- specify a fixed batch size for your model, by passing
a `batch_input_shape=(...)` to the first layer in your model.
if sequential model:
a `batch_input_shape=(...)` to the first layer in your model.
else for functional model with 1 or more Input layers:
a `batch_shape=(...)` to all the first layers in your model.
This is the expected shape of your inputs *including the batch size*.
It should be a tuple of integers, e.g. `(32, 10, 100)`.
To reset the states of your model, call `.reset_states()` on either
a specific layer, or on your entire model.
# Note on using dropout with TensorFlow
When using the TensorFlow backend, specify a fixed batch size for your model
following the notes on statefulness RNNs.
'''
def __init__(self, weights=None,
return_sequences=False, go_backwards=False, stateful=False,
@@ -204,19 +199,6 @@ class Recurrent(Layer):
# note that the .build() method of subclasses MUST define
# self.input_spec with a complete input shape.
input_shape = self.input_spec[0].shape
if K._BACKEND == 'tensorflow':
if not input_shape[1]:
raise Exception('When using TensorFlow, you should define '
'explicitly the number of timesteps of '
'your sequences.\n'
'If your first layer is an Embedding, '
'make sure to pass it an "input_length" '
'argument. Otherwise, make sure '
'the first layer has '
'an "input_shape" or "batch_input_shape" '
'argument, including the time axis. '
'Found input shape at layer ' + self.name +
': ' + str(input_shape))
if self.stateful:
initial_states = self.states
else:
@@ -372,7 +354,7 @@ class SimpleRNN(Recurrent):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
ones = K.tile(ones, (1, self.output_dim))
B_U = K.in_train_phase(K.dropout(ones, self.dropout_U), ones)
constants.append(B_U)
else:
@@ -381,7 +363,7 @@ class SimpleRNN(Recurrent):
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
ones = K.tile(ones, (1, input_dim))
B_W = K.in_train_phase(K.dropout(ones, self.dropout_W), ones)
constants.append(B_W)
else:
@@ -585,7 +567,7 @@ class GRU(Recurrent):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
ones = K.tile(ones, (1, self.output_dim))
B_U = [K.in_train_phase(K.dropout(ones, self.dropout_U), ones) for _ in range(3)]
constants.append(B_U)
else:
@@ -595,7 +577,7 @@ class GRU(Recurrent):
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
ones = K.tile(ones, (1, input_dim))
B_W = [K.in_train_phase(K.dropout(ones, self.dropout_W), ones) for _ in range(3)]
constants.append(B_W)
else:
@@ -825,7 +807,7 @@ class LSTM(Recurrent):
constants = []
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
ones = K.tile(ones, (1, self.output_dim))
B_U = [K.in_train_phase(K.dropout(ones, self.dropout_U), ones) for _ in range(4)]
constants.append(B_U)
else:
@@ -835,7 +817,7 @@ class LSTM(Recurrent):
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
ones = K.tile(ones, (1, input_dim))
B_W = [K.in_train_phase(K.dropout(ones, self.dropout_W), ones) for _ in range(4)]
constants.append(B_W)
else:
+139 -11
Ver Arquivo
@@ -20,6 +20,13 @@ class Wrapper(Layer):
self.regularizers = getattr(self.layer, 'regularizers', [])
self.constraints = getattr(self.layer, 'constraints', {})
# properly attribute the current layer to
# regularizers that need access to it
# (e.g. ActivityRegularizer).
for regularizer in self.regularizers:
if hasattr(regularizer, 'set_layer'):
regularizer.set_layer(self)
def get_weights(self):
weights = self.layer.get_weights()
return weights
@@ -86,17 +93,6 @@ class TimeDistributed(Wrapper):
def build(self, input_shape):
assert len(input_shape) >= 3
self.input_spec = [InputSpec(shape=input_shape)]
if K._BACKEND == 'tensorflow':
if not input_shape[1]:
raise Exception('When using TensorFlow, you should define '
'explicitly the number of timesteps of '
'your sequences.\n'
'If your first layer is an Embedding, '
'make sure to pass it an "input_length" '
'argument. Otherwise, make sure '
'the first layer has '
'an "input_shape" or "batch_input_shape" '
'argument, including the time axis.')
child_input_shape = (input_shape[0],) + input_shape[2:]
if not self.layer.built:
self.layer.build(child_input_shape)
@@ -133,3 +129,135 @@ class TimeDistributed(Wrapper):
output_shape = self.get_output_shape_for(input_shape)
y = K.reshape(y, (-1, input_length) + output_shape[2:])
return y
class Bidirectional(Wrapper):
''' Bidirectional wrapper for RNNs.
# Arguments:
layer: `Recurrent` instance.
merge_mode: Mode by which outputs of the
forward and backward RNNs will be combined.
One of {'sum', 'mul', 'concat', 'ave', None}.
If None, the outputs will not be combined,
they will be returned as a list.
# Examples:
```python
model = Sequential()
model.add(Bidirectional(LSTM(10, return_sequences=True), input_shape=(5, 10)))
model.add(Bidirectional(LSTM(10)))
model.add(Dense(5))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
```
'''
def __init__(self, layer, merge_mode='concat', weights=None, **kwargs):
if merge_mode not in ['sum', 'mul', 'ave', 'concat', None]:
raise ValueError('Invalid merge mode. '
'Merge mode should be one of '
'{"sum", "mul", "ave", "concat", None}')
self.forward_layer = layer
config = layer.get_config()
config['go_backwards'] = not config['go_backwards']
self.backward_layer = layer.__class__.from_config(config)
self.forward_layer.name = 'forward_' + self.forward_layer.name
self.backward_layer.name = 'backward_' + self.backward_layer.name
self.merge_mode = merge_mode
if weights:
nw = len(weights)
self.forward_layer.initial_weights = weights[:nw // 2]
self.backward_layer.initial_weights = weights[nw // 2:]
self.stateful = layer.stateful
self.return_sequences = layer.return_sequences
self.supports_masking = True
super(Bidirectional, self).__init__(layer, **kwargs)
def get_weights(self):
return self.forward_layer.get_weights() + self.backward_layer.get_weights()
def set_weights(self, weights):
nw = len(weights)
self.forward_layer.set_weights(weights[:nw // 2])
self.backward_layer.set_weights(weights[nw // 2:])
def get_output_shape_for(self, input_shape):
if self.merge_mode in ['sum', 'ave', 'mul']:
return self.forward_layer.get_output_shape_for(input_shape)
elif self.merge_mode == 'concat':
shape = list(self.forward_layer.get_output_shape_for(input_shape))
shape[-1] *= 2
return tuple(shape)
elif self.merge_mode is None:
return [self.forward_layer.get_output_shape_for(input_shape)] * 2
def call(self, X, mask=None):
Y = self.forward_layer.call(X, mask)
Y_rev = self.backward_layer.call(X, mask)
if self.return_sequences:
Y_rev = K.reverse(Y_rev, 1)
if self.merge_mode == 'concat':
return K.concatenate([Y, Y_rev])
elif self.merge_mode == 'sum':
return Y + Y_rev
elif self.merge_mode == 'ave':
return (Y + Y_rev) / 2
elif self.merge_mode == 'mul':
return Y * Y_rev
elif self.merge_mode is None:
return [Y, Y_rev]
def reset_states(self):
self.forward_layer.reset_states()
self.backward_layer.reset_states()
def build(self, input_shape):
self.forward_layer.build(input_shape)
self.backward_layer.build(input_shape)
def compute_mask(self, input, mask):
if self.return_sequences:
if not self.merge_mode:
return [mask, mask]
else:
return mask
else:
return None
@property
def trainable_weights(self):
if hasattr(self.forward_layer, 'trainable_weights'):
return self.forward_layer.trainable_weights + self.backward_layer.trainable_weights
return []
@property
def non_trainable_weights(self):
if hasattr(self.forward_layer, 'non_trainable_weights'):
return self.forward_layer.non_trainable_weights + self.backward_layer.non_trainable_weights
return []
@property
def updates(self):
if hasattr(self.forward_layer, 'updates'):
return self.forward_layer.updates + self.backward_layer.updates
return []
@property
def regularizers(self):
if hasattr(self.forward_layer, 'regularizers'):
return self.forward_layer.regularizers + self.backward_layer.regularizers
return []
@property
def constraints(self):
_constraints = {}
if hasattr(self.forward_layer, 'constraints'):
_constraints.update(self.forward_layer.constraints)
_constraints.update(self.backward_layer.constraints)
return _constraints
def get_config(self):
config = {"merge_mode": self.merge_mode}
base_config = super(Bidirectional, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+20
Ver Arquivo
@@ -71,6 +71,26 @@ def cosine_proximity(y_true, y_pred):
return -K.mean(y_true * y_pred)
def matthews_correlation(y_true, y_pred):
''' Matthews correlation coefficient
'''
y_pred_pos = K.round(K.clip(y_pred, 0, 1))
y_pred_neg = 1 - y_pred_pos
y_pos = K.round(K.clip(y_true, 0, 1))
y_neg = 1 - y_pos
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)
numerator = (tp * tn - fp * fn)
denominator = K.sqrt((tp + fp) * (tp + fn) * (tn + fp) * (tn + fn))
return numerator / (denominator + K.epsilon())
# aliases
mse = MSE = mean_squared_error
mae = MAE = mean_absolute_error
+195 -4
Ver Arquivo
@@ -1,13 +1,174 @@
from __future__ import print_function
import warnings
import copy
import json
import os
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 .optimizers import optimizer_from_config
from .legacy.models import Graph
def save_model(model, filepath, overwrite=True):
def get_json_type(obj):
# if obj is a serializable Keras class instance
# e.g. optimizer, layer
if hasattr(obj, 'get_config'):
return {'class_name': obj.__class__.__name__,
'config': obj.get_config()}
# if obj is any numpy type
if type(obj).__module__ == np.__name__:
return obj.item()
# misc functions (e.g. loss function)
if hasattr(obj, '__call__'):
return obj.__name__
# if obj is a python 'type'
if type(obj).__name__ == type.__name__:
return obj.__name__
raise TypeError('Not JSON Serializable:', obj)
import h5py
from keras import __version__ as keras_version
# if file exists and should not be overwritten
if not overwrite and os.path.isfile(filepath):
proceed = ask_to_proceed_with_overwrite(filepath)
if not proceed:
return
f = h5py.File(filepath, 'w')
f.attrs['keras_version'] = str(keras_version).encode('utf8')
f.attrs['model_config'] = json.dumps({
'class_name': model.__class__.__name__,
'config': model.get_config()
}, default=get_json_type).encode('utf8')
model_weights_group = f.create_group('model_weights')
model.save_weights_to_hdf5_group(model_weights_group)
if hasattr(model, 'optimizer'):
f.attrs['training_config'] = json.dumps({
'optimizer_config': {
'class_name': model.optimizer.__class__.__name__,
'config': model.optimizer.get_config()
},
'loss': model.loss,
'metrics': model.metrics,
'sample_weight_mode': model.sample_weight_mode,
'loss_weights': model.loss_weights,
}, default=get_json_type).encode('utf8')
# save optimizer weights
symbolic_weights = getattr(model.optimizer, 'weights')
if symbolic_weights:
optimizer_weights_group = f.create_group('optimizer_weights')
weight_values = K.batch_get_value(symbolic_weights)
weight_names = []
for i, (w, val) in enumerate(zip(symbolic_weights, weight_values)):
if hasattr(w, 'name') and w.name:
name = str(w.name)
else:
name = 'param_' + str(i)
weight_names.append(name.encode('utf8'))
optimizer_weights_group.attrs['weight_names'] = weight_names
for name, val in zip(weight_names, weight_values):
param_dset = optimizer_weights_group.create_dataset(
name,
val.shape,
dtype=val.dtype)
if not val.shape:
# scalar
param_dset[()] = val
else:
param_dset[:] = val
f.flush()
f.close()
def load_model(filepath, custom_objects={}):
def deserialize(obj):
if type(obj) is list:
deserialized = []
for value in obj:
if value in custom_objects:
deserialized.append(custom_objects[value])
else:
deserialized.append(value)
return deserialized
if type(obj) is dict:
deserialized = {}
for key, value in obj.items():
if value in custom_objects:
deserialized[key] = custom_objects[value]
else:
deserialized[key] = value
return deserialized
if obj in custom_objects:
return custom_objects[obj]
return obj
import h5py
f = h5py.File(filepath, mode='r')
# instantiate model
model_config = f.attrs.get('model_config')
if model_config is None:
raise ValueError('No model found in config file.')
model_config = json.loads(model_config.decode('utf-8'))
model = model_from_config(model_config, custom_objects=custom_objects)
# set weights
model.load_weights_from_hdf5_group(f['model_weights'])
# instantiate optimizer
training_config = f.attrs.get('training_config')
if training_config is None:
warnings.warn('No training configuration found in save file: '
'the model was *not* compiled. Compile it manually.')
f.close()
return model
training_config = json.loads(training_config.decode('utf-8'))
optimizer_config = training_config['optimizer_config']
optimizer = optimizer_from_config(optimizer_config)
# recover loss functions and metrics
loss = deserialize(training_config['loss'])
metrics = deserialize(training_config['metrics'])
sample_weight_mode = training_config['sample_weight_mode']
loss_weights = training_config['loss_weights']
# compile model
model.compile(optimizer=optimizer,
loss=loss,
metrics=metrics,
loss_weights=loss_weights,
sample_weight_mode=sample_weight_mode)
# set optimizer weights
if 'optimizer_weights' in f:
# build train function (to get weight updates)
if model.__class__.__name__ == 'Sequential':
model.model._make_train_function()
else:
model._make_train_function()
optimizer_weights_group = f['optimizer_weights']
optimizer_weight_names = [n.decode('utf8') for n in optimizer_weights_group.attrs['weight_names']]
optimizer_weight_values = [optimizer_weights_group[n] for n in optimizer_weight_names]
model.optimizer.set_weights(optimizer_weight_values)
f.close()
return model
def model_from_config(config, custom_objects={}):
from keras.utils.layer_utils import layer_from_config
if isinstance(config, list):
@@ -77,6 +238,7 @@ class Sequential(Model):
self.model = None # internal Model instance
self.inputs = [] # tensors
self.outputs = [] # tensors (length 1)
self.trainable = True
# model attributes
self.inbound_nodes = []
@@ -172,7 +334,27 @@ class Sequential(Model):
else:
self.layers[-1].outbound_nodes = []
self.outputs = [self.layers[-1].output]
# update self.inbound_nodes
self.inbound_nodes[0].output_tensors = self.outputs
self.inbound_nodes[0].output_shapes = [self.outputs[0]._keras_shape]
self.built = False
self._flattened_layers = None
def get_layer(self, name=None, index=None):
'''Returns a layer based on either its name (unique)
or its index in the graph. Indices are based on
order of horizontal graph traversal (bottom-up).
# Arguments
name: string, name of layer.
index: integer, index of layer.
# Returns
A layer instance.
'''
if not self.built:
self.build()
return self.model.get_layer(name, index)
def call(self, x, mask=None):
if not self.built:
@@ -257,13 +439,19 @@ class Sequential(Model):
@property
def trainable_weights(self):
if not self.trainable:
return []
# support for legacy behavior
return self._gather_list_attr('trainable_weights')
@property
def non_trainable_weights(self):
# support for legacy behavior
return self._gather_list_attr('non_trainable_weights')
weights = self._gather_list_attr('non_trainable_weights')
if not self.trainable:
trainable_weights = self._gather_list_attr('trainable_weights')
return trainable_weights + weights
return weights
@property
def updates(self):
@@ -303,7 +491,7 @@ class Sequential(Model):
'''
# support for legacy behavior
for layer in self.flattened_layers:
nb_param = len(layer.get_weights())
nb_param = len(layer.weights)
layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
@@ -359,6 +547,9 @@ class Sequential(Model):
**kwargs)
self.optimizer = self.model.optimizer
self.loss = self.model.loss
self.loss_weights = self.model.loss_weights
self.metrics = self.model.metrics
self.metrics_tensors = self.model.metrics_tensors
self.metrics_names = self.model.metrics_names
self.sample_weight_mode = self.model.sample_weight_mode
@@ -627,7 +818,7 @@ class Sequential(Model):
max_q_size: maximum size for the generator queue
nb_worker: maximum number of processes to spin up
pickle_safe: if True, use process based threading. Note that because
this implementation relies on multiprocessing, you should not pass non
this implementation relies on multiprocessing, you should not pass
non picklable arguments to the generator as they can't be passed
easily to children processes.
@@ -686,7 +877,7 @@ class Sequential(Model):
'''Evaluates the model on a data generator. The generator should
return the same kind of data as accepted by `test_on_batch`.
Arguments:
# Arguments
generator:
generator yielding tuples (inputs, targets)
or (inputs, targets, sample_weights)
+140 -70
Ver Arquivo
@@ -1,6 +1,5 @@
from __future__ import absolute_import
from . import backend as K
import numpy as np
from .utils.generic_utils import get_from_module
from six.moves import zip
@@ -11,8 +10,24 @@ def clip_norm(g, c, n):
return g
def kl_divergence(p, p_hat):
return p_hat - p + p * K.log(p / p_hat)
def optimizer_from_config(config, custom_objects={}):
all_classes = {
'sgd': SGD,
'rmsprop': RMSprop,
'adagrad': Adagrad,
'adadelta': Adadelta,
'adam': Adam,
'adamax': Adamax,
'nadam': Nadam,
}
class_name = config['class_name']
if class_name in custom_objects:
cls = custom_objects[class_name]
else:
if class_name.lower() not in all_classes:
raise ValueError('Optimizer class not found:', class_name)
cls = all_classes[class_name.lower()]
return cls.from_config(config['config'])
class Optimizer(object):
@@ -72,35 +87,35 @@ class Optimizer(object):
output of `get_weights`).
'''
params = self.weights
if len(params) != len(weights):
raise Exception('Provided weight array does not match weights (' +
str(len(params)) + ' optimizer params vs. ' +
str(len(weights)) + ' provided weights)')
for p, w in zip(params, weights):
if K.get_value(p).shape != w.shape:
weight_value_tuples = []
param_values = K.batch_get_value(params)
for pv, p, w in zip(param_values, params, weights):
if pv.shape != w.shape:
raise Exception('Optimizer weight shape ' +
str(K.get_value(p).shape) +
str(pv.shape) +
' not compatible with '
'provided weight shape ' + str(w.shape))
K.set_value(p, w)
weight_value_tuples.append((p, w))
K.batch_set_value(weight_value_tuples)
def get_weights(self):
'''Returns the current weights of the optimizer,
as a list of numpy arrays.
'''
weights = []
for p in self.weights:
weights.append(K.get_value(p))
return weights
return K.batch_get_value(self.weights)
def get_config(self):
config = {'name': self.__class__.__name__}
config = {}
if hasattr(self, 'clipnorm'):
config['clipnorm'] = self.clipnorm
if hasattr(self, 'clipvalue'):
config['clipvalue'] = self.clipvalue
return config
@classmethod
def from_config(cls, config):
return cls(**config)
class SGD(Optimizer):
'''Stochastic gradient descent, with support for momentum,
@@ -120,17 +135,24 @@ class SGD(Optimizer):
self.lr = K.variable(lr)
self.momentum = K.variable(momentum)
self.decay = K.variable(decay)
self.inital_decay = decay
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
lr = self.lr * (1. / (1. + self.decay * self.iterations))
self.updates = [(self.iterations, self.iterations + 1.)]
self.updates = []
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
self.updates .append(K.update_add(self.iterations, 1))
# momentum
self.weights = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
for p, g, m in zip(params, grads, self.weights):
shapes = [K.get_variable_shape(p) for p in params]
moments = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + moments
for p, g, m in zip(params, grads, moments):
v = self.momentum * m - lr * g # velocity
self.updates.append((m, v))
self.updates.append(K.update(m, v))
if self.nesterov:
new_p = p + self.momentum * v - lr * g
@@ -141,7 +163,8 @@ class SGD(Optimizer):
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
@@ -167,30 +190,41 @@ class RMSprop(Optimizer):
lr: float >= 0. Learning rate.
rho: float >= 0.
epsilon: float >= 0. Fuzz factor.
decay: float >= 0. Learning rate decay over each update.
'''
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-8, **kwargs):
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-8, decay=0.,
**kwargs):
super(RMSprop, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
self.rho = K.variable(rho)
self.decay = K.variable(decay)
self.inital_decay = decay
self.iterations = K.variable(0.)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
# accumulators
self.weights = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
shapes = [K.get_variable_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
for p, g, a in zip(params, grads, self.weights):
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
self.updates.append(K.update_add(self.iterations, 1))
for p, g, a in zip(params, grads, accumulators):
# update accumulator
new_a = self.rho * a + (1. - self.rho) * K.square(g)
self.updates.append((a, new_a))
new_p = p - self.lr * g / (K.sqrt(new_a) + self.epsilon)
self.updates.append(K.update(a, new_a))
new_p = p - lr * g / (K.sqrt(new_a) + self.epsilon)
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
@@ -210,27 +244,39 @@ class Adagrad(Optimizer):
# Arguments
lr: float >= 0. Learning rate.
epsilon: float >= 0.
# References
- [Adaptive Subgradient Methods for Online Learning and Stochastic Optimization](http://www.jmlr.org/papers/volume12/duchi11a/duchi11a.pdf)
'''
def __init__(self, lr=0.01, epsilon=1e-8, **kwargs):
def __init__(self, lr=0.01, epsilon=1e-8, decay=0., **kwargs):
super(Adagrad, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
self.decay = K.variable(decay)
self.inital_decay = decay
self.iterations = K.variable(0.)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
# accumulators
self.weights = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
shapes = [K.get_variable_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
for p, g, a in zip(params, grads, self.weights):
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
self.updates.append(K.update_add(self.iterations, 1))
for p, g, a in zip(params, grads, accumulators):
new_a = a + K.square(g) # update accumulator
self.updates.append((a, new_a))
new_p = p - self.lr * g / (K.sqrt(new_a) + self.epsilon)
self.updates.append(K.update(a, new_a))
new_p = p - lr * g / (K.sqrt(new_a) + self.epsilon)
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
@@ -255,36 +301,46 @@ class Adadelta(Optimizer):
# References
- [Adadelta - an adaptive learning rate method](http://arxiv.org/abs/1212.5701)
'''
def __init__(self, lr=1.0, rho=0.95, epsilon=1e-8, **kwargs):
def __init__(self, lr=1.0, rho=0.95, epsilon=1e-8, decay=0.,
**kwargs):
super(Adadelta, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
self.decay = K.variable(decay)
self.inital_decay = decay
self.iterations = K.variable(0.)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
delta_accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
shapes = [K.get_variable_shape(p) for p in params]
accumulators = [K.zeros(shape) for shape in shapes]
delta_accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators + delta_accumulators
self.updates = []
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
self.updates.append(K.update_add(self.iterations, 1))
for p, g, a, d_a in zip(params, grads, accumulators, delta_accumulators):
# update accumulator
new_a = self.rho * a + (1. - self.rho) * K.square(g)
self.updates.append((a, new_a))
self.updates.append(K.update(a, new_a))
# use the new accumulator and the *old* delta_accumulator
update = g * K.sqrt(d_a + self.epsilon) / K.sqrt(new_a + self.epsilon)
new_p = p - self.lr * update
new_p = p - lr * update
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
# update delta_accumulator
new_d_a = self.rho * d_a + (1 - self.rho) * K.square(update)
self.updates.append((d_a, new_d_a))
self.updates.append(K.update(d_a, new_d_a))
return self.updates
def get_config(self):
@@ -309,39 +365,46 @@ class Adam(Optimizer):
- [Adam - A Method for Stochastic Optimization](http://arxiv.org/abs/1412.6980v8)
'''
def __init__(self, lr=0.001, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, **kwargs):
epsilon=1e-8, decay=0., **kwargs):
super(Adam, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0)
self.lr = K.variable(lr)
self.beta_1 = K.variable(beta_1)
self.beta_2 = K.variable(beta_2)
self.decay = K.variable(decay)
self.inital_decay = decay
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations + 1)]
self.updates = [K.update_add(self.iterations, 1)]
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
t = self.iterations + 1
lr_t = self.lr * K.sqrt(1. - K.pow(self.beta_2, t)) / (1. - K.pow(self.beta_1, t))
lr_t = lr * K.sqrt(1. - K.pow(self.beta_2, t)) / (1. - K.pow(self.beta_1, t))
ms = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
vs = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.weights = ms + vs
shapes = [K.get_variable_shape(p) for p in params]
ms = [K.zeros(shape) for shape in shapes]
vs = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + ms + vs
for p, g, m, v in zip(params, grads, ms, vs):
m_t = (self.beta_1 * m) + (1. - self.beta_1) * g
v_t = (self.beta_2 * v) + (1. - self.beta_2) * K.square(g)
p_t = p - lr_t * m_t / (K.sqrt(v_t) + self.epsilon)
self.updates.append((m, m_t))
self.updates.append((v, v_t))
self.updates.append(K.update(m, m_t))
self.updates.append(K.update(v, v_t))
new_p = p_t
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
@@ -368,26 +431,33 @@ class Adamax(Optimizer):
- [Adam - A Method for Stochastic Optimization](http://arxiv.org/abs/1412.6980v8)
'''
def __init__(self, lr=0.002, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, **kwargs):
epsilon=1e-8, decay=0., **kwargs):
super(Adamax, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0.)
self.lr = K.variable(lr)
self.beta_1 = K.variable(beta_1)
self.beta_2 = K.variable(beta_2)
self.decay = K.variable(decay)
self.inital_decay = decay
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations + 1)]
self.updates = [K.update_add(self.iterations, 1)]
lr = self.lr
if self.inital_decay > 0:
lr *= (1. / (1. + self.decay * self.iterations))
t = self.iterations + 1
lr_t = self.lr / (1. - K.pow(self.beta_1, t))
shapes = [K.get_variable_shape(p) for p in params]
# zero init of 1st moment
ms = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
ms = [K.zeros(shape) for shape in shapes]
# zero init of exponentially weighted infinity norm
us = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.weights = ms + us
us = [K.zeros(shape) for shape in shapes]
self.weights = [self.iterations] + ms + us
for p, g, m, u in zip(params, grads, ms, us):
@@ -395,15 +465,15 @@ class Adamax(Optimizer):
u_t = K.maximum(self.beta_2 * u, K.abs(g))
p_t = p - lr_t * m_t / (u_t + self.epsilon)
self.updates.append((m, m_t))
self.updates.append((u, u_t))
self.updates.append(K.update(m, m_t))
self.updates.append(K.update(u, u_t))
new_p = p_t
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
@@ -430,9 +500,8 @@ class Nadam(Optimizer):
epsilon: float >= 0. Fuzz factor.
# References
[1] Nadam report - http://cs229.stanford.edu/proj2015/054_report.pdf
[2] On the importance of initialization and momentum in deep learning -
http://www.cs.toronto.edu/~fritz/absps/momentum.pdf
- [Nadam report](http://cs229.stanford.edu/proj2015/054_report.pdf)
- [On the importance of initialization and momentum in deep learning](http://www.cs.toronto.edu/~fritz/absps/momentum.pdf)
'''
def __init__(self, lr=0.002, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, schedule_decay=0.004, **kwargs):
@@ -447,7 +516,7 @@ class Nadam(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations + 1)]
self.updates = [K.update_add(self.iterations, 1)]
t = self.iterations + 1
@@ -458,10 +527,11 @@ class Nadam(Optimizer):
m_schedule_next = self.m_schedule * momentum_cache_t * momentum_cache_t_1
self.updates.append((self.m_schedule, m_schedule_new))
ms = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
vs = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
shapes = [K.get_variable_shape(p) for p in params]
ms = [K.zeros(shape) for shape in shapes]
vs = [K.zeros(shape) for shape in shapes]
self.weights = ms + vs
self.weights = [self.iterations] + ms + vs
for p, g, m, v in zip(params, grads, ms, vs):
# the following equations given in [1]
@@ -472,8 +542,8 @@ class Nadam(Optimizer):
v_t_prime = v_t / (1. - K.pow(self.beta_2, t))
m_t_bar = (1. - momentum_cache_t) * g_prime + momentum_cache_t_1 * m_t_prime
self.updates.append((m, m_t))
self.updates.append((v, v_t))
self.updates.append(K.update(m, m_t))
self.updates.append(K.update(v, v_t))
p_t = p - self.lr * m_t_bar / (K.sqrt(v_t_prime) + self.epsilon)
new_p = p_t
@@ -482,7 +552,7 @@ class Nadam(Optimizer):
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append((p, new_p))
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
+27 -7
Ver Arquivo
@@ -118,13 +118,17 @@ def flip_axis(x, axis):
return x
def array_to_img(x, dim_ordering=K.image_dim_ordering(), scale=True):
def array_to_img(x, dim_ordering='default', scale=True):
from PIL import Image
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if dim_ordering == 'th':
x = x.transpose(1, 2, 0)
if scale:
x += max(-np.min(x), 0)
x /= np.max(x)
x_max = np.max(x)
if x_max != 0:
x /= x_max
x *= 255
if x.shape[2] == 3:
# RGB
@@ -136,7 +140,9 @@ def array_to_img(x, dim_ordering=K.image_dim_ordering(), scale=True):
raise Exception('Unsupported channel number: ', x.shape[2])
def img_to_array(img, dim_ordering=K.image_dim_ordering()):
def img_to_array(img, dim_ordering='default'):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
if dim_ordering not in ['th', 'tf']:
raise Exception('Unknown dim_ordering: ', dim_ordering)
# image has dim_ordering (height, width, channel)
@@ -155,6 +161,14 @@ def img_to_array(img, dim_ordering=K.image_dim_ordering()):
def load_img(path, grayscale=False, target_size=None):
'''Load an image into PIL format.
# Arguments
path: path to image file
grayscale: boolean
target_size: None (default to original size)
or (img_height, img_width)
'''
from PIL import Image
img = Image.open(path)
if grayscale:
@@ -162,7 +176,7 @@ def load_img(path, grayscale=False, target_size=None):
else: # Ensure 3 channel even when loaded image is grayscale
img = img.convert('RGB')
if target_size:
img = img.resize(target_size)
img = img.resize((target_size[1], target_size[0]))
return img
@@ -222,7 +236,9 @@ class ImageDataGenerator(object):
horizontal_flip=False,
vertical_flip=False,
rescale=None,
dim_ordering=K.image_dim_ordering()):
dim_ordering='default'):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.__dict__.update(locals())
self.mean = None
self.std = None
@@ -446,12 +462,14 @@ class NumpyArrayIterator(Iterator):
def __init__(self, X, y, image_data_generator,
batch_size=32, shuffle=False, seed=None,
dim_ordering=K.image_dim_ordering(),
dim_ordering='default',
save_to_dir=None, save_prefix='', save_format='jpeg'):
if y is not None and len(X) != len(y):
raise Exception('X (images tensor) and y (labels) '
'should have the same length. '
'Found: X.shape = %s, y.shape = %s' % (np.asarray(X).shape, np.asarray(y).shape))
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.X = X
self.y = y
self.image_data_generator = image_data_generator
@@ -493,10 +511,12 @@ class DirectoryIterator(Iterator):
def __init__(self, directory, image_data_generator,
target_size=(256, 256), color_mode='rgb',
dim_ordering=K.image_dim_ordering,
dim_ordering='default',
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.directory = directory
self.image_data_generator = image_data_generator
self.target_size = tuple(target_size)
+3 -3
Ver Arquivo
@@ -138,7 +138,7 @@ def skipgrams(sequence, vocabulary_size,
continue
couples.append([wi, wj])
if categorical:
labels.append([0,1])
labels.append([0, 1])
else:
labels.append(1)
@@ -149,12 +149,12 @@ def skipgrams(sequence, vocabulary_size,
couples += [[words[i %len(words)], random.randint(1, vocabulary_size-1)] for i in range(nb_negative_samples)]
if categorical:
labels += [[1,0]]*nb_negative_samples
labels += [[1, 0]]*nb_negative_samples
else:
labels += [0]*nb_negative_samples
if shuffle:
seed = random.randint(0,10e6)
seed = random.randint(0, 10e6)
random.seed(seed)
random.shuffle(couples)
random.seed(seed)
+1
Ver Arquivo
@@ -99,6 +99,7 @@ class Tokenizer(object):
wcounts = list(self.word_counts.items())
wcounts.sort(key=lambda x: x[1], reverse=True)
sorted_voc = [wc[0] for wc in wcounts]
# note that index 0 is reserved, never assigned to an existing word
self.word_index = dict(list(zip(sorted_voc, list(range(1, len(sorted_voc) + 1)))))
self.index_docs = {}
+32 -12
Ver Arquivo
@@ -1,8 +1,10 @@
from __future__ import absolute_import
from . import backend as K
from .utils.generic_utils import get_from_module
class Regularizer(object):
def set_param(self, p):
self.p = p
@@ -29,6 +31,9 @@ class EigenvalueRegularizer(Regularizer):
self.uses_learning_phase = True
def set_param(self, p):
if hasattr(self, 'p'):
raise Exception('Regularizers cannot be reused. '
'Instantiate one regularizer per layer.')
self.p = p
def __call__(self, loss):
@@ -43,30 +48,37 @@ class EigenvalueRegularizer(Regularizer):
# power method for approximating the dominant eigenvector:
o = K.ones([dim1, 1]) # initial values for the dominant eigenvector
domin_eigenvect = K.dot(WW, o)
main_eigenvect = K.dot(WW, o)
for n in range(power - 1):
domin_eigenvect = K.dot(WW, domin_eigenvect)
main_eigenvect = K.dot(WW, main_eigenvect)
WWd = K.dot(WW, domin_eigenvect)
WWd = K.dot(WW, main_eigenvect)
# the corresponding dominant eigenvalue:
domin_eigenval = K.dot(K.transpose(WWd), domin_eigenvect) / K.dot(K.transpose(domin_eigenvect), domin_eigenvect)
regularized_loss = loss + (domin_eigenval ** 0.5) * self.k # multiplied by the given regularization gain
main_eigenval = (K.dot(K.transpose(WWd), main_eigenvect) /
K.dot(K.transpose(main_eigenvect), main_eigenvect))
# multiplied by the given regularization gain
regularized_loss = loss + (main_eigenval ** 0.5) * self.k
return K.in_train_phase(regularized_loss[0, 0], loss)
class WeightRegularizer(Regularizer):
def __init__(self, l1=0., l2=0.):
self.l1 = K.cast_to_floatx(l1)
self.l2 = K.cast_to_floatx(l2)
self.uses_learning_phase = True
self.p = None
def set_param(self, p):
if self.p is not None:
raise Exception('Regularizers cannot be reused. '
'Instantiate one regularizer per layer.')
self.p = p
def __call__(self, loss):
if not hasattr(self, 'p'):
if self.p is None:
raise Exception('Need to call `set_param` on '
'WeightRegularizer instance '
'before calling the instance. '
@@ -75,8 +87,11 @@ class WeightRegularizer(Regularizer):
'ActivityRegularizer '
'(i.e. activity_regularizer="l2" instead '
'of activity_regularizer="activity_l2".')
regularized_loss = loss + K.sum(K.abs(self.p)) * self.l1
regularized_loss += K.sum(K.square(self.p)) * self.l2
regularized_loss = loss
if self.l1:
regularized_loss += K.sum(self.l1 * K.abs(self.p))
if self.l2:
regularized_loss += K.sum(self.l2 * K.square(self.p))
return K.in_train_phase(regularized_loss, loss)
def get_config(self):
@@ -86,24 +101,30 @@ class WeightRegularizer(Regularizer):
class ActivityRegularizer(Regularizer):
def __init__(self, l1=0., l2=0.):
self.l1 = K.cast_to_floatx(l1)
self.l2 = K.cast_to_floatx(l2)
self.uses_learning_phase = True
self.layer = None
def set_layer(self, layer):
if self.layer is not None:
raise Exception('Regularizers cannot be reused')
self.layer = layer
def __call__(self, loss):
if not hasattr(self, 'layer'):
if self.layer is None:
raise Exception('Need to call `set_layer` on '
'ActivityRegularizer instance '
'before calling the instance.')
regularized_loss = loss
for i in range(len(self.layer.inbound_nodes)):
output = self.layer.get_output_at(i)
regularized_loss += self.l1 * K.sum(K.mean(K.abs(output), axis=0))
regularized_loss += self.l2 * K.sum(K.mean(K.square(output), axis=0))
if self.l1:
regularized_loss += K.sum(self.l1 * K.abs(output))
if self.l2:
regularized_loss += K.sum(self.l2 * K.square(output))
return K.in_train_phase(regularized_loss, loss)
def get_config(self):
@@ -136,7 +157,6 @@ def activity_l1l2(l1=0.01, l2=0.01):
return ActivityRegularizer(l1=l1, l2=l2)
from .utils.generic_utils import get_from_module
def get(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'regularizer',
instantiate=True, kwargs=kwargs)
+32 -7
Ver Arquivo
@@ -5,6 +5,7 @@ import tarfile
import os
import sys
import shutil
import hashlib
from six.moves.urllib.request import urlopen
from six.moves.urllib.error import URLError, HTTPError
@@ -21,9 +22,10 @@ if sys.version_info[0] == 2:
count = 0
while 1:
chunk = response.read(chunk_size)
if not chunk:
break
count += 1
if not chunk:
reporthook(count, total_size, total_size)
break
if reporthook:
reporthook(count, chunk_size, total_size)
yield chunk
@@ -36,11 +38,12 @@ else:
from six.moves.urllib.request import urlretrieve
def get_file(fname, origin, untar=False):
def get_file(fname, origin, untar=False,
md5_hash=None, cache_subdir='datasets'):
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')
datadir = os.path.join(datadir_base, 'datasets')
datadir = os.path.join(datadir_base, cache_subdir)
if not os.path.exists(datadir):
os.makedirs(datadir)
@@ -50,8 +53,19 @@ def get_file(fname, origin, untar=False):
else:
fpath = os.path.join(datadir, fname)
if not os.path.exists(fpath):
print('Downloading data from', origin)
download = False
if os.path.exists(fpath):
# file found; verify integrity if a hash was provided
if md5_hash is not None:
if not validate_file(fpath, md5_hash):
print('A local file was found, but it seems to be '
'incomplete or outdated.')
download = True
else:
download = True
if download:
print('Downloading data from', origin)
global progbar
progbar = None
@@ -60,7 +74,7 @@ def get_file(fname, origin, untar=False):
if progbar is None:
progbar = Progbar(total_size)
else:
progbar.update(count*block_size)
progbar.update(count * block_size)
error_msg = 'URL fetch failure on {}: {} -- {}'
try:
@@ -93,3 +107,14 @@ def get_file(fname, origin, untar=False):
return untar_fpath
return fpath
def validate_file(fpath, md5_hash):
hasher = hashlib.md5()
with open(fpath, 'rb') as f:
buf = f.read()
hasher.update(buf)
if str(hasher.hexdigest()) == str(md5_hash):
return True
else:
return False
+39
Ver Arquivo
@@ -3,6 +3,8 @@ import numpy as np
import time
import sys
import six
import marshal
import types as python_types
def get_from_module(identifier, module_params, module_name,
@@ -33,6 +35,43 @@ def make_tuple(*args):
return args
def func_dump(func):
'''Serialize user defined function.'''
code = marshal.dumps(func.__code__).decode('raw_unicode_escape')
defaults = func.__defaults__
if func.__closure__:
closure = tuple(c.cell_contents for c in func.__closure__)
else:
closure = None
return code, defaults, closure
def func_load(code, defaults=None, closure=None, globs=None):
'''Deserialize user defined function.'''
if isinstance(code, (tuple, list)): # unpack previous dump
code, defaults, closure = code
code = marshal.loads(code.encode('raw_unicode_escape'))
if closure is not None:
closure = func_reconstruct_closure(closure)
if globs is None:
globs = globals()
return python_types.FunctionType(code, globs, name=code.co_name, argdefs=defaults, closure=closure)
def func_reconstruct_closure(values):
'''Deserialization helper that reconstructs a closure.'''
nums = range(len(values))
src = ["def func(arg):"]
src += [" _%d = arg[%d]" % (n, n) for n in nums]
src += [" return lambda:(%s)" % ','.join(["_%d" % n for n in nums]), ""]
src = '\n'.join(src)
try:
exec(src)
except:
raise SyntaxError(src)
return func(values).__closure__
class Progbar(object):
def __init__(self, target, width=30, verbose=1, interval=0.01):
'''
+20 -3
Ver Arquivo
@@ -1,6 +1,7 @@
from __future__ import absolute_import
import h5py
from __future__ import print_function
import numpy as np
import sys
from collections import defaultdict
@@ -8,6 +9,8 @@ class HDF5Matrix():
refs = defaultdict(int)
def __init__(self, datapath, dataset, start, end, normalizer=None):
import h5py
if datapath not in list(self.refs.keys()):
f = h5py.File(datapath)
self.refs[datapath] = f
@@ -29,7 +32,7 @@ class HDF5Matrix():
raise IndexError
elif isinstance(key, int):
if key + self.start < self.end:
idx = key+self.start
idx = key + self.start
else:
raise IndexError
elif isinstance(key, np.ndarray):
@@ -49,7 +52,7 @@ class HDF5Matrix():
@property
def shape(self):
return tuple([self.end - self.start, self.data.shape[1]])
return (self.end - self.start,) + self.data.shape[1:]
def save_array(array, name):
@@ -69,3 +72,17 @@ def load_array(name):
a[:] = array[:]
f.close()
return a
def ask_to_proceed_with_overwrite(filepath):
get_input = input
if sys.version_info[:2] <= (2, 7):
get_input = raw_input
overwrite = get_input('[WARNING] %s already exists - overwrite? '
'[y/n]' % (filepath))
while overwrite not in ['y', 'n']:
overwrite = get_input('Enter "y" (overwrite) or "n" (cancel).')
if overwrite == 'n':
return False
print('[TIP] Next time specify overwrite=True!')
return True
+20
Ver Arquivo
@@ -1,6 +1,7 @@
from __future__ import print_function
from .generic_utils import get_from_module
from .np_utils import convert_kernel
from ..layers import *
from ..models import Model, Sequential, Graph
from .. import backend as K
@@ -97,3 +98,22 @@ def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33,
print('Total params: %s' % total_params)
print('_' * line_length)
def convert_all_kernels_in_model(model):
# Note: SeparableConvolution not included
# since only supported by TF.
conv_classes = {
'Convolution1D',
'Convolution2D',
'Convolution3D',
'AtrousConvolution2D',
'Deconvolution2D',
}
to_assign = []
for layer in model.layers:
if layer.__class__.__name__ in conv_classes:
original_w = K.get_value(layer.W)
converted_w = convert_kernel(original_w)
to_assign.append((layer.W, converted_w))
K.batch_set_value(to_assign)
+11
Ver Arquivo
@@ -120,3 +120,14 @@ def conv_output_length(input_length, filter_size, border_mode, stride, dilation=
elif border_mode == 'valid':
output_length = input_length - dilated_filter_size + 1
return (output_length + stride - 1) // stride
def conv_input_length(output_length, filter_size, border_mode, stride):
if output_length is None:
return None
assert border_mode in {'same', 'valid'}
if border_mode == 'same':
pad = filter_size // 2
elif border_mode == 'valid':
pad = 0
return (output_length - 1) * stride - 2 * pad + filter_size
+19 -2
Ver Arquivo
@@ -1,6 +1,7 @@
import numpy as np
from numpy.testing import assert_allclose
import inspect
import functools
from ..engine import Model, Input
from ..models import Sequential, model_from_json
@@ -35,7 +36,8 @@ def get_test_data(nb_train=1000, nb_test=500, input_shape=(10,),
def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
input_data=None, expected_output=None, expected_output_dtype=None):
input_data=None, expected_output=None,
expected_output_dtype=None, fixed_batch_size=False):
'''Test routine for a layer with a single input tensor
and single output tensor.
'''
@@ -63,7 +65,10 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
layer = layer_cls(**kwargs)
# test in functional API
x = Input(shape=input_shape[1:], dtype=input_dtype)
if fixed_batch_size:
x = Input(batch_shape=input_shape, dtype=input_dtype)
else:
x = Input(shape=input_shape[1:], dtype=input_dtype)
y = layer(x)
assert K.dtype(y) == expected_output_dtype
@@ -102,3 +107,15 @@ def layer_test(layer_cls, kwargs={}, input_shape=None, input_dtype=None,
# for further checks in the caller function
return actual_output
def keras_test(func):
'''Clean up after tensorflow tests.
'''
@functools.wraps(func)
def wrapper(*args, **kwargs):
output = func(*args, **kwargs)
if K._BACKEND == 'tensorflow':
K.clear_session()
return output
return wrapper
+9 -2
Ver Arquivo
@@ -78,7 +78,7 @@ class BaseWrapper(object):
for params_name in params:
if params_name not in legal_params:
assert False, '{} is not a legal parameter'.format(params_name)
raise ValueError('{} is not a legal parameter'.format(params_name))
def get_params(self, deep=True):
'''Get parameters for this estimator.
@@ -234,6 +234,13 @@ class KerasClassifier(BaseWrapper):
Mean accuracy of predictions on X wrt. y.
'''
kwargs = self.filter_sk_params(Sequential.evaluate, kwargs)
loss_name = self.model.loss
if hasattr(loss_name, '__name__'):
loss_name = loss_name.__name__
if loss_name == 'categorical_crossentropy' and len(y.shape) != 2:
y = to_categorical(y)
outputs = self.model.evaluate(X, y, **kwargs)
if type(outputs) is not list:
outputs = [outputs]
@@ -263,7 +270,7 @@ class KerasRegressor(BaseWrapper):
Predictions.
'''
kwargs = self.filter_sk_params(Sequential.predict, kwargs)
return self.model.predict(X, **kwargs)
return np.squeeze(self.model.predict(X, **kwargs))
def score(self, X, y, **kwargs):
'''Returns the mean loss on the given test data and labels.
-6
Ver Arquivo
@@ -13,26 +13,20 @@ norecursedirs= build
# E251 unexpected spaces around keyword / parameter equals
# E225 missing whitespace around operator
# E226 missing whitespace around arithmetic operator
# W291 trailing whitespace
# W293 blank line contains whitespace
# E501 line too long (82 > 79 characters)
# E402 module level import not at top of file - temporary measure to coninue adding ros python packaged in sys.path
# E731 do not assign a lambda expression, use a def
# E302 two blank lines between the functions
# E231 missing whitespace after ,
# E241 multiple spaces after ','
# E261 at least two spaces before inline comment
pep8ignore=* E251 \
* E225 \
* E226 \
* W291 \
* W293 \
* E501 \
* E402 \
* E731 \
* E302 \
* E231 \
* E241 \
* E261
+3 -2
Ver Arquivo
@@ -3,15 +3,16 @@ from setuptools import find_packages
setup(name='Keras',
version='1.0.6',
version='1.1.0',
description='Deep Learning for Python',
author='Francois Chollet',
author_email='francois.chollet@gmail.com',
url='https://github.com/fchollet/keras',
download_url='https://github.com/fchollet/keras/tarball/1.0.6',
download_url='https://github.com/fchollet/keras/tarball/1.1.0',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
'h5py': ['h5py'],
'visualize': ['pydot-ng'],
},
packages=find_packages())
@@ -2,20 +2,21 @@ from __future__ import print_function
import numpy as np
import pytest
from keras.utils.test_utils import get_test_data
from keras.utils.test_utils import get_test_data, keras_test
from keras.models import Sequential
from keras.layers.core import Dense, Flatten, Activation
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.utils.np_utils import to_categorical
@keras_test
def test_image_classification():
'''
Classify random 16x16 color images into several classes using logistic regression
with convolutional hidden layer.
'''
np.random.seed(1337)
input_shape = (3, 16, 16)
input_shape = (16, 16, 3)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
nb_test=200,
input_shape=input_shape,
@@ -1,9 +1,10 @@
from __future__ import print_function
import numpy as np
np.random.seed(1337)
import pytest
import string
from keras.utils.test_utils import get_test_data
from keras.utils.test_utils import get_test_data, keras_test
from keras.utils.np_utils import to_categorical
from keras.models import Sequential
from keras.layers import TimeDistributedDense
@@ -14,6 +15,7 @@ from keras.layers import LSTM
from keras.layers import Embedding
@keras_test
def test_temporal_classification():
'''
Classify temporal sequences of float numbers
@@ -21,7 +23,6 @@ def test_temporal_classification():
single layer of GRU units and softmax applied
to the last activations of the units
'''
np.random.seed(1337)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
nb_test=500,
input_shape=(3, 5),
@@ -40,17 +41,17 @@ def test_temporal_classification():
history = model.fit(X_train, y_train, nb_epoch=20, batch_size=32,
validation_data=(X_test, y_test),
verbose=0)
assert(history.history['val_acc'][-1] >= 0.85)
assert(history.history['val_acc'][-1] >= 0.8)
@keras_test
def test_temporal_regression():
'''
Predict float numbers (regression) based on sequences
of float numbers of length 3 using a single layer of GRU units
'''
np.random.seed(1337)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
nb_test=200,
nb_test=400,
input_shape=(3, 5),
output_shape=(2,),
classification=False)
@@ -60,9 +61,10 @@ def test_temporal_regression():
model.compile(loss='hinge', optimizer='adam')
history = model.fit(X_train, y_train, nb_epoch=5, batch_size=16,
validation_data=(X_test, y_test), verbose=0)
assert(history.history['val_loss'][-1] < 0.75)
assert(history.history['val_loss'][-1] < 1.)
@keras_test
def test_sequence_to_sequence():
'''
Apply a same Dense layer for each element of time dimension of the input
@@ -70,7 +72,6 @@ def test_sequence_to_sequence():
This does not make use of the temporal structure of the sequence
(see TimeDistributedDense for more details)
'''
np.random.seed(1337)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
nb_test=200,
input_shape=(3, 5),
@@ -86,13 +87,13 @@ def test_sequence_to_sequence():
assert(history.history['val_loss'][-1] < 0.8)
@keras_test
def test_stacked_lstm_char_prediction():
'''
Learn alphabetical char sequence with stacked LSTM.
Predict the whole alphabet based on the first two letters ('ab' -> 'ab...z')
See non-toy example in examples/lstm_text_generation.py
'''
np.random.seed(1336)
# generate alphabet: http://stackoverflow.com/questions/16060899/alphabet-range-python
alphabet = string.ascii_lowercase
number_of_chars = len(alphabet)
@@ -135,6 +136,7 @@ def test_stacked_lstm_char_prediction():
assert(generated == alphabet)
@keras_test
def test_masked_temporal():
'''
Confirm that even with masking on both inputs and outputs, cross-entropies are
@@ -147,7 +149,6 @@ def test_masked_temporal():
The ground-truth best cross-entropy loss should, then be -log(0.5) = 0.69
'''
np.random.seed(55318)
model = Sequential()
model.add(Embedding(10, 20, mask_zero=True, input_length=20))
model.add(TimeDistributedDense(10))
@@ -182,5 +183,4 @@ def test_masked_temporal():
assert(np.abs(history.history['val_loss'][-1] - ground_truth) < 0.06)
if __name__ == '__main__':
# pytest.main([__file__])
test_temporal_classification()
pytest.main([__file__])
@@ -2,12 +2,13 @@ from __future__ import print_function
import numpy as np
import pytest
from keras.utils.test_utils import get_test_data
from keras.utils.test_utils import get_test_data, keras_test
from keras.models import Sequential
from keras.layers.core import Dense
from keras.utils.np_utils import to_categorical
@keras_test
def test_vector_classification():
'''
Classify random float vectors into 2 classes with logistic regression
@@ -37,6 +38,7 @@ def test_vector_classification():
assert(history.history['val_acc'][-1] > 0.8)
@keras_test
def test_vector_regression():
'''
Perform float data prediction (regression) using 2 layer MLP
+326 -13
Ver Arquivo
@@ -2,6 +2,7 @@ import sys
import pytest
from numpy.testing import assert_allclose
import numpy as np
import scipy.sparse as sparse
from keras.backend import theano_backend as KTH
from keras.backend import tensorflow_backend as KTF
@@ -38,6 +39,7 @@ def check_two_tensor_operation(function_name, x_input_shape,
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
def check_composed_tensor_operations(first_function_name, first_function_args,
second_function_name, second_function_args,
input_shape):
@@ -59,6 +61,7 @@ def check_composed_tensor_operations(first_function_name, first_function_args,
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
class TestBackend(object):
def test_linear_operations(self):
@@ -68,6 +71,8 @@ class TestBackend(object):
check_two_tensor_operation('batch_dot', (4, 2, 3), (4, 5, 3),
axes=(2, 2))
check_single_tensor_operation('transpose', (4, 2))
check_single_tensor_operation('reverse', (4, 3, 2), axes=1)
check_single_tensor_operation('reverse', (4, 3, 2), axes=(1, 2))
def test_shape_operations(self):
# concatenate
@@ -90,14 +95,15 @@ class TestBackend(object):
check_single_tensor_operation('expand_dims', (4, 3), dim=-1)
check_single_tensor_operation('expand_dims', (4, 3, 2), dim=1)
check_single_tensor_operation('squeeze', (4, 3, 1), axis=2)
check_composed_tensor_operations('reshape', {'shape':(4,3,1,1)},
'squeeze', {'axis':2},
check_single_tensor_operation('squeeze', (4, 1, 1), axis=1)
check_composed_tensor_operations('reshape', {'shape': (4, 3, 1, 1)},
'squeeze', {'axis': 2},
(4, 3, 1, 1))
def test_repeat_elements(self):
reps = 3
for ndims in [1, 2, 3]:
shape = np.arange(2, 2+ndims)
shape = np.arange(2, 2 + ndims)
arr = np.arange(np.prod(shape)).reshape(shape)
arr_th = KTH.variable(arr)
arr_tf = KTF.variable(arr)
@@ -149,6 +155,17 @@ class TestBackend(object):
# count_params
assert KTH.count_params(xth) == KTF.count_params(xtf)
# print_tensor
check_single_tensor_operation('print_tensor', ())
check_single_tensor_operation('print_tensor', (2,))
check_single_tensor_operation('print_tensor', (4, 3))
check_single_tensor_operation('print_tensor', (1, 2, 3))
val = np.random.random((3, 2))
xth = KTH.variable(val)
xtf = KTF.variable(val)
assert KTH.get_variable_shape(xth) == KTF.get_variable_shape(xtf)
def test_elementwise_operations(self):
check_single_tensor_operation('max', (4, 2))
check_single_tensor_operation('max', (4, 2), axis=1, keepdims=True)
@@ -196,6 +213,11 @@ class TestBackend(object):
# two-tensor ops
check_two_tensor_operation('equal', (4, 2), (4, 2))
check_two_tensor_operation('not_equal', (4, 2), (4, 2))
check_two_tensor_operation('greater', (4, 2), (4, 2))
check_two_tensor_operation('greater_equal', (4, 2), (4, 2))
check_two_tensor_operation('lesser', (4, 2), (4, 2))
check_two_tensor_operation('lesser_equal', (4, 2), (4, 2))
check_two_tensor_operation('maximum', (4, 2), (4, 2))
check_two_tensor_operation('minimum', (4, 2), (4, 2))
@@ -276,6 +298,7 @@ class TestBackend(object):
return output, [output]
return step_function
# test default setup
th_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTH)
th_inputs = KTH.variable(input_val)
th_initial_states = [KTH.variable(init_state_val)]
@@ -321,6 +344,35 @@ class TestBackend(object):
assert_allclose(th_outputs, unrolled_th_outputs, atol=1e-04)
assert_allclose(th_state, unrolled_th_state, atol=1e-04)
# test go_backwards
th_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTH)
th_inputs = KTH.variable(input_val)
th_initial_states = [KTH.variable(init_state_val)]
last_output, outputs, new_states = KTH.rnn(th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=True,
mask=None)
th_last_output = KTH.eval(last_output)
th_outputs = KTH.eval(outputs)
assert len(new_states) == 1
th_state = KTH.eval(new_states[0])
tf_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTF)
tf_inputs = KTF.variable(input_val)
tf_initial_states = [KTF.variable(init_state_val)]
last_output, outputs, new_states = KTF.rnn(tf_rnn_step_fn, tf_inputs,
tf_initial_states,
go_backwards=True,
mask=None)
tf_last_output = KTF.eval(last_output)
tf_outputs = KTF.eval(outputs)
assert len(new_states) == 1
tf_state = KTF.eval(new_states[0])
assert_allclose(tf_last_output, th_last_output, atol=1e-04)
assert_allclose(tf_outputs, th_outputs, atol=1e-04)
assert_allclose(tf_state, th_state, atol=1e-04)
# test unroll with backwards = True
bwd_last_output, bwd_outputs, bwd_new_states = KTH.rnn(
th_rnn_step_fn, th_inputs,
@@ -378,6 +430,50 @@ class TestBackend(object):
assert_allclose(unrolled_masked_th_outputs, masked_th_outputs, atol=1e-04)
assert_allclose(unrolled_masked_th_state, masked_th_state, atol=1e-04)
def test_rnn_no_states(self):
# implement a simple RNN without states
input_dim = 8
output_dim = 4
timesteps = 5
input_val = np.random.random((32, timesteps, input_dim))
W_i_val = np.random.random((input_dim, output_dim))
def rnn_step_fn(input_dim, output_dim, K):
W_i = K.variable(W_i_val)
def step_function(x, states):
assert len(states) == 0
output = K.dot(x, W_i)
return output, []
return step_function
# test default setup
th_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTH)
th_inputs = KTH.variable(input_val)
th_initial_states = []
last_output, outputs, new_states = KTH.rnn(th_rnn_step_fn, th_inputs,
th_initial_states,
go_backwards=False,
mask=None)
th_last_output = KTH.eval(last_output)
th_outputs = KTH.eval(outputs)
assert len(new_states) == 0
tf_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTF)
tf_inputs = KTF.variable(input_val)
tf_initial_states = []
last_output, outputs, new_states = KTF.rnn(tf_rnn_step_fn, tf_inputs,
tf_initial_states,
go_backwards=False,
mask=None)
tf_last_output = KTF.eval(last_output)
tf_outputs = KTF.eval(outputs)
assert len(new_states) == 0
assert_allclose(tf_last_output, th_last_output, atol=1e-04)
assert_allclose(tf_outputs, th_outputs, atol=1e-04)
def test_switch(self):
val = np.random.random()
xth = KTH.variable(val)
@@ -435,8 +531,8 @@ class TestBackend(object):
kernel_th = KTH.variable(convert_kernel(kernel_val))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv2d(xth, kernel_th))
ztf = KTF.eval(KTF.conv2d(xtf, kernel_tf))
zth = KTH.eval(KTH.conv2d(xth, kernel_th, dim_ordering='th'))
ztf = KTF.eval(KTF.conv2d(xtf, kernel_tf, dim_ordering='th'))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
@@ -479,8 +575,8 @@ class TestBackend(object):
kernel_th = KTH.variable(convert_kernel(kernel_val))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv3d(xth, kernel_th))
ztf = KTF.eval(KTF.conv3d(xtf, kernel_tf))
zth = KTH.eval(KTH.conv3d(xth, kernel_th, dim_ordering='th'))
ztf = KTF.eval(KTF.conv3d(xtf, kernel_tf, dim_ordering='th'))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
@@ -506,23 +602,23 @@ class TestBackend(object):
assert_allclose(zth, ztf, atol=1e-05)
def test_pool2d(self):
check_single_tensor_operation('pool2d', (5, 3, 10, 12), pool_size=(2, 2),
check_single_tensor_operation('pool2d', (5, 10, 12, 3), pool_size=(2, 2),
strides=(1, 1), border_mode='valid')
check_single_tensor_operation('pool2d', (5, 3, 9, 11), pool_size=(2, 2),
check_single_tensor_operation('pool2d', (5, 9, 11, 3), pool_size=(2, 2),
strides=(1, 1), border_mode='valid')
check_single_tensor_operation('pool2d', (5, 3, 9, 11), pool_size=(2, 3),
check_single_tensor_operation('pool2d', (5, 9, 11, 3), pool_size=(2, 3),
strides=(1, 1), border_mode='valid')
def test_pool3d(self):
check_single_tensor_operation('pool3d', (5, 3, 10, 12, 5), pool_size=(2, 2, 2),
check_single_tensor_operation('pool3d', (5, 10, 12, 5, 3), pool_size=(2, 2, 2),
strides=(1, 1, 1), border_mode='valid')
check_single_tensor_operation('pool3d', (5, 3, 9, 11, 5), pool_size=(2, 2, 2),
check_single_tensor_operation('pool3d', (5, 9, 11, 5, 3), pool_size=(2, 2, 2),
strides=(1, 1, 1), border_mode='valid')
check_single_tensor_operation('pool3d', (5, 3, 9, 11, 5), pool_size=(2, 3, 2),
check_single_tensor_operation('pool3d', (5, 9, 11, 5, 3), pool_size=(2, 3, 2),
strides=(1, 1, 1), border_mode='valid')
def test_random_normal(self):
@@ -567,6 +663,223 @@ class TestBackend(object):
assert(np.max(rand) == 1)
assert(np.min(rand) == 0)
def test_ctc(self):
# simplified version of TensorFlow's test
label_lens = np.expand_dims(np.asarray([5, 4]), 1)
input_lens = np.expand_dims(np.asarray([5, 5]), 1) # number of timesteps
# the Theano and Tensorflow CTC code use different methods to ensure
# numerical stability. The Theano code subtracts out the max
# before the final log, so the results are different but scale
# identically and still train properly
loss_log_probs_tf = [3.34211, 5.42262]
loss_log_probs_th = [1.73308, 3.81351]
# dimensions are batch x time x categories
labels = np.asarray([[0, 1, 2, 1, 0], [0, 1, 1, 0, -1]])
inputs = np.asarray(
[[[0.633766, 0.221185, 0.0917319, 0.0129757, 0.0142857, 0.0260553],
[0.111121, 0.588392, 0.278779, 0.0055756, 0.00569609, 0.010436],
[0.0357786, 0.633813, 0.321418, 0.00249248, 0.00272882, 0.0037688],
[0.0663296, 0.643849, 0.280111, 0.00283995, 0.0035545, 0.00331533],
[0.458235, 0.396634, 0.123377, 0.00648837, 0.00903441, 0.00623107]],
[[0.30176, 0.28562, 0.0831517, 0.0862751, 0.0816851, 0.161508],
[0.24082, 0.397533, 0.0557226, 0.0546814, 0.0557528, 0.19549],
[0.230246, 0.450868, 0.0389607, 0.038309, 0.0391602, 0.202456],
[0.280884, 0.429522, 0.0326593, 0.0339046, 0.0326856, 0.190345],
[0.423286, 0.315517, 0.0338439, 0.0393744, 0.0339315, 0.154046]]],
dtype=np.float32)
labels_tf = KTF.variable(labels, dtype="int32")
inputs_tf = KTF.variable(inputs, dtype="float32")
input_lens_tf = KTF.variable(input_lens, dtype="int32")
label_lens_tf = KTF.variable(label_lens, dtype="int32")
res = KTF.eval(KTF.ctc_batch_cost(labels_tf, inputs_tf, input_lens_tf, label_lens_tf))
assert_allclose(res[:, 0], loss_log_probs_tf, atol=1e-05)
labels_th = KTH.variable(labels, dtype="int32")
inputs_th = KTH.variable(inputs, dtype="float32")
input_lens_th = KTH.variable(input_lens, dtype="int32")
label_lens_th = KTH.variable(label_lens, dtype="int32")
res = KTH.eval(KTH.ctc_batch_cost(labels_th, inputs_th, input_lens_th, label_lens_th))
assert_allclose(res[0, :], loss_log_probs_th, atol=1e-05)
def test_ctc_decode_greedy(self):
# Test adapted from tensorflow
"""Test two batch entries - best path decoder."""
max_time_steps = 6
seq_len_0 = 4
input_prob_matrix_0 = np.asarray(
[[1.0, 0.0, 0.0, 0.0], # t=0
[0.0, 0.0, 0.4, 0.6], # t=1
[0.0, 0.0, 0.4, 0.6], # t=2
[0.0, 0.9, 0.1, 0.0], # t=3
[0.0, 0.0, 0.0, 0.0], # t=4 (ignored)
[0.0, 0.0, 0.0, 0.0]], # t=5 (ignored)
dtype=np.float32)
input_log_prob_matrix_0 = np.log(input_prob_matrix_0)
seq_len_1 = 5
# dimensions are time x depth
input_prob_matrix_1 = np.asarray(
[[0.1, 0.9, 0.0, 0.0], # t=0
[0.0, 0.9, 0.1, 0.0], # t=1
[0.0, 0.0, 0.1, 0.9], # t=2
[0.0, 0.9, 0.1, 0.1], # t=3
[0.9, 0.1, 0.0, 0.0], # t=4
[0.0, 0.0, 0.0, 0.0]], # t=5 (ignored)
dtype=np.float32)
# len max_time_steps array of batch_size x depth matrices
inputs = [np.vstack([input_prob_matrix_0[t, :],
input_prob_matrix_1[t, :]])
for t in range(max_time_steps)]
# change tensorflow order to keras backend order
inputs = KTF.variable(np.asarray(inputs).transpose((1, 0, 2)))
# batch_size length vector of sequence_lengths
input_length = KTF.variable(np.array([seq_len_0, seq_len_1], dtype=np.int32))
# batch_size length vector of negative log probabilities
log_prob_truth = np.array([
np.sum(-np.log([1.0, 0.6, 0.6, 0.9])),
np.sum(-np.log([0.9, 0.9, 0.9, 0.9, 0.9]))
], np.float32)[:, np.newaxis]
# keras output, unlike tensorflow, is a dense (not sparse) tensor
decode_truth = np.array([[0, 1, -1], [1, 1, 0]])
decode_pred_tf, log_prob_pred_tf = KTF.ctc_decode(inputs,
input_length,
greedy=True)
assert len(decode_pred_tf) == 1
decode_pred = KTF.eval(decode_pred_tf[0])
log_prob_pred = KTF.eval(log_prob_pred_tf)
assert np.alltrue(decode_truth == decode_pred)
assert np.allclose(log_prob_truth, log_prob_pred)
def test_ctc_decode_beam_search(self):
"""Test one batch, two beams - hibernating beam search."""
depth = 6
seq_len_0 = 5
input_prob_matrix_0 = np.asarray(
[[0.30999, 0.309938, 0.0679938, 0.0673362, 0.0708352, 0.173908],
[0.215136, 0.439699, 0.0370931, 0.0393967, 0.0381581, 0.230517],
[0.199959, 0.489485, 0.0233221, 0.0251417, 0.0233289, 0.238763],
[0.279611, 0.452966, 0.0204795, 0.0209126, 0.0194803, 0.20655],
[0.51286, 0.288951, 0.0243026, 0.0220788, 0.0219297, 0.129878],
# Random entry added in at time=5
[0.155251, 0.164444, 0.173517, 0.176138, 0.169979, 0.160671]],
dtype=np.float32)
# len max_time_steps array of batch_size x depth matrices
inputs = ([input_prob_matrix_0[t, :][np.newaxis, :]
for t in range(seq_len_0)] + # Pad to max_time_steps = 8
2 * [np.zeros((1, depth), dtype=np.float32)])
inputs = KTF.variable(np.asarray(inputs).transpose((1, 0, 2)))
# batch_size length vector of sequence_lengths
input_length = KTF.variable(np.array([seq_len_0], dtype=np.int32))
# batch_size length vector of negative log probabilities
log_prob_truth = np.array([
0.584855, # output beam 0
0.389139 # output beam 1
], np.float32)[np.newaxis, :]
decode_truth = [np.array([1, 0]), np.array([0, 1, 0])]
beam_width = 2
top_paths = 2
decode_pred_tf, log_prob_pred_tf = KTF.ctc_decode(inputs,
input_length,
greedy=False,
beam_width=beam_width,
top_paths=top_paths)
assert len(decode_pred_tf) == top_paths
log_prob_pred = KTF.eval(log_prob_pred_tf)
for i in range(top_paths):
assert np.alltrue(decode_truth[i] == KTF.eval(decode_pred_tf[i]))
assert np.allclose(log_prob_truth, log_prob_pred)
def test_one_hot(self):
input_length = 10
nb_classes = 20
batch_size = 30
indices = np.random.randint(0, nb_classes, size=(batch_size, input_length))
oh = np.eye(nb_classes)[indices]
for K in [KTH, KTF]:
koh = K.eval(K.one_hot(K.variable(indices, dtype='int32'), nb_classes))
assert np.all(koh == oh)
def test_sparse_dot(self):
x_d = np.array([0, 7, 2, 3], dtype=np.float32)
x_r = np.array([0, 2, 2, 3], dtype=np.int64)
x_c = np.array([4, 3, 2, 3], dtype=np.int64)
x_sparse = sparse.csr_matrix((x_d, (x_r, x_c)), shape=(4, 5))
x_dense = x_sparse.toarray()
W = np.random.random((5, 4))
backends = [KTF]
if KTH.th_sparse_module:
# Theano has some dependency issues for sparse
backends.append(KTH)
for K in backends:
t_W = K.variable(W)
k_s = K.eval(K.dot(K.variable(x_sparse), t_W))
k_d = K.eval(K.dot(K.variable(x_dense), t_W))
assert k_s.shape == k_d.shape
assert_allclose(k_s, k_d, atol=1e-05)
def test_sparse_concat(self):
x_d = np.array([0, 7, 2, 3], dtype=np.float32)
x_r = np.array([0, 2, 2, 3], dtype=np.int64)
x_c = np.array([4, 3, 2, 3], dtype=np.int64)
x_sparse_1 = sparse.csr_matrix((x_d, (x_r, x_c)), shape=(4, 5))
x_d = np.array([0, 7, 2, 3], dtype=np.float32)
x_r = np.array([0, 2, 2, 3], dtype=np.int64)
x_c = np.array([4, 3, 2, 3], dtype=np.int64)
x_sparse_2 = sparse.csr_matrix((x_d, (x_r, x_c)), shape=(4, 5))
x_dense_1 = x_sparse_1.toarray()
x_dense_2 = x_sparse_2.toarray()
backends = [KTF]
if KTH.th_sparse_module:
# Theano has some dependency issues for sparse
backends.append(KTH)
for K in backends:
k_s = K.concatenate([K.variable(x_sparse_1), K.variable(x_sparse_2)])
assert K.is_sparse(k_s)
k_s_d = K.eval(k_s)
k_d = K.eval(K.concatenate([K.variable(x_dense_1), K.variable(x_dense_2)]))
assert k_s_d.shape == k_d.shape
assert_allclose(k_s_d, k_d, atol=1e-05)
if __name__ == '__main__':
pytest.main([__file__])
+125 -75
Ver Arquivo
@@ -4,11 +4,56 @@ import numpy as np
from keras.layers import Dense, Dropout, InputLayer
from keras.engine import merge, Input, get_source_inputs
from keras.models import Model
from keras.models import Model, Sequential
from keras import backend as K
from keras.models import model_from_json, model_from_yaml
from keras.utils.test_utils import keras_test
@keras_test
def test_trainable_weights():
a = Input(shape=(2,))
b = Dense(1)(a)
model = Model(a, b)
weights = model.weights
assert model.trainable_weights == weights
assert model.non_trainable_weights == []
model.trainable = False
assert model.trainable_weights == []
assert model.non_trainable_weights == weights
model.trainable = True
assert model.trainable_weights == weights
assert model.non_trainable_weights == []
model.layers[1].trainable = False
assert model.trainable_weights == []
assert model.non_trainable_weights == weights
# sequential model
model = Sequential()
model.add(Dense(1, input_dim=2))
weights = model.weights
assert model.trainable_weights == weights
assert model.non_trainable_weights == []
model.trainable = False
assert model.trainable_weights == []
assert model.non_trainable_weights == weights
model.trainable = True
assert model.trainable_weights == weights
assert model.non_trainable_weights == []
model.layers[0].trainable = False
assert model.trainable_weights == []
assert model.non_trainable_weights == weights
@keras_test
def test_learning_phase():
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
@@ -50,6 +95,7 @@ def test_learning_phase():
assert fn_outputs_no_dp[1].sum() != fn_outputs_dp[1].sum()
@keras_test
def test_node_construction():
####################################################
# test basics
@@ -128,6 +174,7 @@ def test_node_construction():
assert dense.get_output_mask_at(1) is None
@keras_test
def test_multi_input_layer():
####################################################
# test multi-input layer
@@ -209,6 +256,7 @@ def test_multi_input_layer():
assert [x.shape for x in fn_outputs] == [(10, 64), (10, 5)]
@keras_test
def test_recursion():
####################################################
# test recursion
@@ -400,98 +448,100 @@ def test_recursion():
y = Dense(2)(x)
def test_functional_guide():
# MNIST
from keras.layers import Input, Dense, LSTM
from keras.models import Model
from keras.utils import np_utils
# @keras_test
# def test_functional_guide():
# # MNIST
# from keras.layers import Input, Dense, LSTM
# from keras.models import Model
# from keras.utils import np_utils
# this returns a tensor
inputs = Input(shape=(784,))
# # this returns a tensor
# inputs = Input(shape=(784,))
# a layer instance is callable on a tensor, and returns a tensor
x = Dense(64, activation='relu')(inputs)
x = Dense(64, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
# # a layer instance is callable on a tensor, and returns a tensor
# x = Dense(64, activation='relu')(inputs)
# x = Dense(64, activation='relu')(x)
# predictions = Dense(10, activation='softmax')(x)
# this creates a model that includes
# the Input layer and three Dense layers
model = Model(input=inputs, output=predictions)
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# # this creates a model that includes
# # the Input layer and three Dense layers
# model = Model(input=inputs, output=predictions)
# model.compile(optimizer='rmsprop',
# loss='categorical_crossentropy',
# metrics=['accuracy'])
# the data, shuffled and split between tran and test sets
X_train = np.random.random((100, 784))
Y_train = np.random.random((100, 10))
# # the data, shuffled and split between tran and test sets
# X_train = np.random.random((100, 784))
# Y_train = np.random.random((100, 10))
model.fit(X_train, Y_train, nb_epoch=2, batch_size=128)
# model.fit(X_train, Y_train, nb_epoch=2, batch_size=128)
assert model.inputs == [inputs]
assert model.outputs == [predictions]
assert model.input == inputs
assert model.output == predictions
assert model.input_shape == (None, 784)
assert model.output_shape == (None, 10)
# assert model.inputs == [inputs]
# assert model.outputs == [predictions]
# assert model.input == inputs
# assert model.output == predictions
# assert model.input_shape == (None, 784)
# assert model.output_shape == (None, 10)
# try calling the sequential model
inputs = Input(shape=(784,))
new_outputs = model(inputs)
new_model = Model(input=inputs, output=new_outputs)
new_model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
# # try calling the sequential model
# inputs = Input(shape=(784,))
# new_outputs = model(inputs)
# new_model = Model(input=inputs, output=new_outputs)
# new_model.compile(optimizer='rmsprop',
# loss='categorical_crossentropy',
# metrics=['accuracy'])
##################################################
# multi-io
##################################################
tweet_a = Input(shape=(4, 25))
tweet_b = Input(shape=(4, 25))
# this layer can take as input a matrix
# and will return a vector of size 64
shared_lstm = LSTM(64)
# ##################################################
# # multi-io
# ##################################################
# tweet_a = Input(shape=(4, 25))
# tweet_b = Input(shape=(4, 25))
# # this layer can take as input a matrix
# # and will return a vector of size 64
# shared_lstm = LSTM(64)
# when we reuse the same layer instance
# multiple times, the weights of the layer
# are also being reused
# (it is effectively *the same* layer)
encoded_a = shared_lstm(tweet_a)
encoded_b = shared_lstm(tweet_b)
# # when we reuse the same layer instance
# # multiple times, the weights of the layer
# # are also being reused
# # (it is effectively *the same* layer)
# encoded_a = shared_lstm(tweet_a)
# encoded_b = shared_lstm(tweet_b)
# we can then concatenate the two vectors:
merged_vector = merge([encoded_a, encoded_b],
mode='concat', concat_axis=-1)
# # we can then concatenate the two vectors:
# merged_vector = merge([encoded_a, encoded_b],
# mode='concat', concat_axis=-1)
# and add a logistic regression on top
predictions = Dense(1, activation='sigmoid')(merged_vector)
# # and add a logistic regression on top
# predictions = Dense(1, activation='sigmoid')(merged_vector)
# we define a trainable model linking the
# tweet inputs to the predictions
model = Model(input=[tweet_a, tweet_b], output=predictions)
# # we define a trainable model linking the
# # tweet inputs to the predictions
# model = Model(input=[tweet_a, tweet_b], output=predictions)
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
data_a = np.random.random((1000, 4, 25))
data_b = np.random.random((1000, 4, 25))
labels = np.random.random((1000,))
model.fit([data_a, data_b], labels, nb_epoch=1)
# model.compile(optimizer='rmsprop',
# loss='binary_crossentropy',
# metrics=['accuracy'])
# data_a = np.random.random((1000, 4, 25))
# data_b = np.random.random((1000, 4, 25))
# labels = np.random.random((1000,))
# model.fit([data_a, data_b], labels, nb_epoch=1)
model.summary()
assert model.inputs == [tweet_a, tweet_b]
assert model.outputs == [predictions]
assert model.input == [tweet_a, tweet_b]
assert model.output == predictions
# model.summary()
# assert model.inputs == [tweet_a, tweet_b]
# assert model.outputs == [predictions]
# assert model.input == [tweet_a, tweet_b]
# assert model.output == predictions
assert model.output == predictions
assert model.input_shape == [(None, 4, 25), (None, 4, 25)]
assert model.output_shape == (None, 1)
# assert model.output == predictions
# assert model.input_shape == [(None, 4, 25), (None, 4, 25)]
# assert model.output_shape == (None, 1)
assert shared_lstm.get_output_at(0) == encoded_a
assert shared_lstm.get_output_at(1) == encoded_b
assert shared_lstm.input_shape == (None, 4, 25)
# assert shared_lstm.get_output_at(0) == encoded_a
# assert shared_lstm.get_output_at(1) == encoded_b
# assert shared_lstm.input_shape == (None, 4, 25)
@keras_test
def test_sequential_regression():
from keras.models import Sequential, Model
from keras.layers import Merge, Embedding, BatchNormalization, LSTM, InputLayer, Input
+3
Ver Arquivo
@@ -7,8 +7,10 @@ from keras.engine.topology import merge, Input
from keras.engine.training import Model
from keras.models import Sequential, Graph
from keras import backend as K
from keras.utils.test_utils import keras_test
@keras_test
def test_model_methods():
a = Input(shape=(3,), name='input_a')
b = Input(shape=(3,), name='input_b')
@@ -167,6 +169,7 @@ def test_model_methods():
out = model.predict([input_a_np, input_b_np], batch_size=4)
@keras_test
def test_trainable_argument():
x = np.random.random((5, 3))
y = np.random.random((5, 2))
+7 -1
Ver Arquivo
@@ -1,7 +1,8 @@
import pytest
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
@keras_test
def test_leaky_relu():
from keras.layers.advanced_activations import LeakyReLU
for alpha in [0., .5, -1.]:
@@ -9,12 +10,14 @@ def test_leaky_relu():
input_shape=(2, 3, 4))
@keras_test
def test_prelu():
from keras.layers.advanced_activations import PReLU
layer_test(PReLU, kwargs={},
input_shape=(2, 3, 4))
@keras_test
def test_elu():
from keras.layers.advanced_activations import ELU
for alpha in [0., .5, -1.]:
@@ -22,6 +25,7 @@ def test_elu():
input_shape=(2, 3, 4))
@keras_test
def test_parametric_softplus():
from keras.layers.advanced_activations import ParametricSoftplus
for alpha in [0., .5, -1.]:
@@ -31,12 +35,14 @@ def test_parametric_softplus():
input_shape=(2, 3, 4))
@keras_test
def test_thresholded_relu():
from keras.layers.advanced_activations import ThresholdedReLU
layer_test(ThresholdedReLU, kwargs={'theta': 0.5},
input_shape=(2, 3, 4))
@keras_test
def test_srelu():
from keras.layers.advanced_activations import SReLU
layer_test(SReLU, kwargs={},
+244 -38
Ver Arquivo
@@ -2,22 +2,25 @@ import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
from keras.utils.np_utils import conv_input_length
from keras import backend as K
from keras.layers import convolutional
from keras.layers import convolutional, pooling
@keras_test
def test_convolution_1d():
nb_samples = 2
nb_steps = 8
input_dim = 5
input_dim = 2
filter_length = 3
nb_filter = 4
nb_filter = 3
for border_mode in ['valid', 'same']:
for subsample_length in [1]:
for subsample_length in [1, 2]:
if border_mode == 'same' and subsample_length != 1:
continue
layer_test(convolutional.Convolution1D,
kwargs={'nb_filter': nb_filter,
'filter_length': filter_length,
@@ -36,6 +39,43 @@ def test_convolution_1d():
input_shape=(nb_samples, nb_steps, input_dim))
@keras_test
def test_atrous_conv_1d():
nb_samples = 2
nb_steps = 8
input_dim = 2
filter_length = 3
nb_filter = 3
for border_mode in ['valid', 'same']:
for subsample_length in [1, 2]:
for atrous_rate in [1, 2]:
if border_mode == 'same' and subsample_length != 1:
continue
if subsample_length != 1 and atrous_rate != 1:
continue
layer_test(convolutional.AtrousConv1D,
kwargs={'nb_filter': nb_filter,
'filter_length': filter_length,
'border_mode': border_mode,
'subsample_length': subsample_length,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, nb_steps, input_dim))
layer_test(convolutional.AtrousConv1D,
kwargs={'nb_filter': nb_filter,
'filter_length': filter_length,
'border_mode': border_mode,
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample_length': subsample_length,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, nb_steps, input_dim))
@keras_test
def test_maxpooling_1d():
for stride in [1, 2]:
layer_test(convolutional.MaxPooling1D,
@@ -44,6 +84,7 @@ def test_maxpooling_1d():
input_shape=(3, 5, 4))
@keras_test
def test_averagepooling_1d():
for stride in [1, 2]:
layer_test(convolutional.AveragePooling1D,
@@ -52,10 +93,11 @@ def test_averagepooling_1d():
input_shape=(3, 5, 4))
@keras_test
def test_convolution_2d():
nb_samples = 2
nb_filter = 3
stack_size = 4
nb_filter = 2
stack_size = 3
nb_row = 10
nb_col = 6
@@ -70,7 +112,7 @@ def test_convolution_2d():
'nb_col': 3,
'border_mode': border_mode,
'subsample': subsample},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
layer_test(convolutional.Convolution2D,
kwargs={'nb_filter': nb_filter,
@@ -81,13 +123,55 @@ def test_convolution_2d():
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
@keras_test
def test_deconvolution_2d():
nb_samples = 2
nb_filter = 2
stack_size = 3
nb_row = 10
nb_col = 6
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
if border_mode == 'same' and subsample != (1, 1):
continue
rows = conv_input_length(nb_row, 3, border_mode, subsample[0])
cols = conv_input_length(nb_col, 3, border_mode, subsample[1])
layer_test(convolutional.Deconvolution2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'output_shape': (nb_samples, nb_filter, rows, cols),
'border_mode': border_mode,
'subsample': subsample,
'dim_ordering': 'th'},
input_shape=(nb_samples, stack_size, nb_row, nb_col),
fixed_batch_size=True)
layer_test(convolutional.Deconvolution2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'output_shape': (nb_samples, nb_filter, rows, cols),
'border_mode': border_mode,
'dim_ordering': 'th',
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample},
input_shape=(nb_samples, stack_size, nb_row, nb_col),
fixed_batch_size=True)
@keras_test
def test_atrous_conv_2d():
nb_samples = 2
nb_filter = 3
stack_size = 4
nb_filter = 2
stack_size = 3
nb_row = 10
nb_col = 6
@@ -106,7 +190,7 @@ def test_atrous_conv_2d():
'border_mode': border_mode,
'subsample': subsample,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
layer_test(convolutional.AtrousConv2D,
kwargs={'nb_filter': nb_filter,
@@ -118,14 +202,15 @@ def test_atrous_conv_2d():
'activity_regularizer': 'activity_l2',
'subsample': subsample,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
@pytest.mark.skipif(K._BACKEND != 'tensorflow', reason="Requires TF backend")
@keras_test
def test_separable_conv_2d():
nb_samples = 2
nb_filter = 8
stack_size = 4
nb_filter = 6
stack_size = 3
nb_row = 10
nb_col = 6
@@ -142,7 +227,7 @@ def test_separable_conv_2d():
'border_mode': border_mode,
'subsample': subsample,
'depth_multiplier': multiplier},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
layer_test(convolutional.SeparableConv2D,
kwargs={'nb_filter': nb_filter,
@@ -157,9 +242,34 @@ def test_separable_conv_2d():
'depthwise_constraint': 'unitnorm',
'subsample': subsample,
'depth_multiplier': multiplier},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
input_shape=(nb_samples, nb_row, nb_col, stack_size))
@keras_test
def test_globalpooling_1d():
layer_test(pooling.GlobalMaxPooling1D,
input_shape=(3, 4, 5))
layer_test(pooling.GlobalAveragePooling1D,
input_shape=(3, 4, 5))
@keras_test
def test_globalpooling_2d():
layer_test(pooling.GlobalMaxPooling2D,
kwargs={'dim_ordering': 'th'},
input_shape=(3, 4, 5, 6))
layer_test(pooling.GlobalMaxPooling2D,
kwargs={'dim_ordering': 'tf'},
input_shape=(3, 5, 6, 4))
layer_test(pooling.GlobalAveragePooling2D,
kwargs={'dim_ordering': 'th'},
input_shape=(3, 4, 5, 6))
layer_test(pooling.GlobalAveragePooling2D,
kwargs={'dim_ordering': 'tf'},
input_shape=(3, 5, 6, 4))
@keras_test
def test_maxpooling_2d():
pool_size = (3, 3)
@@ -168,9 +278,10 @@ def test_maxpooling_2d():
kwargs={'strides': strides,
'border_mode': 'valid',
'pool_size': pool_size},
input_shape=(3, 4, 11, 12))
input_shape=(3, 11, 12, 4))
@keras_test
def test_averagepooling_2d():
pool_size = (3, 3)
@@ -181,13 +292,14 @@ def test_averagepooling_2d():
kwargs={'strides': strides,
'border_mode': border_mode,
'pool_size': pool_size},
input_shape=(3, 4, 11, 12))
input_shape=(3, 11, 12, 4))
@keras_test
def test_convolution_3d():
nb_samples = 2
nb_filter = 5
stack_size = 4
nb_filter = 2
stack_size = 3
kernel_dim1 = 2
kernel_dim2 = 3
kernel_dim3 = 1
@@ -208,8 +320,9 @@ def test_convolution_3d():
'kernel_dim3': kernel_dim3,
'border_mode': border_mode,
'subsample': subsample},
input_shape=(nb_samples, stack_size,
input_len_dim1, input_len_dim2, input_len_dim3))
input_shape=(nb_samples,
input_len_dim1, input_len_dim2, input_len_dim3,
stack_size))
layer_test(convolutional.Convolution3D,
kwargs={'nb_filter': nb_filter,
@@ -221,10 +334,12 @@ def test_convolution_3d():
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample},
input_shape=(nb_samples, stack_size,
input_len_dim1, input_len_dim2, input_len_dim3))
input_shape=(nb_samples,
input_len_dim1, input_len_dim2, input_len_dim3,
stack_size))
@keras_test
def test_maxpooling_3d():
pool_size = (3, 3, 3)
@@ -236,6 +351,7 @@ def test_maxpooling_3d():
input_shape=(3, 4, 11, 12, 10))
@keras_test
def test_averagepooling_3d():
pool_size = (3, 3, 3)
@@ -247,13 +363,14 @@ def test_averagepooling_3d():
input_shape=(3, 4, 11, 12, 10))
@keras_test
def test_zero_padding_2d():
nb_samples = 2
stack_size = 7
stack_size = 2
input_nb_row = 11
input_nb_col = 12
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
input = np.ones((nb_samples, input_nb_row, input_nb_col, stack_size))
# basic test
layer_test(convolutional.ZeroPadding2D,
@@ -266,22 +383,22 @@ def test_zero_padding_2d():
out = K.eval(layer.output)
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, offset, :, :], 0.)
assert_allclose(out[:, :, offset, :], 0.)
assert_allclose(out[:, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2], 1.)
assert_allclose(out[:, 2:-2, 2:-2, :], 1.)
layer.get_config()
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_zero_padding_3d():
nb_samples = 2
stack_size = 7
stack_size = 2
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
input = np.ones((nb_samples, stack_size, input_len_dim1,
input_len_dim2, input_len_dim3))
input = np.ones((nb_samples,
input_len_dim1, input_len_dim2, input_len_dim3,
stack_size))
# basic test
layer_test(convolutional.ZeroPadding3D,
@@ -293,22 +410,24 @@ def test_zero_padding_3d():
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, offset, :, :, :], 0.)
assert_allclose(out[:, :, offset, :, :], 0.)
assert_allclose(out[:, :, :, offset, :], 0.)
assert_allclose(out[:, :, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2, 2:-2], 1.)
assert_allclose(out[:, 2:-2, 2:-2, 2:-2, :], 1.)
layer.get_config()
@keras_test
def test_upsampling_1d():
layer_test(convolutional.UpSampling1D,
kwargs={'length': 2},
input_shape=(3, 5, 4))
@keras_test
def test_upsampling_2d():
nb_samples = 2
stack_size = 7
stack_size = 2
input_nb_row = 11
input_nb_col = 12
@@ -346,10 +465,9 @@ def test_upsampling_2d():
assert_allclose(out, expected_out)
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_upsampling_3d():
nb_samples = 2
stack_size = 7
stack_size = 2
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
@@ -392,5 +510,93 @@ def test_upsampling_3d():
assert_allclose(out, expected_out)
@keras_test
def test_cropping_1d():
nb_samples = 2
time_length = 10
input_len_dim1 = 2
input = np.random.rand(nb_samples, time_length, input_len_dim1)
layer_test(convolutional.Cropping1D,
kwargs={'cropping': (2, 2)},
input_shape=input.shape)
def test_cropping_2d():
nb_samples = 2
stack_size = 2
input_len_dim1 = 8
input_len_dim2 = 8
cropping = ((2, 2), (3, 3))
dim_ordering = K.image_dim_ordering()
if dim_ordering == 'th':
input = np.random.rand(nb_samples, stack_size, input_len_dim1, input_len_dim2)
else:
input = np.random.rand(nb_samples, input_len_dim1, input_len_dim2, stack_size)
# basic test
layer_test(convolutional.Cropping2D,
kwargs={'cropping': cropping,
'dim_ordering': dim_ordering},
input_shape=input.shape)
# correctness test
layer = convolutional.Cropping2D(cropping=cropping, dim_ordering=dim_ordering)
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
# compare with numpy
if dim_ordering == 'th':
expected_out = input[:,
:,
cropping[0][0]:-cropping[0][1],
cropping[1][0]:-cropping[1][1]]
else:
expected_out = input[:,
cropping[0][0]:-cropping[0][1],
cropping[1][0]:-cropping[1][1],
:]
assert_allclose(out, expected_out)
def test_cropping_3d():
nb_samples = 2
stack_size = 2
input_len_dim1 = 8
input_len_dim2 = 8
input_len_dim3 = 8
cropping = ((2, 2), (3, 3), (2, 3))
dim_ordering = K.image_dim_ordering()
if dim_ordering == 'th':
input = np.random.rand(nb_samples, stack_size, input_len_dim1, input_len_dim2, input_len_dim3)
else:
input = np.random.rand(nb_samples, input_len_dim1, input_len_dim2, input_len_dim3, stack_size)
# basic test
layer_test(convolutional.Cropping3D,
kwargs={'cropping': cropping,
'dim_ordering': dim_ordering},
input_shape=input.shape)
# correctness test
layer = convolutional.Cropping3D(cropping=cropping, dim_ordering=dim_ordering)
layer.set_input(K.variable(input), shape=input.shape)
out = K.eval(layer.output)
# compare with numpy
if dim_ordering == 'th':
expected_out = input[:,
:,
cropping[0][0]:-cropping[0][1],
cropping[1][0]:-cropping[1][1],
cropping[2][0]:-cropping[2][1]]
else:
expected_out = input[:,
cropping[0][0]:-cropping[0][1],
cropping[1][0]:-cropping[1][1],
cropping[2][0]:-cropping[2][1],
:]
assert_allclose(out, expected_out)
if __name__ == '__main__':
pytest.main([__file__])
+35 -5
Ver Arquivo
@@ -3,15 +3,17 @@ import numpy as np
from keras import backend as K
from keras.layers import core
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
@keras_test
def test_masking():
layer_test(core.Masking,
kwargs={},
input_shape=(3, 2, 3))
@keras_test
def test_merge():
from keras.layers import Input, merge, Merge
from keras.models import Model
@@ -83,6 +85,7 @@ def test_merge():
model.compile('rmsprop', 'mse')
@keras_test
def test_merge_mask_2d():
from keras.layers import Input, merge, Masking
from keras.models import Model
@@ -97,21 +100,28 @@ def test_merge_mask_2d():
masked_a = Masking(mask_value=0)(input_a)
masked_b = Masking(mask_value=0)(input_b)
# two different types of merging
# three different types of merging
merged_sum = merge([masked_a, masked_b], mode='sum')
merged_concat = merge([masked_a, masked_b], mode='concat', concat_axis=1)
merged_concat_mixed = merge([masked_a, input_b], mode='concat', concat_axis=1)
# test sum
model_sum = Model([input_a, input_b], [merged_sum])
model_sum.compile(loss='mse', optimizer='sgd')
model_sum.fit([rand(2,3), rand(2,3)], [rand(2,3)], nb_epoch=1)
model_sum.fit([rand(2, 3), rand(2, 3)], [rand(2, 3)], nb_epoch=1)
# test concatenation
model_concat = Model([input_a, input_b], [merged_concat])
model_concat.compile(loss='mse', optimizer='sgd')
model_concat.fit([rand(2,3), rand(2,3)], [rand(2,6)], nb_epoch=1)
model_concat.fit([rand(2, 3), rand(2, 3)], [rand(2, 6)], nb_epoch=1)
# test concatenation with masked and non-masked inputs
model_concat = Model([input_a, input_b], [merged_concat_mixed])
model_concat.compile(loss='mse', optimizer='sgd')
model_concat.fit([rand(2, 3), rand(2, 3)], [rand(2, 6)], nb_epoch=1)
@keras_test
def test_merge_mask_3d():
from keras.layers import Input, merge, Embedding, SimpleRNN
from keras.models import Model
@@ -134,15 +144,25 @@ def test_merge_mask_3d():
merged_concat = merge([rnn_a, rnn_b], mode='concat', concat_axis=-1)
model = Model([input_a, input_b], [merged_concat])
model.compile(loss='mse', optimizer='sgd')
model.fit([rand(2,3), rand(2,3)], [rand(2,3,6)])
model.fit([rand(2, 3), rand(2, 3)], [rand(2, 3, 6)])
@keras_test
def test_dropout():
layer_test(core.Dropout,
kwargs={'p': 0.5},
input_shape=(3, 2))
layer_test(core.SpatialDropout2D,
kwargs={'p': 0.5},
input_shape=(2, 3, 4, 5))
layer_test(core.SpatialDropout3D,
kwargs={'p': 0.5},
input_shape=(2, 3, 4, 5, 6))
@keras_test
def test_activation():
# with string argument
layer_test(core.Activation,
@@ -155,30 +175,35 @@ def test_activation():
input_shape=(3, 2))
@keras_test
def test_reshape():
layer_test(core.Reshape,
kwargs={'target_shape': (8, 1)},
input_shape=(3, 2, 4))
@keras_test
def test_permute():
layer_test(core.Permute,
kwargs={'dims': (2, 1)},
input_shape=(3, 2, 4))
@keras_test
def test_flatten():
layer_test(core.Flatten,
kwargs={},
input_shape=(3, 2, 4))
@keras_test
def test_repeat_vector():
layer_test(core.RepeatVector,
kwargs={'n': 3},
input_shape=(3, 2))
@keras_test
def test_lambda():
from keras.utils.layer_utils import layer_from_config
Lambda = core.Lambda
@@ -212,6 +237,7 @@ def test_lambda():
ld = layer_from_config({'class_name': 'Lambda', 'config': config})
@keras_test
def test_dense():
from keras import regularizers
from keras import constraints
@@ -230,6 +256,7 @@ def test_dense():
input_shape=(3, 2))
@keras_test
def test_activity_regularization():
from keras.engine import Input, Model
@@ -250,6 +277,7 @@ def test_activity_regularization():
model.compile('rmsprop', 'mse')
@keras_test
def test_maxout_dense():
from keras import regularizers
from keras import constraints
@@ -268,6 +296,7 @@ def test_maxout_dense():
input_shape=(3, 2))
@keras_test
def test_highway():
from keras import regularizers
from keras import constraints
@@ -285,6 +314,7 @@ def test_highway():
input_shape=(3, 2))
@keras_test
def test_timedistributeddense():
from keras import regularizers
from keras import constraints
+3 -2
Ver Arquivo
@@ -1,12 +1,13 @@
import pytest
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
from keras.layers.embeddings import Embedding
import keras.backend as K
@keras_test
def test_embedding():
layer_test(Embedding,
kwargs={'output_dim': 4., 'input_dim': 10, 'input_length': 2},
kwargs={'output_dim': 4, 'input_dim': 10, 'input_length': 2},
input_shape=(3, 2),
input_dtype='int32',
expected_output_dtype=K.floatx())
+3 -1
Ver Arquivo
@@ -1,9 +1,10 @@
import pytest
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
from keras.layers import local
@keras_test
def test_locallyconnected_1d():
nb_samples = 2
nb_steps = 8
@@ -33,6 +34,7 @@ def test_locallyconnected_1d():
input_shape=(nb_samples, nb_steps, input_dim))
@keras_test
def test_locallyconnected_2d():
nb_samples = 8
nb_filter = 3
+3 -1
Ver Arquivo
@@ -1,14 +1,16 @@
import pytest
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
from keras.layers import noise
@keras_test
def test_GaussianNoise():
layer_test(noise.GaussianNoise,
kwargs={'sigma': 1.},
input_shape=(3, 2, 3))
@keras_test
def test_GaussianDropout():
layer_test(noise.GaussianDropout,
kwargs={'p': 0.5},
+13 -7
Ver Arquivo
@@ -3,37 +3,41 @@ import numpy as np
from numpy.testing import assert_allclose
from keras.layers.core import Dense, Activation
from keras.utils.test_utils import layer_test
from keras.utils.test_utils import layer_test, keras_test
from keras.layers import normalization
from keras.models import Sequential, Graph
from keras import backend as K
input_1 = np.arange(10)
input_2 = np.zeros(10)
input_3 = np.ones((10))
input_shapes = [np.ones((10, 10)), np.ones((10, 10, 10))]
@keras_test
def basic_batchnorm_test():
from keras import regularizers
layer_test(normalization.BatchNormalization,
kwargs={'mode': 1},
kwargs={'mode': 1,
'gamma_regularizer': regularizers.l2(0.01),
'beta_regularizer': regularizers.l2(0.01)},
input_shape=(3, 4, 2))
layer_test(normalization.BatchNormalization,
kwargs={'mode': 0},
input_shape=(3, 4, 2))
@keras_test
def test_batchnorm_mode_0_or_2():
for mode in [0, 2]:
model = Sequential()
norm_m0 = normalization.BatchNormalization(mode=mode, input_shape=(10,))
norm_m0 = normalization.BatchNormalization(mode=mode, input_shape=(10,), momentum=0.8)
model.add(norm_m0)
model.compile(loss='mse', optimizer='sgd')
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 10))
model.fit(X, X, nb_epoch=5, verbose=0)
model.fit(X, X, nb_epoch=4, verbose=0)
out = model.predict(X)
out -= K.eval(norm_m0.beta)
out /= K.eval(norm_m0.gamma)
@@ -42,15 +46,16 @@ def test_batchnorm_mode_0_or_2():
assert_allclose(out.std(), 1.0, atol=1e-1)
@keras_test
def test_batchnorm_mode_0_convnet():
model = Sequential()
norm_m0 = normalization.BatchNormalization(mode=0, axis=1, input_shape=(3, 4, 4))
norm_m0 = normalization.BatchNormalization(mode=0, axis=1, input_shape=(3, 4, 4), momentum=0.8)
model.add(norm_m0)
model.compile(loss='mse', optimizer='sgd')
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 3, 4, 4))
model.fit(X, X, nb_epoch=5, verbose=0)
model.fit(X, X, nb_epoch=4, verbose=0)
out = model.predict(X)
out -= np.reshape(K.eval(norm_m0.beta), (1, 3, 1, 1))
out /= np.reshape(K.eval(norm_m0.gamma), (1, 3, 1, 1))
@@ -59,6 +64,7 @@ def test_batchnorm_mode_0_convnet():
assert_allclose(np.std(out, axis=(0, 2, 3)), 1.0, atol=1e-1)
@keras_test
def test_batchnorm_mode_1():
norm_m1 = normalization.BatchNormalization(input_shape=(10,), mode=1)
norm_m1.build(input_shape=(None, 10))
+18 -6
Ver Arquivo
@@ -7,10 +7,11 @@ from keras.layers import recurrent, embeddings
from keras.models import Sequential
from keras.layers.core import Masking
from keras import regularizers
from keras.utils.test_utils import keras_test
from keras import backend as K
nb_samples, timesteps, embedding_dim, output_dim = 3, 5, 10, 5
nb_samples, timesteps, embedding_dim, output_dim = 2, 5, 4, 3
embedding_num = 12
@@ -23,21 +24,30 @@ def _runner(layer_class):
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'return_sequences': True},
input_shape=(3, 2, 3))
input_shape=(nb_samples, timesteps, embedding_dim))
# check dynamic behavior
layer = layer_class(output_dim, input_dim=embedding_dim)
model = Sequential()
model.add(layer)
model.compile('sgd', 'mse')
x = np.random.random((nb_samples, timesteps, embedding_dim))
y = np.random.random((nb_samples, output_dim))
model.train_on_batch(x, y)
# check dropout
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'dropout_U': 0.1,
'dropout_W': 0.1},
input_shape=(3, 2, 3))
input_shape=(nb_samples, timesteps, embedding_dim))
# check implementation modes
for mode in ['cpu', 'mem', 'gpu']:
layer_test(layer_class,
kwargs={'output_dim': output_dim,
'consume_less': mode},
input_shape=(3, 2, 3))
input_shape=(nb_samples, timesteps, embedding_dim))
# check statefulness
model = Sequential()
@@ -82,7 +92,6 @@ def _runner(layer_class):
left_padded_input = np.ones((nb_samples, timesteps))
left_padded_input[0, :1] = 0
left_padded_input[1, :2] = 0
left_padded_input[2, :3] = 0
out6 = model.predict(left_padded_input)
layer.reset_states()
@@ -90,7 +99,6 @@ def _runner(layer_class):
right_padded_input = np.ones((nb_samples, timesteps))
right_padded_input[0, -1:] = 0
right_padded_input[1, -2:] = 0
right_padded_input[2, -3:] = 0
out7 = model.predict(right_padded_input)
assert_allclose(out7, out6, atol=1e-5)
@@ -107,18 +115,22 @@ 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:
https://github.com/fchollet/keras/issues/1567

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