Comparar commits

...

369 Commits

Autor SHA1 Mensagem Data
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
Francois Chollet 892d9fae84 Prepare 1.0.6 release 2016-07-16 12:25:03 -07:00
Francois Chollet 796f895f01 Start to nativify variable initialization in TF 2016-07-16 11:19:41 -07:00
Francois Chollet 489bb4eb10 Update docs for pooling 2016-07-16 10:28:35 -07:00
Francois Chollet 8f458066bb Update docs for initializations 2016-07-16 10:28:18 -07:00
Francois Chollet 5dd7454260 Merge branch 'master' of https://github.com/fchollet/keras 2016-07-15 17:36:21 -07:00
Francois Chollet 571db82371 Add variable initialization override option in TF 2016-07-15 17:36:00 -07:00
fchollet d971e0cca5 Style fixes in SeparableConv2D 2016-07-14 18:22:33 -07:00
Fariz Rahman fde0aac733 Convnet aliases (#3226)
* Convnet aliases

Not very important, but kinda handy.

* Update convolutional.py

* pep8
2016-07-14 18:16:00 -07:00
Maruan b9d904c12f Add masking support to BatchNormalization layer. (#3228) 2016-07-14 17:02:56 -07:00
Eder Santana aa2ec42da6 stop gradients (#3221)
* stop gradients

* fix stop grad test

* stop gradients
2016-07-14 16:13:55 -07:00
Francois Chollet d90d473104 Add pooling layers page in docs 2016-07-14 15:27:46 -07:00
Francois Chollet 5a1e63990a Refactor batch norm 2016-07-14 15:05:48 -07:00
Francois Chollet e836c10c6f Fast BN for TF 2016-07-14 14:13:06 -07:00
Francois Chollet 47c09d9557 Add SeparableConv2D layer (TF only) 2016-07-14 11:22:27 -07:00
Francois Chollet b35b943364 Add support for None activations 2016-07-14 04:38:53 -07:00
Francois Chollet ca467cc50e Add support for input tensors in InputLayer 2016-07-14 04:30:21 -07:00
Francois Chollet 51f7cf0367 Doc formatting fix 2016-07-14 04:20:12 -07:00
Francois Chollet 642eaca618 Doc formatting fix 2016-07-13 12:38:45 -07:00
Francois Chollet 55e5680535 Update doc generation script 2016-07-13 12:35:11 -07:00
Francois Chollet 52ea31b65c Add FAQ entry on pre-trained models 2016-07-13 12:34:58 -07:00
Wei Ouyang b3a26a5b30 Add AtrousConv2D layer for dilated convolution (#3183) 2016-07-13 08:28:23 -07:00
Dave Challis 98974efa5f Fix to error message in exception (#3213)
Was incorrectly reporting the `loss` argument instead of the `loss_weights` argument when an exception related to loss_weights was thrown.
2016-07-13 08:27:03 -07:00
fchollet b6a776b242 Add Sequential.pop() method 2016-07-12 20:17:03 -07:00
Francois Chollet 1ea3f44f06 Fix dtype consistency issue in random_binomial 2016-07-12 17:05:47 -07:00
Michael Oliver 64e1320ca0 add dtype to zeros and ones allocations (#3187) 2016-07-09 10:10:15 -07:00
Francois Chollet 6e0b50fbdc Merge branch 'master' of https://github.com/fchollet/keras 2016-07-08 18:44:37 -07:00
Francois Chollet 22502a8fe8 Style fixes in regularizers 2016-07-08 18:44:23 -07:00
Jason Yosinski a78ad01bb4 Create initial_state tensor filled with zeros without use of K.zeros (#3123)
* Create initial_state tensor filled with zeros without use of K.zeros

* minor PEP8 fix
2016-07-06 12:47:14 -07:00
Carl Thomé 729e802e85 Added optional field name argument to RemoteMonitor callback (#3157)
* Added optional path argument

* Added optional field name argument
2016-07-06 09:47:03 -07:00
Joshua Chin 3ffff6d579 fix get_output_shape_for in Merge, when mode is callable (#3144) 2016-07-05 09:29:40 -07:00
Francois Chollet 6e5f97fca5 Merge branch 'master' of https://github.com/fchollet/keras 2016-07-04 14:21:13 -07:00
Francois Chollet eaff5bdfd7 Style touch-ups in TF backend 2016-07-04 14:20:54 -07:00
Francois Chollet 28819d36a4 Less frequent dataset tests 2016-07-04 14:17:35 -07:00
lucasmoura f9a4f6f306 Use defaultdict for _UID_PREFIXES (#3087)
The method get_uid on common.py first check if a prefix is in _UID_PREFIXED dict
and if it is not, a variable is added to the dict.

However, using a defaultdict, this check is no longer necessary.
2016-07-04 13:26:44 -07:00
Dmytro Mishkin 27c83c693d Added 'max' operation to Merge layer (#3128)
* Added 'max' operation to Merge layer. It allows to implement convolutional maxout with two (or more) convoluion layers and one Merge.

* Added 'max' to merge test
2016-07-04 11:03:07 -07:00
Eder Santana d106908a57 fix docs bugs (#3142)
* fix docs bugs

* fix docs bugs
2016-07-04 11:02:47 -07:00
Brian McMahan b4adce34dc Lambda output shape (#2680)
* updating the info for lambda

* updated lambda doc a bit more

made it more readable and stuff
2016-07-03 21:57:46 -07:00
Thibault de Boissière 3927505d1a Add multiprocessing for fit generator (#3049)
* Add multiprocessing for fit generator

* Change maxproc to nb_worker and update documentation

* Simplify multiprocessing test, clarify doc replace maxproc by nb_worker

* Replace maxproc by nb_worker in test

* Replace maxproc by nb_worker in test

* Update the doc: specify non picklable arguments should not be used with multiprocessing

* Add multiprocessing as an option with the pickle_safe argument
2016-07-03 21:50:01 -07:00
fchollet ede79f818e Add MIT license badge to README 2016-07-03 21:19:05 -07:00
Francois Chollet 742ac53262 Merge branch 'locally_connected' 2016-07-03 20:52:54 -07:00
Francois Chollet ee17ccc374 Add tests for locally connected layers 2016-07-03 20:51:58 -07:00
joelthchao 835a02c037 locally-connected layer
add unittest, fix output shape

PEP8

flatten weight, improve example

update docstring, remove cifar10 Alex exmaple

improve docstring, remove duplicate func

parallel by batch_dot

fix theano batch_dot

dim_ordering unit test, theano only use dot

dim_ordering unit test

Update locally connected layers
2016-07-03 20:48:22 -07:00
François Chollet ee8ff00a2a New conv ops (#3134)
* New function signature for conv2d in backend

* Clean up stuff

* Touch-up TF deconv op

* More cleanup

* Support for TF 3D conv/pool

* Move pooling layers to their own file

* Update TF version in Travis config

* Fix conv3d tests
2016-07-03 20:33:21 -07:00
fchollet 229f13a864 Lambda should not support masking implicitly 2016-07-02 15:12:46 -07:00
Rompei 0d60d637af TimeDistributedDense -> TimeDistributed(Dense()) in doc example 2016-07-02 12:12:54 -07:00
Francois Chollet c20e34a8b0 Prevent image_dim_ordering from being overwritten 2016-07-02 10:24:48 -07:00
Fariz Rahman 8d3f39852a Validate dot_axes argument in cos mode and fix output shape (#3116)
* Validate dot_axes argument in cos mode

* Update topology.py

* Update topology.py
2016-07-01 11:41:13 -07:00
Carl Thomé aa45dee5a4 Added optional path argument (#3118) 2016-07-01 10:56:17 -07:00
fchollet 885e6e621b Style fix in test 2016-06-30 23:22:06 -07:00
fchollet dc122c31ef Fix masking test 2016-06-30 23:19:51 -07:00
fchollet 3bc80d3db4 Remove unnecessary assert 2016-06-30 23:04:12 -07:00
Francois Chollet 439f2f3b2b Fix issue with multi-io + BatchNorm mask computing 2016-06-30 22:19:17 -07:00
Joshua Chin a1610eb274 model should use binary accuracy for binary crossentropy loss (#3098) 2016-06-28 12:45:34 -07:00
Francois Chollet 6b90eff03c Fix flaky test 2016-06-27 12:16:54 -07:00
Francois Chollet 4d404d1a54 Prepare 1.0.5 PyPI release 2016-06-27 12:01:20 -07:00
Francois Chollet fffa6a80ca Add attribute caching for flattened_layers 2016-06-27 11:51:28 -07:00
Francois Chollet 3f6b38b34f Fix duplicated updates issue 2016-06-27 11:51:12 -07:00
Francois Chollet 8166a55761 Fix flaky test 2016-06-27 11:50:56 -07:00
Shota 89f6d374e9 Fix typo (#3070) 2016-06-25 12:01:20 -07:00
M.Yasoob Ullah Khalid ☺ 9b3c2cf348 A small typo (#3067) 2016-06-24 19:04:28 -07:00
Francois Chollet 76406dd0c2 Remove unnecessary space 2016-06-23 16:17:36 -07:00
Francois Chollet d266b75423 Small fixes in text gen example 2016-06-23 16:17:24 -07:00
Francois Chollet 5bb5eb1657 Fix flaky test 2016-06-23 12:08:25 -07:00
Benjamin Bolte 258cf3b0f7 Support for masking in merged layers (#2413)
* added masking to merge layer (#2413)

* added documentation, fixed stylistic issues

* removed casting

* changed to using K.all
2016-06-23 12:03:55 -07:00
Utkarsh Upadhyay cdb5b09cd7 fix: Sort subdirs before mapping them to classes. (#3052)
The documentation says that [1]: 

> If [classes are] not provided, the list of classes will be automatically inferred (and the order of the classes, which will map to the label indices, will be alphanumeric).

However, the code was adding classes in the order `os.listdir` returned them. This commit alphanumerically sorts the sub-directories before mapping them to label indices.

[1] http://keras.io/preprocessing/image/
2016-06-23 11:32:40 -07:00
MikeAmy cb3469215a Moved epoch_logs = {} before batch loop to avoid UnboundLocalError. (#3019) 2016-06-20 08:18:01 -07:00
ηzw 703c2925b3 Add comment for a note of caution (#3024) 2016-06-19 12:36:05 -07:00
lucasmoura b6ca3ef051 Avoid double key lookup on callback.py (#3018)
On method on_epoch_end, to add new keys to the history dict, first it is
verified if a key is not on the history dict and if that is the case, a new key
is created on the history dict with an empty list as value.

However, this operation search for a key twice in the dict. This same behavior
can be achieved in a single step using dict setdefault method.
2016-06-19 10:48:53 -07:00
André Artelt b235f91cc7 doc: fix example for recurrent layer (#3022) 2016-06-19 10:39:23 -07:00
jkleint 3513472467 Allow re-use of EarlyStopping callback objects. (#3000)
An EarlyStopping callback object has internal state variables to tell it
when it has reached its stopping point.  These were initialized in __init__(),
so attempting to re-use the same object resulted in immediate stopping. This
prevents (for example) performing early stopping during cross-validation with
the scikit-learn wrapper.

This patch initializes the variables in on_train_begin(), so they are re-set
for each training fold.  Tests included.
2016-06-18 15:04:30 -07:00
Carlos Bentes 60e0c96f6c Fix typo in training (#3014) 2016-06-18 10:42:38 -07:00
Tsukasa ŌMOTO e37df7ca85 Fix json serialization in Lambda layer (#3012)
Fix #2582
Fix #3001
2016-06-17 21:26:45 -07:00
Tsukasa ŌMOTO a13a35fe52 Fix json serialization in merge layer with lamda output shape (#3011)
Fix #3008
2016-06-17 21:26:29 -07:00
Zhengping Che f421600218 fix wrong calls of __init__ in callbacks (#2999) 2016-06-16 14:51:28 -07:00
Francois Chollet 2a4492d74f Fix typo in docs 2016-06-16 10:56:34 -07:00
Tsukasa ŌMOTO 10368d867f Fix TF-IDF in Python 2 (#2992)
Fix #2974
2016-06-16 08:49:17 -07:00
Tsukasa ŌMOTO 936360020c Fix tf-idf again (#2986)
Fix 53aaa842ed
Fix #2974
2016-06-15 09:11:01 -07:00
ηzw c53c64d7fa Fix get_word_index (#2981) 2016-06-14 18:59:10 -07:00
Francois Chollet 6b122ba25f Allow arbitrary output shapes for custom losses 2016-06-14 16:40:58 -07:00
Francois Chollet 6501b587c0 Clarify use of two-branch models 2016-06-14 12:12:21 -07:00
Tsukasa ŌMOTO 53aaa842ed Fix tf-idf (#2980)
Fix #2974
2016-06-14 11:39:07 -07:00
Francois Chollet dc569e952d Merge branch 'master' of https://github.com/fchollet/keras 2016-06-13 12:06:45 -07:00
Francois Chollet c9aee4126e Fix issue with cascade of Merge layers 2016-06-13 12:05:48 -07:00
githubnemo 7397f4b0d0 Resolve #2960 (#2961)
* Resolve #2960

Introduce `K.var` so that the standard deviation computation can
be made numerically stable. Instead of

	K.std(x)

the user is able to write

	K.sqrt(K.var(x) + self.epsilon)

avoiding a division by zero in the gradient computation of `sqrt`.

* Fix typos
2016-06-12 21:16:21 -07:00
Rompei 3b83a1b1ac Fix initial variable in Evaluator. (#2955) 2016-06-12 14:50:56 -07:00
fchollet 8f8e4574dc Fix issue with Sequential deserialization 2016-06-12 11:04:09 -07:00
fchollet c30432a665 Nadam optimizer style fixes 2016-06-11 16:49:56 -07:00
Ilya Kulikov c4c2d8bbd4 Nadam optimizer and test for it added (#2764)
* Nadam optimizer and test for it added

* pep8 fix

* add comment in docstring and one more pep8 fix
2016-06-11 16:30:05 -07:00
Francois Chollet e49ba233f9 Convolution1D: apply activation after reshape 2016-06-10 15:05:34 -07:00
mpt5 cea6c1821f Update visualization.md (#2942)
* Update visualization.md

Added show_layer_names argument and its default value to docs

* Update visualization.md
2016-06-09 21:50:32 -07:00
Shaun Harker ab4bf447c6 Fix 1D convolution layers under Theano backend (#2938)
This issue is due to an unexpected loss of dimensionality when
composing the backend tensor operations "reshape" and "squeeze"
when there are dimensions of length 1.

For example, using a Theano backend the following fails with a
complaint about dimension mismatch:

UpSampling1D(2)(MaxPooling1D(2)(Reshape((2,1))(Input(shape=(2,)))))

The issue arises due to the conflict of two behaviors specific
to the Theano backend:

-   Reshape uses Theano's reshape function. Theano's reshape
    automatically makes dimensions with length 1 "broadcastable"

-   MaxPooling1D's implementation class _Pooling1D has a call method
    which uses a dummy dimension which it has to remove. The manner
    in which this dummy method is removed it to call "squeeze(x, axis)"
    from the backend. The squeeze implementation tells Theano to make
    the dummy dimension broadcastable, and then calls Theano's "squeeze",
    which removes ALL the broadcastable dimensions; not just the dummy
    dimension, but also the length 1 dimension flagged as broadcastable
    by reshape. This causes the problem observed above. This behavior
    is distinct from the behavior of the TensorFlow backend, which
    removes only the requested dimension.

This PR addresses this issue in two ways:

First, it introduces a test which checks the composition of "reshape"
and "squeeze" to make sure we get the same result using both Theano
and TensorFlow backends.

Second, it changes the implementation of squeeze(x,axis) so that the
Theano backend should behave similarly to the TensorFlow backend. With
this change the introduced test passes and the above example works.
2016-06-09 12:00:50 -07:00
Oswaldo Ludwig 4e0c8cf25b Eigenvalue Decay regularization (#2846)
* Update regularizers.py

I included a new regularizer named Eigenvalue Decay to the deep learning practitioner that aims at maximum-margin learning. This version approximates the dominant eigenvalue by a soft function given by the power method. For details, see:
Oswaldo Ludwig. "Deep learning with Eigenvalue Decay regularizer." ArXiv eprint arXiv:1604.06985 [cs.LG], (2016). https://www.researchgate.net/publication/301648136_Deep_Learning_with_Eigenvalue_Decay_Regularizer

The syntax for Eigenvalue Decay is similar to the other Keras weight regularizers, e.g.:

 model.add(Dense(100, W_regularizer=EigenvalueRegularizer(0.0005)))

* Example with Eigenvalue Decay regularization.

An example from Keras including regularization with Eigenvalue Decay. After training, you have to save the trained weights, create/compile a similar model without Eingenvalue Decay and save this model. Then, you can use your trained weights with this model, see lines 123-153 of  	CIFAR10_with_Eigenvalue_Decay.py (This is still an open issue).
This example yields a gain in the accuracy by the use of Eigenvalue Decay of 2.71% (averaged over 10 runs).

* Update CIFAR10_with_Eigenvalue_Decay.py

* Update CIFAR10_with_Eigenvalue_Decay.py

* Update CIFAR10_with_Eigenvalue_Decay.py

* Update regularizers.py

* Update regularizers.py

* Delete CIFAR10_with_Eigenvalue_Decay.py

* Update test_regularizers.py

* Update regularizers.py

* Update test_regularizers.py

* Update regularizers.py

* Update regularizers.py

I needed another reading in Keras backend...

* Issue to get shape of a tensor.

Issue to get shape of a tensor in the class EigenvalueRegularizer: the type returned for shape is different for Theano backend (Theano tensor type) and TF backend (TF TensorShape).

* Update regularizers.py

* Update regularizers.py

* Update regularizers.py

* Update regularizers.py

* Update regularizers.py

* Update regularizers.py

* Update regularizers.py
2016-06-08 12:20:25 -07:00
Francois Chollet e4b3a052a4 Small style fixes 2016-06-08 11:56:05 -07:00
Ziheng Jiang 825beb42c4 fix bug: rename duplicated loss name (#2842)
* rename duplicated loss name

* make python3 happy

* rewritten code to make it easy to read
2016-06-08 11:51:34 -07:00
Tammy Yang c8d605db55 Make DirectoryIterator case insensitive (#2932)
* make DirectoryIterator case insensitive

* Also need to make filename case insensitive while appending it into self.filenames
2016-06-08 11:27:19 -07:00
Ryo ASAKURA f6ecab58cb Fix description about parameter output_shape for function merge (#2933) 2016-06-08 11:26:56 -07:00
Tsukasa ŌMOTO d7e39347b9 Add mode=2 option to the docstring in BatchNormalization (#2919)
Fix a tiny typo.
2016-06-07 23:09:03 -07:00
Colin Rofls 25c10af596 fix 2852 (#2927) 2016-06-07 16:48:13 -07:00
Francois Chollet ded23f14c7 Fix typo in docs 2016-06-07 15:51:29 -07:00
Michael Crawford b0d52d930a Fix predict_proba method of KerasClassifier to return probabilites for both classes in case of binary classification. issue:2864 (#2924) 2016-06-07 11:48:04 -07:00
jakeleeme af5c5b6a55 Spellcheck source files (#2907) 2016-06-06 13:29:25 -07:00
ηzw ce51e19970 Fix typos in image preprocessing docs (#2906) 2016-06-06 13:28:39 -07:00
Francois Chollet 97e31b6090 Cleanup docs autogen script 2016-06-06 10:18:09 -07:00
Francois Chollet 62053e68e2 Prepare 1.0.4 PyPI release 2016-06-06 10:17:47 -07:00
Francois Chollet 489c07e748 Docs adjustment 2016-06-06 10:15:22 -07:00
fchollet 604ea8d68a Fix PEP8 BS 2016-06-05 20:41:19 -07:00
fchollet fd3cfb196b Allow no layer names in plot() 2016-06-05 20:20:14 -07:00
fchollet b71f6ba864 Allow absence of labels in flow() 2016-06-05 20:19:55 -07:00
fchollet dfc128b89a Fix some py3 generator issue 2016-06-05 14:52:10 -07:00
fchollet 34b8b57c2f Update image preprocessing docs 2016-06-05 14:01:28 -07:00
fchollet 3bba409d9e Improve docstring in preprocessing/image 2016-06-05 14:01:11 -07:00
fchollet 7869cdccec Merge branch 'master' of ssh://github.com/fchollet/keras 2016-06-05 13:39:55 -07:00
fchollet 0e18e345b0 Refactor ImageDataGenerator, add directory support 2016-06-05 10:24:54 -07:00
fchollet e5b99c7512 Tiny fixes in Sequential methods 2016-06-05 10:24:20 -07:00
aaditya prakash 7d4c85018a MaxoutDense no activation; incorrect docs (#2895)
Since MaxoutDense does not have activation it might be misleading to include "activation" as one of the arguments in the function docs.
2016-06-03 23:45:24 -07:00
fchollet edbec2dbc9 Remove bit of deprecated code 2016-06-03 23:13:46 -07:00
fchollet 973ece9809 Make dim_ordering a global default 2016-06-03 23:13:11 -07:00
lorenzoritter 90f441a6a0 fixed formatting error in the docstring (#2797)
* fixed formatting error in the docstring

* fixed formatting error in TimeDistributedDense of core.py
2016-06-02 19:07:34 -07:00
Andrew Stromnov 5a71090476 limit progress bar update rate (#2860)
* limit progress bar update rate

Limit progress bar update rate in verbose=1 mode. This patch allows to
reduce terminal I/O throughput while keeping reasonable high visual
update rate (defaults to 100 refreshes per second). It helps greatly
when working with large but simple data sets with small batches, which
leads to millions of relatively useless screen updates per second. Also
it helps to keep network traffic at reasonable rates, which
exceptionally useful within laggy networking conditions when using
keras over telnet/ssh, and improve web browser responsibility when
using keras within Jupyter Notebook.

* add docstrings for 'interval' and 'force' arguments
2016-06-02 13:06:37 -07:00
matthewmok 76cae0ec44 fix bug: change seed range for RandomStreams in Theano (#2865)
* bug fixed, numpy randint only output positive numbers ranging from 1 to 10e6

* Update theano_backend.py

changed style and numpy randint range

* Update theano_backend.py

removed extra spaces
2016-06-02 13:05:51 -07:00
talpay 273f0dda9d Added objective: Kullback Leibler Divergence (#2872)
* Added objective: Kullback Leibler Divergence

* KLD: Clip at 1
2016-06-02 10:23:00 -07:00
Tsukasa ŌMOTO 882b5a1d89 Fix YAML serialization when using Regularizers (#2883)
Fix #2871
2016-06-01 21:40:16 -07:00
ηzw 8c84ad1a86 fix typo (#2881)
* fix typo

* Update scikit-learn-api.md
2016-06-01 21:39:46 -07:00
Francois Chollet 80bfec7253 Fix JSON deserialization issue 2016-05-30 22:36:57 -07:00
fchollet 91b930298b Make Merge output_shape consistent with lambda 2016-05-30 20:50:59 -07:00
Tsukasa ŌMOTO 9c56b91548 Fix json serialization in merge layer (#2854)
Fix #2818
2016-05-30 20:30:07 -07:00
fchollet 7b5bab83f4 Merge branch 'master' of ssh://github.com/fchollet/keras 2016-05-29 15:36:21 -07:00
fchollet c5e2116ead Fix typo in doc 2016-05-29 15:36:14 -07:00
mittagessen d9db73a791 s/TimeDistributedDense/TimeDistribute(Dense(.../g (#2843) 2016-05-29 14:12:57 -07:00
Kumar Ayush 01ece4ef7b added required import line (#2839) 2016-05-27 23:56:51 -07:00
Francois Chollet 601f3e7cdb BN only uses learning phase in mode 0 2016-05-27 21:36:08 -07:00
Francois Chollet a9ca2c547f Merge branch 'master' of https://github.com/fchollet/keras 2016-05-27 21:32:53 -07:00
Francois Chollet 594cbed03b Small changes in mask caching 2016-05-27 21:32:43 -07:00
Monami Sharma 3938a905a1 Default values corrected for featurewise_std_normalization and featurewise_center (#2831)
For ImageDataGenerator, False is the default value for for featurewise_std_normalization and featurewise_center.
2016-05-27 08:59:10 -07:00
Francois Chollet 88d523e01b Add stateless batchnorm mode 2016-05-26 16:01:24 -07:00
Francois Chollet 0419fe67fc Merge branch 'master' of https://github.com/fchollet/keras 2016-05-25 16:46:21 -07:00
Francois Chollet 33ddeb5cbe Change way node depth is computed for shared layer 2016-05-25 16:46:06 -07:00
Colin Rofls 1f5d5b391b correctly serialize loss function (#2806) 2016-05-24 21:27:57 -07:00
fchollet 198c515208 Simplify imports in README 2016-05-23 23:59:34 -07:00
fchollet 5156673e17 Fix serialization issue with nested Sequential 2016-05-21 18:11:51 -07:00
fchollet 1529c9c438 Clarify error message 2016-05-21 17:01:39 -07:00
fchollet 32b10a8832 Fix first axis dim validation in multi-input model 2016-05-21 16:06:19 -07:00
fchollet 24501d4361 Fix ActivityReg layer 2016-05-21 15:46:32 -07:00
fchollet bf0c08e24a Add FAQ entry about layer freezing 2016-05-21 13:53:23 -07:00
RyosukeHonda 34d8cce6bc Fixed typo (#2770)
Fixed the year from "7 Apr 201" to "7 Apr 2015".
2016-05-21 10:12:45 -07:00
Joshua Loyal f0bfc24adc Correction to fan_out initializaiton (#2252)
* account for receptive field size in fan_out

* added test for conv layer initializations

* removed old reference to kernel_size
2016-05-19 22:11:41 -07:00
Xingdi (Eric) Yuan 2f8acfe4bf changeable print_summary (#2761)
* use changeable print_summary

* minor
2016-05-19 12:40:06 -07:00
gw0 e2fb8b2786 Add download error suggestion for babi_rnn.py and babi_memnn.py. (#2752) 2016-05-19 10:20:36 -07:00
Francois Chollet ebbc4d9fb8 Fix TB callback with non-standard TF version nums 2016-05-18 10:28:12 -07:00
Francois Chollet 8fc5b90e9a Update bibtex entry 2016-05-16 15:04:49 -07:00
mat kelcey 8a717f5b6c rename z_log_sigma to z_log_std to match z_mean (which is not z_mu) (#2729) 2016-05-16 11:08:00 -07:00
Colin Rofls aa91994166 save keras version & compile args when serializing models (#2690)
* save keras version & compile args when serializing models

* renamed prepare_config -> _updated_config + cleaner implementation
2016-05-15 20:18:31 -07:00
Joel 2091347a71 Fix zero division in merge mode='cos' (#2725)
* fix cos zero division

* use backend epsilon
2016-05-15 20:16:46 -07:00
Mikhail Korobov e0ed174f2c Input: proper error message for missing "shape" argument (#2727) 2016-05-15 15:15:14 -07:00
Francois Chollet 8c2a573ebf Prepare 1.0.3 release 2016-05-15 13:13:19 -07:00
Francois Chollet d7ff7cde92 Add VAE example 2016-05-14 12:06:23 -07:00
Francois Chollet 15d0b0ea08 Add K.tile test 2016-05-14 12:06:02 -07:00
Francois Chollet 3695bc2db5 Remove references to "join" merge mode 2016-05-13 11:06:08 -07:00
Francois Chollet a08995a90d Fix common LaTeX encoding issue 2016-05-12 12:03:20 -07:00
Tsukasa ŌMOTO aea00258e7 Update the reference of Batch Normalization (#2700)
We should refer the paper accepted in ICML 2015, instead of arXiv.
2016-05-12 09:54:46 -07:00
fchollet b581eb3f27 Update RMSprop 2016-05-11 21:35:11 -07:00
Francois Chollet 610ccba9f5 Normalize layer imports in examples 2016-05-11 18:45:37 -07:00
Francois Chollet d5ae6f32dd Fix flaky test 2016-05-11 18:01:01 -07:00
Francois Chollet 5308033936 Update RMSprop, Adagrad, Adadelta 2016-05-11 17:20:27 -07:00
Francois Chollet e2abb5ef2c Fix merge conflicts 2016-05-11 16:07:43 -07:00
Francois Chollet 1b11b4eeb6 Fix shape inference issue with TF.resize_images 2016-05-11 16:06:03 -07:00
Dieuwke Hupkes 39357b3045 Update documentation docstring Embedding (#2693)
From the documentation it is not entirely clear that if mask_zero is set
to True, the input_dim argument should be equal to the size of the
vocabulary + 2, as index 0 cannot be used anymore.

(This behaviour seems a bit strange, as it has as a consequence that the
first column of the weights of the embeddings will never be used or
updated. The resulting network thus has a redundant set of parameters).
2016-05-11 14:10:58 -07:00
Kai Sasaki ed7a5a1418 Residual connection should have the same dimension in case of no projection matrix (#2688) 2016-05-10 21:18:39 -07:00
Kyle McDonald ae682a71f9 functional API intermediate output doc in faq (#2682) 2016-05-10 08:22:53 -07:00
Brian McMahan 8327b37a0b fixed shape typo (#2679)
* fixed shape typo

* pep8
2016-05-09 22:17:12 -07:00
fchollet 973b5570aa Style touch-up 2016-05-06 20:37:46 -07:00
fchollet 7cb41fc5cc Fix weight saving issue 2016-05-06 20:37:35 -07:00
Tsukasa ŌMOTO 595d67ad7d Fix initialization of index_array (#2590)
index_array should be initialized when self.batch_index is zero.
2016-05-06 18:13:11 -07:00
François Chollet bb626c120e Revert "Revert "remove unused import statement in keras dir"" (#2647) 2016-05-06 13:32:43 -07:00
Xingdi (Eric) Yuan ba8fefa8ec Faster GRU (#2633)
* add a simple named entity recognition example

add a simple named entity recognition example

* add fast version of GRU

add fast version of GRU

* remove useless stuff
2016-05-06 11:10:46 -07:00
François Chollet 4b24f6d7b1 Revert "remove unused import statement in keras dir" (#2641) 2016-05-05 23:22:28 -07:00
ηzw 1c460e1e08 remove unused import statement in keras dir (#2638)
* remove unused import statement in keras dir

* rewrite import graph statement
2016-05-05 21:33:04 -07:00
Colin Rofls 7b4e157356 fixed docs for Sequential.get_config, and added a more helpful (#2635)
exception to `model_from_config`.
2016-05-05 15:24:52 -07:00
Dr. Kashif Rasul 5749f1b971 fix soft sign deprecation warning (#2623)
and backward compatible
2016-05-05 13:02:37 -07:00
Francois Chollet 3c57aff85b Style fixes 2016-05-05 11:17:25 -07:00
Carl Thomé 18504bcc86 Faster LSTM (#2523)
* Faster LSTM

* PEP8

* RNN dropout fix

* PEP

* PEP

* Less code duplication

* LSTM benchmark example

* PEP

* Test implementation modes

* Go through Keras backend
2016-05-05 11:01:48 -07:00
Francois Chollet d8864bfe48 Allow use of predict without compilation 2016-05-05 08:24:12 -07:00
Nic Eggert 078b20169b Add batch_get_value to backends (#2615)
* Add function to get multiple values at once

* Change to match existing batch_set_value

* Fix typo
2016-05-04 17:13:17 -07:00
Francois Chollet 5f7e78df65 Improve optimizer configuration 2016-05-04 14:18:06 -07:00
Francois Chollet fc470db7ab Fix typos in layer writing guide 2016-05-03 11:29:50 -07:00
jingzhehu f576f37801 one line fix for TensorBoard callback issue (#2574)
* one line fix for TensorBoard callback issue

Ref: https://github.com/fchollet/keras/issues/2570

* handle SummaryWriter based on tensorflow version

code contributed by @bnaul

https://github.com/bnaul/keras/commit/e04ce5e37ec234debaea8c6482ef90be1f
88286d
2016-05-03 10:51:43 -07:00
Francois Chollet b74118a766 Fix typo in documentation 2016-05-02 15:59:04 -07:00
Brian McMahan 1c7a0248b9 updated for list check bug in predict/predict_on_batch (#2585)
* updated for list check bug in predict/predict_on_batch

* pep fix

I think that's going to be the only pep complain..
2016-05-02 15:33:25 -07:00
Francois Chollet 36a829c20d Add doc page about writing custom layers. 2016-05-02 14:16:09 -07:00
chentingpc 33af75aa39 fix activity regularizer so it can deal with multiple inbound nodes as well (#2573) 2016-05-01 16:36:31 -07:00
jpeg729 844420425e Added softsign activation function (#2097) 2016-04-30 18:29:33 -07:00
Francois Chollet da57a530f9 "total_loss" -> "loss" 2016-04-30 16:38:23 -07:00
fchollet 1f17013949 Misc fixes 2016-04-30 15:09:35 -07:00
fchollet f18899cb36 Merge branch 'master' of https://github.com/commaai/keras into commaai-master 2016-04-30 14:09:56 -07:00
Sasank Chilamkurthy 877f946e24 Improved docs of ImageDataGenerator (#2565) 2016-04-30 11:53:44 -07:00
Francois Chollet a981a8c42c Make bias optional everywhere 2016-04-29 16:54:39 -07:00
Francois Chollet 5467107fc9 Prepare 1.0.2 PyPI release 2016-04-29 10:39:52 -07:00
Gijs van Tulder ad3107073b Re-raise exceptions to preserve stack trace (#2350) 2016-04-28 12:38:36 -07:00
Francois Chollet 8d62f4da6c Minor UX fix 2016-04-27 17:34:33 -07:00
Joel 3779b8a008 Fix test_image path non-exist error in ci-travis (#2531)
* correct inception_v3 network

* store test images in class attribute

* PEP8
2016-04-27 11:35:31 -07:00
Francois Chollet 6ec5e48969 Style touch-ups 2016-04-27 10:53:54 -07:00
fchollet bfa5ca553d Fix docstring 2016-04-27 09:20:19 -07:00
Francois Chollet c9f7d970e9 Style fixes in preprocessing/image 2016-04-26 15:24:05 -07:00
Sasank Chilamkurthy f26ce6e236 Rewriting image augmenter (#2446)
* Much better image data augmentor

* removed unnecessary functions

* shift origin to centre of the image for homographies

* init commit

* change to zoom_range

* Added scikit-image to extras_require in setup.py

* add zoom_range test, exception for invalid zoom_range

* add scikit-image to dependency

* fix fit and retain old functions for unit test

* use ndi insteadskimage in random_transform

* removed buggy code in random_rotations, shears etc  and replaced it with todos.

* remove sci-image, implement ndimage based methods, refactor random_transform

* random_zoom, array_to_img consider dim_ordering

* add random_channel_shift, support fill_mode and cval

* image doc, update test_image, PEP8

* fix channel shift clip

* fix doc, refine code

* detail explain of zoom range

* check coding style
2016-04-26 15:21:14 -07:00
Brian McMahan b001e36f18 adding a disable_b boolean to Dense (#2512)
* adding a disable_b boolean to Dense

* changing 'disable_b' to 'bias' 

Changing the name of the boolean & flipping its behavior so that the default is True and when set to False the bias is not used.

* integrating bias flag fully

changed the bias flag to affect the creation of the self.b variable as well as the output calculation

* fixing a blank line to appease pep8
2016-04-26 14:25:00 -07:00
Francois Chollet 9abb6ef723 Add TF graph management warning 2016-04-26 13:02:39 -07:00
Francois Chollet bfbdbb05bc Add root imports 2016-04-26 13:02:11 -07:00
Francois Chollet bd2bd51b5d Fix typo in README 2016-04-25 19:06:31 -07:00
Francois Chollet 4e547a31ed Improve TF session & variable management 2016-04-25 18:49:19 -07:00
Francois Chollet de8d0defcd Fix PEP8 2016-04-25 18:48:23 -07:00
gw0 344437c491 Fix plot with show_shapes and multiple inputs/outputs. (#2421) 2016-04-25 15:29:16 -07:00
George Hotz ed365e94fd Added simple support for returning a multitarget loss 2016-04-25 14:46:03 -07:00
TobyPDE 5910278ca8 Fixed minor typo in getting-started/sequential-model-guide (#2499) 2016-04-25 09:14:18 -07:00
fchollet 18841fa58d Fix build 2016-04-24 22:18:02 -07:00
Carl Thomé 6fb4e0e441 Add cos and sin to backend (#2493) 2016-04-24 21:43:57 -07:00
Francois Chollet 39051ef3ca Add model_from_config in models.py 2016-04-24 14:33:27 -07:00
fchollet 1f4084870b Add new metrics and metrics tests 2016-04-24 12:10:47 -07:00
fchollet 00e9d5b219 Update regularizer tests 2016-04-24 10:27:45 -07:00
fchollet 7f93747602 Remove outdated comment 2016-04-24 10:27:45 -07:00
Kai Li a7156b8c27 Update antirectifier.py (#2485) 2016-04-24 09:34:20 -07:00
fchollet b1e47f7741 Fix PEP8 2016-04-23 13:55:20 -07:00
Ke Ding 59f8d6ca22 add weights for SGD optimizer (#2478) 2016-04-23 13:33:14 -07:00
Rich P. I. Lewis 5f4019d980 fixed Merge Layer functional API (#2460)
* fixed Merge Layer functional API

* moved test to layers/test_core
2016-04-23 13:32:45 -07:00
Ke Ding f84389da08 fix a benign but wrong range number in GRU's get_constants (#2475) 2016-04-22 18:55:38 -07:00
Jiyuan Qian 63c1757df5 fix accuracy with sparse_categorical_crossentropy (#2471) 2016-04-22 10:41:14 -07:00
Joel d6ab850f45 correct inception_v3 network (#2472) 2016-04-22 10:38:19 -07:00
graham 61dd53e262 allows python3.5 to build alongside < 3.5 (#2457) 2016-04-21 15:31:25 -07:00
Francois Chollet 423a633b5b Update merge tests 2016-04-21 09:44:44 -07:00
Colin Rofls 256d4ef71b clarified usage of sparse_categorical_crossentropy (#2450)
- addressess #2444
2016-04-21 09:36:39 -07:00
Philip Bachman ad49962ba9 fix layer/node topo sort problem (#2433)
* fix layer/node topo sort problem

* fix to only iterate over valid layer/node keys
2016-04-20 21:38:23 -07:00
Brian McMahan 4680d70a78 fixing the constants thing in theano rnn (#2429) 2016-04-20 11:17:05 -07:00
Dapid ee7f056779 DOC: models should be compiled upon loading (#2428) 2016-04-20 10:23:26 -07:00
Francois Chollet 66c8d7baf2 Merge branch 'master' of https://github.com/fchollet/keras 2016-04-20 09:43:12 -07:00
Francois Chollet 9f929999d1 Fix Travis concurrent directory creation issue 2016-04-20 09:43:01 -07:00
fchollet 24f96262ec Add additional input data validation check 2016-04-20 08:53:40 -07:00
Brian McMahan 0e6e7a41f4 adding built check inside TimeDistributed (#2426) 2016-04-20 08:41:27 -07:00
Dan Becker 5cac088d98 Add scikit_learn wrapper example (#2388)
* Add scikit_learn wrapper example

* Extract and evaluate best model in examples/mnist_sklearn_wrapper.py
2016-04-19 21:50:50 -07:00
Francois Chollet 85f0448fee Make merge work with pure TF/TH tensors 2016-04-19 18:46:54 -07:00
Francois Chollet 106c0b753a Merge branch 'master' of https://github.com/fchollet/keras 2016-04-19 11:57:30 -07:00
Francois Chollet c525e634dc Fix loss compatibility validation 2016-04-19 11:57:19 -07:00
Eder Santana c398c0891b add eye to backened (#2407) 2016-04-19 11:38:21 -07:00
Francois Chollet 5ab48ac5d4 Update imagedatagenerator 2016-04-19 11:19:12 -07:00
Jeffery Ye ba29cd8e46 set input_length before reshape (#2410) 2016-04-19 10:49:47 -07:00
chardmeier b61235b77f Fixed typo. (#2401) 2016-04-19 10:20:13 -07:00
Francois Chollet 0ed00e38f0 Add inception v3 example 2016-04-18 21:51:43 -07:00
Francois Chollet 36eef0dd9a Add reset function to ImageDataGenerator 2016-04-18 21:51:43 -07:00
fchollet 1904194c7a Fix wrapper learning phase 2016-04-18 20:07:30 -07:00
Francois Chollet 7ce144881a Fix stateful unrolled RNNs in Theano 2016-04-18 17:09:20 -07:00
Eder Santana 55159cf451 Update topology.py (#2373) 2016-04-17 14:21:31 -07:00
Francois Chollet 7a12fd0f85 1.0.1 release 2016-04-16 14:11:34 -07:00
Steven Hugg 9d60126661 fixed TensorBoard callback (#2363) 2016-04-16 13:56:56 -07:00
Francois Chollet e341e73c6a Fix Dropout in RNNs 2016-04-16 09:08:15 -07:00
Francois Chollet 5dad3786f6 Add batch_set_value for faster TF weight loading 2016-04-15 22:40:54 -07:00
Francois Chollet ed0cd2c60d Add TF/TH kernel conversion util 2016-04-15 22:37:41 -07:00
Kai Li 2eea3a4c5d Update model.md (#2348) 2016-04-15 08:21:46 -07:00
Gijs van Tulder 090a46763e Fix support for custom metrics functions (#2351) 2016-04-15 08:21:16 -07:00
Dan Becker c4ed82cdf6 Fix typo in docs. loss_weight should be loss_weights (#2343) 2016-04-14 21:53:33 -07:00
Dan Becker b32248d615 Change error message in standardize_input_data (#2338) 2016-04-14 19:18:53 -07:00
Francois Chollet ca7437502b Shape inference fix for Embedding 2016-04-14 15:44:36 -07:00
Francois Chollet fe9b797a46 Style fixes in preprocessing/image 2016-04-14 15:44:24 -07:00
Francois Chollet b8059aeaba Fix test_image unit test 2016-04-14 13:38:07 -07:00
Daniele Bonadiman 85f80714c2 Max Over Time in imdb_cnn.py (#2320)
* Max Over Time in imdb_cnn.py

Following this issue https://github.com/fchollet/keras/issues/2296 i propose this PR.
The mayor optimisation a part of the Max over time are:

- Dropout in the Embedding layer.
- Longer input sequences (400 instead of 100), made possible from the speedup of the Max Over Time.
- Adam optimizer.

Overall it takes 90 to 100 sec per epoch on my laptop CPU and in two epochs it reaches 0.885 accuracy that is a 5 points improvement over the previous implementation. Moreover it requires less memory (300k parameters vs 3M+) since the number of parameters do not depend  by the length of the input sequence anymore.

* Update imdb_cnn.py
2016-04-14 13:22:06 -07:00
fchollet 2cc9ebf28b Add set_learning_phase in TF backend. 2016-04-14 08:32:04 -07:00
fchollet cb5d69c769 Fix case where output_shape in Merge is tuple 2016-04-13 21:20:21 -07:00
Francois Chollet 3b961a6b7b Fix Graph generator methods 2016-04-13 19:30:11 -07:00
Francois Chollet cba3ea9d90 Fix PEP8 2016-04-13 18:32:18 -07:00
Thomas Boquet 57ea065db7 Added learning phase to callbacks (#2297) (#2303)
* added learning phase to callbacks (#2297)

* cleaned imports

* replaced tabs by spaces

* added case where uses_learning_phase is False

* fixed pep8 blank line bug
2016-04-13 18:00:49 -07:00
Ben Cook 4f5f88b9ba Expose max_q_size and other generator_queue args (#2300)
* [#2287] expose generator_queue args

* [#2287] only expose max_q_size
2016-04-13 18:00:25 -07:00
Francois Chollet c1c2b330a1 Fix "trainable" argument 2016-04-13 17:58:05 -07:00
Francois Chollet 05e1d8e5f4 Fix siamese example 2016-04-13 12:05:42 -07:00
Francois Chollet 3cbca7bdba Fix validation_split 2016-04-13 11:39:16 -07:00
Francois Chollet 3e3c210f1d Update preprocessing/image documentation 2016-04-13 10:15:26 -07:00
Dan Becker cb65139aa8 Allow 'tf' ordering in ImageDataGenerator (#2291) 2016-04-13 10:14:59 -07:00
Francois Chollet 1206120d10 Fix callback issue with Sequential model 2016-04-12 15:22:05 -07:00
Francois Chollet 80ebe80138 Callback style fix 2016-04-12 15:21:02 -07:00
Francois Chollet fa1d6b478e Fix generators methods when passing data as dicts 2016-04-12 13:51:45 -07:00
Francois Chollet 345413fb8c Merge branch 'master' of https://github.com/fchollet/keras 2016-04-12 12:52:05 -07:00
Kyle McDonald 66ebd2a843 corrected parameter for learning_phase (#2284) 2016-04-12 10:18:42 -07:00
fchollet d50f469c09 Fix for invalid dropout values 2016-04-12 09:41:29 -07:00
Charles-Emmanuel 26714bc635 Small typo (#2282)
Small type
2016-04-12 09:23:20 -07:00
Pasquale Minervini 30208ae08b Fix for issue #2276 (#2277) 2016-04-12 09:20:20 -07:00
Francois Chollet 6ea3188971 Fix typo 2016-04-11 22:47:18 -07:00
Kyle McDonald 1db555a530 remove creation of np.asarray in to_categorical (#2268) 2016-04-11 22:36:37 -07:00
Francois Chollet 0772210dea Better error messages for Sequential 2016-04-11 16:41:08 -07:00
120 arquivos alterados com 7980 adições e 2587 exclusões
+4 -2
Ver Arquivo
@@ -49,14 +49,16 @@ install:
# install TensorFlow
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl;
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0-cp27-none-linux_x86_64.whl;
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp34-none-linux_x86_64.whl;
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.9.0-cp34-cp34m-linux_x86_64.whl;
fi
# command to run tests
script:
# run keras backend init to initialize backend config
- python -c "import keras.backend"
# create dataset directory to avoid concurrent directory creation at runtime
- mkdir ~/.keras/datasets
# set up keras backend
- sed -i -e 's/"backend":[[:space:]]*"[^"]*/"backend":\ "'$KERAS_BACKEND'/g' ~/.keras/keras.json;
- echo -e "Running tests with the following config:\n$(cat ~/.keras/keras.json)"
+3 -2
Ver Arquivo
@@ -2,6 +2,7 @@
[![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)
## You have just found Keras.
@@ -38,7 +39,7 @@ 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 function API](http://keras.io/getting-started/functional-api-guide).
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).
Here's the `Sequential` model:
@@ -51,7 +52,7 @@ model = Sequential()
Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
from keras.layers import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
+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
+21 -108
Ver Arquivo
@@ -53,10 +53,16 @@ Scikit-learn API
'''
from __future__ import print_function
from __future__ import unicode_literals
import re
import inspect
import os
import shutil
import sys
if sys.version[0] == '2':
reload(sys)
sys.setdefaultencoding('utf8')
from keras.layers import convolutional
from keras.layers import recurrent
@@ -76,11 +82,13 @@ from keras import constraints
from keras import activations
from keras import regularizers
EXCLUDE = {
'Optimizer',
'Wrapper',
'get_session',
'set_session',
'CallbackList',
}
PAGES = [
@@ -139,13 +147,8 @@ PAGES = [
'classes': [
convolutional.Convolution1D,
convolutional.Convolution2D,
convolutional.AtrousConv2D,
convolutional.Convolution3D,
convolutional.MaxPooling1D,
convolutional.MaxPooling2D,
convolutional.MaxPooling3D,
convolutional.AveragePooling1D,
convolutional.AveragePooling2D,
convolutional.AveragePooling3D,
convolutional.UpSampling1D,
convolutional.UpSampling2D,
convolutional.UpSampling3D,
@@ -154,6 +157,17 @@ PAGES = [
convolutional.ZeroPadding3D,
],
},
{
'page': 'layers/pooling.md',
'classes': [
convolutional.MaxPooling1D,
convolutional.MaxPooling2D,
convolutional.MaxPooling3D,
convolutional.AveragePooling1D,
convolutional.AveragePooling2D,
convolutional.AveragePooling3D,
],
},
{
'page': 'layers/recurrent.md',
'classes': [
@@ -250,8 +264,6 @@ def get_function_signature(function, method=True):
for a, v in kwargs:
if type(v) == str:
v = '\'' + v + '\''
elif type(v) == unicode:
v = 'u\'' + v + '\''
st += str(a) + '=' + str(v) + ', '
if kwargs or args:
return st[:-2] + ')'
@@ -330,6 +342,7 @@ def process_function_docstring(docstring):
print('Cleaning up existing sources directory.')
if os.path.exists('sources'):
shutil.rmtree('sources')
print('Populating sources directory with templates.')
for subdir, dirs, fnames in os.walk('templates'):
for fname in fnames:
@@ -414,103 +427,3 @@ for page_data in PAGES:
if not os.path.exists(subdir):
os.makedirs(subdir)
open(path, 'w').write(mkdown)
# covered_so_far = set()
# for module, module_name in MODULES:
# class_pages = []
# for name in dir(module):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# module_member = getattr(module, name)
# if module_member in covered_so_far:
# continue
# if inspect.isclass(module_member):
# cls = module_member
# if cls.__module__ == module_name:
# try:
# class_signature = get_function_signature(cls.__init__)
# class_signature = class_signature.replace('__init__', cls.__name__)
# except:
# # in case the class inherits from object and does not
# # define __init__
# class_signature = module_name + '.' + cls.__name__ + '()'
# functions = []
# functions_not_defined_here = []
# for name in dir(cls):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# cls_member = getattr(cls, name)
# if inspect.isfunction(cls_member):
# function = cls_member
# signature = inspect.getargspec(function)
# defaults = signature.defaults
# args = signature.args[1:]
# if defaults:
# kwargs = zip(args[-len(defaults):], defaults)
# args = args[:-len(defaults)]
# else:
# kwargs = []
# defined_by = get_earliest_class_that_defined_member(function.__name__, cls)
# if cls == defined_by:
# functions.append(function)
# else:
# functions_not_defined_here.append((function, defined_by))
# blocks = []
# blocks.append('<span style="float:right;">' + class_to_source_link(cls) + '</span>')
# blocks.append('# ' + cls.__name__ + '\n')
# blocks.append(code_snippet(class_signature))
# docstring = cls.__doc__
# if docstring:
# blocks.append(process_class_docstring(docstring))
# if cls.__name__ in INCLUDE_functionS_FOR:
# if functions or functions_not_defined_here:
# blocks.append('### functions\n')
# for function in functions:
# signature = get_function_signature(function)
# signature = signature.replace(module_name + '.', '')
# blocks.append(code_snippet(signature))
# docstring = function.__doc__
# if docstring:
# blocks.append(process_function_docstring(docstring))
# for function, defined_by in functions_not_defined_here:
# signature = get_function_signature(function)
# function_module_name = function.__module__
# signature = signature.replace(function_module_name + '.', '')
# link = '[' + defined_by.__name__ + '](' + class_to_docs_link(defined_by) + ')'
# blocks.append(code_snippet(signature))
# blocks.append('Defined by ' + link + '.\n')
# mkdown = '\n'.join(blocks)
# class_pages.append((id(cls), mkdown))
# covered_so_far.add(module_member)
# class_pages.sort(key=lambda x: x[0])
# class_pages = [x[1] for x in class_pages]
# module_page = '\n----\n\n'.join(class_pages)
# # save module page.
# # Either insert content into existing page,
# # or create page otherwise
# path = 'sources/' + module_name.replace('.', '/')[6:] + '.md'
# if os.path.exists(path):
# template = open(path).read()
# assert '{{autogenerated}}' in template, ('Template found for ' + path +
# ' but missing {{autogenerated}} tag.')
# module_page = template.replace('{{autogenerated}}', module_page)
# print('...inserting autogenerated content into template:', path)
# else:
# print('...creating new page with autogenerated content:', path)
# subdir = os.path.dirname(path)
# if not os.path.exists(subdir):
# os.makedirs(subdir)
# open(path, 'w').write(module_page)
+1
Ver Arquivo
@@ -24,6 +24,7 @@ pages:
- About Keras layers: layers/about-keras-layers.md
- Core Layers: layers/core.md
- Convolutional Layers: layers/convolutional.md
- Pooling Layers: layers/pooling.md
- Recurrent Layers: layers/recurrent.md
- Embedding Layers: layers/embeddings.md
- Advanced Activations Layers: layers/advanced-activations.md
+1
Ver Arquivo
@@ -30,6 +30,7 @@ model.add(Activation(tanh))
- __softmax__: Softmax applied across inputs last dimension. Expects shape either `(nb_samples, nb_timesteps, nb_dims)` or `(nb_samples, nb_dims)`.
- __softplus__
- __softsign__
- __relu__
- __tanh__
- __sigmoid__
+1 -1
Ver Arquivo
@@ -29,7 +29,7 @@ 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; print(backend._BACKEND)"
Using TensorFlow backend.
tensorflow
```
+123 -22
Ver Arquivo
@@ -10,7 +10,10 @@
- [How is the validation split computed?](#how-is-the-validation-split-computed)
- [Is the data shuffled during training?](#is-the-data-shuffled-during-training)
- [How can I record the training / validation loss / accuracy at each epoch?](#how-can-i-record-the-training-validation-loss-accuracy-at-each-epoch)
- [How can I "freeze" layers?](#how-can-i-freeze-keras-layers)
- [How can I use stateful RNNs?](#how-can-i-use-stateful-rnns)
- [How can I remove a layer from a Sequential model?](#how-can-i-remove-a-layer-from-a-sequential-model)
- [How can I use pre-trained models in Keras?](#how-can-i-use-pre-trained-models-in-keras)
---
@@ -20,12 +23,11 @@ Please cite Keras in your publications if it helps your research. Here is an exa
```
@misc{chollet2015keras,
author = {Chollet, François},
title = {Keras},
year = {2015},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/fchollet/keras}}
title={Keras},
author={Chollet, Fran\c{c}ois},
year={2015},
publisher={GitHub},
howpublished={\url{https://github.com/fchollet/keras}},
}
```
@@ -56,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
@@ -66,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
@@ -77,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.
@@ -91,17 +119,6 @@ Assuming you have code for instantiating your model, you can then load the weigh
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')
# elsewhere...
model = model_from_json(open('my_model_architecture.json').read())
model.load_weights('my_model_weights.h5')
```
---
### Why is the training loss much higher than the testing loss?
@@ -134,13 +151,29 @@ to pass the learning phase flag to your function:
get_3rd_layer_output = K.function([model.layers[0].input, K.learning_phase()],
[model.layers[3].output])
# output in train mode
layer_output = get_3rd_layer_output([X, 1])[0]
# output in test mode = 0
layer_output = get_3rd_layer_output([X, 0])[0]
# output in test mode
# output in train mode = 1
layer_output = get_3rd_layer_output([X, 1])[0]
```
Another more flexible way of getting output from intermediate layers is to use the [functional API](/getting-started/functional-api-guide). For example, if you have created an autoencoder for MNIST:
```python
inputs = Input(shape=(784,))
encoded = Dense(32, activation='relu')(inputs)
decoded = Dense(784)(encoded)
model = Model(input=inputs, output=decoded)
```
After compiling and training the model, you can get the output of the data from the encoder like this:
```python
encoder = Model(input=inputs, output=encoded)
X_encoded = encoder.predict(X)
```
---
### How can I use Keras with datasets that don't fit in memory?
@@ -194,6 +227,40 @@ print(hist.history)
---
### How can I "freeze" Keras layers?
To "freeze" a layer means to exclude it from training, i.e. its weights will never be updated. This is useful in the context of fine-tuning a model, or using fixed embeddings for a text input.
You can pass a `trainable` argument (boolean) to a layer constructor to set a layer to be non-trainable:
```python
frozen_layer = Dense(32, trainable=False)
```
Additionally, you can set the `trainable` property of a layer to `True` or `False` after instantiation. For this to take effect, you will need to call `compile()` on your model after modifying the `trainable` property. Here's an example:
```python
x = Input(shape=(32,))
layer = Dense(32)
layer.trainable = False
y = layer(x)
frozen_model = Model(x, y)
# in the model below, the weights of `layer` will not be updated during training
frozen_model.compile(optimizer='rmsprop', loss='mse')
layer.trainable = True
trainable_model = Model(x, y)
# with this model the weights of the layer will be updated during training
# (which will also affect the above model since it uses the same layer instance)
trainable_model.compile(optimizer='rmsprop', loss='mse')
frozen_model.fit(data, labels) # this does NOT update the weights of `layer`
trainable_model.fit(data, labels) # this updates the weights of `layer`
```
---
### How can I use stateful RNNs?
Making a RNN stateful means that the states for the samples of each batch will be reused as initial states for the samples in the next batch.
@@ -241,3 +308,37 @@ model.layers[0].reset_states()
Notes that the methods `predict`, `fit`, `train_on_batch`, `predict_classes`, etc. will *all* update the states of the stateful layers in a model. This allows you to do not only stateful training, but also stateful prediction.
---
### How can I remove a layer from a Sequential model?
You can remove the last added layer in a Sequential model by calling `.pop()`:
```python
model = Sequential()
model.add(Dense(32, activation='relu', input_dim=784))
model.add(Dense(32, activation='relu'))
print(len(model.layers)) # "2"
model.pop()
print(len(model.layers)) # "1"
```
---
### How can I use pre-trained models in Keras?
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)
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).
The VGG-16 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)
- [Deep dream](https://github.com/fchollet/keras/blob/master/examples/deep_dream.py)
+9 -9
Ver Arquivo
@@ -45,7 +45,7 @@ With the functional API, it is easy to re-use trained models: you can treat any
```python
x = Input(shape=(784,))
# this works, and returns the 10-way softmax we defined above.
# this works, and returns the 10-way softmax we defined above.
y = model(x)
```
@@ -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.
@@ -127,12 +127,12 @@ model = Model(input=[main_input, auxiliary_input], output=[main_loss, auxiliary_
```
We compile the model and assign a weight of 0.2 to the auxiliary loss.
To specify different `loss_weight` or `loss` for each different output, you can use a list or a dictionary.
To specify different `loss_weights` or `loss` for each different output, you can use a list or a dictionary.
Here we pass a single loss as the `loss` argument, so the same loss will be used on all outputs.
```python
model.compile(optimizer='rmsprop', loss='binary_crossentropy',
loss_weight=[1., 0.2])
loss_weights=[1., 0.2])
```
We can train the model by passing it lists of input arrays and target arrays:
@@ -148,7 +148,7 @@ We could also have compiled the model via:
```python
model.compile(optimizer='rmsprop',
loss={'main_output': 'binary_crossentropy', 'aux_output': 'binary_crossentropy'},
loss_weight={'main_output': 1., 'aux_output': 0.2})
loss_weights={'main_output': 1., 'aux_output': 0.2})
# and trained it via:
model.fit({'main_input': headline_data, 'aux_input': additional_data},
@@ -166,7 +166,7 @@ Let's consider a dataset of tweets. We want to build a model that can tell wheth
One way to achieve this is to build a model that encodes two tweets into two vectors, concatenates the vectors and adds a logistic regression of top, outputting a probability that the two tweets share the same author. The model would then be trained on positive tweet pairs and negative tweet pairs.
Because the problem is symetric, the mechanism that encodes the first tweet should be reused (weights and all) to encode the second tweet. Here we use a shared LSTM layer to encode the tweets.
Because the problem is symmetric, the mechanism that encodes the first tweet should be reused (weights and all) to encode the second tweet. Here we use a shared LSTM layer to encode the tweets.
Let's build this with the functional API. We will take as input for a tweet a binary matrix of shape `(140, 256)`, i.e. a sequence of 140 vectors of size 256, where each dimension in the 256-dimensional vector encodes the presence/absence of a character (out of an alphabet of 256 frequent characters).
@@ -196,7 +196,7 @@ encoded_b = shared_lstm(tweet_b)
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)
predictions = Dense(1, activation='sigmoid')(merged_vector)
# we define a trainable model linking the
# tweet inputs to the predictions
@@ -309,8 +309,8 @@ from keras.layers import merge, Convolution2D, Input
# input tensor for a 3-channel 256x256 image
x = Input(shape=(3, 256, 256))
# 3x3 conv with 16 output channels
y = Convolution2D(16, 3, 3, border_mode='same')
# 3x3 conv with 3 output channels (same as input channels)
y = Convolution2D(3, 3, 3, border_mode='same')(x)
# this returns x + y.
z = merge([x, y], mode='sum')
```
+15 -7
Ver Arquivo
@@ -6,6 +6,7 @@ You can create a `Sequential` model by passing a list of layer instances to the
```python
from keras.models import Sequential
from keras.layers import Dense, Activation
model = Sequential([
Dense(32, input_dim=784),
@@ -85,7 +86,14 @@ 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.:
```python
final_model.compile(optimizer='rmsprop', loss='categorical_crossentropy')
final_model.fit([input_data_1, input_data_2], targets) # we pass one data array per model input
```
The `Merge` layer supports a number of pre-defined modes:
@@ -112,7 +120,7 @@ Now you know enough to be able to define *almost* any model with Keras. For comp
Before training a model, you need to configure the learning process, which is done via the `compile` method. It receives three arguments:
- an optimizer. This could be the string identifier of an existing optimizer (such as `rmsprop` or `adagrad`), or an instance of the `Optimizer` class. See: [optimizers](/optimizers).
- a loss function. This is the objective that the model will try to minimize. If can be the string identifier of an existing loss function (such as `categorical_crossentropy` or `mse`), or it can be an objective function. See: [objectives](/objectives).
- a loss function. This is the objective that the model will try to minimize. It can be the string identifier of an existing loss function (such as `categorical_crossentropy` or `mse`), or it can be an objective function. See: [objectives](/objectives).
- a list of metrics. For any classification problem you will want to set this to `metrics=['accuracy']`. A metric could be the string identifier of an existing metric (only `accuracy` is supported at this point), or a custom metric function.
```python
@@ -141,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'])
@@ -373,7 +381,7 @@ image_model.load_weights('weight_file.h5')
language_model = Sequential()
language_model.add(Embedding(vocab_size, 256, input_length=max_caption_len))
language_model.add(GRU(output_dim=128, return_sequences=True))
language_model.add(TimeDistributedDense(128))
language_model.add(TimeDistributed(Dense(128)))
# let's repeat the image vector to turn it into a sequence.
image_model.add(RepeatVector(max_caption_len))
@@ -410,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
@@ -499,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
@@ -538,4 +546,4 @@ y_val = np.random.random((100, nb_classes))
decoder.fit([x_train_a, x_train_b], y_train,
batch_size=64, nb_epoch=5,
validation_data=([x_val_a, x_val_b], y_val))
```
```
+2 -2
Ver Arquivo
@@ -36,7 +36,7 @@ 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 function API](http://keras.io/getting-started/functional-api-guide).
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).
Here's the `Sequential` model:
@@ -49,7 +49,7 @@ model = Sequential()
Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
from keras.layers import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
+28 -1
Ver Arquivo
@@ -1,7 +1,7 @@
## Usage of initializations
Initializations define the probability distribution used to set the initial random weights of Keras layers.
Initializations define the way to set the initial random weights of Keras layers.
The keyword arguments used for passing initializations to layers will depend on the layer. Usually it is simply `init`:
@@ -21,3 +21,30 @@ model.add(Dense(64, init='uniform'))
- __glorot_uniform__
- __he_normal__: Gaussian initialization scaled by fan_in (He et al., 2014)
- __he_uniform__
An initialization may be passed as a string (must match one of the available initializations above), or as a callable.
If a callable, then it must take two arguments: `shape` (shape of the variable to initialize) and `name` (name of the variable),
and it must return a variable (e.g. output of `K.variable()`):
```python
from keras import backend as K
import numpy as np
def my_init(shape, name=None):
value = np.random.random(shape)
return K.variable(value, name=name)
model.add(Dense(64, init=my_init))
```
You could also use functions from `keras.initializations` in this way:
```python
from keras import initializations
def my_init(shape, name=None):
return initializations.normal(shape, scale=0.01, name=name)
model.add(Dense(64, init=my_init))
```
+34
Ver Arquivo
@@ -0,0 +1,34 @@
# Writing your own Keras layers
For simple, stateless custom operations, you are probably better off using `layers.core.Lambda` layers. But for any custom operation that has trainable weights, you should implement your own layer.
Here is the skeleton of a Keras layer. There are only three methods you need to implement:
- `build(input_shape)`: this is where you will define your weights. Trainable weights should be added to the list `self.trainable_weights`. Other attributes of note are: `self.non_trainable_weights` (list) and `self.updates` (list of update tuples (tensor, new_tensor)). For an example of how to use `non_trainable_weights` and `updates`, see the code for the `BatchNormalization` layer.
- `call(x)`: this is where the layer's logic lives. Unless you want your layer to support masking, you only have to care about the first argument passed to `call`: the input tensor.
- `get_output_shape_for(input_shape)`: in case your layer modifies the shape of its input, you should specify here the shape transformation logic. This allows Keras to do automatic shape inference.
```python
from keras import backend as K
from keras.engine.topology import Layer
import numpy as np
class MyLayer(Layer):
def __init__(self, output_dim, **kwargs):
self.output_dim = output_dim
super(MyLayer, self).__init__(**kwargs)
def build(self, input_shape):
input_dim = input_shape[1]
initial_weight_value = np.random.random((input_dim, output_dim))
self.W = K.variable(initial_weight_value)
self.trainable_weights = [self.W]
def call(self, x, mask=None):
return K.dot(x, self.W)
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.output_dim)
```
The existing Keras layers provide ample examples of how to implement almost anything. Never hesitate to read the source code!
+2 -2
Ver Arquivo
@@ -11,7 +11,7 @@ b = Dense(32)(a)
model = Model(input=a, output=b)
```
This model will include all layers required in the computation of `a` given `b`.
This model will include all layers required in the computation of `b` given `a`.
In the case of multi-input or multi-output models, you can use lists as well:
@@ -29,4 +29,4 @@ For a detailed introduction of what `Model` can do, read [this guide to the Kera
## Methods
{{autogenerated}}
{{autogenerated}}
+4 -2
Ver Arquivo
@@ -26,5 +26,7 @@ For a few examples of such functions, check out the [objectives source](https://
- __hinge__
- __binary_crossentropy__: Also known as logloss.
- __categorical_crossentropy__: Also known as multiclass logloss. __Note__: using this objective requires that your labels are binary arrays of shape `(nb_samples, nb_classes)`.
- __poisson__: mean of `(predictions - targets * log(predictions))`
- __cosine_proximity__: the opposite (negative) of the mean cosine proximity between predictions and targets.
- __sparse_categorical_crossentropy__: As above but accepts sparse labels. __Note__: this objective still requires that your labels have the same number of dimensions as your outputs; you may need to add a length-1 dimension to the shape of your labels, e.g with `np.expand_dims(y, -1)`.
- __kullback_leibler_divergence__ / __kld__: Information gain from a predicted probability distribution Q to a true probability distribution P. Gives a measure of difference between both distributions.
- __poisson__: Mean of `(predictions - targets * log(predictions))`
- __cosine_proximity__: The opposite (negative) of the mean cosine proximity between predictions and targets.
+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}}
+81 -10
Ver Arquivo
@@ -2,17 +2,23 @@
## ImageDataGenerator
```python
keras.preprocessing.image.ImageDataGenerator(featurewise_center=True,
keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=True,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=0.,
width_shift_range=0.,
height_shift_range=0.,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode='nearest',
cval=0.,
horizontal_flip=False,
vertical_flip=False)
vertical_flip=False,
rescale=None,
dim_ordering=K.image_dim_ordering())
```
Generate batches of tensor image data with real-time data augmentation. The data will be looped over (in batches) indefinitely.
@@ -27,28 +33,62 @@ Generate batches of tensor image data with real-time data augmentation. The data
- __width_shift_range__: Float (fraction of total width). Range for random horizontal shifts.
- __height_shift_range__: Float (fraction of total height). Range for random vertical shifts.
- __shear_range__: Float. Shear Intensity (Shear angle in counter-clockwise direction as radians)
- __zoom_range__: Float or [lower, upper]. Range for random zoom. If a float, `[lower, upper] = [1-zoom_range, 1+zoom_range]`.
- __channel_shift_range__: Float. Range for random channel shifts.
- __fill_mode__: One of {"constant", "nearest", "reflect" or "wrap"}. Points outside the boundaries of the input are filled according to the given mode.
- __cval__: Float or Int. Value used for points outside the boundaries when `fill_mode = "constant"`.
- __horizontal_flip__: Boolean. Randomly flip inputs horizontally.
- __vertical_flip__: Boolean. Randomly flip inputs vertically.
- __rescale__: rescaling factor. Defaults to None. If None or 0, no rescaling is applied,
otherwise we multiply the data by the value provided (before applying
any other transformation).
- __dim_ordering__: One of {"th", "tf"}.
"tf" mode means that the images should have shape `(samples, width, height, channels)`,
"th" mode means that the images should have shape `(samples, channels, width, height)`.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
- __Methods__:
- __fit(X)__: Required if featurewise_center or featurewise_std_normalization or zca_whitening. Compute necessary quantities on some sample data.
- __fit(X)__: Compute the internal data stats related to the data-dependent transformations, based on an array of sample data.
Only required if featurewise_center or featurewise_std_normalization or zca_whitening.
- __Arguments__:
- __X__: sample data.
- __augment__: Boolean (default: False). Whether to fit on randomly augmented samples.
- __rounds__: int (default: 1). If augment, how many augmentation passes over the data to use.
- __flow(X, y)__:
- __flow(X, y)__: Takes numpy data & label arrays, and generates batches of augmented/normalized data. Yields batches indefinitely, in an infinite loop.
- __Arguments__:
- __X__: data.
- __y__: labels.
- __batch_size__: int (default: 32).
- __shuffle__: boolean (defaut: False).
- __save_to_dir__: None or str. This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str. Prefix to use for filenames of saved pictures.
- __save_format__: one of "png", jpeg".
- __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.
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,
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.
- __classes__: optional list of class subdirectories (e.g. `['dogs', 'cats']`). Default: None. If not provided, the list of classes will be automatically inferred (and the order of the classes, which will map to the label indices, will be alphanumeric).
- __class_mode__: one of "categorical", "binary", "sparse" or None. Default: "categorical". Determines the type of label arrays that are returned: "categorical" will be 2D one-hot encoded labels, "binary" will be 1D binary labels, "sparse" will be 1D integer labels. If None, no labels are returned (the generator will only yield batches of image data, which is useful to use `model.predict_generator()`, `model.evaluate_generator()`, etc.).
- __batch_size__: size of the batches of data (default: 32).
- __shuffle__: whether to shuffle the data (default: True)
- __seed__: optional random seed for shuffling.
- __save_to_dir__: None or str (default: None). This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str. Prefix to use for filenames of saved pictures (only relevant if `save_to_dir` is set).
- __save_format__: one of "png", "jpeg" (only relevant if `save_to_dir` is set). Default: "jpeg".
- __Examples__:
Example of using `.flow(X, y)`:
- __Example__:
```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)
@@ -80,3 +120,34 @@ for e in range(nb_epoch):
# the generator loops indefinitely
break
```
Example of using `.flow_from_directory(directory)`:
```python
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
'data/train',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
'data/validation',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
model.fit_generator(
train_generator,
samples_per_epoch=2000,
nb_epoch=50,
validation_data=validation_generator,
nb_val_samples=800)
```
+10 -10
Ver Arquivo
@@ -4,14 +4,14 @@
keras.preprocessing.sequence.pad_sequences(sequences, maxlen=None, dtype='int32')
```
Transform a list of `nb_samples sequences` (lists of scalars) into a 2D numpy array of shape `(nb_samples, nb_timesteps)`. `nb_timesteps` is either the `maxlen` argument if provided, or the length of the longest sequence otherwise. Sequences that are shorter than `nb_timesteps` are padded with zeros at the end.
Transform a list of `nb_samples sequences` (lists of scalars) into a 2D Numpy array of shape `(nb_samples, nb_timesteps)`. `nb_timesteps` is either the `maxlen` argument if provided, or the length of the longest sequence otherwise. Sequences that are shorter than `nb_timesteps` are padded with zeros at the end.
- __Return__: 2D numpy array of shape `(nb_samples, nb_timesteps)`.
- __Return__: 2D Numpy array of shape `(nb_samples, nb_timesteps)`.
- __Arguments__:
- __sequences__: List of lists of int or float.
- __maxlen__: None or int. Maximum sequence length, longer sequences are truncated and shorter sequences are padded with zeros at the end.
- __dtype__: datatype of the numpy array returned.
- __dtype__: datatype of the Numpy array returned.
- __padding__: 'pre' or 'post', pad either before or after each sequence.
- __truncating__: 'pre' or 'post', remove values from sequences larger than maxlen either in the beginning or in the end of the sequence
- __value__: float, value to pad the sequences to the desired value.
@@ -21,12 +21,12 @@ Transform a list of `nb_samples sequences` (lists of scalars) into a 2D numpy ar
## skipgrams
```python
keras.preprocessing.sequence.skipgrams(sequence, vocabulary_size,
window_size=4, negative_samples=1., shuffle=True,
keras.preprocessing.sequence.skipgrams(sequence, vocabulary_size,
window_size=4, negative_samples=1., shuffle=True,
categorical=False, sampling_table=None)
```
Transforms a sequence of word indexes (list of int) into couples of the form:
Transforms a sequence of word indexes (list of int) into couples of the form:
- (word, word in the same window), with label 1 (positive samples).
- (word, random word from the vocabulary), with label 0 (negative samples).
@@ -34,8 +34,8 @@ Transforms a sequence of word indexes (list of int) into couples of the form:
Read more about Skipgram in this gnomic paper by Mikolov et al.: [Efficient Estimation of Word Representations in
Vector Space](http://arxiv.org/pdf/1301.3781v3.pdf)
- __Return__: tuple `(couples, labels)`.
- `couples` is a list of 2-elements lists of int: `[word_index, other_word_index]`.
- __Return__: tuple `(couples, labels)`.
- `couples` is a list of 2-elements lists of int: `[word_index, other_word_index]`.
- `labels` is a list of 0 and 1, where 1 indicates that `other_word_index` was found in the same window as `word_index`, and 0 indicates that `other_word_index` was random.
- if categorical is set to True, the labels are categorical, ie. 1 becomes [0,1], and 0 becomes [1, 0].
@@ -46,7 +46,7 @@ Vector Space](http://arxiv.org/pdf/1301.3781v3.pdf)
- __negative_samples__: float >= 0. 0 for no negative (=random) samples. 1 for same number as positive samples. etc.
- __shuffle__: boolean. Whether to shuffle the samples.
- __categorical__: boolean. Whether to make the returned labels categorical.
- __sampling_table__: numpy array of shape `(vocabulary_size,)` where `sampling_table[i]` is the probability of sampling the word with index i (assumed to be i-th most common word in the dataset).
- __sampling_table__: Numpy array of shape `(vocabulary_size,)` where `sampling_table[i]` is the probability of sampling the word with index i (assumed to be i-th most common word in the dataset).
---
@@ -59,7 +59,7 @@ keras.preprocessing.sequence.make_sampling_table(size, sampling_factor=1e-5)
Used for generating the `sampling_table` argument for `skipgrams`. `sampling_table[i]` is the probability of sampling the word i-th most common word in a dataset (more common words should be sampled less frequently, for balance).
- __Return__: numpy array of shape `(size,)`.
- __Return__: Numpy array of shape `(size,)`.
- __Arguments__:
- __size__: size of the vocabulary considered.
+6 -6
Ver Arquivo
@@ -1,12 +1,12 @@
# Wrappers for the Sciki-Learn API
# 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
@@ -25,7 +25,7 @@ present class will then be treated as the default build_fn.
`sk_params` takes both model parameters and fitting parameters. Legal model
parameters are the arguments of `build_fn`. Note that like all other
estimators in scikit-learn, 'build_fn' should provide defalult values for
estimators in scikit-learn, 'build_fn' should provide default values for
its arguments, so that you could create the estimator without passing any
values to `sk_params`.
@@ -42,4 +42,4 @@ fitting (predicting) parameters are selected in the following order:
When using scikit-learn's `grid_search` API, legal tunable parameters are
those you could pass to `sk_params`, including fitting parameters.
In other words, you could use `grid_search` to search for the best
`batch_size` or `nb_epoch` as well as the model parameters.
`batch_size` or `nb_epoch` as well as the model parameters.
+2 -1
Ver Arquivo
@@ -10,9 +10,10 @@ from keras.utils.visualize_util import plot
plot(model, to_file='model.png')
```
`plot` takes one optional arguments:
`plot` takes two optional arguments:
- `show_shapes` (defaults to False) controls whether output shapes are shown in the graph.
- `show_layer_names` (defaults to True) controls whether layer names are shown in the graph.
You can also directly obtain the `pydot.Graph` object and render it yourself,
for example to show it in an ipython notebook :
+3 -4
Ver Arquivo
@@ -29,8 +29,7 @@ Five digits inverted:
from __future__ import print_function
from keras.models import Sequential
from keras.engine.training import slice_X
from keras.layers.core import Activation, TimeDistributedDense, RepeatVector
from keras.layers import recurrent
from keras.layers import Activation, TimeDistributed, Dense, RepeatVector, recurrent
import numpy as np
from six.moves import range
@@ -40,7 +39,7 @@ class CharacterTable(object):
Given a set of characters:
+ Encode them to a one hot integer representation
+ Decode the one hot integer representation to their character output
+ Decode a vector of probabilties to their character output
+ Decode a vector of probabilities to their character output
'''
def __init__(self, chars, maxlen):
self.chars = sorted(set(chars))
@@ -140,7 +139,7 @@ for _ in range(LAYERS):
model.add(RNN(HIDDEN_SIZE, return_sequences=True))
# For each of step of the output sequence, decide which character should be chosen
model.add(TimeDistributedDense(len(chars)))
model.add(TimeDistributed(Dense(len(chars))))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
+2 -2
Ver Arquivo
@@ -2,7 +2,7 @@
We build a custom activation layer called 'Antirectifier',
which modifies the shape of the tensor that passes through it.
We need to specify two methods: `output_shape` and `get_output`.
We need to specify two methods: `get_output_shape_for` and `call`.
Note that the same result can also be achieved via a Lambda layer.
@@ -12,7 +12,7 @@ backend (`K`), our code can run both on TensorFlow and Theano.
from __future__ import print_function
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Layer, Activation
from keras.layers import Dense, Dropout, Layer, Activation
from keras.datasets import mnist
from keras import backend as K
from keras.utils import np_utils
+9 -4
Ver Arquivo
@@ -16,8 +16,8 @@ Time per epoch: 3s on CPU (core i7).
from __future__ import print_function
from keras.models import Sequential
from keras.layers.embeddings import Embedding
from keras.layers.core import Activation, Dense, Merge, Permute, Dropout
from keras.layers.recurrent import LSTM
from keras.layers import Activation, Dense, Merge, Permute, Dropout
from keras.layers import LSTM
from keras.utils.data_utils import get_file
from keras.preprocessing.sequence import pad_sequences
from functools import reduce
@@ -94,8 +94,13 @@ def vectorize_stories(data, word_idx, story_maxlen, query_maxlen):
pad_sequences(Xq, maxlen=query_maxlen), np.array(Y))
path = get_file('babi-tasks-v1-2.tar.gz',
origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/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'
'$ mv tasks_1-20_v1-2.tar.gz ~/.keras/datasets/babi-tasks-v1-2.tar.gz')
raise
tar = tarfile.open(path)
challenges = {
+8 -2
Ver Arquivo
@@ -66,7 +66,7 @@ np.random.seed(1337) # for reproducibility
from keras.utils.data_utils import get_file
from keras.layers.embeddings import Embedding
from keras.layers.core import Dense, Merge, Dropout, RepeatVector
from keras.layers import Dense, Merge, Dropout, RepeatVector
from keras.layers import recurrent
from keras.models import Sequential
from keras.preprocessing.sequence import pad_sequences
@@ -146,7 +146,13 @@ BATCH_SIZE = 32
EPOCHS = 40
print('RNN / Embed / Sent / Query = {}, {}, {}, {}'.format(RNN, EMBED_HIDDEN_SIZE, SENT_HIDDEN_SIZE, QUERY_HIDDEN_SIZE))
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/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'
'$ mv tasks_1-20_v1-2.tar.gz ~/.keras/datasets/babi-tasks-v1-2.tar.gz')
raise
tar = tarfile.open(path)
# Default QA1 with 1000 samples
# challenge = 'tasks_1-20_v1-2/en/qa1_single-supporting-fact_{}.txt'
+2 -2
Ver Arquivo
@@ -15,8 +15,8 @@ from __future__ import print_function
from keras.datasets import cifar10
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
from keras.utils import np_utils
+3 -3
Ver Arquivo
@@ -9,7 +9,7 @@ e.g.:
python deep_dream.py img/mypic.jpg results/dream
```
It is preferrable to run this script on GPU, for speed.
It is preferable to run this script on GPU, for speed.
If running on CPU, prefer the TensorFlow backend (much faster).
Example results: http://i.imgur.com/FX6ROg9.jpg
@@ -24,7 +24,7 @@ import h5py
import os
from keras.models import Sequential
from keras.layers.convolutional import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras import backend as K
parser = argparse.ArgumentParser(description='Deep Dreams with Keras.')
@@ -189,7 +189,7 @@ def eval_loss_and_grads(x):
class Evaluator(object):
def __init__(self):
self.loss_value = None
self.grads_values = None
self.grad_values = None
def loss(self, x):
assert self.loss_value is None
+1 -2
Ver Arquivo
@@ -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')
+19 -14
Ver Arquivo
@@ -1,6 +1,9 @@
'''This example demonstrates the use of Convolution1D for text classification.
Gets to 0.835 test accuracy after 2 epochs. 100s/epoch on K520 GPU.
Gets to 0.89 test accuracy after 2 epochs.
90s/epoch on Intel i5 2.4Ghz CPU.
10s/epoch on Tesla K40 GPU.
'''
from __future__ import print_function
@@ -9,25 +12,25 @@ np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.embeddings import Embedding
from keras.layers.convolutional import Convolution1D, MaxPooling1D
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Embedding
from keras.layers import Convolution1D, MaxPooling1D
from keras.datasets import imdb
from keras import backend as K
# set parameters:
max_features = 5000
maxlen = 100
maxlen = 400
batch_size = 32
embedding_dims = 100
embedding_dims = 50
nb_filter = 250
filter_length = 3
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')
@@ -42,8 +45,10 @@ 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))
model.add(Dropout(0.25))
model.add(Embedding(max_features,
embedding_dims,
input_length=maxlen,
dropout=0.2))
# we add a Convolution1D, which will learn nb_filter
# word group filters of size filter_length:
@@ -52,8 +57,8 @@ model.add(Convolution1D(nb_filter=nb_filter,
border_mode='valid',
activation='relu',
subsample_length=1))
# we use standard max pooling (halving the output of the previous layer):
model.add(MaxPooling1D(pool_length=2))
# we use max pooling:
model.add(MaxPooling1D(pool_length=model.output_shape[1]))
# We flatten the output of the conv layer,
# so that we can add a vanilla dense layer:
@@ -61,7 +66,7 @@ model.add(Flatten())
# We add a vanilla hidden layer:
model.add(Dense(hidden_dims))
model.add(Dropout(0.25))
model.add(Dropout(0.2))
model.add(Activation('relu'))
# We project onto a single unit output layer, and squash it with a sigmoid:
@@ -69,7 +74,7 @@ model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
optimizer='adam',
metrics=['accuracy'])
model.fit(X_train, y_train,
batch_size=batch_size,
+7 -7
Ver Arquivo
@@ -9,10 +9,10 @@ np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM, GRU, SimpleRNN
from keras.layers.convolutional import Convolution1D, MaxPooling1D
from keras.layers import Dense, Dropout, Activation
from keras.layers import Embedding
from keras.layers import LSTM, GRU, SimpleRNN
from keras.layers import Convolution1D, MaxPooling1D
from keras.datasets import imdb
@@ -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')
+4 -8
Ver Arquivo
@@ -1,7 +1,7 @@
'''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:
@@ -19,9 +19,8 @@ np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.utils import np_utils
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM, SimpleRNN, GRU
from keras.layers import Dense, Dropout, Activation, Embedding
from keras.layers import LSTM, SimpleRNN, GRU
from keras.datasets import imdb
max_features = 20000
@@ -29,8 +28,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')
@@ -53,8 +51,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
@@ -0,0 +1,290 @@
'''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).
+83
Ver Arquivo
@@ -0,0 +1,83 @@
'''Compare LSTM implementations on the IMDB sentiment classification task.
consume_less='cpu' preprocesses input to the LSTM which typically results in
faster computations at the expense of increased peak memory usage as the
preprocessed input must be kept in memory.
consume_less='mem' does away with the preprocessing, meaning that it might take
a little longer, but should require less peak memory.
consume_less='gpu' concatenates the input, output and forget gate's weights
into one, large matrix, resulting in faster computation time as the GPU can
utilize more cores, at the expense of reduced regularization because the same
dropout is shared across the gates.
Note that the relative performance of the different `consume_less` modes
can vary depending on your device, your model and the size of your data.
'''
import time
import numpy as np
import matplotlib.pyplot as plt
from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Embedding, Dense, LSTM
from keras.datasets import imdb
max_features = 20000
max_length = 80
embedding_dim = 256
batch_size = 128
epochs = 10
modes = ['cpu', 'mem', 'gpu']
print('Loading data...')
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features)
X_train = sequence.pad_sequences(X_train, max_length)
X_test = sequence.pad_sequences(X_test, max_length)
# Compile and train different models while meauring performance.
results = []
for mode in modes:
print('Testing mode: consume_less="{}"'.format(mode))
model = Sequential()
model.add(Embedding(max_features, embedding_dim, input_length=max_length, dropout=0.2))
model.add(LSTM(embedding_dim, dropout_W=0.2, dropout_U=0.2, consume_less=mode))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
start_time = time.time()
history = model.fit(X_train, y_train,
batch_size=batch_size,
nb_epoch=epochs,
validation_data=(X_test, y_test))
average_time_per_epoch = (time.time() - start_time) / epochs
results.append((history, average_time_per_epoch))
# Compare models' accuracy, loss and elapsed time per epoch.
plt.style.use('ggplot')
ax1 = plt.subplot2grid((2, 2), (0, 0))
ax1.set_title('Accuracy')
ax1.set_ylabel('Validation Accuracy')
ax1.set_xlabel('Epochs')
ax2 = plt.subplot2grid((2, 2), (1, 0))
ax2.set_title('Loss')
ax2.set_ylabel('Validation Loss')
ax2.set_xlabel('Epochs')
ax3 = plt.subplot2grid((2, 2), (0, 1), rowspan=2)
ax3.set_title('Time')
ax3.set_ylabel('Seconds')
for mode, result in zip(modes, results):
ax1.plot(result[0].epoch, result[0].history['val_acc'], label=mode)
ax2.plot(result[0].epoch, result[0].history['val_loss'], label=mode)
ax1.legend()
ax2.legend()
ax3.bar(np.arange(len(results)), [x[1] for x in results],
tick_label=modes, align='center')
plt.tight_layout()
plt.show()
+14 -12
Ver Arquivo
@@ -12,8 +12,9 @@ has at least ~100k characters. ~1M is better.
from __future__ import print_function
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Dropout
from keras.layers.recurrent import LSTM
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
@@ -23,7 +24,7 @@ path = get_file('nietzsche.txt', origin="https://s3.amazonaws.com/text-datasets/
text = open(path).read().lower()
print('corpus length:', len(text))
chars = set(text)
chars = sorted(list(set(text)))
print('total chars:', len(chars))
char_indices = dict((c, i) for i, c in enumerate(chars))
indices_char = dict((i, c) for i, c in enumerate(chars))
@@ -50,21 +51,22 @@ for i, sentence in enumerate(sentences):
# build the model: 2 stacked LSTM
print('Build model...')
model = Sequential()
model.add(LSTM(512, return_sequences=True, input_shape=(maxlen, len(chars))))
model.add(Dropout(0.2))
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):
+2 -2
Ver Arquivo
@@ -11,8 +11,8 @@ np.random.seed(1337) # for reproducibility
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
batch_size = 128
+3 -3
Ver Arquivo
@@ -3,7 +3,7 @@ with pixel-by-pixel sequential MNIST in
"A Simple Way to Initialize Recurrent Networks of Rectified Linear Units"
by Quoc V. Le, Navdeep Jaitly, Geoffrey E. Hinton
arXiv:1504.00941v2 [cs.NE] 7 Apr 201
arXiv:1504.00941v2 [cs.NE] 7 Apr 2015
http://arxiv.org/pdf/1504.00941v2.pdf
Optimizer is replaced with RMSprop which yields more stable and steady
@@ -17,9 +17,9 @@ from __future__ import print_function
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.layers import Dense, Activation
from keras.layers import SimpleRNN
from keras.initializations import normal, identity
from keras.layers.recurrent import SimpleRNN
from keras.optimizers import RMSprop
from keras.utils import np_utils
+6 -1
Ver Arquivo
@@ -28,6 +28,11 @@ def euclidean_distance(vects):
return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True))
def eucl_dist_output_shape(shapes):
shape1, shape2 = shapes
return (shape1[0], 1)
def contrastive_loss(y_true, y_pred):
'''Contrastive loss from Hadsell-et-al.'06
http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
@@ -103,7 +108,7 @@ input_b = Input(shape=(input_dim,))
processed_a = base_network(input_a)
processed_b = base_network(input_b)
distance = Lambda(euclidean_distance)([processed_a, processed_b])
distance = Lambda(euclidean_distance, output_shape=eucl_dist_output_shape)([processed_a, processed_b])
model = Model(input=[input_a, input_b], output=distance)
+94
Ver Arquivo
@@ -0,0 +1,94 @@
'''Example of how to use sklearn wrapper
Builds simple CNN models on MNIST and uses sklearn's GridSearchCV to find best model
'''
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.wrappers.scikit_learn import KerasClassifier
from sklearn.grid_search import GridSearchCV
nb_classes = 10
# input image dimensions
img_rows, img_cols = 28, 28
# load training data and do basic data normalization
(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)
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
# convert 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)
def make_model(dense_layer_sizes, nb_filters, nb_conv, nb_pool):
'''Creates model comprised of 2 convolutional layers followed by dense layers
dense_layer_sizes: List of layer sizes. This list has one number for each layer
nb_filters: Number of convolutional filters in each convolutional layer
nb_conv: Convolutional kernel size
nb_pool: Size of pooling area for max pooling
'''
model = Sequential()
model.add(Convolution2D(nb_filters, nb_conv, nb_conv,
border_mode='valid',
input_shape=(1, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, nb_conv, nb_conv))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool)))
model.add(Dropout(0.25))
model.add(Flatten())
for layer_size in dense_layer_sizes:
model.add(Dense(layer_size))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
metrics=['accuracy'])
return model
dense_size_candidates = [[32], [64], [32, 32], [64, 64]]
my_classifier = KerasClassifier(make_model, batch_size=32)
validator = GridSearchCV(my_classifier,
param_grid={'dense_layer_sizes': dense_size_candidates,
# nb_epoch is avail for tuning even when not
# an argument to model building function
'nb_epoch': [3, 6],
'nb_filters': [8],
'nb_conv': [3],
'nb_pool': [2]},
scoring='log_loss',
n_jobs=1)
validator.fit(X_train, y_train)
print('The parameters of the best model are: ')
print(validator.best_params_)
# validator.best_estimator_ returns sklearn-wrapped version of best model.
# validator.best_estimator_.model returns the (unwrapped) keras model
best_model = validator.best_estimator_.model
metric_names = best_model.metrics_names
metric_values = best_model.evaluate(X_test, y_test)
for metric, value in zip(metric_names, metric_values):
print(metric, ': ', value)
+2 -2
Ver Arquivo
@@ -19,8 +19,8 @@ np.random.seed(1337) # for reproducibility
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.layers import Dense, Dropout, Activation, Flatten
from keras.layers import Convolution2D, MaxPooling2D
from keras.utils import np_utils
+17 -5
Ver Arquivo
@@ -14,7 +14,7 @@ e.g.:
python neural_style_transfer.py img/tuebingen.jpg img/starry_night.jpg results/my_result
```
It is preferrable to run this script on GPU, for speed.
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
@@ -34,7 +34,7 @@ the pixels of the combination image, giving it visual coherence.
- The style loss is where the deep learning keeps in --that one is defined
using a deep convolutional neural network. Precisely, it consists in a sum of
L2 distances betwen the Gram matrices of the representations of
L2 distances between the Gram matrices of the representations of
the base image and the style reference image, extracted from
different layers of a convnet (trained on ImageNet). The general idea
is to capture color/texture information at different spatial
@@ -58,7 +58,7 @@ import argparse
import h5py
from keras.models import Sequential
from keras.layers.convolutional import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D
from keras import backend as K
parser = argparse.ArgumentParser(description='Neural style transfer with Keras.')
@@ -80,6 +80,7 @@ total_variation_weight = 1.
style_weight = 1.
content_weight = 0.025
# dimensions of the generated picture.
img_width = 400
img_height = 400
@@ -88,13 +89,21 @@ assert img_height == img_width, 'Due to the use of the Gram matrix, width and he
# 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 = img[:, :, ::-1].astype('float64')
img[:, :, 0] -= 103.939
img[:, :, 1] -= 116.779
img[:, :, 2] -= 123.68
img = img.transpose((2, 0, 1))
img = np.expand_dims(img, axis=0)
return img
# util function to convert a tensor into a valid image
def deprocess_image(x):
x = x.transpose((1, 2, 0))
x[:, :, 0] += 103.939
x[:, :, 1] += 116.779
x[:, :, 2] += 123.68
x = x[:, :, ::-1]
x = np.clip(x, 0, 255).astype('uint8')
return x
@@ -275,6 +284,9 @@ 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))
x[0, 0, :, :] -= 103.939
x[0, 1, :, :] -= 116.779
x[0, 2, :, :] -= 123.68
for i in range(10):
print('Start of iteration', i)
start_time = time.time()
@@ -282,7 +294,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().reshape((3, img_width, img_height)))
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)
+220
Ver Arquivo
@@ -0,0 +1,220 @@
'''This script demonstrates how to build a deep residual network
using the Keras functional API.
get_resnet50() returns the deep residual network model (50 layers)
Please visit Kaiming He's GitHub homepage:
https://github.com/KaimingHe
for more information.
The related paper is
'Deep Residual Learning for Image Recognition'
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun
http://arxiv.org/abs/1512.03385
Pretrained weights were converted from Kaiming He's caffe model directly.
For now we provide weights for the tensorflow backend only,
thus use 'tf' dim_ordering (e.g. input_shape=(224, 224, 3) for 224*224 color image)
would accelerate the computation, but we also provide weights for 'th' dim_ordering for compatibility.
You can set your default dim ordering in your Keras config file at ~/.keras/keras.json
please donwload them at:
http://pan.baidu.com/s/1o8pO2q2 ('th' dim ordering, for China)
http://pan.baidu.com/s/1pLanuTt ('tf' dim ordering, for China)
https://drive.google.com/open?id=0B4ChsjFJvew3NVQ2U041Q0xHRHM ('th' dim ordering, for other countries)
https://drive.google.com/open?id=0B4ChsjFJvew3NWN5THdxcTdSWmc ('tf' dim ordering, for other countries)
@author: BigMoyan, University of Electronic Science and Technology of China
'''
from __future__ import print_function
from keras.layers import merge
from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D, AveragePooling2D
from keras.layers.core import Dense, Activation, Flatten
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.layers import Input
from keras.preprocessing.image import load_img, img_to_array
import keras.backend as K
import numpy as np
# The names of layers in resnet50 are generated with the following format
# [type][stage][block]_branch[branch][layer]
# type: 'res' for conv layer, 'bn' and 'scale' for BN layer
# stage: from '2' to '5', current stage number
# block: 'a','b','c'... for different blocks in a stage
# branch: '1' for shortcut and '2' for main path
# layer: 'a','b','c'... for different layers in a block
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
'''
dim_ordering = K.image_dim_ordering()
nb_filter1, nb_filter2, nb_filter3 = filters
if 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'
out = Convolution2D(nb_filter1, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2a')(input_tensor)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(out)
out = Activation('relu')(out)
out = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same',
dim_ordering=dim_ordering, name=conv_name_base + '2b')(out)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(out)
out = Activation('relu')(out)
out = Convolution2D(nb_filter3, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2c')(out)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(out)
out = merge([out, input_tensor], mode='sum')
out = Activation('relu')(out)
return out
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 has subsample=(2,2) as well
'''
nb_filter1, nb_filter2, nb_filter3 = filters
dim_ordering = K.image_dim_ordering()
if 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'
out = Convolution2D(nb_filter1, 1, 1, subsample=strides,
dim_ordering=dim_ordering, name=conv_name_base + '2a')(input_tensor)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2a')(out)
out = Activation('relu')(out)
out = Convolution2D(nb_filter2, kernel_size, kernel_size, border_mode='same',
dim_ordering=dim_ordering, name=conv_name_base + '2b')(out)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2b')(out)
out = Activation('relu')(out)
out = Convolution2D(nb_filter3, 1, 1, dim_ordering=dim_ordering, name=conv_name_base + '2c')(out)
out = BatchNormalization(axis=bn_axis, name=bn_name_base + '2c')(out)
shortcut = Convolution2D(nb_filter3, 1, 1, subsample=strides,
dim_ordering=dim_ordering, name=conv_name_base + '1')(input_tensor)
shortcut = BatchNormalization(axis=bn_axis, name=bn_name_base + '1')(shortcut)
out = merge([out, shortcut], mode='sum')
out = Activation('relu')(out)
return out
def read_img(img_path):
'''This function returns a preprocessed image
'''
dim_ordering = K.image_dim_ordering()
mean = (103.939, 116.779, 123.68)
img = load_img(img_path, target_size=(224, 224))
img = img_to_array(img, dim_ordering=dim_ordering)
if dim_ordering == 'th':
img[0, :, :] -= mean[0]
img[1, :, :] -= mean[1]
img[2, :, :] -= mean[2]
# 'RGB'->'BGR'
img = img[::-1, :, :]
else:
img[:, :, 0] -= mean[0]
img[:, :, 1] -= mean[1]
img[:, :, 2] -= mean[2]
img = img[:, :, ::-1]
img = np.expand_dims(img, axis=0)
return img
def get_resnet50():
'''This function returns the 50-layer residual network model
you should load pretrained weights if you want to use it directly.
Note that since the pretrained weights is converted from caffemodel
the order of channels for input image should be 'BGR' (the channel order of caffe)
'''
if K.image_dim_ordering() == 'tf':
inp = Input(shape=(224, 224, 3))
bn_axis = 3
else:
inp = Input(shape=(3, 224, 224))
bn_axis = 1
dim_ordering = K.image_dim_ordering()
out = ZeroPadding2D((3, 3), dim_ordering=dim_ordering)(inp)
out = Convolution2D(64, 7, 7, subsample=(2, 2), dim_ordering=dim_ordering, name='conv1')(out)
out = BatchNormalization(axis=bn_axis, name='bn_conv1')(out)
out = Activation('relu')(out)
out = MaxPooling2D((3, 3), strides=(2, 2), dim_ordering=dim_ordering)(out)
out = conv_block(out, 3, [64, 64, 256], stage=2, block='a', strides=(1, 1))
out = identity_block(out, 3, [64, 64, 256], stage=2, block='b')
out = identity_block(out, 3, [64, 64, 256], stage=2, block='c')
out = conv_block(out, 3, [128, 128, 512], stage=3, block='a')
out = identity_block(out, 3, [128, 128, 512], stage=3, block='b')
out = identity_block(out, 3, [128, 128, 512], stage=3, block='c')
out = identity_block(out, 3, [128, 128, 512], stage=3, block='d')
out = conv_block(out, 3, [256, 256, 1024], stage=4, block='a')
out = identity_block(out, 3, [256, 256, 1024], stage=4, block='b')
out = identity_block(out, 3, [256, 256, 1024], stage=4, block='c')
out = identity_block(out, 3, [256, 256, 1024], stage=4, block='d')
out = identity_block(out, 3, [256, 256, 1024], stage=4, block='e')
out = identity_block(out, 3, [256, 256, 1024], stage=4, block='f')
out = conv_block(out, 3, [512, 512, 2048], stage=5, block='a')
out = identity_block(out, 3, [512, 512, 2048], stage=5, block='b')
out = identity_block(out, 3, [512, 512, 2048], stage=5, block='c')
out = AveragePooling2D((7, 7), dim_ordering=dim_ordering)(out)
out = Flatten()(out)
out = Dense(1000, activation='softmax', name='fc1000')(out)
model = Model(inp, out)
return model
if __name__ == '__main__':
weights_file = K.image_dim_ordering() + '_dim_ordering_resnet50.h5'
resnet_model = get_resnet50()
resnet_model.load_weights(weights_file)
# you may download synset_words from the address given at the begining of this file
class_table = open('synset_words.txt', 'r')
lines = class_table.readlines()
test_img1 = read_img('cat.jpg')
print('Result for test 1 is:')
print(lines[np.argmax(resnet_model.predict(test_img1)[0])])
test_img2 = read_img('elephant.jpg')
print('Result for test 2 is:')
print(lines[np.argmax(resnet_model.predict(test_img2)[0])])
class_table.close()
+1 -2
Ver Arquivo
@@ -8,8 +8,7 @@ np.random.seed(1337) # for reproducibility
from keras.datasets import reuters
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.layers.normalization import BatchNormalization
from keras.layers import Dense, Dropout, Activation
from keras.utils import np_utils
from keras.preprocessing.text import Tokenizer
+4 -5
Ver Arquivo
@@ -5,8 +5,7 @@ from __future__ import print_function
import numpy as np
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers.core import Dense
from keras.layers.recurrent import LSTM
from keras.layers import Dense, LSTM
# since we are using stateful rnn tsteps can be set to 1
@@ -17,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
@@ -32,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
@@ -75,7 +74,7 @@ for i in range(epochs):
print('Predicting')
predicted_output = model.predict(cos, batch_size=batch_size)
print('Ploting Results')
print('Plotting Results')
plt.subplot(2, 1, 1)
plt.plot(expected_output)
plt.title('Expected')
+97
Ver Arquivo
@@ -0,0 +1,97 @@
'''This script demonstrates how to build a variational autoencoder with Keras.
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
from keras.models import Model
from keras import backend as K
from keras import objectives
from keras.datasets import mnist
batch_size = 100
original_dim = 784
latent_dim = 2
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_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.)
return z_mean + K.exp(z_log_var / 2) * epsilon
# note that "output_shape" isn't necessary with the TensorFlow backend
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_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 = 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)
vae.compile(optimizer='rmsprop', loss=vae_loss)
# train the VAE on MNIST digits
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.astype('float32') / 255.
x_test = x_test.astype('float32') / 255.
x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
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)
_x_decoded_mean = decoder_mean(_h_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()
+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()
+18 -1
Ver Arquivo
@@ -1 +1,18 @@
__version__ = '1.0.0'
from __future__ import absolute_import
from . import backend
from . import datasets
from . import engine
from . import layers
from . import preprocessing
from . import utils
from . import wrappers
from . import callbacks
from . import constraints
from . import initializations
from . import metrics
from . import models
from . import objectives
from . import optimizers
from . import regularizers
__version__ = '1.0.7'
+6
Ver Arquivo
@@ -19,6 +19,10 @@ def softplus(x):
return K.softplus(x)
def softsign(x):
return K.softsign(x)
def relu(x, alpha=0., max_value=None):
return K.relu(x, alpha=alpha, max_value=max_value)
@@ -44,4 +48,6 @@ def linear(x):
from .utils.generic_utils import get_from_module
def get(identifier):
if identifier is None:
return linear
return get_from_module(identifier, globals(), 'activation function')
+22 -8
Ver Arquivo
@@ -9,6 +9,9 @@ from .common import set_epsilon
from .common import set_floatx
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
_keras_base_dir = os.path.expanduser('~')
if not os.access(_keras_base_dir, os.W_OK):
@@ -28,24 +31,28 @@ if os.path.exists(_config_path):
assert type(_epsilon) == float
_backend = _config.get('backend', _BACKEND)
assert _backend in {'theano', 'tensorflow'}
_image_dim_ordering = _config.get('image_dim_ordering', image_dim_ordering())
assert _image_dim_ordering in {'tf', 'th'}
set_floatx(_floatx)
set_epsilon(_epsilon)
set_image_dim_ordering(_image_dim_ordering)
_BACKEND = _backend
else:
# save config file, for easy edition
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND}
with open(_config_path, 'w') as f:
# add new line in order for bash 'cat' display the content correctly
f.write(json.dumps(_config) + '\n')
# 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 'KERAS_BACKEND' in os.environ:
_backend = os.environ['KERAS_BACKEND']
assert _backend in {'theano', 'tensorflow'}
_BACKEND = _backend
# import backend
if _BACKEND == 'theano':
sys.stderr.write('Using Theano backend.\n')
from .theano_backend import *
@@ -54,3 +61,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
+41 -8
Ver Arquivo
@@ -1,16 +1,25 @@
import numpy as np
from collections import defaultdict
# the type of float to use throughout the session.
_FLOATX = 'float32'
_EPSILON = 10e-8
_UID_PREFIXES = {}
_UID_PREFIXES = defaultdict(int)
_IMAGE_DIM_ORDERING = 'th'
def epsilon():
'''Returns the value of the fuzz
factor used in numeric expressions.
'''
return _EPSILON
def set_epsilon(e):
'''Sets the value of the fuzz
factor used in numeric expressions.
'''
global _EPSILON
_EPSILON = e
@@ -26,8 +35,7 @@ def set_floatx(floatx):
global _FLOATX
if floatx not in {'float16', 'float32', 'float64'}:
raise Exception('Unknown floatx type: ' + str(floatx))
floatx = str(floatx)
_FLOATX = floatx
_FLOATX = str(floatx)
def cast_to_floatx(x):
@@ -36,10 +44,35 @@ def cast_to_floatx(x):
return np.asarray(x, dtype=_FLOATX)
def image_dim_ordering():
'''Returns the image dimension ordering
convention ('th' or 'tf').
'''
return _IMAGE_DIM_ORDERING
def set_image_dim_ordering(dim_ordering):
'''Sets the value of the image dimension
ordering convention ('th' or 'tf').
'''
global _IMAGE_DIM_ORDERING
if dim_ordering not in {'tf', 'th'}:
raise Exception('Unknown dim_ordering:', dim_ordering)
_IMAGE_DIM_ORDERING = str(dim_ordering)
def get_uid(prefix=''):
if prefix not in _UID_PREFIXES:
_UID_PREFIXES[prefix] = 1
return 1
_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:
_UID_PREFIXES[prefix] += 1
return _UID_PREFIXES[prefix]
return False
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+339 -54
Ver Arquivo
@@ -3,9 +3,14 @@ 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:
from theano.tensor.nnet.nnet import softsign as T_softsign
except ImportError:
from theano.sandbox.softsign import softsign as T_softsign
import inspect
import numpy as np
from .common import _FLOATX, _EPSILON
from .common import _FLOATX, _EPSILON, _IMAGE_DIM_ORDERING
# INTERNAL UTILS
@@ -18,6 +23,14 @@ 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 variable(value, dtype=_FLOATX, name=None):
@@ -79,6 +92,12 @@ def ones(shape, dtype=_FLOATX, name=None):
return variable(np.ones(shape), dtype, name)
def eye(size, dtype=_FLOATX, name=None):
'''Instantiate an identity matrix.
'''
return variable(np.eye(size), dtype, name)
def ones_like(x):
return T.ones_like(x)
@@ -87,6 +106,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.
@@ -99,6 +128,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
'''
@@ -112,25 +160,42 @@ def 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] and y = [[5, 6]
[3, 4]] [7, 8]]
batch_dot(x, y, axes=1) = [[17, 53]] which is the main diagonal
of x.dot(y.T), although we never have to calculate the off-diagonal
elements.
# Arguments
x, y: tensors with ndim >= 2
axes: list (or single) int with target dimensions
# Returns
Tensor with ndim >= 2
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)
@@ -190,12 +255,22 @@ def std(x, axis=None, keepdims=False):
return T.std(x, axis=axis, keepdims=keepdims)
def var(x, axis=None, keepdims=False):
return T.var(x, axis=axis, keepdims=keepdims)
def any(x, axis=None, keepdims=False):
'''Bitwise reduction (logical OR).
'''
return T.any(x, axis=axis, keepdims=keepdims)
def all(x, axis=None, keepdims=False):
'''Bitwise reduction (logical AND).
'''
return T.all(x, axis=axis, keepdims=keepdims)
def argmax(x, axis=-1):
return T.argmax(x, axis=axis, keepdims=False)
@@ -251,6 +326,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)
@@ -259,6 +350,48 @@ def minimum(x, y):
return T.minimum(x, y)
def sin(x):
return T.sin(x)
def cos(x):
return T.cos(x)
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.
'''
var = x.var(reduction_axes)
mean = x.mean(reduction_axes)
target_shape = []
for axis in range(ndim(x)):
if axis in reduction_axes:
target_shape.append(1)
else:
target_shape.append(x.shape[axis])
target_shape = T.stack(*target_shape)
broadcast_mean = T.reshape(mean, 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_var,
broadcast_beta, broadcast_gamma,
epsilon)
return normed, mean, var
def batch_normalization(x, mean, var, beta, gamma, epsilon=0.0001):
'''Apply batch normalization on x given mean, var, beta and gamma.
'''
normed = T.nnet.bn.batch_normalization(x, gamma, beta, mean,
sqrt(var) + epsilon,
mode='high_mem')
return normed
# SHAPE OPERATIONS
def concatenate(tensors, axis=-1):
@@ -371,15 +504,18 @@ def expand_dims(x, dim=-1):
def squeeze(x, axis):
'''Remove a 1-dimension from the tensor at index "axis".
'''
x = T.addbroadcast(x, axis)
return T.squeeze(x)
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
def temporal_padding(x, padding=1):
'''Pad the middle dimension of a 3D tensor
with "padding" zeros left and right.
Appologies for the inane API, but Theano makes this
Apologies for the inane API, but Theano makes this
really hard.
'''
input_shape = x.shape
@@ -459,6 +595,19 @@ 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
# VALUE MANIPULATION
@@ -469,10 +618,30 @@ def get_value(x):
return x.get_value()
def batch_get_value(xs):
'''Returns the value of more than one tensor variable,
as a list of Numpy arrays.
'''
return [get_value(x) for x in xs]
def set_value(x, value):
x.set_value(np.asarray(value, dtype=x.dtype))
def batch_set_value(tuples):
for x, value in tuples:
x.set_value(np.asarray(value, dtype=x.dtype))
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):
@@ -480,7 +649,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):
@@ -502,6 +671,13 @@ def gradients(loss, variables):
return T.grad(loss, variables)
def stop_gradient(variables):
'''Returns `variables` but with zero gradient with respect to every other
variables.
'''
return theano.gradient.disconnected_grad(variables)
# CONTROL FLOW
def rnn(step_function, inputs, initial_states,
@@ -553,15 +729,15 @@ def rnn(step_function, inputs, initial_states,
axes = [1, 0] + list(range(2, ndim))
inputs = inputs.dimshuffle(axes)
if constants is None:
constants = []
if mask is not None:
if mask.ndim == ndim-1:
mask = expand_dims(mask)
assert mask.ndim == ndim
mask = mask.dimshuffle(axes)
if constants is None:
constants = []
if unroll:
indices = list(range(input_length))
if go_backwards:
@@ -571,7 +747,7 @@ def rnn(step_function, inputs, initial_states,
successive_states = []
states = initial_states
for i in indices:
output, new_states = step_function(inputs[i], states)
output, new_states = step_function(inputs[i], states + constants)
if len(successive_outputs) == 0:
prev_output = zeros_like(output)
@@ -630,7 +806,7 @@ def rnn(step_function, inputs, initial_states,
successive_states = []
states = initial_states
for i in indices:
output, states = step_function(inputs[i], states)
output, states = step_function(inputs[i], states + constants)
successive_outputs.append(output)
successive_states.append(states)
outputs = T.stack(*successive_outputs)
@@ -674,12 +850,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
@@ -706,6 +890,10 @@ def softplus(x):
return T.nnet.softplus(x)
def softsign(x):
return T_softsign(x)
def categorical_crossentropy(output, target, from_logits=False):
if from_logits:
output = T.nnet.softmax(output)
@@ -748,7 +936,7 @@ def dropout(x, level, seed=None):
if level < 0. or level >= 1:
raise Exception('Dropout level must be in interval [0, 1[.')
if seed is None:
seed = np.random.randint(10e6)
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)
@@ -763,68 +951,172 @@ def l2_normalize(x, axis):
# CONVOLUTIONS
def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th',
image_shape=None, filter_shape=None):
'''
border_mode: string, "same" or "valid".
'''
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
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)
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])
return kernel
def _preprocess_border_mode(border_mode):
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))
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
conv_out = T.nnet.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
input_shape=image_shape,
filter_shape=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)):
'''2D convolution.
# Arguments
kernel: kernel tensor.
strides: strides tuple.
border_mode: string, "same" or "valid".
dim_ordering: "tf" or "th".
Whether to use Theano or TensorFlow dimension ordering
in inputs/kernels/ouputs.
'''
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
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):
conv_out = T.nnet.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
input_shape=image_shape,
filter_shape=filter_shape)
else:
conv_out = T.nnet.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides,
input_shape=image_shape,
filter_shape=filter_shape,
filter_dilation=filter_dilation)
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel,
strides, dim_ordering)
return conv_out
def deconv2d(x, kernel, output_shape, strides=(1, 1),
border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING,
image_shape=None, filter_shape=None):
'''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,
border_mode='valid',
dim_ordering=_IMAGE_DIM_ORDERING,
image_shape=None, filter_shape=None):
raise NotImplementedError
def separable_conv2d(x, depthwise_kernel, pointwise_kernel, strides=(1, 1),
border_mode='valid', dim_ordering=_IMAGE_DIM_ORDERING):
raise NotImplementedError
def conv3d(x, kernel, strides=(1, 1, 1),
border_mode='valid', dim_ordering='th',
volume_shape=None, filter_shape=None):
@@ -993,27 +1285,20 @@ def pool3d(x, pool_size, strides=(1, 1, 1), border_mode='valid',
def random_normal(shape, mean=0.0, std=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.normal(size=shape, avg=mean, std=std, dtype=dtype)
def random_uniform(shape, low=0.0, high=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.uniform(shape, low=low, high=high, dtype=dtype)
def random_binomial(shape, p=0.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.binomial(shape, p=p, dtype=dtype)
'''
more TODO:
tensordot -> soon to be introduced in TF
batched_tensordot -> reimplement
'''
+67 -34
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):
@@ -60,8 +61,7 @@ class CallbackList(object):
callback.on_batch_end(batch, logs)
self._delta_ts_batch_end.append(time.time() - t_before_callbacks)
delta_t_median = np.median(self._delta_ts_batch_end)
if self._delta_t_batch > 0. and delta_t_median > 0.95 * \
self._delta_t_batch and delta_t_median > 0.1:
if self._delta_t_batch > 0. and (delta_t_median > 0.95 * self._delta_t_batch and delta_t_median > 0.1):
warnings.warn('Method on_batch_end() is slow compared '
'to the batch update (%f). Check your callbacks.'
% delta_t_median)
@@ -193,7 +193,7 @@ class ProgbarLogger(Callback):
if k in logs:
self.log_values.append((k, logs[k]))
if self.verbose:
self.progbar.update(self.seen, self.log_values)
self.progbar.update(self.seen, self.log_values, force=True)
class History(Callback):
@@ -211,9 +211,7 @@ class History(Callback):
def on_epoch_end(self, epoch, logs={}):
self.epoch.append(epoch)
for k, v in logs.items():
if k not in self.history:
self.history[k] = []
self.history[k].append(v)
self.history.setdefault(k, []).append(v)
class ModelCheckpoint(Callback):
@@ -233,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'):
super(Callback, self).__init__()
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, '
@@ -288,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' %
@@ -296,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):
@@ -314,7 +322,7 @@ class EarlyStopping(Callback):
monitored has stopped increasing.
'''
def __init__(self, monitor='val_loss', patience=0, verbose=0, mode='auto'):
super(Callback, self).__init__()
super(EarlyStopping, self).__init__()
self.monitor = monitor
self.patience = patience
@@ -323,22 +331,23 @@ 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':
self.monitor_op = np.less
self.best = np.Inf
elif mode == 'max':
self.monitor_op = np.greater
self.best = -np.Inf
else:
if 'acc' in self.monitor:
self.monitor_op = np.greater
self.best = -np.Inf
else:
self.monitor_op = np.less
self.best = np.Inf
def on_train_begin(self, logs={}):
self.wait = 0 # Allow instances to be re-used
self.best = np.Inf if self.monitor_op == np.less else -np.Inf
def on_epoch_end(self, epoch, logs={}):
current = logs.get(self.monitor)
@@ -365,12 +374,19 @@ 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/'`. Calls are HTTP POST,
with a `data` argument which is a JSON-encoded dictionary
of event data.
`root + '/publish/epoch/end/'` by default. Calls are
HTTP POST, with a `data` argument which is a
JSON-encoded dictionary of event data.
'''
def __init__(self, root='http://localhost:9000'):
def __init__(self,
root='http://localhost:9000',
path='/publish/epoch/end/',
field='data'):
super(RemoteMonitor, self).__init__()
self.root = root
self.path = path
self.field = field
def on_epoch_end(self, epoch, logs={}):
import requests
@@ -378,10 +394,9 @@ class RemoteMonitor(Callback):
send['epoch'] = epoch
for k, v in logs.items():
send[k] = v
try:
requests.post(self.root + '/publish/epoch/end/',
{'data': json.dumps(send)})
requests.post(self.root + self.path,
{self.field: json.dumps(send)})
except:
print('Warning: could not reach RemoteMonitor '
'root server at ' + str(self.root))
@@ -427,19 +442,24 @@ class TensorBoard(Callback):
# Arguments
log_dir: the path of the directory where to save the log
files to be parsed by tensorboard
files to be parsed by Tensorboard
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.
'''
def __init__(self, log_dir='./logs', histogram_freq=0):
super(Callback, self).__init__()
def __init__(self, log_dir='./logs', histogram_freq=0, write_graph=True):
super(TensorBoard, self).__init__()
if K._BACKEND != 'tensorflow':
raise Exception('TensorBoard callback only works '
'with the TensorFlow backend.')
self.log_dir = log_dir
self.histogram_freq = histogram_freq
self.merged = None
self.write_graph = write_graph
def _set_model(self, model):
import tensorflow as tf
@@ -447,7 +467,7 @@ class TensorBoard(Callback):
self.model = model
self.sess = KTF.get_session()
if self.histogram_freq and not self.merged:
if self.histogram_freq and self.merged is None:
layers = self.model.layers
for layer in layers:
if hasattr(layer, 'W'):
@@ -458,8 +478,15 @@ class TensorBoard(Callback):
tf.histogram_summary('{}_out'.format(layer),
layer.output)
self.merged = tf.merge_all_summaries()
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph_def)
if self.write_graph:
if parse_version(tf.__version__) >= parse_version('0.8.0'):
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph)
else:
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph_def)
else:
self.writer = tf.train.SummaryWriter(self.log_dir)
def on_epoch_end(self, epoch, logs={}):
import tensorflow as tf
@@ -468,8 +495,14 @@ class TensorBoard(Callback):
if epoch % self.histogram_freq == 0:
# TODO: implement batched calls to sess.run
# (current call will likely go OOM on GPU)
feed_dict = dict(zip(self.model.inputs,
self.model.validation_data))
if self.model.uses_learning_phase:
cut_v_data = len(self.model.inputs)
val_data = self.model.validation_data[:cut_v_data] + [0]
tensors = self.model.inputs + [K.learning_phase()]
else:
val_data = self.model.validation_data
tensors = self.model.inputs
feed_dict = dict(zip(tensors, val_data))
result = self.sess.run([self.merged], feed_dict=feed_dict)
summary_str = result[0]
self.writer.add_summary(summary_str, epoch)
-1
Ver Arquivo
@@ -2,7 +2,6 @@
from __future__ import absolute_import
import sys
from six.moves import cPickle
from six.moves import range
def load_batch(fpath, label_key='labels'):
+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
+13 -5
Ver Arquivo
@@ -4,13 +4,14 @@ from ..utils.data_utils import get_file
from six.moves import cPickle
from six.moves import zip
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):
path = get_file(path, origin="https://s3.amazonaws.com/text-datasets/reuters.pkl")
path = get_file(path, origin='https://s3.amazonaws.com/text-datasets/reuters.pkl')
f = open(path, 'rb')
X, labels = cPickle.load(f)
f.close()
@@ -61,7 +62,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')
return cPickle.load(f)
if sys.version_info < (3,):
data = cPickle.load(f)
else:
data = cPickle.load(f, encoding='latin1')
f.close()
return data
+413 -184
Ver Arquivo
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+249 -114
Ver Arquivo
@@ -5,6 +5,7 @@ import warnings
import copy
import time
import numpy as np
import multiprocessing
import threading
try:
import queue
@@ -20,7 +21,8 @@ from ..utils.generic_utils import Progbar
from .. import callbacks as cbks
def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
def standardize_input_data(data, names, shapes=None,
check_batch_dim=True,
exception_prefix=''):
'''Users may pass data as a list of arrays, dictionary of arrays,
or as a single array. We normalize this to an ordered list of
@@ -31,8 +33,8 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
arrays = []
for name in names:
if name not in data:
raise Exception('No data provided for input "' +
name + '". Input data keys: ' +
raise Exception('No data provided for "' +
name + '". Need data for each key in: ' +
str(data.keys()))
arrays.append(data[name])
elif type(data) is list:
@@ -54,7 +56,7 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
raise Exception('Error when checking ' + exception_prefix +
': you are passing a list as '
'input to your model, '
'but the model expects a '
'but the model expects '
'a list of ' + str(len(names)) +
' Numpy arrays instead. '
'The list you passed was: ' +
@@ -66,6 +68,12 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
': data should be a Numpy array, '
'or list/dict of Numpy arrays. '
'Found: ' + str(data)[:200] + '...')
if len(names) != 1:
# case: model expects multiple inputs but only received
# a single Numpy array
raise Exception('The model expects ' + str(len(names)) +
' input arrays, but only received one array. '
'Found: array with shape ' + str(data.shape))
arrays = [data]
# make arrays at least 2D
@@ -78,8 +86,7 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
# check shapes compatibility
if shapes:
for i in range(len(names)):
if not i and not check_batch_dim:
# skip the first axis
if shapes[i] is None:
continue
array = arrays[i]
if len(array.shape) != len(shapes[i]):
@@ -88,7 +95,10 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
' to have ' + str(len(shapes[i])) +
' dimensions, but got array with shape ' +
str(array.shape))
for dim, ref_dim in zip(array.shape, shapes[i]):
for j, (dim, ref_dim) in enumerate(zip(array.shape, shapes[i])):
if not j and not check_batch_dim:
# skip the first axis
continue
if ref_dim:
if ref_dim != dim:
raise Exception('Error when checking ' + exception_prefix +
@@ -153,7 +163,7 @@ def check_array_lengths(X, Y, W):
raise Exception('All input arrays (x) should have '
'the same number of samples.')
set_y = set(y_lengths)
if len(set_x) != 1:
if len(set_y) != 1:
raise Exception('All target arrays (y) should have '
'the same number of samples.')
set_w = set(w_lengths)
@@ -195,13 +205,13 @@ def check_loss_and_target_compatibility(targets, losses, output_shapes):
'Alternatively, you can use the loss function '
'`sparse_categorical_crossentropy` instead, '
'which does expect integer targets.')
if loss.__name__ in key_losses and y.shape[1] != shape[1]:
raise Exception('A target array with shape ' + str(y.shape) +
' was passed for an output of shape ' + str(shape) +
' while using as loss `' + loss.__name__ + '`. '
'This loss expects '
'targets to have the same shape '
'as the output.')
if loss.__name__ in key_losses and shape[1] is not None and y.shape[1] != shape[1]:
raise Exception('A target array with shape ' + str(y.shape) +
' was passed for an output of shape ' + str(shape) +
' while using as loss `' + loss.__name__ + '`. '
'This loss expects '
'targets to have the same shape '
'as the output.')
def collect_metrics(metrics, output_names):
@@ -224,6 +234,31 @@ def collect_metrics(metrics, output_names):
str(metrics))
def collect_trainable_weights(layer):
'''Collects all `trainable_weights` attributes,
excluding any sublayers where `trainable` is set the `False`.
'''
trainable = getattr(layer, 'trainable', True)
if not trainable:
return []
weights = []
if layer.__class__.__name__ == 'Sequential':
for sublayer in layer.flattened_layers:
weights += collect_trainable_weights(sublayer)
elif layer.__class__.__name__ == 'Model':
for sublayer in layer.layers:
weights += collect_trainable_weights(sublayer)
elif layer.__class__.__name__ == 'Graph':
for sublayer in layer._graph_nodes.values():
weights += collect_trainable_weights(sublayer)
else:
weights += layer.trainable_weights
# dedupe weights
weights = list(set(weights))
weights.sort(key=lambda x: x.name)
return weights
def batch_shuffle(index_array, batch_size):
'''This shuffles an array in a batch-wise fashion.
Useful for shuffling HDF5 arrays
@@ -361,40 +396,62 @@ def standardize_weights(y, sample_weight=None, class_weight=None,
return weights
else:
if sample_weight_mode is None:
return np.ones((y.shape[0],))
return np.ones((y.shape[0],), dtype=K.floatx())
else:
return np.ones((y.shape[0], y.shape[1]))
return np.ones((y.shape[0], y.shape[1]), dtype=K.floatx())
def generator_queue(generator, max_q_size=10,
wait_time=0.05, nb_worker=1):
'''Builds a threading queue out of a data generator.
Used in `fit_generator`, `evaluate_generator`.
wait_time=0.05, nb_worker=1, pickle_safe=False):
'''Builds a queue out of a data generator.
If pickle_safe, use a multiprocessing approach. Else, use threading.
Used in `fit_generator`, `evaluate_generator`, `predict_generator`.
'''
q = queue.Queue()
_stop = threading.Event()
def data_generator_task():
while not _stop.is_set():
try:
if q.qsize() < max_q_size:
try:
generator_output = next(generator)
except ValueError:
continue
q.put(generator_output)
else:
time.sleep(wait_time)
except Exception:
_stop.set()
raise
generator_threads = []
if pickle_safe:
q = multiprocessing.Queue(maxsize=max_q_size)
_stop = multiprocessing.Event()
else:
q = queue.Queue()
_stop = threading.Event()
generator_threads = [threading.Thread(target=data_generator_task)
for _ in range(nb_worker)]
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
q.put(generator_output)
else:
time.sleep(wait_time)
except Exception:
_stop.set()
raise
for thread in generator_threads:
thread.daemon = True
thread.start()
for i in range(nb_worker):
if pickle_safe:
# Reset random seed else all children processes share the same seed
np.random.seed()
thread = multiprocessing.Process(target=data_generator_task)
else:
thread = threading.Thread(target=data_generator_task)
generator_threads.append(thread)
thread.daemon = True
thread.start()
except:
_stop.set()
if pickle_safe:
# Terminate all daemon processes
for p in generator_threads:
if p.is_alive():
p.terminate()
q.close()
raise
return q, _stop
@@ -430,6 +487,7 @@ class Model(Container):
self.optimizer = optimizers.get(optimizer)
self.sample_weight_mode = sample_weight_mode
self.loss = loss
self.loss_weights = loss_weights
# prepare loss weights
if loss_weights is None:
@@ -450,7 +508,7 @@ class Model(Container):
'it should have one entry per model outputs. '
'The model has ' + str(len(self.outputs)) +
' outputs, but you passed loss_weights=' +
str(loss))
str(loss_weights))
loss_weights_list = loss_weights
else:
raise Exception('Could not interpret loss_weights argument: ' +
@@ -549,6 +607,11 @@ class Model(Container):
name = self.output_names[i]
self.targets.append(K.placeholder(ndim=len(shape), name=name + '_target'))
# prepare metrics
self.metrics = metrics
self.metrics_names = ['loss']
self.metrics_tensors = []
# compute total loss
total_loss = None
for i in range(len(self.outputs)):
@@ -558,19 +621,20 @@ class Model(Container):
sample_weight = sample_weights[i]
mask = masks[i]
loss_weight = loss_weights_list[i]
output_loss = loss_weight * weighted_loss(y_true, y_pred,
sample_weight, mask)
output_loss = weighted_loss(y_true, y_pred,
sample_weight, mask)
if len(self.outputs) > 1:
self.metrics_tensors.append(output_loss)
self.metrics_names.append(self.output_names[i] + '_loss')
if total_loss is None:
total_loss = output_loss
total_loss = loss_weight * output_loss
else:
total_loss += output_loss
total_loss += loss_weight * output_loss
# add regularization penalties to the loss
for r in self.regularizers:
total_loss = r(total_loss)
# prepare metrics
self.metrics_names = ['loss']
self.metrics = []
# list of same size as output_names.
# contains tuples (metrics for output, names of metrics)
nested_metrics = collect_metrics(metrics, self.output_names)
@@ -583,19 +647,23 @@ class Model(Container):
if metric == 'accuracy' or metric == 'acc':
# custom handling of accuracy (because of class mode duality)
output_shape = self.internal_output_shapes[i]
if output_shape[-1] == 1:
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_tensors.append(
metrics_module.sparse_categorical_accuracy(y_true, y_pred))
else:
# case: categorical accuracy
self.metrics.append(metrics_module.categorical_accuracy(y_true, y_pred))
# case: categorical accuracy with dense targets
self.metrics_tensors.append(metrics_module.categorical_accuracy(y_true, y_pred))
if len(self.output_names) == 1:
self.metrics_names.append('acc')
else:
self.metrics_names.append(self.output_layers[i].name + '_acc')
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:
@@ -616,54 +684,55 @@ class Model(Container):
self.predict_function = None
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
# dedupe trainable weights
trainable_weights_set = set()
trainable_weights = []
for w in self.trainable_weights:
if w not in trainable_weights_set:
trainable_weights_set.add(w)
trainable_weights.append(w)
# get trainable weights
trainable_weights = collect_trainable_weights(self)
training_updates = self.optimizer.get_updates(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)
def _make_test_function(self):
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)
def _make_predict_function(self):
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
# returns network outputs. Does not update weights.
# Does update the network states.
kwargs = getattr(self, '_function_kwargs', {})
self.predict_function = K.function(inputs,
self.outputs,
updates=self.state_updates,
**self._function_kwargs)
**kwargs)
def _fit_loop(self, f, ins, out_labels=[], batch_size=32,
nb_epoch=100, verbose=1, callbacks=[],
@@ -692,8 +761,6 @@ class Model(Container):
# Returns
`History` object.
'''
self.training_data = ins
self.validation_data = val_ins
do_validation = False
if val_f and val_ins:
do_validation = True
@@ -710,7 +777,14 @@ class Model(Container):
callbacks += [cbks.ProgbarLogger()]
callbacks = cbks.CallbackList(callbacks)
callbacks._set_model(self)
# it's possible to callback a different model than self
# (used by Sequential models)
if hasattr(self, 'callback_model') and self.callback_model:
callback_model = self.callback_model
else:
callback_model = self
callbacks._set_model(callback_model)
callbacks._set_params({
'batch_size': batch_size,
'nb_epoch': nb_epoch,
@@ -720,8 +794,9 @@ class Model(Container):
'metrics': callback_metrics,
})
callbacks.on_train_begin()
callback_model.stop_training = False
self.validation_data = val_ins
self.stop_training = False
for epoch in range(nb_epoch):
callbacks.on_epoch_begin(epoch)
if shuffle == 'batch':
@@ -730,6 +805,7 @@ class Model(Container):
np.random.shuffle(index_array)
batches = make_batches(nb_train_sample, batch_size)
epoch_logs = {}
for batch_index, (batch_start, batch_end) in enumerate(batches):
batch_ids = index_array[batch_start:batch_end]
try:
@@ -754,7 +830,6 @@ class Model(Container):
callbacks.on_batch_end(batch_index, batch_logs)
epoch_logs = {}
if batch_index == len(batches) - 1: # last batch
# validation
if do_validation:
@@ -768,7 +843,7 @@ class Model(Container):
for l, o in zip(out_labels, val_outs):
epoch_logs['val_' + l] = o
callbacks.on_epoch_end(epoch, epoch_logs)
if self.stop_training:
if callback_model.stop_training:
break
callbacks.on_train_end()
return self.history
@@ -783,7 +858,7 @@ class Model(Container):
verbose: verbosity mode.
# Returns
Array of prections (if the model has a single output)
Array of predictions (if the model has a single output)
or list of arrays of predictions
(if the model has multiple outputs).
'''
@@ -807,7 +882,7 @@ class Model(Container):
if batch_index == 0:
for batch_out in batch_outs:
shape = (nb_sample,) + batch_out.shape[1:]
outs.append(np.zeros(shape))
outs.append(np.zeros(shape, dtype=K.floatx()))
for i, batch_out in enumerate(batch_outs):
outs[i][batch_start:batch_end] = batch_out
@@ -873,12 +948,20 @@ class Model(Container):
raise Exception('You must compile a model before training/testing.'
' Use `model.compile(optimizer, loss)`.')
output_shapes = []
for output_shape, loss_fn in zip(self.internal_output_shapes, self.loss_functions):
if loss_fn.__name__ == 'sparse_categorical_crossentropy':
output_shapes.append(output_shape[:-1] + (1,))
elif getattr(objectives, loss_fn.__name__, None) is None:
output_shapes.append(None)
else:
output_shapes.append(output_shape)
x = standardize_input_data(x, self.input_names,
self.internal_input_shapes,
check_batch_dim=False,
exception_prefix='model input')
y = standardize_input_data(y, self.output_names,
self.internal_output_shapes,
output_shapes,
check_batch_dim=False,
exception_prefix='model target')
sample_weights = standardize_sample_weights(sample_weight,
@@ -927,7 +1010,7 @@ class Model(Container):
at the end of each epoch. The model will not be trained on this data.
This could be a tuple (x_val, y_val) or a tuple (val_x, val_y, val_sample_weights).
shuffle: boolean, whether to shuffle the training data before each epoch.
class_weight: optional dictionary mapping classe indices (integers) to
class_weight: optional dictionary mapping class indices (integers) to
a weight (float) to apply to the model's loss for the samples
from this class during training.
This can be useful to tell the model to "pay more attention" to
@@ -950,14 +1033,6 @@ class Model(Container):
class_weight=class_weight,
check_batch_dim=False,
batch_size=batch_size)
# prepare input arrays and training function
if self.uses_learning_phase:
ins = x + y + sample_weights + [1.]
else:
ins = x + y + sample_weights
self._make_train_function()
f = self.train_function
# prepare validation data
if validation_data:
do_validation = True
@@ -974,7 +1049,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
@@ -984,10 +1059,11 @@ class Model(Container):
split_at = int(len(x[0]) * (1. - validation_split))
x, val_x = (slice_X(x, 0, split_at), slice_X(x, split_at))
y, val_y = (slice_X(y, 0, split_at), slice_X(y, split_at))
sample_weights, val_sample_weights = (slice_X(sample_weights, 0, split_at), slice_X(sample_weights, split_at))
sample_weights, val_sample_weights = (
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
@@ -996,8 +1072,28 @@ class Model(Container):
val_f = None
val_ins = None
# prepare input arrays and training function
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
self._make_train_function()
f = self.train_function
# prepare display labels
out_labels = self.metrics_names
# rename duplicated metrics name
# (can happen with an output layer shared among multiple dataflows)
deduped_out_labels = []
for i, label in enumerate(out_labels):
new_label = label
if out_labels.count(label) > 1:
dup_idx = out_labels[:i].count(label)
new_label += '_' + str(dup_idx + 1)
deduped_out_labels.append(new_label)
out_labels = deduped_out_labels
if do_validation:
callback_metrics = copy.copy(out_labels) + ['val_' + n for n in out_labels]
else:
@@ -1012,7 +1108,7 @@ class Model(Container):
def evaluate(self, x, y, batch_size=32, verbose=1, sample_weight=None):
'''Returns the loss value and metrics values for the model
in test mode. Computation in done in batches.
in test mode. Computation is done in batches.
# Arguments
x: Numpy array of test data,
@@ -1037,7 +1133,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
@@ -1074,7 +1170,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
@@ -1102,7 +1198,7 @@ class Model(Container):
with shape (samples, sequence_length),
to apply a different weight to every timestep of every sample.
In this case you should make sure to specify sample_weight_mode="temporal" in compile().
class_weight: optional dictionary mapping classe indices (integers) to
class_weight: optional dictionary mapping class indices (integers) to
a weight (float) to apply to the model's loss for the samples
from this class during training.
This can be useful to tell the model to "pay more attention" to
@@ -1118,7 +1214,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
@@ -1156,7 +1252,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
@@ -1171,7 +1267,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
@@ -1184,7 +1280,7 @@ class Model(Container):
def fit_generator(self, generator, samples_per_epoch, nb_epoch,
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight={}):
class_weight={}, max_q_size=10, nb_worker=1, pickle_safe=False):
'''Fits the model on data generated batch-by-batch by
a Python generator.
The generator is run in parallel to the model, for efficiency.
@@ -1214,6 +1310,12 @@ class Model(Container):
at the end of every epoch.
class_weight: dictionary mapping class indices to a weight
for the class.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
# Returns
A `History` object.
@@ -1261,7 +1363,12 @@ class Model(Container):
callbacks += [cbks.ProgbarLogger()]
callbacks = cbks.CallbackList(callbacks)
callbacks._set_model(self)
# it's possible to callback a different model than self:
if hasattr(self, 'callback_model') and self.callback_model:
callback_model = self.callback_model
else:
callback_model = self
callbacks._set_model(callback_model)
callbacks._set_params({
'nb_epoch': nb_epoch,
'nb_sample': samples_per_epoch,
@@ -1287,9 +1394,10 @@ class Model(Container):
self.validation_data = None
# start generator thread storing batches into a queue
data_gen_queue, _stop = generator_queue(generator)
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
self.stop_training = False
callback_model.stop_training = False
while epoch < nb_epoch:
callbacks.on_epoch_begin(epoch)
samples_seen = 0
@@ -1322,6 +1430,8 @@ class Model(Container):
batch_logs = {}
if type(x) is list:
batch_size = len(x[0])
elif type(x) is dict:
batch_size = len(list(x.values())[0])
else:
batch_size = len(x)
batch_logs['batch'] = batch_index
@@ -1332,9 +1442,9 @@ class Model(Container):
outs = self.train_on_batch(x, y,
sample_weight=sample_weight,
class_weight=class_weight)
except Exception as e:
except:
_stop.set()
raise e
raise
if type(outs) != list:
outs = [outs]
@@ -1358,7 +1468,8 @@ class Model(Container):
if samples_seen >= samples_per_epoch and do_validation:
if val_gen:
val_outs = self.evaluate_generator(validation_data,
nb_val_samples)
nb_val_samples,
max_q_size=max_q_size)
else:
# no need for try/except because
# data has already been validated
@@ -1373,14 +1484,16 @@ class Model(Container):
callbacks.on_epoch_end(epoch, epoch_logs)
epoch += 1
if self.stop_training:
if callback_model.stop_training:
break
_stop.set()
if pickle_safe:
data_gen_queue.close()
callbacks.on_train_end()
return self.history
def evaluate_generator(self, generator, val_samples):
def evaluate_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False):
'''Evaluates the model on a data generator. The generator should
return the same kind of data as accepted by `test_on_batch`.
@@ -1391,6 +1504,12 @@ class Model(Container):
val_samples:
total number of samples to generate from `generator`
before returning.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
# Returns
Scalar test loss (if the model has a single output and no metrics)
@@ -1404,7 +1523,8 @@ class Model(Container):
wait_time = 0.01
all_outs = []
weights = []
data_gen_queue, _stop = generator_queue(generator)
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
while processed_samples < val_samples:
generator_output = None
@@ -1432,12 +1552,14 @@ class Model(Container):
'or (x, y). Found: ' + str(generator_output))
try:
outs = self.test_on_batch(x, y, sample_weight=sample_weight)
except Exception as e:
except:
_stop.set()
raise e
raise
if type(x) is list:
nb_samples = len(x[0])
elif type(x) is dict:
nb_samples = len(list(x.values())[0])
else:
nb_samples = len(x)
all_outs.append(outs)
@@ -1446,6 +1568,8 @@ class Model(Container):
weights.append(nb_samples)
_stop.set()
if pickle_safe:
data_gen_queue.close()
if type(outs) is not list:
return np.average(np.asarray(all_outs),
weights=weights)
@@ -1453,10 +1577,10 @@ class Model(Container):
averages = []
for i in range(len(outs)):
averages.append(np.average([out[i] for out in all_outs],
weights=weights))
weights=weights))
return averages
def predict_generator(self, generator, val_samples):
def predict_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False):
'''Generates predictions for the input samples from a data generator.
The generator should return the same kind of data as accepted by
`predict_on_batch`.
@@ -1465,6 +1589,12 @@ class Model(Container):
generator: generator yielding batches of input samples.
val_samples: total number of samples to generate from `generator`
before returning.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
# Returns
Numpy array(s) of predictions.
@@ -1474,7 +1604,8 @@ class Model(Container):
processed_samples = 0
wait_time = 0.01
all_outs = []
data_gen_queue, _stop = generator_queue(generator)
data_gen_queue, _stop = generator_queue(generator, max_q_size=max_q_size, nb_worker=nb_worker,
pickle_safe=pickle_safe)
while processed_samples < val_samples:
generator_output = None
@@ -1501,12 +1632,14 @@ class Model(Container):
try:
outs = self.predict_on_batch(x)
except Exception as e:
except:
_stop.set()
raise e
raise
if type(x) is list:
nb_samples = len(x[0])
elif type(x) is dict:
nb_samples = len(list(x.values())[0])
else:
nb_samples = len(x)
@@ -1516,7 +1649,7 @@ class Model(Container):
if len(all_outs) == 0:
for out in outs:
shape = (val_samples,) + out.shape[1:]
all_outs.append(np.zeros(shape))
all_outs.append(np.zeros(shape, dtype=K.floatx()))
for i, out in enumerate(outs):
all_outs[i][processed_samples:(processed_samples + nb_samples)] = out
@@ -1524,6 +1657,8 @@ class Model(Container):
processed_samples += nb_samples
_stop.set()
if pickle_safe:
data_gen_queue.close()
if len(all_outs) == 1:
return all_outs[0]
return all_outs
+8 -8
Ver Arquivo
@@ -12,11 +12,13 @@ def get_fans(shape, dim_ordering='th'):
# TH kernel shape: (depth, input_depth, ...)
# TF kernel shape: (..., input_depth, depth)
if dim_ordering == 'th':
fan_in = np.prod(shape[1:])
fan_out = shape[0]
receptive_field_size = np.prod(shape[2:])
fan_in = shape[1] * receptive_field_size
fan_out = shape[0] * receptive_field_size
elif dim_ordering == 'tf':
fan_in = np.prod(shape[:-1])
fan_out = shape[-1]
receptive_field_size = np.prod(shape[:2])
fan_in = shape[-2] * receptive_field_size
fan_out = shape[-1] * receptive_field_size
else:
raise Exception('Invalid dim_ordering: ' + dim_ordering)
else:
@@ -27,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'):
+2
Ver Arquivo
@@ -2,6 +2,8 @@ from __future__ import absolute_import
from ..engine import Layer, Input, InputLayer, Merge, merge, InputSpec
from .core import *
from .convolutional import *
from .pooling import *
from .local import *
from .recurrent import *
from .normalization import *
from .embeddings import *
+5 -5
Ver Arquivo
@@ -51,7 +51,7 @@ class PReLU(Layer):
# Arguments
init: initialization function for the weights.
weights: initial weights, as a list of a single numpy array.
weights: initial weights, as a list of a single Numpy array.
# References
- [Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification](http://arxiv.org/pdf/1502.01852v1.pdf)
@@ -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()))
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+100 -53
Ver Arquivo
@@ -76,9 +76,10 @@ class Dropout(Layer):
- [Dropout: A Simple Way to Prevent Neural Networks from Overfitting](http://www.cs.toronto.edu/~rsalakhu/papers/srivastava14a.pdf)
'''
def __init__(self, p, **kwargs):
self.supports_masking = True
self.uses_learning_phase = True
self.p = p
if 0. < self.p < 1.:
self.uses_learning_phase = True
self.supports_masking = True
super(Dropout, self).__init__(**kwargs)
def call(self, x, mask=None):
@@ -160,7 +161,7 @@ class Reshape(Layer):
'''Find and replace a single missing dimension in an output shape
given an input shape.
A near direct port of the internal numpy function _fix_unknown_dimension
A near direct port of the internal Numpy function _fix_unknown_dimension
in numpy/core/src/multiarray/shape.c
# Arguments
@@ -386,7 +387,14 @@ class Lambda(Layer):
function: The function to be evaluated.
Takes one argument: the output of previous layer
output_shape: Expected output shape from function.
Could be a tuple or a function of the shape of the input
Can be a tuple or function.
If a tuple, it only specifies the first dimension onward;
sample dimension is assumed either the same as the input:
`output_shape = (input_shape[0], ) + output_shape`
or, the input is `None` and the sample dimension is also `None`:
`output_shape = (None, ) + output_shape`
If a function, it specifies the entire shape as a function of
the input shape: `output_shape = f(input_shape)`
arguments: optional dictionary of keyword arguments to be passed
to the function.
@@ -401,6 +409,8 @@ class Lambda(Layer):
def __init__(self, function, output_shape=None, arguments={}, **kwargs):
self.function = function
self.arguments = arguments
self.supports_masking = False
if output_shape is None:
self._output_shape = None
elif type(output_shape) in {tuple, list}:
@@ -459,9 +469,9 @@ class Lambda(Layer):
if isinstance(self._output_shape, python_types.LambdaType):
if py3:
output_shape = marshal.dumps(self._output_shape.__code__)
output_shape = marshal.dumps(self._output_shape.__code__).decode('raw_unicode_escape')
else:
output_shape = marshal.dumps(self._output_shape.func_code)
output_shape = marshal.dumps(self._output_shape.func_code).decode('raw_unicode_escape')
output_shape_type = 'lambda'
elif callable(self._output_shape):
output_shape = self._output_shape.__name__
@@ -493,7 +503,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'])
output_shape = marshal.loads(config['output_shape'].encode('raw_unicode_escape'))
output_shape = python_types.FunctionType(output_shape, globals())
else:
output_shape = config['output_shape']
@@ -510,12 +520,14 @@ class Dense(Layer):
```python
# as first layer in a sequential model:
model = Sequential(Dense(32, input_dim=16))
model = Sequential()
model.add(Dense(32, input_dim=16))
# now the model will take as input arrays of shape (*, 16)
# and output arrays of shape (*, 32)
# this is equivalent to the above:
model = Sequential(Dense(32, input_shape=(16,)))
model = Sequential()
model.add(Dense(32, input_shape=(16,)))
# after the first layer, you don't need to specify
# the size of the input anymore:
@@ -534,7 +546,7 @@ class Dense(Layer):
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.
weights: list of Numpy arrays to set as initial weights.
The list should have 2 elements, of shape `(input_dim, output_dim)`
and (output_dim,) for weights and biases respectively.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
@@ -547,6 +559,7 @@ class Dense(Layer):
(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: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
@@ -559,7 +572,8 @@ class Dense(Layer):
'''
def __init__(self, output_dim, init='glorot_uniform', activation='linear', weights=None,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None, input_dim=None, **kwargs):
W_constraint=None, b_constraint=None,
bias=True, input_dim=None, **kwargs):
self.init = initializations.get(init)
self.activation = activations.get(activation)
self.output_dim = output_dim
@@ -572,6 +586,7 @@ class Dense(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.initial_weights = weights
self.input_spec = [InputSpec(ndim=2)]
@@ -587,16 +602,19 @@ class Dense(Layer):
self.W = self.init((input_dim, self.output_dim),
name='{}_W'.format(self.name))
self.b = K.zeros((self.output_dim,),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
if self.bias:
self.b = K.zeros((self.output_dim,),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
else:
self.trainable_weights = [self.W]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.b_regularizer:
if self.bias and self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
@@ -607,7 +625,7 @@ class Dense(Layer):
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
if self.bias and self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
@@ -615,7 +633,10 @@ class Dense(Layer):
del self.initial_weights
def call(self, x, mask=None):
return self.activation(K.dot(x, self.W) + self.b)
output = K.dot(x, self.W)
if self.bias:
output += self.b
return self.activation(output)
def get_output_shape_for(self, input_shape):
assert input_shape and len(input_shape) == 2
@@ -630,6 +651,7 @@ class Dense(Layer):
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias,
'input_dim': self.input_dim}
base_config = super(Dense, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -656,10 +678,10 @@ class ActivityRegularization(Layer):
self.l1 = l1
self.l2 = l2
super(ActivityRegularization, self).__init__(**kwargs)
activity_regularizer = ActivityRegularizer(l1=l1, l2=l2)
activity_regularizer.set_layer(self)
self.regularizers = [activity_regularizer]
super(ActivityRegularization, self).__init__(**kwargs)
def get_config(self):
config = {'l1': self.l1,
@@ -689,12 +711,7 @@ class MaxoutDense(Layer):
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.
weights: list of Numpy arrays to set as initial weights.
The list should have 2 elements, of shape `(input_dim, output_dim)`
and (output_dim,) for weights and biases respectively.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
@@ -707,6 +724,7 @@ class MaxoutDense(Layer):
(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: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
@@ -723,7 +741,8 @@ class MaxoutDense(Layer):
def __init__(self, output_dim, nb_feature=4,
init='glorot_uniform', weights=None,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None, input_dim=None, **kwargs):
W_constraint=None, b_constraint=None,
bias=True, input_dim=None, **kwargs):
self.output_dim = output_dim
self.nb_feature = nb_feature
self.init = initializations.get(init)
@@ -735,6 +754,7 @@ class MaxoutDense(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.initial_weights = weights
self.input_spec = [InputSpec(ndim=2)]
@@ -750,17 +770,19 @@ class MaxoutDense(Layer):
self.W = self.init((self.nb_feature, input_dim, self.output_dim),
name='{}_W'.format(self.name))
self.b = K.zeros((self.nb_feature, self.output_dim),
name='{}_b'.format(self.name))
if self.bias:
self.b = K.zeros((self.nb_feature, self.output_dim),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
else:
self.trainable_weights = [self.W]
self.trainable_weights = [self.W, self.b]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.b_regularizer:
if self.bias and self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
@@ -771,7 +793,7 @@ class MaxoutDense(Layer):
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
if self.bias and self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
@@ -784,7 +806,10 @@ class MaxoutDense(Layer):
def call(self, x, mask=None):
# no activation, this layer is only linear.
output = K.max(K.dot(x, self.W) + self.b, axis=1)
output = K.dot(x, self.W)
if self.bias:
output += self.b
output = K.max(output, axis=1)
return output
def get_config(self):
@@ -796,6 +821,7 @@ class MaxoutDense(Layer):
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias,
'input_dim': self.input_dim}
base_config = super(MaxoutDense, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -817,7 +843,7 @@ class Highway(Layer):
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.
weights: list of Numpy arrays to set as initial weights.
The list should have 2 elements, of shape `(input_dim, output_dim)`
and (output_dim,) for weights and biases respectively.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
@@ -830,6 +856,7 @@ class Highway(Layer):
(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: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
@@ -846,7 +873,8 @@ class Highway(Layer):
def __init__(self, init='glorot_uniform', transform_bias=-2,
activation='linear', weights=None,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None, input_dim=None, **kwargs):
W_constraint=None, b_constraint=None,
bias=True, input_dim=None, **kwargs):
self.init = initializations.get(init)
self.transform_bias = transform_bias
self.activation = activations.get(activation)
@@ -858,6 +886,7 @@ class Highway(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.initial_weights = weights
self.input_spec = [InputSpec(ndim=2)]
@@ -876,19 +905,21 @@ class Highway(Layer):
self.W_carry = self.init((input_dim, input_dim),
name='{}_W_carry'.format(self.name))
self.b = K.zeros((input_dim,), name='{}_b'.format(self.name))
# initialize with a vector of values `transform_bias`
self.b_carry = K.variable(np.ones((input_dim,)) * self.transform_bias,
name='{}_b_carry'.format(self.name))
self.trainable_weights = [self.W, self.b, self.W_carry, self.b_carry]
if self.bias:
self.b = K.zeros((input_dim,), name='{}_b'.format(self.name))
# initialize with a vector of values `transform_bias`
self.b_carry = K.variable(np.ones((input_dim,)) * self.transform_bias,
name='{}_b_carry'.format(self.name))
self.trainable_weights = [self.W, self.b, self.W_carry, self.b_carry]
else:
self.trainable_weights = [self.W, self.W_carry]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.b_regularizer:
if self.bias and self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
@@ -899,7 +930,7 @@ class Highway(Layer):
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
if self.bias and self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
@@ -907,8 +938,14 @@ class Highway(Layer):
del self.initial_weights
def call(self, x, mask=None):
transform_weight = activations.sigmoid(K.dot(x, self.W_carry) + self.b_carry)
act = self.activation(K.dot(x, self.W) + self.b)
y = K.dot(x, self.W_carry)
if self.bias:
y += self.b_carry
transform_weight = activations.sigmoid(y)
y = K.dot(x, self.W)
if self.bias:
y += self.b
act = self.activation(y)
act *= transform_weight
output = act + (1 - transform_weight) * x
return output
@@ -922,6 +959,7 @@ class Highway(Layer):
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias,
'input_dim': self.input_dim}
base_config = super(Highway, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -938,8 +976,10 @@ class TimeDistributedDense(Layer):
# Input shape
3D tensor with shape `(nb_sample, time_dimension, input_dim)`.
# Output shape
3D tensor with shape `(nb_sample, time_dimension, output_dim)`.
# Arguments
output_dim: int > 0.
init: name of initialization function for the weights of the layer
@@ -952,7 +992,7 @@ class TimeDistributedDense(Layer):
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.
weights: list of Numpy arrays to set as initial weights.
The list should have 2 elements, of shape `(input_dim, output_dim)`
and (output_dim,) for weights and biases respectively.
W_regularizer: instance of [WeightRegularizer](../regularizers.md)
@@ -965,16 +1005,19 @@ class TimeDistributedDense(Layer):
(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: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
input_length: length of inputs sequences
(integer, or None for variable-length sequences).
'''
def __init__(self, output_dim,
init='glorot_uniform', activation='linear', weights=None,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
input_dim=None, input_length=None, **kwargs):
bias=True, input_dim=None, input_length=None, **kwargs):
warnings.warn('TimeDistributedDense is deprecated, '
'please use TimeDistributed(Dense(...)) instead.')
self.output_dim = output_dim
@@ -988,6 +1031,7 @@ class TimeDistributedDense(Layer):
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.initial_weights = weights
self.input_spec = [InputSpec(ndim=3)]
self.supports_masking = True
@@ -1005,17 +1049,17 @@ class TimeDistributedDense(Layer):
self.W = self.init((input_dim, self.output_dim),
name='{}_W'.format(self.name))
self.b = K.zeros((self.output_dim,),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
if self.bias:
self.b = K.zeros((self.output_dim,),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.b_regularizer:
if self.bias and self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
@@ -1026,7 +1070,7 @@ class TimeDistributedDense(Layer):
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
if self.bias and self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
@@ -1056,7 +1100,9 @@ class TimeDistributedDense(Layer):
# Squash samples and timesteps into a single axis
x = K.reshape(x, (-1, input_shape[-1])) # (samples * timesteps, input_dim)
y = K.dot(x, self.W) + self.b # (samples * timesteps, output_dim)
y = K.dot(x, self.W) # (samples * timesteps, output_dim)
if self.bias:
y += self.b
# We have to reshape Y to (samples, timesteps, output_dim)
y = K.reshape(y, (-1, input_length, self.output_dim)) # (samples, timesteps, output_dim)
y = self.activation(y)
@@ -1071,6 +1117,7 @@ class TimeDistributedDense(Layer):
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias,
'input_dim': self.input_dim,
'input_length': self.input_length}
base_config = super(TimeDistributedDense, self).get_config()
+17 -5
Ver Arquivo
@@ -17,7 +17,7 @@ class Embedding(Layer):
model = Sequential()
model.add(Embedding(1000, 64, input_length=10))
# the model will take as input an integer matrix of size (batch, input_length).
# the largest integer (i.e. word index) in the input should be no larger than 1000 (vocabulary size).
# the largest integer (i.e. word index) in the input should be no larger than 999 (vocabulary size).
# now model.output_shape == (None, 10, 64), where None is the batch dimension.
input_array = np.random.randint(1000, size=(32, 10))
@@ -28,14 +28,14 @@ class Embedding(Layer):
```
# Arguments
input_dim: int >= 0. Size of the vocabulary, ie.
input_dim: int > 0. Size of the vocabulary, ie.
1 + maximum integer index occurring in the input data.
output_dim: int >= 0. Dimension of the dense embedding.
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.
weights: list of numpy arrays to set as initial weights.
weights: list of Numpy arrays to set as initial weights.
The list should have 1 element, of shape `(input_dim, output_dim)`.
W_regularizer: instance of the [regularizers](../regularizers.md) module
(eg. L1 or L2 regularization), applied to the embedding matrix.
@@ -46,6 +46,8 @@ class Embedding(Layer):
This is useful for [recurrent layers](recurrent.md) which may take
variable length input. If this is `True` then all subsequent layers
in the model need to support masking or an exception will be raised.
If mask_zero is set to True, as a consequence, index 0 cannot be
used in the vocabulary (input_dim should equal |vocabulary| + 2).
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
@@ -77,7 +79,6 @@ class Embedding(Layer):
self.dropout = dropout
self.W_constraint = constraints.get(W_constraint)
self.constraints = [self.W_constraint]
self.W_regularizer = regularizers.get(W_regularizer)
self.activity_regularizer = regularizers.get(activity_regularizer)
@@ -93,6 +94,11 @@ class Embedding(Layer):
self.W = self.init((self.input_dim, self.output_dim),
name='{}_W'.format(self.name))
self.trainable_weights = [self.W]
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
@@ -112,9 +118,15 @@ class Embedding(Layer):
return K.not_equal(x, 0)
def get_output_shape_for(self, input_shape):
return (input_shape[0], self.input_length, self.output_dim)
if not self.input_length:
input_length = input_shape[1]
else:
input_length = self.input_length
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)
+423
Ver Arquivo
@@ -0,0 +1,423 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from keras import backend as K
from keras.layers import activations, initializations, regularizers, constraints
from keras.engine import Layer, InputSpec
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`
(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.
# Example
```python
# apply a unshared weight convolution 1d of length 3 to a sequence with
# 10 timesteps, with 64 output filters
model = Sequential()
model.add(LocallyConnected1D(64, 3, input_shape=(10, 32)))
# now model.output_shape == (None, 8, 64)
# add a new conv1d on top
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.
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: Only support 'valid'. Please make good use of
ZeroPadding1D to achieve same output length.
subsample_length: factor by which to subsample output.
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,
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
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 LocallyConnected1D '
'(only "valid" is supported):', border_mode)
self.nb_filter = nb_filter
self.filter_length = filter_length
self.init = initializations.get(init, dim_ordering='th')
self.activation = activations.get(activation)
self.border_mode = border_mode
self.subsample_length = subsample_length
self.W_regularizer = regularizers.get(W_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.activity_regularizer = regularizers.get(activity_regularizer)
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.input_spec = [InputSpec(ndim=3)]
self.initial_weights = weights
self.input_dim = input_dim
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
super(LocallyConnected1D, self).__init__(**kwargs)
def build(self, input_shape):
input_dim = input_shape[2]
_, output_length, nb_filter = self.get_output_shape_for(input_shape)
self.W_shape = (output_length, self.filter_length * input_dim, nb_filter)
self.W = self.init(self.W_shape, name='{}_W'.format(self.name))
if self.bias:
self.b = K.zeros((output_length, self.nb_filter), name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
else:
self.trainable_weights = [self.W]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
if self.activity_regularizer:
self.activity_regularizer.set_layer(self)
self.regularizers.append(self.activity_regularizer)
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
def get_output_shape_for(self, input_shape):
length = conv_output_length(input_shape[1],
self.filter_length,
self.border_mode,
self.subsample_length)
return (input_shape[0], length, self.nb_filter)
def call(self, x, mask=None):
stride = self.subsample_length
output_length, feature_dim, nb_filter = self.W_shape
xs = []
for i in range(output_length):
slice_length = slice(i * stride, i * stride + self.filter_length)
xs.append(K.reshape(x[:, slice_length, :], (1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
# (output_length, batch_size, nb_filter)
output = K.batch_dot(x_aggregate, self.W)
output = K.permute_dimensions(output, (1, 0, 2))
if self.bias:
output += K.reshape(self.b, (1, output_length, nb_filter))
output = self.activation(output)
return output
def get_config(self):
config = {'nb_filter': self.nb_filter,
'filter_length': self.filter_length,
'init': self.init.__name__,
'activation': self.activation.__name__,
'border_mode': self.border_mode,
'subsample_length': self.subsample_length,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias,
'input_dim': self.input_dim,
'input_length': self.input_length}
base_config = super(LocallyConnected1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
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
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.
# Examples
```python
# apply a 3x3 unshared weights convolution with 64 output filters on a 32x32 image:
model = Sequential()
model.add(LocallyConnected2D(64, 3, 3, input_shape=(3, 32, 32)))
# now model.output_shape == (None, 64, 30, 30)
# notice that this layer will consume (30*30)*(3*3*3*64) + (30*30)*64 parameters
# add a 3x3 unshared weights convolution on top, with 32 output filters:
model.add(LocallyConnected2D(32, 3, 3))
# now model.output_shape == (None, 32, 28, 28)
```
# Arguments
nb_filter: Number of convolution filters to use.
nb_row: Number of rows in the convolution kernel.
nb_col: Number of columns in the convolution kernel.
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: Only support 'valid'. Please make good use of
ZeroPadding2D to achieve same output shape.
subsample: tuple of length 2. Factor by which to subsample 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.
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.
'''
def __init__(self, nb_filter, nb_row, nb_col,
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 != 'valid':
raise Exception('Invalid border mode for LocallyConnected2D '
'(only "valid" is supported):', border_mode)
self.nb_filter = nb_filter
self.nb_row = nb_row
self.nb_col = nb_col
self.init = initializations.get(init, dim_ordering=dim_ordering)
self.activation = activations.get(activation)
self.border_mode = border_mode
self.subsample = tuple(subsample)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.W_regularizer = regularizers.get(W_regularizer)
self.b_regularizer = regularizers.get(b_regularizer)
self.activity_regularizer = regularizers.get(activity_regularizer)
self.W_constraint = constraints.get(W_constraint)
self.b_constraint = constraints.get(b_constraint)
self.bias = bias
self.input_spec = [InputSpec(ndim=4)]
self.initial_weights = weights
super(LocallyConnected2D, self).__init__(**kwargs)
def build(self, input_shape):
output_shape = self.get_output_shape_for(input_shape)
if self.dim_ordering == 'th':
_, nb_filter, output_row, output_col = output_shape
input_filter = input_shape[1]
elif self.dim_ordering == 'tf':
_, output_row, output_col, nb_filter = output_shape
input_filter = input_shape[3]
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
self.output_row = output_row
self.output_col = output_col
self.W_shape = (output_row * output_col, self.nb_row * self.nb_col * input_filter, nb_filter)
self.W = self.init(self.W_shape, name='{}_W'.format(self.name))
if self.bias:
self.b = K.zeros((output_row, output_col, nb_filter), name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.b]
else:
self.trainable_weights = [self.W]
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.bias and self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
if self.activity_regularizer:
self.activity_regularizer.set_layer(self)
self.regularizers.append(self.activity_regularizer)
self.constraints = {}
if self.W_constraint:
self.constraints[self.W] = self.W_constraint
if self.bias and self.b_constraint:
self.constraints[self.b] = self.b_constraint
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
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_output_length(rows, self.nb_row,
self.border_mode, self.subsample[0])
cols = conv_output_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):
stride_row, stride_col = self.subsample
_, feature_dim, nb_filter = self.W_shape
if self.dim_ordering == 'th':
if K._backend == 'theano':
output = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.nb_row)
slice_col = slice(j * stride_col,
j * stride_col + self.nb_col)
x_flatten = K.reshape(x[:, :, slice_row, slice_col], (1, -1, feature_dim))
output.append(K.dot(x_flatten, self.W[i * self.output_col + j, :, :]))
output = K.concatenate(output, axis=0)
else:
xs = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.nb_row)
slice_col = slice(j * stride_col,
j * stride_col + self.nb_col)
xs.append(K.reshape(x[:, :, slice_row, slice_col], (1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
output = K.batch_dot(x_aggregate, self.W)
output = K.reshape(output, (self.output_row, self.output_col, -1, nb_filter))
output = K.permute_dimensions(output, (2, 3, 0, 1))
elif self.dim_ordering == 'tf':
xs = []
for i in range(self.output_row):
for j in range(self.output_col):
slice_row = slice(i * stride_row,
i * stride_row + self.nb_row)
slice_col = slice(j * stride_col,
j * stride_col + self.nb_col)
xs.append(K.reshape(x[:, slice_row, slice_col, :], (1, -1, feature_dim)))
x_aggregate = K.concatenate(xs, axis=0)
output = K.batch_dot(x_aggregate, self.W)
output = K.reshape(output, (self.output_row, self.output_col, -1, nb_filter))
output = K.permute_dimensions(output, (2, 0, 1, 3))
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
if self.bias:
if self.dim_ordering == 'th':
output += K.reshape(self.b, (1, nb_filter, self.output_row, self.output_col))
elif self.dim_ordering == 'tf':
output += K.reshape(self.b, (1, self.output_row, self.output_col, nb_filter))
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
output = self.activation(output)
return output
def get_config(self):
config = {'nb_filter': self.nb_filter,
'nb_row': self.nb_row,
'nb_col': self.nb_col,
'init': self.init.__name__,
'activation': self.activation.__name__,
'border_mode': self.border_mode,
'subsample': self.subsample,
'dim_ordering': self.dim_ordering,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,
'activity_regularizer': self.activity_regularizer.get_config() if self.activity_regularizer else None,
'W_constraint': self.W_constraint.get_config() if self.W_constraint else None,
'b_constraint': self.b_constraint.get_config() if self.b_constraint else None,
'bias': self.bias}
base_config = super(LocallyConnected2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+4 -3
Ver Arquivo
@@ -1,10 +1,11 @@
from __future__ import absolute_import
from ..engine import Layer
from .. import backend as K
import numpy as np
class GaussianNoise(Layer):
'''Apply to the input an additive zero-centred gaussian noise with
'''Apply to the input an additive zero-centered Gaussian noise with
standard deviation `sigma`. This is useful to mitigate overfitting
(you could see it as a kind of random data augmentation).
Gaussian Noise (GS) is a natural choice as corruption process
@@ -42,7 +43,7 @@ class GaussianNoise(Layer):
class GaussianDropout(Layer):
'''Apply to the input an multiplicative one-centred gaussian noise
'''Apply to the input an multiplicative one-centered Gaussian noise
with standard deviation `sqrt(p/(1-p))`.
As it is a regularization layer, it is only active at training time.
@@ -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
+61 -27
Ver Arquivo
@@ -10,7 +10,7 @@ class BatchNormalization(Layer):
# Arguments
epsilon: small float > 0. Fuzz parameter.
mode: integer, 0 or 1.
mode: integer, 0, 1 or 2.
- 0: feature-wise normalization.
Each feature map in the input will
be normalized separately. The axis on which
@@ -19,7 +19,13 @@ class BatchNormalization(Layer):
using Theano conventions (samples, channels, rows, cols)
then you should set `axis` to `1` to normalize along
the channels axis.
During training we use per-batch statistics to normalize
the data, and during testing we use running averages
computed during the training phase.
- 1: sample-wise normalization. This mode assumes a 2D input.
- 2: feature-wise normalization, like mode 0, but
using per-batch statistics to normalize the data during both
testing and training.
axis: integer, axis along which to normalize in mode 0. For instance,
if your input tensor has shape (samples, channels, rows, cols),
set axis to 1 to normalize per feature map (channels axis).
@@ -27,8 +33,9 @@ class BatchNormalization(Layer):
exponential average of the mean and standard deviation
of the data, for feature-wise normalization.
weights: Initialization weights.
List of 2 numpy arrays, with shapes:
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.
@@ -47,10 +54,11 @@ class BatchNormalization(Layer):
Same shape as input.
# References
- [Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift](http://arxiv.org/pdf/1502.03167v3.pdf)
- [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,
def __init__(self, epsilon=1e-6, mode=0, axis=-1, momentum=0.99,
weights=None, beta_init='zero', gamma_init='one', **kwargs):
self.supports_masking = True
self.beta_init = initializations.get(beta_init)
self.gamma_init = initializations.get(gamma_init)
self.epsilon = epsilon
@@ -58,7 +66,8 @@ class BatchNormalization(Layer):
self.axis = axis
self.momentum = momentum
self.initial_weights = weights
self.uses_learning_phase = True
if self.mode == 0:
self.uses_learning_phase = True
super(BatchNormalization, self).__init__(**kwargs)
def build(self, input_shape):
@@ -78,9 +87,12 @@ class BatchNormalization(Layer):
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
self.built = True
self.called_with = None
def call(self, x, mask=None):
if self.mode == 0:
if self.mode == 0 or self.mode == 2:
assert self.built, 'Layer must be built before being called'
input_shape = self.input_spec[0].shape
reduction_axes = list(range(len(input_shape)))
@@ -88,34 +100,56 @@ 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)
mean_update = self.momentum * self.running_mean + (1-self.momentum) * mean
std_update = self.momentum * self.running_std + (1-self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
x_normed = (x - brodcast_mean) / (brodcast_std + self.epsilon)
if self.mode == 2:
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}:
raise Exception('You are attempting to share a '
'same `BatchNormalization` layer across '
'different data flows. '
'This is not possible. '
'You should use `mode=2` in '
'`BatchNormalization`, which has '
'a similar behavior but is shareable '
'(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)
# case: test mode (uses running averages)
brodcast_running_mean = K.reshape(self.running_mean, broadcast_shape)
brodcast_running_std = K.reshape(self.running_std, broadcast_shape)
x_normed_running = ((x - brodcast_running_mean) / (brodcast_running_std + self.epsilon))
self.updates = [K.moving_average_update(self.running_mean, mean, self.momentum),
K.moving_average_update(self.running_std, std, self.momentum)]
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
out = K.reshape(self.gamma, broadcast_shape) * x_normed + K.reshape(self.beta, broadcast_shape)
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)
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)
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
elif self.mode == 1:
# sample-wise normalization
m = K.mean(x, axis=-1, keepdims=True)
std = K.std(x, axis=-1, keepdims=True)
std = K.sqrt(K.var(x, axis=-1, keepdims=True) + self.epsilon)
x_normed = (x - m) / (std + self.epsilon)
out = self.gamma * x_normed + self.beta
return out
x_normed = self.gamma * x_normed + self.beta
return x_normed
def get_config(self):
config = {"epsilon": self.epsilon,
+400
Ver Arquivo
@@ -0,0 +1,400 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from .. import backend as K
from ..engine import Layer, InputSpec
from ..utils.np_utils import conv_output_length
class _Pooling1D(Layer):
'''Abstract class for different pooling 1D layers.
'''
input_dim = 3
def __init__(self, pool_length=2, stride=None,
border_mode='valid', **kwargs):
super(_Pooling1D, self).__init__(**kwargs)
if stride is None:
stride = pool_length
self.pool_length = pool_length
self.stride = stride
self.st = (self.stride, 1)
self.pool_size = (pool_length, 1)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
self.input_spec = [InputSpec(ndim=3)]
def get_output_shape_for(self, input_shape):
length = conv_output_length(input_shape[1], self.pool_length,
self.border_mode, self.stride)
return (input_shape[0], length, input_shape[2])
def _pooling_function(self, back_end, inputs, pool_size, strides,
border_mode, dim_ordering):
raise NotImplementedError
def call(self, x, mask=None):
x = K.expand_dims(x, -1) # add dummy last dimension
x = K.permute_dimensions(x, (0, 2, 1, 3))
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.st,
border_mode=self.border_mode,
dim_ordering='th')
output = K.permute_dimensions(output, (0, 2, 1, 3))
return K.squeeze(output, 3) # remove dummy last dimension
def get_config(self):
config = {'stride': self.stride,
'pool_length': self.pool_length,
'border_mode': self.border_mode}
base_config = super(_Pooling1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class MaxPooling1D(_Pooling1D):
'''Max pooling operation for temporal data.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
3D tensor with shape: `(samples, downsampled_steps, features)`.
# Arguments
pool_length: 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.
'''
def __init__(self, pool_length=2, stride=None,
border_mode='valid', **kwargs):
super(MaxPooling1D, self).__init__(pool_length, stride,
border_mode, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool2d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='max')
return output
class AveragePooling1D(_Pooling1D):
'''Average pooling for temporal data.
# Arguments
pool_length: factor by which to downscale. 2 will halve the input.
stride: integer, or None. Stride value.
If None, it will default to `pool_length`.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
# Input shape
3D tensor with shape: `(samples, steps, features)`.
# Output shape
3D tensor with shape: `(samples, downsampled_steps, features)`.
'''
def __init__(self, pool_length=2, stride=None,
border_mode='valid', **kwargs):
super(AveragePooling1D, self).__init__(pool_length, stride,
border_mode, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool2d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='avg')
return output
class _Pooling2D(Layer):
'''Abstract class for different pooling 2D layers.
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
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
self.strides = tuple(strides)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=4)]
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_output_length(rows, self.pool_size[0],
self.border_mode, self.strides[0])
cols = conv_output_length(cols, self.pool_size[1],
self.border_mode, self.strides[1])
if self.dim_ordering == 'th':
return (input_shape[0], input_shape[1], rows, cols)
elif self.dim_ordering == 'tf':
return (input_shape[0], rows, cols, input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
raise NotImplementedError
def call(self, x, mask=None):
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.strides,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
return output
def get_config(self):
config = {'pool_size': self.pool_size,
'border_mode': self.border_mode,
'strides': self.strides,
'dim_ordering': self.dim_ordering}
base_config = super(_Pooling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class MaxPooling2D(_Pooling2D):
'''Max pooling operation for spatial data.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
If None, it will default to `pool_size`.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
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
4D tensor with shape:
`(nb_samples, channels, pooled_rows, pooled_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, pooled_rows, pooled_cols, channels)` if dim_ordering='tf'.
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='default', **kwargs):
super(MaxPooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool2d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='max')
return output
class AveragePooling2D(_Pooling2D):
'''Average pooling operation for spatial data.
# Arguments
pool_size: tuple of 2 integers,
factors by which to downscale (vertical, horizontal).
(2, 2) will halve the image in each dimension.
strides: tuple of 2 integers, or None. Strides values.
If None, it will default to `pool_size`.
border_mode: 'valid' or 'same'.
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
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
4D tensor with shape:
`(nb_samples, channels, pooled_rows, pooled_cols)` if dim_ordering='th'
or 4D tensor with shape:
`(samples, pooled_rows, pooled_cols, channels)` if dim_ordering='tf'.
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='default', **kwargs):
super(AveragePooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool2d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='avg')
return output
class _Pooling3D(Layer):
'''Abstract class for different pooling 3D layers.
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
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
self.strides = tuple(strides)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
self.input_spec = [InputSpec(ndim=5)]
def get_output_shape_for(self, input_shape):
if self.dim_ordering == 'th':
len_dim1 = input_shape[2]
len_dim2 = input_shape[3]
len_dim3 = input_shape[4]
elif self.dim_ordering == 'tf':
len_dim1 = input_shape[1]
len_dim2 = input_shape[2]
len_dim3 = input_shape[3]
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
len_dim1 = conv_output_length(len_dim1, self.pool_size[0],
self.border_mode, self.strides[0])
len_dim2 = conv_output_length(len_dim2, self.pool_size[1],
self.border_mode, self.strides[1])
len_dim3 = conv_output_length(len_dim3, self.pool_size[2],
self.border_mode, self.strides[2])
if self.dim_ordering == 'th':
return (input_shape[0], input_shape[1], len_dim1, len_dim2, len_dim3)
elif self.dim_ordering == 'tf':
return (input_shape[0], len_dim1, len_dim2, len_dim3, input_shape[4])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
raise NotImplementedError
def call(self, x, mask=None):
output = self._pooling_function(inputs=x, pool_size=self.pool_size,
strides=self.strides,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
return output
def get_config(self):
config = {'pool_size': self.pool_size,
'border_mode': self.border_mode,
'strides': self.strides,
'dim_ordering': self.dim_ordering}
base_config = super(_Pooling3D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class MaxPooling3D(_Pooling3D):
'''Max pooling operation for 3D data (spatial or spatio-temporal).
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
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, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)` if dim_ordering='tf'.
# Output shape
5D tensor with shape:
`(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)` if dim_ordering='tf'.
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='default', **kwargs):
super(MaxPooling3D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool3d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='max')
return output
class AveragePooling3D(_Pooling3D):
'''Average pooling operation for 3D data (spatial or spatio-temporal).
# Arguments
pool_size: tuple of 3 integers,
factors by which to downscale (dim1, dim2, dim3).
(2, 2, 2) will halve the size of the 3D input in each dimension.
strides: tuple of 3 integers, or None. Strides values.
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
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, len_pool_dim1, len_pool_dim2, len_pool_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, len_pool_dim1, len_pool_dim2, len_pool_dim3, channels)` if dim_ordering='tf'.
# Output shape
5D tensor with shape:
`(nb_samples, channels, pooled_dim1, pooled_dim2, pooled_dim3)` if dim_ordering='th'
or 5D tensor with shape:
`(samples, pooled_dim1, pooled_dim2, pooled_dim3, channels)` if dim_ordering='tf'.
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='default', **kwargs):
super(AveragePooling3D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
def _pooling_function(self, inputs, pool_size, strides,
border_mode, dim_ordering):
output = K.pool3d(inputs, pool_size, strides,
border_mode, dim_ordering, pool_mode='avg')
return output
+216 -154
Ver Arquivo
@@ -54,7 +54,7 @@ class Recurrent(Layer):
# as the first layer in a Sequential model
model = Sequential()
model.add(LSTM(32, input_shape=(10, 64)))
# now model.output_shape == (None, 10, 32)
# now model.output_shape == (None, 32)
# note: `None` is the batch dimension.
# the following is identical:
@@ -66,7 +66,7 @@ class Recurrent(Layer):
```
# Arguments
weights: list of numpy arrays to set as initial weights.
weights: list of Numpy arrays to set as initial weights.
The list should have 3 elements, of shapes:
`[(input_dim, output_dim), (output_dim, output_dim), (output_dim,)]`.
return_sequences: Boolean. Whether to return the last output
@@ -81,12 +81,18 @@ class Recurrent(Layer):
is always unrolled, so this argument does not do anything.
Unrolling can speed-up a RNN, although it tends to be more memory-intensive.
Unrolling is only suitable for short sequences.
consume_less: one of "cpu", "mem". If set to "cpu", the RNN will use
consume_less: one of "cpu", "mem", or "gpu" (LSTM/GRU only).
If set to "cpu", the RNN will use
an implementation that uses fewer, larger matrix products,
thus running faster (at least on CPU) but consuming more memory.
thus running faster on CPU but consuming more memory.
If set to "mem", the RNN will use more matrix products,
but smaller ones, thus running slower (may actually be faster on GPU)
while consuming less memory.
If set to "gpu" (LSTM/GRU only), the RNN will combine the input gate,
the forget gate and the output gate into a single matrix,
enabling more time-efficient parallelization on the GPU. Note: RNN
dropout must be shared for all gates, resulting in a slightly
reduced regularization.
input_dim: dimensionality of the input (integer).
This argument (or alternatively, the keyword argument `input_shape`)
is required when using this layer as the first layer in a model.
@@ -133,7 +139,10 @@ 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)`.
@@ -184,9 +193,9 @@ class Recurrent(Layer):
def get_initial_states(self, x):
# build an all-zero tensor of shape (samples, output_dim)
initial_state = K.zeros_like(x) # (samples, timesteps, input_dim)
initial_state = K.sum(initial_state, axis=1) # (samples, input_dim)
reducer = K.zeros((self.input_dim, self.output_dim))
initial_state = K.dot(initial_state, reducer) # (samples, output_dim)
initial_state = K.sum(initial_state, axis=(1, 2)) # (samples,)
initial_state = K.expand_dims(initial_state) # (samples, 1)
initial_state = K.tile(initial_state, [1, self.output_dim]) # (samples, output_dim)
initial_states = [initial_state for _ in range(len(self.states))]
return initial_states
@@ -196,7 +205,7 @@ class Recurrent(Layer):
def call(self, x, mask=None):
# input shape: (nb_samples, time (padded with zeros), input_dim)
# note that the .build() method of subclasses MUST define
# self.input_sepc with a complete input shape.
# self.input_spec with a complete input shape.
input_shape = self.input_spec[0].shape
if K._BACKEND == 'tensorflow':
if not input_shape[1]:
@@ -383,15 +392,15 @@ class SimpleRNN(Recurrent):
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
"init": self.init.__name__,
"inner_init": self.inner_init.__name__,
"activation": self.activation.__name__,
"W_regularizer": self.W_regularizer.get_config() if self.W_regularizer else None,
"U_regularizer": self.U_regularizer.get_config() if self.U_regularizer else None,
"b_regularizer": self.b_regularizer.get_config() if self.b_regularizer else None,
"dropout_W": self.dropout_W,
"dropout_U": self.dropout_U}
config = {'output_dim': self.output_dim,
'init': self.init.__name__,
'inner_init': self.inner_init.__name__,
'activation': self.activation.__name__,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'U_regularizer': self.U_regularizer.get_config() if self.U_regularizer else None,
'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,
'dropout_W': self.dropout_W,
'dropout_U': self.dropout_U}
base_config = super(SimpleRNN, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -444,53 +453,66 @@ class GRU(Recurrent):
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
input_dim = input_shape[2]
self.input_dim = input_dim
self.input_dim = input_shape[2]
self.W_z = self.init((input_dim, self.output_dim),
name='{}_W_z'.format(self.name))
self.U_z = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_z'.format(self.name))
self.b_z = K.zeros((self.output_dim,), name='{}_b_z'.format(self.name))
self.W_r = self.init((input_dim, self.output_dim),
name='{}_W_r'.format(self.name))
self.U_r = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_r'.format(self.name))
self.b_r = K.zeros((self.output_dim,), name='{}_b_r'.format(self.name))
self.W_h = self.init((input_dim, self.output_dim),
name='{}_W_h'.format(self.name))
self.U_h = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_h'.format(self.name))
self.b_h = K.zeros((self.output_dim,), name='{}_b_h'.format(self.name))
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(K.concatenate([self.W_z,
self.W_r,
self.W_h]))
self.regularizers.append(self.W_regularizer)
if self.U_regularizer:
self.U_regularizer.set_param(K.concatenate([self.U_z,
self.U_r,
self.U_h]))
self.regularizers.append(self.U_regularizer)
if self.b_regularizer:
self.b_regularizer.set_param(K.concatenate([self.b_z,
self.b_r,
self.b_h]))
self.regularizers.append(self.b_regularizer)
self.trainable_weights = [self.W_z, self.U_z, self.b_z,
self.W_r, self.U_r, self.b_r,
self.W_h, self.U_h, self.b_h]
if self.stateful:
self.reset_states()
else:
# initial states: all-zero tensor of shape (output_dim)
self.states = [None]
if self.consume_less == 'gpu':
self.W = self.init((self.input_dim, 3 * self.output_dim),
name='{}_W'.format(self.name))
self.U = self.inner_init((self.output_dim, 3 * self.output_dim),
name='{}_U'.format(self.name))
self.b = K.variable(np.hstack((np.zeros(self.output_dim),
np.zeros(self.output_dim),
np.zeros(self.output_dim))),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.U, self.b]
else:
self.W_z = self.init((self.input_dim, self.output_dim),
name='{}_W_z'.format(self.name))
self.U_z = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_z'.format(self.name))
self.b_z = K.zeros((self.output_dim,), name='{}_b_z'.format(self.name))
self.W_r = self.init((self.input_dim, self.output_dim),
name='{}_W_r'.format(self.name))
self.U_r = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_r'.format(self.name))
self.b_r = K.zeros((self.output_dim,), name='{}_b_r'.format(self.name))
self.W_h = self.init((self.input_dim, self.output_dim),
name='{}_W_h'.format(self.name))
self.U_h = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_h'.format(self.name))
self.b_h = K.zeros((self.output_dim,), name='{}_b_h'.format(self.name))
self.trainable_weights = [self.W_z, self.U_z, self.b_z,
self.W_r, self.U_r, self.b_r,
self.W_h, self.U_h, self.b_h]
self.W = K.concatenate([self.W_z, self.W_r, self.W_h])
self.U = K.concatenate([self.U_z, self.U_r, self.U_h])
self.b = K.concatenate([self.b_z, self.b_r, self.b_h])
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.U_regularizer:
self.U_regularizer.set_param(self.U)
self.regularizers.append(self.U_regularizer)
if self.b_regularizer:
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
@@ -528,19 +550,37 @@ class GRU(Recurrent):
B_U = states[1] # dropout matrices for recurrent units
B_W = states[2]
if self.consume_less == 'cpu':
x_z = x[:, :self.output_dim]
x_r = x[:, self.output_dim: 2 * self.output_dim]
x_h = x[:, 2 * self.output_dim:]
if self.consume_less == 'gpu':
matrix_x = K.dot(x * B_W[0], self.W) + self.b
matrix_inner = K.dot(h_tm1 * B_U[0], self.U[:, :2 * self.output_dim])
x_z = matrix_x[:, :self.output_dim]
x_r = matrix_x[:, self.output_dim: 2 * self.output_dim]
inner_z = matrix_inner[:, :self.output_dim]
inner_r = matrix_inner[:, self.output_dim: 2 * self.output_dim]
z = self.inner_activation(x_z + inner_z)
r = self.inner_activation(x_r + inner_r)
x_h = matrix_x[:, 2 * self.output_dim:]
inner_h = K.dot(r * h_tm1 * B_U[0], self.U[:, 2 * self.output_dim:])
hh = self.activation(x_h + inner_h)
else:
x_z = K.dot(x * B_W[0], self.W_z) + self.b_z
x_r = K.dot(x * B_W[1], self.W_r) + self.b_r
x_h = K.dot(x * B_W[2], self.W_h) + self.b_h
if self.consume_less == 'cpu':
x_z = x[:, :self.output_dim]
x_r = x[:, self.output_dim: 2 * self.output_dim]
x_h = x[:, 2 * self.output_dim:]
elif self.consume_less == 'mem':
x_z = K.dot(x * B_W[0], self.W_z) + self.b_z
x_r = K.dot(x * B_W[1], self.W_r) + self.b_r
x_h = K.dot(x * B_W[2], self.W_h) + self.b_h
else:
raise Exception('Unknown `consume_less` mode.')
z = self.inner_activation(x_z + K.dot(h_tm1 * B_U[0], self.U_z))
r = self.inner_activation(x_r + K.dot(h_tm1 * B_U[1], self.U_r))
z = self.inner_activation(x_z + K.dot(h_tm1 * B_U[0], self.U_z))
r = self.inner_activation(x_r + K.dot(h_tm1 * B_U[1], self.U_r))
hh = self.activation(x_h + K.dot(r * h_tm1 * B_U[2], self.U_h))
hh = self.activation(x_h + K.dot(r * h_tm1 * B_U[2], self.U_h))
h = z * h_tm1 + (1 - z) * hh
return h, [h]
@@ -549,33 +589,33 @@ class GRU(Recurrent):
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
B_U = [K.dropout(ones, self.dropout_U) for _ in range(3)]
B_U = [K.in_train_phase(K.dropout(ones, self.dropout_U), ones) for _ in range(3)]
constants.append(B_U)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
constants.append([K.cast_to_floatx(1.) for _ in range(3)])
if self.consume_less == 'cpu' and 0 < self.dropout_W < 1:
if 0 < self.dropout_W < 1:
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
B_W = [K.dropout(ones, self.dropout_W) for _ in range(3)]
B_W = [K.in_train_phase(K.dropout(ones, self.dropout_W), ones) for _ in range(3)]
constants.append(B_W)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
constants.append([K.cast_to_floatx(1.) for _ in range(3)])
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
"init": self.init.__name__,
"inner_init": self.inner_init.__name__,
"activation": self.activation.__name__,
"inner_activation": self.inner_activation.__name__,
"W_regularizer": self.W_regularizer.get_config() if self.W_regularizer else None,
"U_regularizer": self.U_regularizer.get_config() if self.U_regularizer else None,
"b_regularizer": self.b_regularizer.get_config() if self.b_regularizer else None,
"dropout_W": self.dropout_W,
"dropout_U": self.dropout_U}
config = {'output_dim': self.output_dim,
'init': self.init.__name__,
'inner_init': self.inner_init.__name__,
'activation': self.activation.__name__,
'inner_activation': self.inner_activation.__name__,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'U_regularizer': self.U_regularizer.get_config() if self.U_regularizer else None,
'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,
'dropout_W': self.dropout_W,
'dropout_U': self.dropout_U}
base_config = super(GRU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -637,8 +677,7 @@ class LSTM(Recurrent):
def build(self, input_shape):
self.input_spec = [InputSpec(shape=input_shape)]
input_dim = input_shape[2]
self.input_dim = input_dim
self.input_dim = input_shape[2]
if self.stateful:
self.reset_states()
@@ -646,56 +685,64 @@ class LSTM(Recurrent):
# initial states: 2 all-zero tensors of shape (output_dim)
self.states = [None, None]
self.W_i = self.init((input_dim, self.output_dim),
name='{}_W_i'.format(self.name))
self.U_i = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_i'.format(self.name))
self.b_i = K.zeros((self.output_dim,), name='{}_b_i'.format(self.name))
if self.consume_less == 'gpu':
self.W = self.init((self.input_dim, 4 * self.output_dim),
name='{}_W'.format(self.name))
self.U = self.inner_init((self.output_dim, 4 * self.output_dim),
name='{}_U'.format(self.name))
self.W_f = self.init((input_dim, self.output_dim),
name='{}_W_f'.format(self.name))
self.U_f = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_f'.format(self.name))
self.b_f = self.forget_bias_init((self.output_dim,),
name='{}_b_f'.format(self.name))
self.b = K.variable(np.hstack((np.zeros(self.output_dim),
K.get_value(self.forget_bias_init((self.output_dim,))),
np.zeros(self.output_dim),
np.zeros(self.output_dim))),
name='{}_b'.format(self.name))
self.trainable_weights = [self.W, self.U, self.b]
else:
self.W_i = self.init((self.input_dim, self.output_dim),
name='{}_W_i'.format(self.name))
self.U_i = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_i'.format(self.name))
self.b_i = K.zeros((self.output_dim,), name='{}_b_i'.format(self.name))
self.W_c = self.init((input_dim, self.output_dim),
name='{}_W_c'.format(self.name))
self.U_c = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_c'.format(self.name))
self.b_c = K.zeros((self.output_dim,), name='{}_b_c'.format(self.name))
self.W_f = self.init((self.input_dim, self.output_dim),
name='{}_W_f'.format(self.name))
self.U_f = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_f'.format(self.name))
self.b_f = self.forget_bias_init((self.output_dim,),
name='{}_b_f'.format(self.name))
self.W_o = self.init((input_dim, self.output_dim),
name='{}_W_o'.format(self.name))
self.U_o = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_o'.format(self.name))
self.b_o = K.zeros((self.output_dim,), name='{}_b_o'.format(self.name))
self.W_c = self.init((self.input_dim, self.output_dim),
name='{}_W_c'.format(self.name))
self.U_c = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_c'.format(self.name))
self.b_c = K.zeros((self.output_dim,), name='{}_b_c'.format(self.name))
self.W_o = self.init((self.input_dim, self.output_dim),
name='{}_W_o'.format(self.name))
self.U_o = self.inner_init((self.output_dim, self.output_dim),
name='{}_U_o'.format(self.name))
self.b_o = K.zeros((self.output_dim,), name='{}_b_o'.format(self.name))
self.trainable_weights = [self.W_i, self.U_i, self.b_i,
self.W_c, self.U_c, self.b_c,
self.W_f, self.U_f, self.b_f,
self.W_o, self.U_o, self.b_o]
self.W = K.concatenate([self.W_i, self.W_f, self.W_c, self.W_o])
self.U = K.concatenate([self.U_i, self.U_f, self.U_c, self.U_o])
self.b = K.concatenate([self.b_i, self.b_f, self.b_c, self.b_o])
self.regularizers = []
if self.W_regularizer:
self.W_regularizer.set_param(K.concatenate([self.W_i,
self.W_f,
self.W_c,
self.W_o]))
self.W_regularizer.set_param(self.W)
self.regularizers.append(self.W_regularizer)
if self.U_regularizer:
self.U_regularizer.set_param(K.concatenate([self.U_i,
self.U_f,
self.U_c,
self.U_o]))
self.U_regularizer.set_param(self.U)
self.regularizers.append(self.U_regularizer)
if self.b_regularizer:
self.b_regularizer.set_param(K.concatenate([self.b_i,
self.b_f,
self.b_c,
self.b_o]))
self.b_regularizer.set_param(self.b)
self.regularizers.append(self.b_regularizer)
self.trainable_weights = [self.W_i, self.U_i, self.b_i,
self.W_c, self.U_c, self.b_c,
self.W_f, self.U_f, self.b_f,
self.W_o, self.U_o, self.b_o]
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
@@ -715,9 +762,9 @@ class LSTM(Recurrent):
self.states = [K.zeros((input_shape[0], self.output_dim)),
K.zeros((input_shape[0], self.output_dim))]
def preprocess_input(self, x, train=False):
def preprocess_input(self, x):
if self.consume_less == 'cpu':
if train and (0 < self.dropout_W < 1):
if 0 < self.dropout_W < 1:
dropout = self.dropout_W
else:
dropout = 0
@@ -743,21 +790,36 @@ class LSTM(Recurrent):
B_U = states[2]
B_W = states[3]
if self.consume_less == 'cpu':
x_i = x[:, :self.output_dim]
x_f = x[:, self.output_dim: 2 * self.output_dim]
x_c = x[:, 2 * self.output_dim: 3 * self.output_dim]
x_o = x[:, 3 * self.output_dim:]
else:
x_i = K.dot(x * B_W[0], self.W_i) + self.b_i
x_f = K.dot(x * B_W[1], self.W_f) + self.b_f
x_c = K.dot(x * B_W[2], self.W_c) + self.b_c
x_o = K.dot(x * B_W[3], self.W_o) + self.b_o
if self.consume_less == 'gpu':
z = K.dot(x * B_W[0], self.W) + K.dot(h_tm1 * B_U[0], self.U) + self.b
i = self.inner_activation(x_i + K.dot(h_tm1 * B_U[0], self.U_i))
f = self.inner_activation(x_f + K.dot(h_tm1 * B_U[1], self.U_f))
c = f * c_tm1 + i * self.activation(x_c + K.dot(h_tm1 * B_U[2], self.U_c))
o = self.inner_activation(x_o + K.dot(h_tm1 * B_U[3], self.U_o))
z0 = z[:, :self.output_dim]
z1 = z[:, self.output_dim: 2 * self.output_dim]
z2 = z[:, 2 * self.output_dim: 3 * self.output_dim]
z3 = z[:, 3 * self.output_dim:]
i = self.inner_activation(z0)
f = self.inner_activation(z1)
c = f * c_tm1 + i * self.activation(z2)
o = self.inner_activation(z3)
else:
if self.consume_less == 'cpu':
x_i = x[:, :self.output_dim]
x_f = x[:, self.output_dim: 2 * self.output_dim]
x_c = x[:, 2 * self.output_dim: 3 * self.output_dim]
x_o = x[:, 3 * self.output_dim:]
elif self.consume_less == 'mem':
x_i = K.dot(x * B_W[0], self.W_i) + self.b_i
x_f = K.dot(x * B_W[1], self.W_f) + self.b_f
x_c = K.dot(x * B_W[2], self.W_c) + self.b_c
x_o = K.dot(x * B_W[3], self.W_o) + self.b_o
else:
raise Exception('Unknown `consume_less` mode.')
i = self.inner_activation(x_i + K.dot(h_tm1 * B_U[0], self.U_i))
f = self.inner_activation(x_f + K.dot(h_tm1 * B_U[1], self.U_f))
c = f * c_tm1 + i * self.activation(x_c + K.dot(h_tm1 * B_U[2], self.U_c))
o = self.inner_activation(x_o + K.dot(h_tm1 * B_U[3], self.U_o))
h = o * self.activation(c)
return h, [h, c]
@@ -767,33 +829,33 @@ class LSTM(Recurrent):
if 0 < self.dropout_U < 1:
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * self.output_dim, 1)
B_U = [K.dropout(ones, self.dropout_U) for _ in range(4)]
B_U = [K.in_train_phase(K.dropout(ones, self.dropout_U), ones) for _ in range(4)]
constants.append(B_U)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
if self.consume_less == 'cpu' and 0 < self.dropout_W < 1:
if 0 < self.dropout_W < 1:
input_shape = self.input_spec[0].shape
input_dim = input_shape[-1]
ones = K.ones_like(K.reshape(x[:, 0, 0], (-1, 1)))
ones = K.concatenate([ones] * input_dim, 1)
B_W = [K.dropout(ones, self.dropout_W) for _ in range(4)]
B_W = [K.in_train_phase(K.dropout(ones, self.dropout_W), ones) for _ in range(4)]
constants.append(B_W)
else:
constants.append([K.cast_to_floatx(1.) for _ in range(4)])
return constants
def get_config(self):
config = {"output_dim": self.output_dim,
"init": self.init.__name__,
"inner_init": self.inner_init.__name__,
"forget_bias_init": self.forget_bias_init.__name__,
"activation": self.activation.__name__,
"inner_activation": self.inner_activation.__name__,
"W_regularizer": self.W_regularizer.get_config() if self.W_regularizer else None,
"U_regularizer": self.U_regularizer.get_config() if self.U_regularizer else None,
"b_regularizer": self.b_regularizer.get_config() if self.b_regularizer else None,
"dropout_W": self.dropout_W,
"dropout_U": self.dropout_U}
config = {'output_dim': self.output_dim,
'init': self.init.__name__,
'inner_init': self.inner_init.__name__,
'forget_bias_init': self.forget_bias_init.__name__,
'activation': self.activation.__name__,
'inner_activation': self.inner_activation.__name__,
'W_regularizer': self.W_regularizer.get_config() if self.W_regularizer else None,
'U_regularizer': self.U_regularizer.get_config() if self.U_regularizer else None,
'b_regularizer': self.b_regularizer.get_config() if self.b_regularizer else None,
'dropout_W': self.dropout_W,
'dropout_U': self.dropout_U}
base_config = super(LSTM, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+6 -3
Ver Arquivo
@@ -6,6 +6,7 @@ class Wrapper(Layer):
def __init__(self, layer, **kwargs):
self.layer = layer
self.uses_learning_phase = layer.uses_learning_phase
super(Wrapper, self).__init__(**kwargs)
def build(self, input_shape=None):
@@ -97,7 +98,9 @@ class TimeDistributed(Wrapper):
'an "input_shape" or "batch_input_shape" '
'argument, including the time axis.')
child_input_shape = (input_shape[0],) + input_shape[2:]
self.layer.build(child_input_shape)
if not self.layer.built:
self.layer.build(child_input_shape)
self.layer.built = True
super(TimeDistributed, self).build()
def get_output_shape_for(self, input_shape):
@@ -121,11 +124,11 @@ class TimeDistributed(Wrapper):
# no batch size specified, therefore the layer will be able
# to process batches of any size
# we can go with reshape-based implementation for performance
X = K.reshape(X, (-1, ) + input_shape[2:]) # (nb_samples * timesteps, ...)
y = self.layer.call(X) # (nb_samples * timesteps, ...)
input_length = input_shape[1]
if not input_length:
input_length = K.shape(X)[1]
X = K.reshape(X, (-1, ) + input_shape[2:]) # (nb_samples * timesteps, ...)
y = self.layer.call(X) # (nb_samples * timesteps, ...)
# (nb_samples, timesteps, ...)
output_shape = self.get_output_shape_for(input_shape)
y = K.reshape(y, (-1, input_length) + output_shape[2:])
+15 -8
Ver Arquivo
@@ -384,7 +384,7 @@ class Graph(Model):
# Arguments
data: dictionary mapping input names and outputs names to
appropriate numpy arrays. All arrays should contain
appropriate Numpy arrays. All arrays should contain
the same number of samples.
batch_size: int. Number of samples per gradient update.
nb_epoch: int.
@@ -395,7 +395,7 @@ class Graph(Model):
validation_split: float (0. < x < 1). Fraction of the data to
use as held-out validation data.
validation_data: dictionary mapping input names and outputs names
to appropriate numpy arrays to be used as
to appropriate Numpy arrays to be used as
held-out validation data.
All arrays should contain the same number of samples.
Will override validation_split.
@@ -473,6 +473,8 @@ class Graph(Model):
x = self._get_x(data)
output_list = super(Graph, self).predict(x, batch_size=batch_size,
verbose=verbose)
if not isinstance(output_list, list):
output_list = [output_list]
return dict(zip(self._graph_outputs, output_list))
def train_on_batch(self, data,
@@ -528,12 +530,15 @@ class Graph(Model):
def predict_on_batch(self, data):
output_list = super(Graph, self).predict_on_batch(data)
if not isinstance(output_list, list):
output_list = [output_list]
return dict(zip(self._graph_outputs, output_list))
def fit_generator(self, generator, samples_per_epoch, nb_epoch,
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight={}, **kwargs):
class_weight={},
max_q_size=10, **kwargs):
'''Fits a model on data generated batch-by-batch by a Python generator.
The generator is run in parallel to the model, for efficiency.
For instance, this allows you to do real-time data augmentation
@@ -555,7 +560,7 @@ class Graph(Model):
verbose: verbosity mode, 0, 1, or 2.
callbacks: list of callbacks to be called during training.
validation_data: dictionary mapping input names and outputs names
to appropriate numpy arrays to be used as
to appropriate Numpy arrays to be used as
held-out validation data, or a generator yielding such
dictionaries. All arrays should contain the same number
of samples. If a generator, will be called until more than
@@ -577,7 +582,7 @@ class Graph(Model):
while 1:
f = open(path)
for line in f:
# create numpy arrays of input data
# create Numpy arrays of input data
# and labels, from each line in the file
x1, x2, y = process_line(line)
yield ({'input_1': x1, 'input_2': x2, 'output': y})
@@ -641,13 +646,14 @@ class Graph(Model):
callbacks=callbacks,
validation_data=validation_data,
nb_val_samples=nb_val_samples,
class_weight=class_weight)
class_weight=class_weight,
max_q_size=max_q_size)
self.train_on_batch = self._train_on_batch
self.evaluate = self._evaluate
return history
def evaluate_generator(self, generator, val_samples,
verbose=1, **kwargs):
verbose=1, max_q_size=10, **kwargs):
'''Evaluates the model on a generator. The generator should
return the same kind of data with every yield as accepted
by `evaluate`.
@@ -700,7 +706,8 @@ class Graph(Model):
generator = fixed_generator()
history = super(Graph, self).evaluate_generator(generator,
val_samples)
val_samples,
max_q_size=max_q_size)
self.test_on_batch = self._test_on_batch
return history
+74
Ver Arquivo
@@ -1,3 +1,4 @@
import numpy as np
from . import backend as K
@@ -8,3 +9,76 @@ def binary_accuracy(y_true, y_pred):
def categorical_accuracy(y_true, y_pred):
return K.mean(K.equal(K.argmax(y_true, axis=-1),
K.argmax(y_pred, axis=-1)))
def sparse_categorical_accuracy(y_true, y_pred):
return K.mean(K.equal(K.max(y_true, axis=-1),
K.cast(K.argmax(y_pred, axis=-1), K.floatx())))
def mean_squared_error(y_true, y_pred):
return K.mean(K.square(y_pred - y_true))
def mean_absolute_error(y_true, y_pred):
return K.mean(K.abs(y_pred - y_true))
def mean_absolute_percentage_error(y_true, y_pred):
diff = K.abs((y_true - y_pred) / K.clip(K.abs(y_true), K.epsilon(), np.inf))
return 100. * K.mean(diff)
def mean_squared_logarithmic_error(y_true, y_pred):
first_log = K.log(K.clip(y_pred, K.epsilon(), np.inf) + 1.)
second_log = K.log(K.clip(y_true, K.epsilon(), np.inf) + 1.)
return K.mean(K.square(first_log - second_log))
def squared_hinge(y_true, y_pred):
return K.mean(K.square(K.maximum(1. - y_true * y_pred, 0.)))
def hinge(y_true, y_pred):
return K.mean(K.maximum(1. - y_true * y_pred, 0.))
def categorical_crossentropy(y_true, y_pred):
'''Expects a binary class matrix instead of a vector of scalar classes.
'''
return K.mean(K.categorical_crossentropy(y_pred, y_true))
def sparse_categorical_crossentropy(y_true, y_pred):
'''expects an array of integer classes.
Note: labels shape must have the same number of dimensions as output shape.
If you get a shape error, add a length-1 dimension to labels.
'''
return K.mean(K.sparse_categorical_crossentropy(y_pred, y_true))
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_pred, y_true))
def poisson(y_true, y_pred):
return K.mean(y_pred - y_true * K.log(y_pred + K.epsilon()))
def cosine_proximity(y_true, y_pred):
y_true = K.l2_normalize(y_true, axis=-1)
y_pred = K.l2_normalize(y_pred, axis=-1)
return -K.mean(y_true * y_pred)
# aliases
mse = MSE = mean_squared_error
mae = MAE = mean_absolute_error
mape = MAPE = mean_absolute_percentage_error
msle = MSLE = mean_squared_logarithmic_error
cosine = cosine_proximity
from .utils.generic_utils import get_from_module
def get(identifier):
return get_from_module(identifier, globals(), 'metric')
+282 -22
Ver Arquivo
@@ -1,18 +1,186 @@
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):
raise Exception('`model_fom_config` expects a dictionary, not a list. '
'Maybe you meant to use `Sequential.from_config(config)`?')
return layer_from_config(config, custom_objects=custom_objects)
def model_from_yaml(yaml_string, custom_objects={}):
'''Parses a yaml model configuration file
and returns a model instance.
'''
# TODO: legacy support?
import yaml
from keras.utils.layer_utils import layer_from_config
config = yaml.load(yaml_string)
@@ -23,7 +191,6 @@ def model_from_json(json_string, custom_objects={}):
'''Parses a JSON model configuration file
and returns a model instance.
'''
# TODO: legacy support?
import json
from keras.utils.layer_utils import layer_from_config
config = json.loads(json_string)
@@ -76,6 +243,7 @@ class Sequential(Model):
self.inbound_nodes = []
self.outbound_nodes = []
self.built = False
self._flattened_layers = None
if not name:
prefix = 'sequential_'
@@ -149,6 +317,27 @@ class Sequential(Model):
self.layers.append(layer)
self.built = False
self._flattened_layers = None
def pop(self):
'''Removes the last layer in the model.
'''
if not self.layers:
raise Exception('There are no layers in the model.')
self.layers.pop()
if not self.layers:
self.outputs = []
self.inbound_nodes = []
self.outbound_nodes = []
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 call(self, x, mask=None):
if not self.built:
@@ -178,6 +367,9 @@ class Sequential(Model):
self.output_names = self.model.output_names
self.input_names = self.model.input_names
# make sure child model callbacks will call the parent Sequential model:
self.model.callback_model = self
self.built = True
@property
@@ -188,6 +380,8 @@ class Sequential(Model):
@property
def flattened_layers(self):
if self._flattened_layers is not None:
return self._flattened_layers
layers = []
if self.layers[0].__class__.__name__ == 'Merge':
merge = self.layers[0]
@@ -209,6 +403,7 @@ class Sequential(Model):
for layer in self.layers[1:]:
if layer not in layers:
layers.append(layer)
self._flattened_layers = layers
return layers
def _gather_list_attr(self, attr):
@@ -273,7 +468,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:]
@@ -312,7 +507,7 @@ class Sequential(Model):
model.add(Dense(10, activation='softmax'))
model.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['acccuracy'])
metrics=['accuracy'])
```
'''
# create the underlying model
@@ -329,6 +524,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
@@ -375,6 +573,8 @@ class Sequential(Model):
at successive epochs, as well as validation loss values
and validation metrics values (if applicable).
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
@@ -414,6 +614,8 @@ class Sequential(Model):
The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
@@ -441,11 +643,15 @@ class Sequential(Model):
# Returns
A Numpy array of predictions.
'''
if self.model is None:
self.build()
return self.model.predict(x, batch_size=batch_size, verbose=verbose)
def predict_on_batch(self, x):
'''Returns predictions for a single batch of samples.
'''
if self.model is None:
self.build()
return self.model.predict_on_batch(x)
def train_on_batch(self, x, y, class_weight=None,
@@ -466,6 +672,8 @@ class Sequential(Model):
The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
@@ -496,6 +704,8 @@ class Sequential(Model):
The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
@@ -552,8 +762,7 @@ class Sequential(Model):
def fit_generator(self, generator, samples_per_epoch, nb_epoch,
verbose=1, callbacks=[],
validation_data=None, nb_val_samples=None,
class_weight=None,
**kwargs):
class_weight=None, max_q_size=10, nb_worker=1, pickle_safe=False, **kwargs):
'''Fits the model on data generated batch-by-batch by
a Python generator.
The generator is run in parallel to the model, for efficiency.
@@ -583,6 +792,12 @@ class Sequential(Model):
at the end of every epoch.
class_weight: dictionary mapping class indices to a weight
for the class.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
# Returns
A `History` object.
@@ -594,7 +809,7 @@ class Sequential(Model):
while 1:
f = open(path)
for line in f:
# create numpy arrays of input data
# create Numpy arrays of input data
# and labels, from each line in the file
x, y = process_line(line)
yield (x, y)
@@ -604,6 +819,11 @@ class Sequential(Model):
samples_per_epoch=10000, nb_epoch=10)
```
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if nb_worker > 1 and not pickle_safe:
warnings.warn('The "nb_worker" argument is deprecated when pickle_safe is False')
nb_worker = 1 # For backward compatibility
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
@@ -611,10 +831,6 @@ class Sequential(Model):
'the model at compile time:\n'
'`model.compile(optimizer, loss, '
'metrics=["accuracy"])`')
if 'nb_worker' in kwargs:
kwargs.pop('nb_worker')
warnings.warn('The "nb_worker" argument is deprecated, '
'please remove it from your code.')
if 'nb_val_worker' in kwargs:
kwargs.pop('nb_val_worker')
warnings.warn('The "nb_val_worker" argument is deprecated, '
@@ -629,10 +845,12 @@ class Sequential(Model):
callbacks=callbacks,
validation_data=validation_data,
nb_val_samples=nb_val_samples,
class_weight=class_weight)
class_weight=class_weight,
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
def evaluate_generator(self, generator, val_samples,
**kwargs):
def evaluate_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False, **kwargs):
'''Evaluates the model on a data generator. The generator should
return the same kind of data as accepted by `test_on_batch`.
@@ -643,7 +861,18 @@ class Sequential(Model):
val_samples:
total number of samples to generate from `generator`
before returning.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if nb_worker > 1 and not pickle_safe:
warnings.warn('The "nb_worker" argument is deprecated when pickle_safe is False')
nb_worker = 1 # For backward compatibility
if 'show_accuracy' in kwargs:
kwargs.pop('show_accuracy')
warnings.warn('The "show_accuracy" argument is deprecated, '
@@ -658,9 +887,12 @@ class Sequential(Model):
raise Exception('Received unknown keyword arguments: ' +
str(kwargs))
return self.model.evaluate_generator(generator,
val_samples)
val_samples,
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
def predict_generator(self, generator, val_samples):
def predict_generator(self, generator, val_samples, max_q_size=10, nb_worker=1, pickle_safe=False):
'''Generates predictions for the input samples from a data generator.
The generator should return the same kind of data as accepted by
`predict_on_batch`.
@@ -669,16 +901,29 @@ class Sequential(Model):
generator: generator yielding batches of input samples.
val_samples: total number of samples to generate from `generator`
before returning.
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
non picklable arguments to the generator as they can't be passed
easily to children processes.
# Returns
A Numpy array of predictions.
'''
return self.model.predict_generator(generator, val_samples)
if self.model is None:
self.build()
if nb_worker > 1 and not pickle_safe:
warnings.warn('The "nb_worker" argument is deprecated when pickle_safe is False')
nb_worker = 1 # For backward compatibility
return self.model.predict_generator(generator, val_samples,
max_q_size=max_q_size,
nb_worker=nb_worker,
pickle_safe=pickle_safe)
def get_config(self):
'''Returns the model configuration
as a Python dictionary.
as a Python list.
'''
config = []
if self.layers[0].__class__.__name__ == 'Merge':
@@ -700,13 +945,16 @@ class Sequential(Model):
return copy.deepcopy(config)
@classmethod
def from_config(cls, config):
def from_config(cls, config, layer_cache=None):
'''Supports legacy formats
'''
from keras.utils.layer_utils import layer_from_config
from keras.layers import Merge
assert type(config) is list
if not layer_cache:
layer_cache = {}
def normalize_legacy_config(conf):
if 'class_name' not in conf:
class_name = conf['name']
@@ -719,8 +967,20 @@ class Sequential(Model):
return new_config
return conf
# the model we will return
model = cls()
def get_or_create_layer(layer_data):
if layer_data['class_name'] == 'Sequential':
return Sequential.from_config(layer_data['config'],
layer_cache=layer_cache)
name = layer_data['config'].get('name')
if name in layer_cache:
return layer_cache[name]
layer = layer_from_config(layer_data)
layer_cache[name] = layer
return layer
first_layer = config[0]
first_layer = normalize_legacy_config(first_layer)
if first_layer['class_name'] == 'Merge':
@@ -733,11 +993,11 @@ class Sequential(Model):
merge = Merge.from_config(first_layer_config)
model.add(merge)
else:
layer = layer_from_config(first_layer)
layer = get_or_create_layer(first_layer)
model.add(layer)
for conf in config[1:]:
conf = normalize_legacy_config(conf)
layer = layer_from_config(conf)
layer = get_or_create_layer(conf)
model.add(layer)
return model
+10 -1
Ver Arquivo
@@ -37,7 +37,9 @@ def categorical_crossentropy(y_true, y_pred):
def sparse_categorical_crossentropy(y_true, y_pred):
'''expects a 1-D or 2-D array of integer classes.
'''expects an array of integer classes.
Note: labels shape must have the same number of dimensions as output shape.
If you get a shape error, add a length-1 dimension to labels.
'''
return K.sparse_categorical_crossentropy(y_pred, y_true)
@@ -46,6 +48,12 @@ def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
def kullback_leibler_divergence(y_true, y_pred):
y_true = K.clip(y_true, K.epsilon(), 1)
y_pred = K.clip(y_pred, K.epsilon(), 1)
return K.sum(y_true * K.log(y_true / y_pred), axis=-1)
def poisson(y_true, y_pred):
return K.mean(y_pred - y_true * K.log(y_pred + K.epsilon()), axis=-1)
@@ -61,6 +69,7 @@ mse = MSE = mean_squared_error
mae = MAE = mean_absolute_error
mape = MAPE = mean_absolute_percentage_error
msle = MSLE = mean_squared_logarithmic_error
kld = KLD = kullback_leibler_divergence
cosine = cosine_proximity
from .utils.generic_utils import get_from_module
+208 -87
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):
@@ -29,6 +44,11 @@ class Optimizer(object):
when their absolute value exceeds this value.
'''
def __init__(self, **kwargs):
allowed_kwargs = {'clipnorm', 'clipvalue'}
for k in kwargs:
if k not in allowed_kwargs:
raise Exception('Unexpected keyword argument '
'passed to optimizer: ' + str(k))
self.__dict__.update(kwargs)
self.updates = []
self.weights = []
@@ -67,29 +87,34 @@ 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):
return {"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):
@@ -102,8 +127,8 @@ class SGD(Optimizer):
decay: float >= 0. Learning rate decay over each update.
nesterov: boolean. Whether to apply Nesterov momentum.
'''
def __init__(self, lr=0.01, momentum=0., decay=0., nesterov=False,
*args, **kwargs):
def __init__(self, lr=0.01, momentum=0., decay=0.,
nesterov=False, **kwargs):
super(SGD, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0.)
@@ -114,12 +139,15 @@ class SGD(Optimizer):
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 = [K.update_add(self.iterations, 1)]
for p, g in zip(params, grads):
m = K.variable(np.zeros(K.get_value(p).shape)) # momentum
# momentum
shapes = [x.shape for x in K.batch_get_value(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
@@ -130,15 +158,17 @@ 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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"momentum": float(K.get_value(self.momentum)),
"decay": float(K.get_value(self.decay)),
"nesterov": self.nesterov}
config = {'lr': float(K.get_value(self.lr)),
'momentum': float(K.get_value(self.momentum)),
'decay': float(K.get_value(self.decay)),
'nesterov': self.nesterov}
base_config = super(SGD, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class RMSprop(Optimizer):
@@ -156,7 +186,7 @@ class RMSprop(Optimizer):
rho: float >= 0.
epsilon: float >= 0. Fuzz factor.
'''
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-6, *args, **kwargs):
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-8, **kwargs):
super(RMSprop, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
@@ -164,28 +194,30 @@ class RMSprop(Optimizer):
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 = [x.shape for x in K.batch_get_value(params)]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
for p, g, a in zip(params, grads, self.weights):
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 - self.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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"rho": float(K.get_value(self.rho)),
"epsilon": self.epsilon}
config = {'lr': float(K.get_value(self.lr)),
'rho': float(K.get_value(self.rho)),
'epsilon': self.epsilon}
base_config = super(RMSprop, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Adagrad(Optimizer):
@@ -198,32 +230,34 @@ class Adagrad(Optimizer):
lr: float >= 0. Learning rate.
epsilon: float >= 0.
'''
def __init__(self, lr=0.01, epsilon=1e-6, *args, **kwargs):
def __init__(self, lr=0.01, epsilon=1e-8, **kwargs):
super(Adagrad, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
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 = [x.shape for x in K.batch_get_value(params)]
accumulators = [K.zeros(shape) for shape in shapes]
self.weights = accumulators
self.updates = []
for p, g, a in zip(params, grads, self.weights):
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 - self.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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"epsilon": self.epsilon}
config = {'lr': float(K.get_value(self.lr)),
'epsilon': self.epsilon}
base_config = super(Adagrad, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Adadelta(Optimizer):
@@ -241,22 +275,23 @@ 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-6, *args, **kwargs):
def __init__(self, lr=1.0, rho=0.95, epsilon=1e-8, **kwargs):
super(Adadelta, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = K.variable(lr)
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 = [x.shape for x in K.batch_get_value(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 = []
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)
@@ -266,18 +301,19 @@ class Adadelta(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))
# 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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"rho": self.rho,
"epsilon": self.epsilon}
config = {'lr': float(K.get_value(self.lr)),
'rho': self.rho,
'epsilon': self.epsilon}
base_config = super(Adadelta, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Adam(Optimizer):
@@ -293,8 +329,8 @@ class Adam(Optimizer):
# References
- [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,
*args, **kwargs):
def __init__(self, lr=0.001, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, **kwargs):
super(Adam, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0)
@@ -304,37 +340,39 @@ class Adam(Optimizer):
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations + 1)]
self.updates = [K.update_add(self.iterations, 1)]
t = self.iterations + 1
lr_t = self.lr * K.sqrt(1. - K.pow(self.beta_2, t)) / (1. - K.pow(self.beta_1, t))
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 = [x.shape for x in K.batch_get_value(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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"beta_1": float(K.get_value(self.beta_1)),
"beta_2": float(K.get_value(self.beta_2)),
"epsilon": self.epsilon}
config = {'lr': float(K.get_value(self.lr)),
'beta_1': float(K.get_value(self.beta_1)),
'beta_2': float(K.get_value(self.beta_2)),
'epsilon': self.epsilon}
base_config = super(Adam, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Adamax(Optimizer):
@@ -351,8 +389,8 @@ class Adamax(Optimizer):
# References
- [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,
*args, **kwargs):
def __init__(self, lr=0.002, beta_1=0.9, beta_2=0.999,
epsilon=1e-8, **kwargs):
super(Adamax, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0.)
@@ -362,16 +400,17 @@ class Adamax(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
lr_t = self.lr / (1. - K.pow(self.beta_1, t))
shapes = [x.shape for x in K.batch_get_value(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):
@@ -379,23 +418,104 @@ 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):
return {"name": self.__class__.__name__,
"lr": float(K.get_value(self.lr)),
"beta_1": float(K.get_value(self.beta_1)),
"beta_2": float(K.get_value(self.beta_2)),
"epsilon": self.epsilon}
config = {'lr': float(K.get_value(self.lr)),
'beta_1': float(K.get_value(self.beta_1)),
'beta_2': float(K.get_value(self.beta_2)),
'epsilon': self.epsilon}
base_config = super(Adamax, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Nadam(Optimizer):
'''
Nesterov Adam optimizer: Much like Adam is essentially RMSprop with momentum,
Nadam is Adam RMSprop with Nesterov momentum.
Default parameters follow those provided in the paper.
It is recommended to leave the parameters of this optimizer
at their default values.
# Arguments
lr: float >= 0. Learning rate.
beta_1/beta_2: floats, 0 < beta < 1. Generally close to 1.
epsilon: float >= 0. Fuzz factor.
# References
- [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):
super(Nadam, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = K.variable(0.)
self.m_schedule = K.variable(1.)
self.lr = K.variable(lr)
self.beta_1 = K.variable(beta_1)
self.beta_2 = K.variable(beta_2)
self.schedule_decay = schedule_decay
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [K.update_add(self.iterations, 1)]
t = self.iterations + 1
# Due to the recommendations in [2], i.e. warming momentum schedule
momentum_cache_t = self.beta_1 * (1. - 0.5 * (K.pow(0.96, t * self.schedule_decay)))
momentum_cache_t_1 = self.beta_1 * (1. - 0.5 * (K.pow(0.96, (t + 1) * self.schedule_decay)))
m_schedule_new = self.m_schedule * momentum_cache_t
m_schedule_next = self.m_schedule * momentum_cache_t * momentum_cache_t_1
self.updates.append((self.m_schedule, m_schedule_new))
shapes = [x.shape for x in K.batch_get_value(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):
# the following equations given in [1]
g_prime = g / (1. - m_schedule_new)
m_t = self.beta_1 * m + (1. - self.beta_1) * g
m_t_prime = m_t / (1. - m_schedule_next)
v_t = self.beta_2 * v + (1. - self.beta_2) * K.square(g)
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(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
# apply constraints
if p in constraints:
c = constraints[p]
new_p = c(new_p)
self.updates.append(K.update(p, new_p))
return self.updates
def get_config(self):
config = {'lr': float(K.get_value(self.lr)),
'beta_1': float(K.get_value(self.beta_1)),
'beta_2': float(K.get_value(self.beta_2)),
'epsilon': self.epsilon,
'schedule_decay': self.schedule_decay}
base_config = super(Nadam, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
# aliases
@@ -405,6 +525,7 @@ adagrad = Adagrad
adadelta = Adadelta
adam = Adam
adamax = Adamax
nadam = Nadam
def get(identifier, kwargs=None):
+453 -148
Ver Arquivo
@@ -1,54 +1,78 @@
'''Fairly basic set of tools for realtime data augmentation on image data.
'''Fairly basic set of tools for real-time data augmentation on image data.
Can easily be extended to include new transformations,
new preprocessing methods, etc...
'''
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import re
from scipy import ndimage
from scipy import linalg
from os import listdir
from os.path import isfile, join
import math
import scipy.ndimage as ndi
from six.moves import range
import os
import threading
from .. import backend as K
def random_rotation(x, rg, fill_mode='nearest', cval=0.):
angle = np.random.uniform(-rg, rg)
x = ndimage.interpolation.rotate(x, angle,
axes=(1, 2),
reshape=False,
mode=fill_mode,
cval=cval)
def random_rotation(x, rg, row_index=1, col_index=2, channel_index=0,
fill_mode='nearest', cval=0.):
theta = np.pi / 180 * np.random.uniform(-rg, rg)
rotation_matrix = np.array([[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0, 1]])
h, w = x.shape[row_index], x.shape[col_index]
transform_matrix = transform_matrix_offset_center(rotation_matrix, h, w)
x = apply_transform(x, transform_matrix, channel_index, fill_mode, cval)
return x
def random_shift(x, wrg, hrg, fill_mode='nearest', cval=0.):
shift_x = shift_y = 0
def random_shift(x, wrg, hrg, row_index=1, col_index=2, channel_index=0,
fill_mode='nearest', cval=0.):
h, w = x.shape[row_index], x.shape[col_index]
tx = np.random.uniform(-hrg, hrg) * h
ty = np.random.uniform(-wrg, wrg) * w
translation_matrix = np.array([[1, 0, tx],
[0, 1, ty],
[0, 0, 1]])
if wrg:
shift_x = np.random.uniform(-wrg, wrg) * x.shape[2]
if hrg:
shift_y = np.random.uniform(-hrg, hrg) * x.shape[1]
x = ndimage.interpolation.shift(x, (0, shift_y, shift_x),
order=0,
mode=fill_mode,
cval=cval)
transform_matrix = translation_matrix # no need to do offset
x = apply_transform(x, transform_matrix, channel_index, fill_mode, cval)
return x
def horizontal_flip(x):
for i in range(x.shape[0]):
x[i] = np.fliplr(x[i])
def random_shear(x, intensity, row_index=1, col_index=2, channel_index=0,
fill_mode='nearest', cval=0.):
shear = np.random.uniform(-intensity, intensity)
shear_matrix = np.array([[1, -np.sin(shear), 0],
[0, np.cos(shear), 0],
[0, 0, 1]])
h, w = x.shape[row_index], x.shape[col_index]
transform_matrix = transform_matrix_offset_center(shear_matrix, h, w)
x = apply_transform(x, transform_matrix, channel_index, fill_mode, cval)
return x
def vertical_flip(x):
for i in range(x.shape[0]):
x[i] = np.flipud(x[i])
def random_zoom(x, zoom_range, row_index=1, col_index=2, channel_index=0,
fill_mode='nearest', cval=0.):
if len(zoom_range) != 2:
raise Exception('zoom_range should be a tuple or list of two floats. '
'Received arg: ', zoom_range)
if zoom_range[0] == 1 and zoom_range[1] == 1:
zx, zy = 1, 1
else:
zx, zy = np.random.uniform(zoom_range[0], zoom_range[1], 2)
zoom_matrix = np.array([[zx, 0, 0],
[0, zy, 0],
[0, 0, 1]])
h, w = x.shape[row_index], x.shape[col_index]
transform_matrix = transform_matrix_offset_center(zoom_matrix, h, w)
x = apply_transform(x, transform_matrix, channel_index, fill_mode, cval)
return x
@@ -57,71 +81,100 @@ def random_barrel_transform(x, intensity):
pass
def random_shear(x, intensity, fill_mode='nearest', cval=0.):
shear = np.random.uniform(-intensity, intensity)
shear_matrix = np.array([[1.0, -math.sin(shear), 0.0],
[0.0, math.cos(shear), 0.0],
[0.0, 0.0, 1.0]])
x = ndimage.interpolation.affine_transform(x, shear_matrix,
mode=fill_mode,
order=3,
cval=cval)
def random_channel_shift(x, intensity, channel_index=0):
x = np.rollaxis(x, channel_index, 0)
min_x, max_x = np.min(x), np.max(x)
channel_images = [np.clip(x_channel + np.random.uniform(-intensity, intensity), min_x, max_x)
for x_channel in x]
x = np.stack(channel_images, axis=0)
x = np.rollaxis(x, 0, channel_index+1)
return x
def random_channel_shift(x, rg):
# TODO
pass
def transform_matrix_offset_center(matrix, x, y):
o_x = float(x) / 2 + 0.5
o_y = float(y) / 2 + 0.5
offset_matrix = np.array([[1, 0, o_x], [0, 1, o_y], [0, 0, 1]])
reset_matrix = np.array([[1, 0, -o_x], [0, 1, -o_y], [0, 0, 1]])
transform_matrix = np.dot(np.dot(offset_matrix, matrix), reset_matrix)
return transform_matrix
def random_zoom(x, rg, fill_mode='nearest', cval=0.):
zoom_w = np.random.uniform(1.-rg, 1.)
zoom_h = np.random.uniform(1.-rg, 1.)
x = ndimage.interpolation.zoom(x, zoom=(1., zoom_w, zoom_h),
mode=fill_mode,
cval=cval)
return x # shape of result will be different from shape of input!
def apply_transform(x, transform_matrix, channel_index=0, fill_mode='nearest', cval=0.):
x = np.rollaxis(x, channel_index, 0)
final_affine_matrix = transform_matrix[:2, :2]
final_offset = transform_matrix[:2, 2]
channel_images = [ndi.interpolation.affine_transform(x_channel, final_affine_matrix,
final_offset, order=0, mode=fill_mode, cval=cval) for x_channel in x]
x = np.stack(channel_images, axis=0)
x = np.rollaxis(x, 0, channel_index+1)
return x
def array_to_img(x, scale=True):
def flip_axis(x, axis):
x = np.asarray(x).swapaxes(axis, 0)
x = x[::-1, ...]
x = x.swapaxes(0, axis)
return x
def array_to_img(x, dim_ordering='default', scale=True):
from PIL import Image
x = x.transpose(1, 2, 0)
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
return Image.fromarray(x.astype('uint8'), 'RGB')
else:
elif x.shape[2] == 1:
# grayscale
return Image.fromarray(x[:, :, 0].astype('uint8'), 'L')
else:
raise Exception('Unsupported channel number: ', x.shape[2])
def img_to_array(img):
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)
x = np.asarray(img, dtype='float32')
if len(x.shape) == 3:
# RGB: height, width, channel -> channel, height, width
x = x.transpose(2, 0, 1)
if dim_ordering == 'th':
x = x.transpose(2, 0, 1)
elif len(x.shape) == 2:
if dim_ordering == 'th':
x = x.reshape((1, x.shape[0], x.shape[1]))
else:
x = x.reshape((x.shape[0], x.shape[1], 1))
else:
# grayscale: height, width -> channel, height, width
x = x.reshape((1, x.shape[0], x.shape[1]))
raise Exception('Unsupported image shape: ', x.shape)
return x
def load_img(path, grayscale=False):
def load_img(path, grayscale=False, target_size=None):
from PIL import Image
img = Image.open(path)
if grayscale:
img = img.convert('L')
else: # Ensure 3 channel even when loaded image is grayscale
img = img.convert('RGB')
if target_size:
img = img.resize((target_size[1], target_size[0]))
return img
def list_pictures(directory, ext='jpg|jpeg|bmp|png'):
return [join(directory, f) for f in listdir(directory)
if isfile(join(directory, f)) and re.match('([\w]+\.(?:' + ext + '))', f)]
return [os.path.join(directory, f) for f in os.listdir(directory)
if os.path.isfile(os.path.join(directory, f)) and re.match('([\w]+\.(?:' + ext + '))', f)]
class ImageDataGenerator(object):
@@ -138,101 +191,105 @@ class ImageDataGenerator(object):
width_shift_range: fraction of total width.
height_shift_range: fraction of total height.
shear_range: shear intensity (shear angle in radians).
zoom_range: amount of zoom. if scalar z, zoom will be randomly picked
in the range [1-z, 1+z]. A sequence of two can be passed instead
to select this range.
channel_shift_range: shift range for each channels.
fill_mode: points outside the boundaries are filled according to the
given mode ('constant', 'nearest', 'reflect' or 'wrap'). Default
is 'nearest'.
cval: value used for points outside the boundaries when fill_mode is
'constant'. Default is 0.
horizontal_flip: whether to randomly flip images horizontally.
vertical_flip: whether to randomly flip images vertically.
rescale: rescaling factor. If None or 0, no rescaling is applied,
otherwise we multiply the data by the value provided (before applying
any other transformation).
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode it is 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".
'''
def __init__(self,
featurewise_center=True,
featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=True,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=0.,
width_shift_range=0.,
height_shift_range=0.,
shear_range=0.,
zoom_range=0.,
channel_shift_range=0.,
fill_mode='nearest',
cval=0.,
horizontal_flip=False,
vertical_flip=False):
vertical_flip=False,
rescale=None,
dim_ordering='default'):
if dim_ordering == 'default':
dim_ordering = K.image_dim_ordering()
self.__dict__.update(locals())
self.mean = None
self.std = None
self.principal_components = None
self.lock = threading.Lock()
self.rescale = rescale
def _flow_index(self, N, batch_size=32, shuffle=False, seed=None):
b = 0
total_b = 0
while 1:
if b == 0:
if seed is not None:
np.random.seed(seed + total_b)
if dim_ordering not in {'tf', 'th'}:
raise Exception('dim_ordering should be "tf" (channel after row and '
'column) or "th" (channel before row and column). '
'Received arg: ', dim_ordering)
self.dim_ordering = dim_ordering
if dim_ordering == 'th':
self.channel_index = 1
self.row_index = 2
self.col_index = 3
if dim_ordering == 'tf':
self.channel_index = 3
self.row_index = 1
self.col_index = 2
if shuffle:
index_array = np.random.permutation(N)
else:
index_array = np.arange(N)
if np.isscalar(zoom_range):
self.zoom_range = [1 - zoom_range, 1 + zoom_range]
elif len(zoom_range) == 2:
self.zoom_range = [zoom_range[0], zoom_range[1]]
else:
raise Exception('zoom_range should be a float or '
'a tuple or list of two floats. '
'Received arg: ', zoom_range)
current_index = (b * batch_size) % N
if N >= current_index + batch_size:
current_batch_size = batch_size
else:
current_batch_size = N - current_index
if current_batch_size == batch_size:
b += 1
else:
b = 0
total_b += 1
yield (index_array[current_index: current_index + current_batch_size],
current_index, current_batch_size)
def flow(self, X, y, batch_size=32, shuffle=False, seed=None,
def flow(self, X, y=None, batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
assert len(X) == len(y)
self.X = X
self.y = y
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
self.flow_generator = self._flow_index(X.shape[0], batch_size,
shuffle, seed)
return self
return NumpyArrayIterator(
X, y, self,
batch_size=batch_size, shuffle=shuffle, seed=seed,
dim_ordering=self.dim_ordering,
save_to_dir=save_to_dir, save_prefix=save_prefix, save_format=save_format)
def __iter__(self):
# needed if we want to do something like:
# for x, y in data_gen.flow(...):
return self
def next(self):
# for python 2.x.
# Keeps under lock only the mechanism which advances
# the indexing of each batch
# see # http://anandology.com/blog/using-iterators-and-generators/
with self.lock:
index_array, current_index, current_batch_size = next(self.flow_generator)
# The transformation of images is not under thread lock so it can be done in parallel
bX = np.zeros(tuple([current_batch_size] + list(self.X.shape)[1:]))
for i, j in enumerate(index_array):
x = self.X[j]
x = self.random_transform(x.astype('float32'))
x = self.standardize(x)
bX[i] = x
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(bX[i], scale=True)
img.save(self.save_to_dir + '/' + self.save_prefix + '_' + str(current_index + i) + '.' + self.save_format)
bY = self.y[index_array]
return bX, bY
def __next__(self):
# for python 3.x.
return self.next()
def flow_from_directory(self, directory,
target_size=(256, 256), color_mode='rgb',
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
return DirectoryIterator(
directory, self,
target_size=target_size, color_mode=color_mode,
classes=classes, class_mode=class_mode,
dim_ordering=self.dim_ordering,
batch_size=batch_size, shuffle=shuffle, seed=seed,
save_to_dir=save_to_dir, save_prefix=save_prefix, save_format=save_format)
def standardize(self, x):
if self.rescale:
x *= self.rescale
# x is a single image, so it doesn't have image number at index 0
img_channel_index = self.channel_index - 1
if self.samplewise_center:
x -= np.mean(x, axis=1, keepdims=True)
x -= np.mean(x, axis=img_channel_index, keepdims=True)
if self.samplewise_std_normalization:
x /= (np.std(x, axis=1, keepdims=True) + 1e-7)
x /= (np.std(x, axis=img_channel_index, keepdims=True) + 1e-7)
if self.featurewise_center:
x -= self.mean
@@ -240,29 +297,75 @@ class ImageDataGenerator(object):
x /= (self.std + 1e-7)
if self.zca_whitening:
flatx = np.reshape(x, (x.shape[0] * x.shape[1] * x.shape[2]))
flatx = np.reshape(x, (x.size))
whitex = np.dot(flatx, self.principal_components)
x = np.reshape(whitex, (x.shape[0], x.shape[1], x.shape[2]))
return x
def random_transform(self, x):
# x is a single image, so it doesn't have image number at index 0
img_row_index = self.row_index - 1
img_col_index = self.col_index - 1
img_channel_index = self.channel_index - 1
# use composition of homographies to generate final transform that needs to be applied
if self.rotation_range:
x = random_rotation(x, self.rotation_range)
if self.width_shift_range or self.height_shift_range:
x = random_shift(x, self.width_shift_range, self.height_shift_range)
theta = np.pi / 180 * np.random.uniform(-self.rotation_range, self.rotation_range)
else:
theta = 0
rotation_matrix = np.array([[np.cos(theta), -np.sin(theta), 0],
[np.sin(theta), np.cos(theta), 0],
[0, 0, 1]])
if self.height_shift_range:
tx = np.random.uniform(-self.height_shift_range, self.height_shift_range) * x.shape[img_row_index]
else:
tx = 0
if self.width_shift_range:
ty = np.random.uniform(-self.width_shift_range, self.width_shift_range) * x.shape[img_col_index]
else:
ty = 0
translation_matrix = np.array([[1, 0, tx],
[0, 1, ty],
[0, 0, 1]])
if self.shear_range:
shear = np.random.uniform(-self.shear_range, self.shear_range)
else:
shear = 0
shear_matrix = np.array([[1, -np.sin(shear), 0],
[0, np.cos(shear), 0],
[0, 0, 1]])
if self.zoom_range[0] == 1 and self.zoom_range[1] == 1:
zx, zy = 1, 1
else:
zx, zy = np.random.uniform(self.zoom_range[0], self.zoom_range[1], 2)
zoom_matrix = np.array([[zx, 0, 0],
[0, zy, 0],
[0, 0, 1]])
transform_matrix = np.dot(np.dot(np.dot(rotation_matrix, translation_matrix), shear_matrix), zoom_matrix)
h, w = x.shape[img_row_index], x.shape[img_col_index]
transform_matrix = transform_matrix_offset_center(transform_matrix, h, w)
x = apply_transform(x, transform_matrix, img_channel_index,
fill_mode=self.fill_mode, cval=self.cval)
if self.channel_shift_range != 0:
x = random_channel_shift(x, self.channel_shift_range, img_channel_index)
if self.horizontal_flip:
if np.random.random() < 0.5:
x = horizontal_flip(x)
x = flip_axis(x, img_col_index)
if self.vertical_flip:
if np.random.random() < 0.5:
x = vertical_flip(x)
if self.shear_range:
x = random_shear(x, self.shear_range)
x = flip_axis(x, img_row_index)
# TODO:
# zoom
# channel-wise normalization
# barrel/fisheye
# channel shifting
return x
def fit(self, X,
@@ -284,14 +387,13 @@ class ImageDataGenerator(object):
aX = np.zeros(tuple([rounds * X.shape[0]] + list(X.shape)[1:]))
for r in range(rounds):
for i in range(X.shape[0]):
img = array_to_img(X[i])
img = self.random_transform(img)
aX[i + r * X.shape[0]] = img_to_array(img)
aX[i + r * X.shape[0]] = self.random_transform(X[i])
X = aX
if self.featurewise_center:
self.mean = np.mean(X, axis=0)
X -= self.mean
if self.featurewise_std_normalization:
self.std = np.std(X, axis=0)
X /= (self.std + 1e-7)
@@ -303,10 +405,213 @@ class ImageDataGenerator(object):
self.principal_components = np.dot(np.dot(U, np.diag(1. / np.sqrt(S + 10e-7))), U.T)
class GraphImageDataGenerator(ImageDataGenerator):
'''Example of how to build a generator for a Graph model
'''
class Iterator(object):
def __init__(self, N, batch_size, shuffle, seed):
self.N = N
self.batch_size = batch_size
self.shuffle = shuffle
self.batch_index = 0
self.total_batches_seen = 0
self.lock = threading.Lock()
self.index_generator = self._flow_index(N, batch_size, shuffle, seed)
def reset(self):
self.batch_index = 0
def _flow_index(self, N, batch_size=32, shuffle=False, seed=None):
# ensure self.batch_index is 0
self.reset()
while 1:
if self.batch_index == 0:
index_array = np.arange(N)
if shuffle:
if seed is not None:
np.random.seed(seed + self.total_batches_seen)
index_array = np.random.permutation(N)
current_index = (self.batch_index * batch_size) % N
if N >= current_index + batch_size:
current_batch_size = batch_size
self.batch_index += 1
else:
current_batch_size = N - current_index
self.batch_index = 0
self.total_batches_seen += 1
yield (index_array[current_index: current_index + current_batch_size],
current_index, current_batch_size)
def __iter__(self):
# needed if we want to do something like:
# for x, y in data_gen.flow(...):
return self
def __next__(self, *args, **kwargs):
return self.next(*args, **kwargs)
class NumpyArrayIterator(Iterator):
def __init__(self, X, y, image_data_generator,
batch_size=32, shuffle=False, seed=None,
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
self.dim_ordering = dim_ordering
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
super(NumpyArrayIterator, self).__init__(X.shape[0], batch_size, shuffle, seed)
def next(self):
bX, bY = super(GraphImageDataGenerator, self).next()
return {'input': bX, 'output': bY}
# for python 2.x.
# Keeps under lock only the mechanism which advances
# the indexing of each batch
# see http://anandology.com/blog/using-iterators-and-generators/
with self.lock:
index_array, current_index, current_batch_size = next(self.index_generator)
# The transformation of images is not under thread lock so it can be done in parallel
batch_x = np.zeros(tuple([current_batch_size] + list(self.X.shape)[1:]))
for i, j in enumerate(index_array):
x = self.X[j]
x = self.image_data_generator.random_transform(x.astype('float32'))
x = self.image_data_generator.standardize(x)
batch_x[i] = x
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(batch_x[i], self.dim_ordering, scale=True)
fname = '{prefix}_{index}_{hash}.{format}'.format(prefix=self.save_prefix,
index=current_index + i,
hash=np.random.randint(1e4),
format=self.save_format)
img.save(os.path.join(self.save_to_dir, fname))
if self.y is None:
return batch_x
batch_y = self.y[index_array]
return batch_x, batch_y
class DirectoryIterator(Iterator):
def __init__(self, directory, image_data_generator,
target_size=(256, 256), color_mode='rgb',
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)
if color_mode not in {'rgb', 'grayscale'}:
raise ValueError('Invalid color mode:', color_mode,
'; expected "rgb" or "grayscale".')
self.color_mode = color_mode
self.dim_ordering = dim_ordering
if self.color_mode == 'rgb':
if self.dim_ordering == 'tf':
self.image_shape = self.target_size + (3,)
else:
self.image_shape = (3,) + self.target_size
else:
if self.dim_ordering == 'tf':
self.image_shape = self.target_size + (1,)
else:
self.image_shape = (1,) + self.target_size
self.classes = classes
if class_mode not in {'categorical', 'binary', 'sparse', None}:
raise ValueError('Invalid class_mode:', class_mode,
'; expected one of "categorical", '
'"binary", "sparse", or None.')
self.class_mode = class_mode
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
white_list_formats = {'png', 'jpg', 'jpeg', 'bmp'}
# first, count the number of samples and classes
self.nb_sample = 0
if not classes:
classes = []
for subdir in sorted(os.listdir(directory)):
if os.path.isdir(os.path.join(directory, subdir)):
classes.append(subdir)
self.nb_class = len(classes)
self.class_indices = dict(zip(classes, range(len(classes))))
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
self.nb_sample += 1
print('Found %d images belonging to %d classes.' % (self.nb_sample, self.nb_class))
# second, build an index of the images in the different class subfolders
self.filenames = []
self.classes = np.zeros((self.nb_sample,), dtype='int32')
i = 0
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
is_valid = False
for extension in white_list_formats:
if fname.lower().endswith('.' + extension):
is_valid = True
break
if is_valid:
self.classes[i] = self.class_indices[subdir]
self.filenames.append(os.path.join(subdir, fname))
i += 1
super(DirectoryIterator, self).__init__(self.nb_sample, batch_size, shuffle, seed)
def next(self):
with self.lock:
index_array, current_index, current_batch_size = next(self.index_generator)
# The transformation of images is not under thread lock so it can be done in parallel
batch_x = np.zeros((current_batch_size,) + self.image_shape)
grayscale = self.color_mode == 'grayscale'
# build batch of image data
for i, j in enumerate(index_array):
fname = self.filenames[j]
img = load_img(os.path.join(self.directory, fname), grayscale=grayscale, target_size=self.target_size)
x = img_to_array(img, dim_ordering=self.dim_ordering)
x = self.image_data_generator.random_transform(x)
x = self.image_data_generator.standardize(x)
batch_x[i] = x
# optionally save augmented images to disk for debugging purposes
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(batch_x[i], self.dim_ordering, scale=True)
fname = '{prefix}_{index}_{hash}.{format}'.format(prefix=self.save_prefix,
index=current_index + i,
hash=np.random.randint(1e4),
format=self.save_format)
img.save(os.path.join(self.save_to_dir, fname))
# build batch of labels
if self.class_mode == 'sparse':
batch_y = self.classes[index_array]
elif self.class_mode == 'binary':
batch_y = self.classes[index_array].astype('float32')
elif self.class_mode == 'categorical':
batch_y = np.zeros((len(batch_x), self.nb_class), dtype='float32')
for i, label in enumerate(self.classes[index_array]):
batch_y[i, label] = 1.
else:
return batch_x
return batch_x, batch_y
+2 -2
Ver Arquivo
@@ -100,7 +100,7 @@ def skipgrams(sequence, vocabulary_size,
'''Take a sequence (list of indexes of words),
returns couples of [word_index, other_word index] and labels (1s or 0s),
where label = 1 if 'other_word' belongs to the context of 'word',
and label=0 if 'other_word' is ramdomly sampled
and label=0 if 'other_word' is randomly sampled
# Arguments
vocabulary_size: int. maximum possible word index + 1
@@ -113,7 +113,7 @@ def skipgrams(sequence, vocabulary_size,
if True labels will be categorical eg. [[1,0],[0,1],[0,1] .. ]
# Returns
couples, lables: where `couples` are int pairs and
couples, labels: where `couples` are int pairs and
`labels` are either 0 or 1.
# Notes
+7 -3
Ver Arquivo
@@ -3,6 +3,7 @@
from a fast Cython rewrite.
'''
from __future__ import absolute_import
from __future__ import division
import string
import sys
@@ -98,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 = {}
@@ -206,9 +208,11 @@ class Tokenizer(object):
elif mode == 'binary':
X[i][j] = 1
elif mode == 'tfidf':
tf = np.log(c / len(seq))
df = (1 + np.log(1 + self.index_docs.get(j, 0) / (1 + self.document_count)))
X[i][j] = tf / df
# Use weighting scheme 2 in
# https://en.wikipedia.org/wiki/Tf%E2%80%93idf
tf = 1 + np.log(c)
idf = np.log(1 + self.document_count / (1 + self.index_docs.get(j, 0)))
X[i][j] = tf * idf
else:
raise Exception('Unknown vectorization mode: ' + str(mode))
return X
+56 -9
Ver Arquivo
@@ -16,6 +16,46 @@ class Regularizer(object):
return {'name': self.__class__.__name__}
class EigenvalueRegularizer(Regularizer):
'''This takes a constant that controls
the regularization by Eigenvalue Decay on the
current layer and outputs the regularized
loss (evaluated on the training data) and
the original loss (evaluated on the
validation data).
'''
def __init__(self, k):
self.k = k
self.uses_learning_phase = True
def set_param(self, p):
self.p = p
def __call__(self, loss):
power = 9 # number of iterations of the power method
W = self.p
if K.ndim(W) > 2:
raise Exception('Eigenvalue Decay regularizer '
'is only available for dense '
'and embedding layers.')
WW = K.dot(K.transpose(W), W)
dim1, dim2 = K.eval(K.shape(WW)) # number of neurons in the layer
# power method for approximating the dominant eigenvector:
o = K.ones([dim1, 1]) # initial values for the dominant eigenvector
main_eigenvect = K.dot(WW, o)
for n in range(power - 1):
main_eigenvect = K.dot(WW, main_eigenvect)
WWd = K.dot(WW, main_eigenvect)
# the corresponding dominant eigenvalue:
main_eigenval = K.dot(K.transpose(WWd), main_eigenvect) / K.dot(K.transpose(main_eigenvect), main_eigenvect)
regularized_loss = loss + (main_eigenval ** 0.5) * self.k # multiplied by the given regularization gain
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)
@@ -35,14 +75,17 @@ 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):
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
'l1': float(self.l1),
'l2': float(self.l2)}
class ActivityRegularizer(Regularizer):
@@ -59,15 +102,19 @@ class ActivityRegularizer(Regularizer):
raise Exception('Need to call `set_layer` on '
'ActivityRegularizer instance '
'before calling the instance.')
output = self.layer.output
regularized_loss = loss + self.l1 * K.sum(K.mean(K.abs(output), axis=0))
regularized_loss += self.l2 * K.sum(K.mean(K.square(output), axis=0))
regularized_loss = loss
for i in range(len(self.layer.inbound_nodes)):
output = self.layer.get_output_at(i)
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):
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
'l1': float(self.l1),
'l2': float(self.l2)}
def l1(l=0.01):
+29 -5
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
@@ -36,11 +37,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,7 +52,18 @@ def get_file(fname, origin, untar=False):
else:
fpath = os.path.join(datadir, fname)
if not os.path.exists(fpath):
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
@@ -73,7 +86,7 @@ def get_file(fname, origin, untar=False):
except (Exception, KeyboardInterrupt) as e:
if os.path.exists(fpath):
os.remove(fpath)
raise e
raise
progbar = None
if untar:
@@ -88,8 +101,19 @@ def get_file(fname, origin, untar=False):
os.remove(untar_fpath)
else:
shutil.rmtree(untar_fpath)
raise e
raise
tfile.close()
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
+11 -2
Ver Arquivo
@@ -34,24 +34,28 @@ def make_tuple(*args):
class Progbar(object):
def __init__(self, target, width=30, verbose=1):
def __init__(self, target, width=30, verbose=1, interval=0.01):
'''
@param target: total number of steps expected
@param interval: minimum visual progress update interval (in seconds)
'''
self.width = width
self.target = target
self.sum_values = {}
self.unique_values = []
self.start = time.time()
self.last_update = 0
self.interval = interval
self.total_width = 0
self.seen_so_far = 0
self.verbose = verbose
def update(self, current, values=[]):
def update(self, current, values=[], force=False):
'''
@param current: index of current step
@param values: list of tuples (name, value_for_last_step).
The progress bar will display averages for these values.
@param force: force visual progress update
'''
for k, v in values:
if k not in self.sum_values:
@@ -64,6 +68,9 @@ class Progbar(object):
now = time.time()
if self.verbose == 1:
if not force and (now - self.last_update) < self.interval:
return
prev_total_width = self.total_width
sys.stdout.write("\b" * prev_total_width)
sys.stdout.write("\r")
@@ -127,6 +134,8 @@ class Progbar(object):
info += ' %.4e' % avg
sys.stdout.write(info + "\n")
self.last_update = now
def add(self, n, values=[]):
self.update(self.seen_so_far + n, values)
+16
Ver Arquivo
@@ -1,6 +1,8 @@
from __future__ import absolute_import
from __future__ import print_function
import h5py
import numpy as np
import sys
from collections import defaultdict
@@ -69,3 +71,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
+25 -3
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
@@ -35,9 +36,11 @@ def layer_from_config(config, custom_objects={}):
return layer_class.from_config(config['config'])
def print_summary(layers, relevant_nodes=None):
line_length = 100 # total length of printed lines
positions = [35, 55, 67, 100] # absolute positions of log elements in each line
def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33, .55, .67, 1.]):
# line_length: total length of printed lines
# positions: relative or absolute positions of log elements in each line
if positions[-1] <= 1:
positions = [int(line_length * p) for p in positions]
# header names for the different log elements
to_display = ['Layer (type)', 'Output Shape', 'Param #', 'Connected to']
@@ -95,3 +98,22 @@ def print_summary(layers, relevant_nodes=None):
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)
+81 -1
Ver Arquivo
@@ -9,7 +9,6 @@ def to_categorical(y, nb_classes=None):
'''Convert class vector (integers from 0 to nb_classes)
to binary class matrix, for use with categorical_crossentropy.
'''
y = np.asarray(y, dtype='int32')
if not nb_classes:
nb_classes = np.max(y)+1
Y = np.zeros((len(y), nb_classes))
@@ -51,3 +50,84 @@ def probas_to_classes(y_pred):
def categorical_probas_to_classes(p):
return np.argmax(p, axis=1)
def convert_kernel(kernel, dim_ordering='th'):
'''Converts a kernel matrix (Numpy array)
from Theano format to TensorFlow format
(or reciprocally, since the transformation
is its own inverse).
'''
new_kernel = np.copy(kernel)
if kernel.ndim == 4:
# conv 2d
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
if dim_ordering == 'th':
w = kernel.shape[2]
h = kernel.shape[3]
for i in range(w):
for j in range(h):
new_kernel[:, :, i, j] = kernel[:, :, w - i - 1, h - j - 1]
elif dim_ordering == 'tf':
w = kernel.shape[0]
h = kernel.shape[1]
for i in range(w):
for j in range(h):
new_kernel[i, j, :, :] = kernel[w - i - 1, h - j - 1, :, :]
else:
raise Exception('Invalid dim_ordering: ' + str(dim_ordering))
elif kernel.ndim == 5:
# conv 3d
# TH kernel shape: (out_depth, input_depth, kernel_dim1, kernel_dim2, kernel_dim3)
# TF kernel shape: (kernel_dim1, kernel_dim2, kernel_dim3, input_depth, out_depth)
if dim_ordering == 'th':
w = kernel.shape[2]
h = kernel.shape[3]
z = kernel.shape[4]
for i in range(w):
for j in range(h):
for k in range(z):
new_kernel[:, :, i, j, k] = kernel[:, :,
w - i - 1,
h - j - 1,
z - k - 1]
elif dim_ordering == 'tf':
w = kernel.shape[0]
h = kernel.shape[1]
z = kernel.shape[2]
for i in range(w):
for j in range(h):
for k in range(z):
new_kernel[i, j, k, :, :] = kernel[w - i - 1,
h - j - 1,
z - k - 1,
:, :]
else:
raise Exception('Invalid dim_ordering: ' + str(dim_ordering))
else:
raise ValueError('Invalid kernel shape:', kernel.shape)
return new_kernel
def conv_output_length(input_length, filter_size, border_mode, stride, dilation=1):
if input_length is None:
return None
assert border_mode in {'same', 'valid'}
dilated_filter_size = filter_size + (filter_size - 1) * (dilation - 1)
if border_mode == 'same':
output_length = input_length
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
+12 -6
Ver Arquivo
@@ -9,7 +9,7 @@ if not pydot.find_graphviz():
' and graphviz for `pydotprint` to work.')
def model_to_dot(model, show_shapes=False):
def model_to_dot(model, show_shapes=False, show_layer_names=True):
dot = pydot.Dot()
dot.set('rankdir', 'TB')
dot.set('concentrate', True)
@@ -24,19 +24,25 @@ def model_to_dot(model, show_shapes=False):
# first, populate the nodes of the graph
for layer in layers:
layer_id = str(id(layer))
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
if show_layer_names:
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
else:
label = layer.__class__.__name__
if show_shapes:
# Build the label that will actually contain a table with the
# input/output
outputlabels = str(layer.output_shape)
try:
outputlabels = str(layer.output_shape)
except:
outputlabels = 'multiple'
if hasattr(layer, 'input_shape'):
inputlabels = str(layer.input_shape)
elif hasattr(layer, 'input_shapes'):
inputlabels = ', '.join(
[str(ishape) for ishape in layer.input_shapes])
else:
inputlabels = ''
inputlabels = 'multiple'
label = '%s\n|{input:|output:}|{{%s}|{%s}}' % (label, inputlabels, outputlabels)
node = pydot.Node(layer_id, label=label)
@@ -56,6 +62,6 @@ def model_to_dot(model, show_shapes=False):
return dot
def plot(model, to_file='model.png', show_shapes=False):
dot = model_to_dot(model, show_shapes)
def plot(model, to_file='model.png', show_shapes=False, show_layer_names=True):
dot = model_to_dot(model, show_shapes, show_layer_names)
dot.write_png(to_file)
+14 -4
Ver Arquivo
@@ -29,7 +29,7 @@ class BaseWrapper(object):
`sk_params` takes both model parameters and fitting parameters. Legal model
parameters are the arguments of `build_fn`. Note that like all other
estimators in scikit-learn, 'build_fn' should provide defalult values for
estimators in scikit-learn, 'build_fn' should provide default values for
its arguments, so that you could create the estimator without passing any
values to `sk_params`.
@@ -154,10 +154,10 @@ class BaseWrapper(object):
# Arguments
fn : arbitrary function
override: dictionary, values to overrid sk_params
override: dictionary, values to override sk_params
# Returns
res : dictionary dictionary containing variabls
res : dictionary dictionary containing variables
in both sk_params and fn's arguments.
'''
res = {}
@@ -203,9 +203,19 @@ class KerasClassifier(BaseWrapper):
# Returns
proba: array-like, shape `(n_samples, n_outputs)`
Class probability estimates.
In the case of binary classification,
tp match the scikit-learn API,
will return an array of shape '(n_samples, 2)'
(instead of `(n_sample, 1)` as in Keras).
'''
kwargs = self.filter_sk_params(Sequential.predict_proba, kwargs)
return self.model.predict_proba(X, **kwargs)
probs = self.model.predict_proba(X, **kwargs)
# check if binary classification
if probs.shape[1] == 1:
# first column is probability of class 0 and second is of class 1
probs = np.hstack([1 - probs, probs])
return probs
def score(self, X, y, **kwargs):
'''Returns the mean accuracy on the given test data and labels.
+2 -2
Ver Arquivo
@@ -3,12 +3,12 @@ from setuptools import find_packages
setup(name='Keras',
version='1.0.0',
version='1.0.7',
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.0',
download_url='https://github.com/fchollet/keras/tarball/1.0.7',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
@@ -2,13 +2,14 @@ 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
@@ -3,7 +3,7 @@ import numpy as np
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 +14,7 @@ from keras.layers import LSTM
from keras.layers import Embedding
@keras_test
def test_temporal_classification():
'''
Classify temporal sequences of float numbers
@@ -23,7 +24,7 @@ def test_temporal_classification():
'''
np.random.seed(1337)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=500,
nb_test=200,
nb_test=500,
input_shape=(3, 5),
classification=True,
nb_class=2)
@@ -35,14 +36,15 @@ def test_temporal_classification():
input_shape=(X_train.shape[1], X_train.shape[2]),
activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='adadelta',
optimizer='adagrad',
metrics=['accuracy'])
history = model.fit(X_train, y_train, nb_epoch=5, batch_size=16,
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.9)
assert(history.history['val_acc'][-1] >= 0.85)
@keras_test
def test_temporal_regression():
'''
Predict float numbers (regression) based on sequences
@@ -63,6 +65,7 @@ def test_temporal_regression():
assert(history.history['val_loss'][-1] < 0.75)
@keras_test
def test_sequence_to_sequence():
'''
Apply a same Dense layer for each element of time dimension of the input
@@ -86,6 +89,7 @@ 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.
@@ -135,6 +139,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
@@ -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
+172 -30
Ver Arquivo
@@ -5,6 +5,7 @@ import numpy as np
from keras.backend import theano_backend as KTH
from keras.backend import tensorflow_backend as KTF
from keras.utils.np_utils import convert_kernel
def check_single_tensor_operation(function_name, input_shape, **kwargs):
@@ -22,10 +23,12 @@ def check_single_tensor_operation(function_name, input_shape, **kwargs):
def check_two_tensor_operation(function_name, x_input_shape,
y_input_shape, **kwargs):
xval = np.random.random(x_input_shape) - 0.5
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
yval = np.random.random(y_input_shape) - 0.5
yth = KTH.variable(yval)
ytf = KTF.variable(yval)
@@ -36,6 +39,28 @@ def check_two_tensor_operation(function_name, x_input_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):
''' Creates a random tensor t0 with shape input_shape and compute
t1 = first_function_name(t0, **first_function_args)
t2 = second_function_name(t1, **second_function_args)
with both Theano and TensorFlow backends and ensures the answers match.
'''
val = np.random.random(input_shape) - 0.5
xth = KTH.variable(val)
xtf = KTF.variable(val)
yth = getattr(KTH, first_function_name)(xth, **first_function_args)
ytf = getattr(KTF, first_function_name)(xtf, **first_function_args)
zth = KTH.eval(getattr(KTH, second_function_name)(yth, **second_function_args))
ztf = KTF.eval(getattr(KTF, second_function_name)(ytf, **second_function_args))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
class TestBackend(object):
def test_linear_operations(self):
@@ -67,6 +92,9 @@ 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},
(4, 3, 1, 1))
def test_repeat_elements(self):
reps = 3
@@ -88,6 +116,17 @@ class TestBackend(object):
assert_allclose(np_rep, th_rep, atol=1e-05)
assert_allclose(np_rep, tf_rep, atol=1e-05)
def test_tile(self):
shape = (3, 4)
arr = np.arange(np.prod(shape)).reshape(shape)
arr_th = KTH.variable(arr)
arr_tf = KTF.variable(arr)
n = (2, 1)
th_rep = KTH.eval(KTH.tile(arr_th, n))
tf_rep = KTF.eval(KTF.tile(arr_tf, n))
assert_allclose(tf_rep, th_rep, atol=1e-05)
def test_value_manipulation(self):
val = np.random.random((4, 2))
xth = KTH.variable(val)
@@ -112,6 +151,12 @@ 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))
def test_elementwise_operations(self):
check_single_tensor_operation('max', (4, 2))
check_single_tensor_operation('max', (4, 2), axis=1, keepdims=True)
@@ -136,6 +181,9 @@ class TestBackend(object):
# does not work yet, wait for bool <-> int casting in TF (coming soon)
# check_single_tensor_operation('any', (4, 2))
# check_single_tensor_operation('any', (4, 2), axis=1, keepdims=True)
#
# check_single_tensor_operation('any', (4, 2))
# check_single_tensor_operation('any', (4, 2), axis=1, keepdims=True)
check_single_tensor_operation('argmax', (4, 2))
check_single_tensor_operation('argmax', (4, 2), axis=1)
@@ -156,6 +204,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))
@@ -168,14 +221,24 @@ class TestBackend(object):
exptf = xtf * KTF.exp(xtf)
lossth = KTH.sum(expth)
losstf = KTF.sum(exptf)
zero_lossth = KTH.stop_gradient(lossth)
zero_losstf = KTF.stop_gradient(losstf)
gradth = KTH.gradients(lossth, [expth])
gradtf = KTF.gradients(losstf, [exptf])
zero_gradth = KTH.gradients(lossth + zero_lossth, [expth])
zero_gradtf = KTF.gradients(losstf + zero_losstf, [exptf])
zth = KTH.eval(gradth[0])
ztf = KTF.eval(gradtf[0])
zero_zth = KTH.eval(zero_gradth[0])
zero_ztf = KTF.eval(zero_gradtf[0])
assert zth.shape == ztf.shape
assert zero_zth.shape == zero_ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
assert_allclose(zero_zth, zero_ztf, atol=1e-05)
assert_allclose(zero_zth, zth, atol=1e-05)
assert_allclose(zero_ztf, ztf, atol=1e-05)
def test_function(self):
val = np.random.random((4, 2))
@@ -369,42 +432,111 @@ class TestBackend(object):
check_single_tensor_operation('l2_normalize', (4, 3), axis=-1)
check_single_tensor_operation('l2_normalize', (4, 3), axis=1)
# def test_conv2d(self):
# '''conv2d works "properly" with Theano and TF but outputs different
# values in each case. Cause unclear (input / kernel shape format?)
# '''
# # TH kernel shape: (depth, input_depth, rows, cols)
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 2, 2),
# strides=(1, 1), border_mode='valid')
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 2, 2),
# strides=(1, 1), border_mode='same')
def test_conv2d(self):
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
# # TF kernel shape: (rows, cols, input_depth, depth)
# check_two_tensor_operation('conv2d', (5, 10, 12, 3), (2, 2, 3, 4),
# strides=(1, 1), border_mode='valid', dim_ordering='tf')
# check_two_tensor_operation('conv2d', (5, 10, 12, 3), (2, 2, 3, 4),
# strides=(1, 1), border_mode='same', dim_ordering='tf')
for input_shape in [(2, 3, 4, 5), (2, 3, 5, 6)]:
for kernel_shape in [(4, 3, 2, 2), (4, 3, 3, 4)]:
xval = np.random.random(input_shape)
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 3, 3),
# strides=(1, 1), border_mode='valid')
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 3, 3),
# strides=(1, 1), border_mode='same')
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 3, 3),
# strides=(2, 2), border_mode='valid')
kernel_val = np.random.random(kernel_shape) - 0.5
# def test_pool2d(self):
# '''pool2d works "properly" with Theano and TF but outputs different
# values in each case. Cause unclear (input shape format?)
# '''
# check_single_tensor_operation('pool2d', (5, 3, 10, 12), pool_size=(2, 2),
# strides=(1, 1), border_mode='valid')
kernel_th = KTH.variable(convert_kernel(kernel_val))
kernel_tf = KTF.variable(kernel_val)
# check_single_tensor_operation('pool2d', (5, 3, 9, 11), pool_size=(2, 2),
# strides=(1, 1), border_mode='valid')
zth = KTH.eval(KTH.conv2d(xth, kernel_th))
ztf = KTF.eval(KTF.conv2d(xtf, kernel_tf))
# check_single_tensor_operation('pool2d', (5, 3, 9, 11), pool_size=(2, 3),
# strides=(1, 1), border_mode='valid')
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
input_shape = (1, 6, 5, 3)
kernel_shape = (3, 3, 3, 2)
xval = np.random.random(input_shape)
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
kernel_val = np.random.random(kernel_shape) - 0.5
kernel_th = KTH.variable(convert_kernel(kernel_val, dim_ordering='tf'))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv2d(xth, kernel_th, dim_ordering='tf'))
ztf = KTF.eval(KTF.conv2d(xtf, kernel_tf, dim_ordering='tf'))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
def test_conv3d(self):
# TH input shape: (samples, input_depth, conv_dim1, conv_dim2, conv_dim3)
# TF input shape: (samples, conv_dim1, conv_dim2, conv_dim3, input_depth)
# TH kernel shape: (depth, input_depth, x, y, z)
# TF kernel shape: (x, y, z, input_depth, depth)
# test in dim_ordering = th
for input_shape in [(2, 3, 4, 5, 4), (2, 3, 5, 4, 6)]:
for kernel_shape in [(4, 3, 2, 2, 2), (4, 3, 3, 2, 4)]:
xval = np.random.random(input_shape)
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
kernel_val = np.random.random(kernel_shape) - 0.5
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))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
# test in dim_ordering = tf
input_shape = (1, 2, 2, 2, 1)
kernel_shape = (2, 2, 2, 1, 1)
xval = np.random.random(input_shape)
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
kernel_val = np.random.random(kernel_shape) - 0.5
kernel_th = KTH.variable(convert_kernel(kernel_val, dim_ordering='tf'))
kernel_tf = KTF.variable(kernel_val)
zth = KTH.eval(KTH.conv3d(xth, kernel_th, dim_ordering='tf'))
ztf = KTF.eval(KTF.conv3d(xtf, kernel_tf, dim_ordering='tf'))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-05)
def test_pool2d(self):
check_single_tensor_operation('pool2d', (5, 3, 10, 12), pool_size=(2, 2),
strides=(1, 1), border_mode='valid')
check_single_tensor_operation('pool2d', (5, 3, 9, 11), pool_size=(2, 2),
strides=(1, 1), border_mode='valid')
check_single_tensor_operation('pool2d', (5, 3, 9, 11), 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),
strides=(1, 1, 1), border_mode='valid')
check_single_tensor_operation('pool3d', (5, 3, 9, 11, 5), 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),
strides=(1, 1, 1), border_mode='valid')
def test_random_normal(self):
mean = 0.
@@ -448,6 +580,16 @@ class TestBackend(object):
assert(np.max(rand) == 1)
assert(np.min(rand) == 0)
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)
if __name__ == '__main__':
pytest.main([__file__])
+26 -8
Ver Arquivo
@@ -1,26 +1,44 @@
from __future__ import print_function
import pytest
import time
import random
from keras.datasets import cifar10, cifar100, reuters, imdb, mnist
def test_cifar():
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
(X_train, y_train), (X_test, y_test) = cifar100.load_data('fine')
(X_train, y_train), (X_test, y_test) = cifar100.load_data('coarse')
# only run data download tests 20% of the time
# to speed up frequent testing
random.seed(time.time())
if random.random() > 0.8:
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
(X_train, y_train), (X_test, y_test) = cifar100.load_data('fine')
(X_train, y_train), (X_test, y_test) = cifar100.load_data('coarse')
def test_reuters():
(X_train, y_train), (X_test, y_test) = reuters.load_data()
(X_train, y_train), (X_test, y_test) = reuters.load_data(maxlen=10)
# only run data download tests 20% of the time
# to speed up frequent testing
random.seed(time.time())
if random.random() > 0.8:
(X_train, y_train), (X_test, y_test) = reuters.load_data()
(X_train, y_train), (X_test, y_test) = reuters.load_data(maxlen=10)
def test_mnist():
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# only run data download tests 20% of the time
# to speed up frequent testing
random.seed(time.time())
if random.random() > 0.8:
(X_train, y_train), (X_test, y_test) = mnist.load_data()
def test_imdb():
(X_train, y_train), (X_test, y_test) = imdb.load_data()
(X_train, y_train), (X_test, y_test) = imdb.load_data(maxlen=40)
# only run data download tests 20% of the time
# to speed up frequent testing
random.seed(time.time())
if random.random() > 0.8:
(X_train, y_train), (X_test, y_test) = imdb.load_data()
(X_train, y_train), (X_test, y_test) = imdb.load_data(maxlen=40)
if __name__ == '__main__':
+18 -3
Ver Arquivo
@@ -2,13 +2,15 @@ import pytest
import json
import numpy as np
from keras.layers import Dense, Dropout
from keras.layers import Dense, Dropout, InputLayer
from keras.engine import merge, Input, get_source_inputs
from keras.models import Model
from keras import backend as K
from keras.models import model_from_json, model_from_yaml
from keras.utils.test_utils import keras_test
@keras_test
def test_learning_phase():
a = Input(shape=(32,), name='input_a')
b = Input(shape=(32,), name='input_b')
@@ -50,6 +52,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 +131,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 +213,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
@@ -389,7 +394,18 @@ def test_recursion():
assert K.int_shape(m_tf) == (None, 64)
assert K.int_shape(n_tf) == (None, 5)
# test merge
o_tf = merge([j_tf, k_tf], mode='concat', concat_axis=1)
# test tensor input
x = tf.placeholder(shape=(None, 2), dtype=K.floatx())
input_layer = InputLayer(input_tensor=x)
x = Input(tensor=x)
y = Dense(2)(x)
@keras_test
def test_functional_guide():
# MNIST
from keras.layers import Input, Dense, LSTM
@@ -482,6 +498,7 @@ def test_functional_guide():
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
@@ -512,8 +529,6 @@ def test_sequential_regression():
name='embed_1'))
branch_1.add(LSTM(32, name='lstm_1'))
branch_1.add(BatchNormalization())
branch_2 = Sequential(name='branch_2')
branch_2.add(Dense(32, input_shape=(8,), name='dense_2'))
+46 -6
Ver Arquivo
@@ -1,12 +1,16 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
from keras.layers import Dense, Dropout
from keras.engine.topology import merge, Input
from keras.engine.training import Model
from keras.models import Sequential, Graph
from keras 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')
@@ -115,10 +119,10 @@ def test_model_methods():
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 3
assert len(out) == 5
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 3
assert len(out) == 5
# this should also work
model.compile(optimizer, loss, metrics={'dense_1': 'acc'},
@@ -126,10 +130,10 @@ def test_model_methods():
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
assert len(out) == 4
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
assert len(out) == 4
# and this as well
model.compile(optimizer, loss, metrics={'dense_1': ['acc']},
@@ -137,10 +141,22 @@ def test_model_methods():
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
assert len(out) == 4
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 2
assert len(out) == 4
# test with a custom metric function
mse = lambda y_true, y_pred: K.mean(K.pow(y_true - y_pred, 2))
model.compile(optimizer, loss, metrics=[mse],
sample_weight_mode=None)
out = model.train_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 5
out = model.test_on_batch([input_a_np, input_b_np],
[output_a_np, output_b_np])
assert len(out) == 5
input_a_np = np.random.random((10, 3))
input_b_np = np.random.random((10, 3))
@@ -153,5 +169,29 @@ 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))
model = Sequential()
model.add(Dense(2, input_dim=3, trainable=False))
model.compile('rmsprop', 'mse')
out = model.predict(x)
model.train_on_batch(x, y)
out_2 = model.predict(x)
assert_allclose(out, out_2)
# test with nesting
input = Input(shape=(3,))
output = model(input)
model = Model(input, output)
model.compile('rmsprop', 'mse')
out = model.predict(x)
model.train_on_batch(x, y)
out_2 = model.predict(x)
assert_allclose(out, out_2)
if __name__ == '__main__':
pytest.main([__file__])
+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={},
+147 -23
Ver Arquivo
@@ -2,17 +2,19 @@ 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
@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]:
@@ -36,6 +38,7 @@ def test_convolution_1d():
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 +47,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 +56,11 @@ def test_averagepooling_1d():
input_shape=(3, 5, 4))
@keras_test
def test_convolution_2d():
nb_samples = 8
nb_filter = 3
stack_size = 4
nb_samples = 2
nb_filter = 2
stack_size = 3
nb_row = 10
nb_col = 6
@@ -84,6 +89,124 @@ def test_convolution_2d():
input_shape=(nb_samples, stack_size, nb_row, nb_col))
@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},
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,
'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 = 2
stack_size = 3
nb_row = 10
nb_col = 6
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
for atrous_rate in [(1, 1), (2, 2)]:
if border_mode == 'same' and subsample != (1, 1):
continue
if subsample != (1, 1) and atrous_rate != (1, 1):
continue
layer_test(convolutional.AtrousConv2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'subsample': subsample,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
layer_test(convolutional.AtrousConv2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'W_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'subsample': subsample,
'atrous_rate': atrous_rate},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
@pytest.mark.skipif(K._BACKEND != 'tensorflow', reason="Requires TF backend")
@keras_test
def test_separable_conv_2d():
nb_samples = 2
nb_filter = 6
stack_size = 3
nb_row = 10
nb_col = 6
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
for multiplier in [1, 2]:
if border_mode == 'same' and subsample != (1, 1):
continue
layer_test(convolutional.SeparableConv2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'subsample': subsample,
'depth_multiplier': multiplier},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
layer_test(convolutional.SeparableConv2D,
kwargs={'nb_filter': nb_filter,
'nb_row': 3,
'nb_col': 3,
'border_mode': border_mode,
'depthwise_regularizer': 'l2',
'pointwise_regularizer': 'l2',
'b_regularizer': 'l2',
'activity_regularizer': 'activity_l2',
'pointwise_constraint': 'unitnorm',
'depthwise_constraint': 'unitnorm',
'subsample': subsample,
'depth_multiplier': multiplier},
input_shape=(nb_samples, stack_size, nb_row, nb_col))
@keras_test
def test_maxpooling_2d():
pool_size = (3, 3)
@@ -95,6 +218,7 @@ def test_maxpooling_2d():
input_shape=(3, 4, 11, 12))
@keras_test
def test_averagepooling_2d():
pool_size = (3, 3)
@@ -108,11 +232,11 @@ def test_averagepooling_2d():
input_shape=(3, 4, 11, 12))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
@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
@@ -150,7 +274,7 @@ def test_convolution_3d():
input_len_dim1, input_len_dim2, input_len_dim3))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
@keras_test
def test_maxpooling_3d():
pool_size = (3, 3, 3)
@@ -162,7 +286,7 @@ def test_maxpooling_3d():
input_shape=(3, 4, 11, 12, 10))
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
@keras_test
def test_averagepooling_3d():
pool_size = (3, 3, 3)
@@ -174,9 +298,10 @@ def test_averagepooling_3d():
input_shape=(3, 4, 11, 12, 10))
@keras_test
def test_zero_padding_2d():
nb_samples = 9
stack_size = 7
nb_samples = 2
stack_size = 2
input_nb_row = 11
input_nb_col = 12
@@ -199,10 +324,9 @@ def test_zero_padding_2d():
layer.get_config()
@pytest.mark.skipif(K._BACKEND != 'theano', reason="Requires Theano backend")
def test_zero_padding_3d():
nb_samples = 9
stack_size = 7
nb_samples = 2
stack_size = 2
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
@@ -227,15 +351,17 @@ def test_zero_padding_3d():
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 = 9
stack_size = 7
nb_samples = 2
stack_size = 2
input_nb_row = 11
input_nb_col = 12
@@ -273,10 +399,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 = 9
stack_size = 7
nb_samples = 2
stack_size = 2
input_len_dim1 = 10
input_len_dim2 = 11
input_len_dim3 = 12
@@ -320,5 +445,4 @@ def test_upsampling_3d():
if __name__ == '__main__':
# pytest.main([__file__])
test_convolution_3d()
pytest.main([__file__])
+89 -6
Ver Arquivo
@@ -1,32 +1,33 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
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
from keras.layers import Input, merge, Merge
from keras.models import Model
# test modes: 'sum', 'mul', 'concat', 'ave', 'cos', 'dot'.
input_shapes = [(3, 2), (3, 2)]
inputs = [np.random.random(shape) for shape in input_shapes]
# test graph API
for mode in ['sum', 'mul', 'concat', 'ave', 'cos', 'dot']:
# test functional API
for mode in ['sum', 'mul', 'concat', 'ave', 'max']:
print(mode)
input_a = Input(shape=input_shapes[0][1:])
input_b = Input(shape=input_shapes[1][1:])
merged = merge([input_a, input_b], mode='sum')
merged = merge([input_a, input_b], mode=mode)
model = Model([input_a, input_b], merged)
model.compile('rmsprop', 'mse')
@@ -38,6 +39,15 @@ def test_merge():
model = Model.from_config(config)
model.compile('rmsprop', 'mse')
# test Merge (#2460)
merged = Merge(mode=mode)([input_a, input_b])
model = Model([input_a, input_b], merged)
model.compile('rmsprop', 'mse')
expected_output_shape = model.get_output_shape_for(input_shapes)
actual_output_shape = model.predict(inputs).shape
assert expected_output_shape == actual_output_shape
# test lambda with output_shape lambda
input_a = Input(shape=input_shapes[0][1:])
input_b = Input(shape=input_shapes[1][1:])
@@ -75,12 +85,75 @@ 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
rand = lambda *shape: np.asarray(np.random.random(shape) > 0.5, dtype='int32')
# inputs
input_a = Input(shape=(3,))
input_b = Input(shape=(3,))
# masks
masked_a = Masking(mask_value=0)(input_a)
masked_b = Masking(mask_value=0)(input_b)
# 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)
# 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)
# 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
rand = lambda *shape: np.asarray(np.random.random(shape) > 0.5, dtype='int32')
# embeddings
input_a = Input(shape=(3,), dtype='int32')
input_b = Input(shape=(3,), dtype='int32')
embedding = Embedding(3, 4, mask_zero=True)
embedding_a = embedding(input_a)
embedding_b = embedding(input_b)
# rnn
rnn = SimpleRNN(3, return_sequences=True)
rnn_a = rnn(embedding_a)
rnn_b = rnn(embedding_b)
# concatenation
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)])
@keras_test
def test_dropout():
layer_test(core.Dropout,
kwargs={'p': 0.5},
input_shape=(3, 2))
@keras_test
def test_activation():
# with string argument
layer_test(core.Activation,
@@ -93,30 +166,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
@@ -150,6 +228,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
@@ -168,6 +247,7 @@ def test_dense():
input_shape=(3, 2))
@keras_test
def test_activity_regularization():
from keras.engine import Input, Model
@@ -188,6 +268,7 @@ def test_activity_regularization():
model.compile('rmsprop', 'mse')
@keras_test
def test_maxout_dense():
from keras import regularizers
from keras import constraints
@@ -206,6 +287,7 @@ def test_maxout_dense():
input_shape=(3, 2))
@keras_test
def test_highway():
from keras import regularizers
from keras import constraints
@@ -223,6 +305,7 @@ def test_highway():
input_shape=(3, 2))
@keras_test
def test_timedistributeddense():
from keras import regularizers
from keras import constraints

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