Comparar commits

...

261 Commits

Autor SHA1 Mensagem Data
Francois Chollet df860fdb94 Update IRNN example 2015-11-29 13:08:45 -08:00
Francois Chollet 361a7cfe41 Update addition example 2015-11-29 12:54:45 -08:00
Francois Chollet 8f2d6d2714 Add support for time-distributed softmax. 2015-11-29 12:54:26 -08:00
Francois Chollet cbee000b66 Fix TF RNN issues 2015-11-29 12:22:41 -08:00
Francois Chollet 7ecd6c3c5f Fix backend tests 2015-11-29 10:38:48 -08:00
Francois Chollet 060ef32ce0 Merge branch 'backend' of https://github.com/fchollet/keras into backend 2015-11-29 10:15:45 -08:00
Francois Chollet 36392c75d7 Fix backend tests 2015-11-29 10:15:37 -08:00
François Chollet 2f01f29995 Merge pull request #1105 from transcranial/backend
fix tensorflow travis config
2015-11-28 21:13:41 -08:00
Leon Chen 0ab3a6c00c use ubuntu 14.04 on travis 2015-11-28 23:42:54 -05:00
Leon Chen 475fa79ec4 fix tensorflow travis config 2015-11-28 23:18:07 -05:00
Francois Chollet e600b0d947 Attempt to fix Travis config 2015-11-28 17:51:35 -08:00
Francois Chollet 677e15cd02 Attempt to fix Travis config 2015-11-28 17:50:23 -08:00
Francois Chollet ea2fd6526b Attempt to fix TF on Travis 2015-11-28 17:43:48 -08:00
Francois Chollet 26b040effe Attempt to fix TF in Travis config 2015-11-28 17:36:52 -08:00
Francois Chollet ef3ef71ee6 Add exception for TF + NTM 2015-11-28 17:19:13 -08:00
Francois Chollet 5c3aea2202 Fix backend init 2015-11-28 17:05:49 -08:00
Francois Chollet b6ea543a46 Fix Travis config. 2015-11-28 16:59:48 -08:00
Francois Chollet e32436144b Add tests 2015-11-28 16:39:42 -08:00
Francois Chollet 2bc900c3d2 Upate Travis config. 2015-11-28 16:36:09 -08:00
Francois Chollet 6c458ff281 Update layers. 2015-11-28 16:35:55 -08:00
Francois Chollet 69a8acc05a Update backend functionality. 2015-11-28 16:35:20 -08:00
Francois Chollet 71c6c83e30 Update examples. 2015-11-28 16:34:52 -08:00
Francois Chollet 634aedca1a Update documentation. 2015-11-28 16:34:35 -08:00
Francois Chollet 4b39b5f36b Remove deprecated code. 2015-11-28 16:34:06 -08:00
Francois Chollet 25e85b616f Merge master 2015-11-26 12:28:38 -08:00
Francois Chollet 47ed18a3af Update backends with rnn support 2015-11-26 10:42:52 -08:00
François Chollet febc604fc4 Merge pull request #1081 from farizrahman4u/patch-17
Bug fix - Siamese layer
2015-11-25 13:28:59 -08:00
François Chollet 8612da30a9 Merge pull request #1082 from PFischbeck/patch-1
Fix typo in index.md
2015-11-25 13:27:04 -08:00
Fariz Rahman 9c1afbb667 Update containers.py 2015-11-26 02:38:25 +05:30
Philipp Fischbeck 8c9c8ae5ad Fix typo in index.md 2015-11-25 22:06:56 +01:00
Fariz Rahman b92cec3d48 Fix for nested models 2015-11-26 02:21:42 +05:30
Fariz Rahman cbb9d00106 Update core.py 2015-11-26 02:09:43 +05:30
Fariz Rahman aca4a7735e Bug fix 2015-11-26 02:07:51 +05:30
Francois Chollet 6afce5862a Merge branch 'farizrahman4u-patch-16' 2015-11-25 11:53:57 -08:00
Francois Chollet f2a14a9b57 Update doc for add_shared_node in Graph model. 2015-11-25 11:53:28 -08:00
Francois Chollet 4429547354 Merge branch 'patch-16' of https://github.com/farizrahman4u/keras into farizrahman4u-patch-16 2015-11-25 11:45:06 -08:00
François Chollet b733951a19 Merge pull request #1079 from transcranial/elu
add exponential linear units activation layer
2015-11-25 10:30:12 -08:00
Fariz Rahman 78c61c65c2 Update containers.py 2015-11-25 23:38:18 +05:30
Fariz Rahman 242793a223 Update Graph doc 2015-11-25 23:36:16 +05:30
Fariz Rahman 5c1e5d5e40 Update core.py 2015-11-25 23:25:16 +05:30
Fariz Rahman e34022bf12 Docstrings 2015-11-25 23:13:49 +05:30
Fariz Rahman dac1e8ec65 Add add_shared_node() 2015-11-25 23:12:52 +05:30
Fariz Rahman 7867abdd69 Docstrings 2015-11-25 22:53:03 +05:30
Fariz Rahman 2685134832 Add add_shared_layer() 2015-11-25 22:52:29 +05:30
Fariz Rahman 138e77d0d6 Add Siamese layer 2015-11-25 22:50:53 +05:30
François Chollet 59a30e99a3 Merge pull request #1073 from pse1202/master
Typo fix
2015-11-25 09:03:38 -08:00
Leon Chen 71ee360c20 add exponential linear units activation layer 2015-11-25 11:20:49 -05:00
Sangeon Park 88cc300103 Typo fix
tran and test sets -> train and test sets
2015-11-25 07:42:15 +09:00
François Chollet b059945195 Merge pull request #1059 from farizrahman4u/patch-15
Fix misleading comment in babi_memnn.py
2015-11-22 14:57:29 -08:00
Fariz Rahman 819f569ca8 Update babi_memnn.py 2015-11-23 04:16:32 +05:30
Fariz Rahman d322785543 Fix misleading comment in babi_memnn.py
Output of question_encoder is 3D : sequence of vectors, not single vector.
2015-11-23 03:54:32 +05:30
Francois Chollet 05aecbc0bc Fix README, docs captioning example 2015-11-22 12:05:26 -08:00
Francois Chollet 37ebbc3a1c Remove outdated comment 2015-11-22 12:03:53 -08:00
François Chollet 252db48746 Merge pull request #1052 from EderSantana/patch-4
Fix typos and even more informative docs.
2015-11-21 14:39:15 -08:00
Eder Santana 2d3880dc35 Fix typos and even more informative docs.
Even more informative docs. Sorry for not doing all the work at once.
2015-11-20 21:25:24 -05:00
François Chollet 50467e32a2 Merge pull request #990 from EderSantana/ntm
Neural Turing Machines
2015-11-20 17:56:38 -08:00
François Chollet e1cc291a25 Merge pull request #1046 from julienr/visutil_to_graph
Add visualize_util.to_graph and docs
2015-11-20 08:55:34 -08:00
Julien Rebetez 71b258d21e Add visualization section to docs 2015-11-20 11:03:31 +01:00
Julien Rebetez c1b54159b8 Add a new to_graph function in visualize_util that allow one to get the pydot.Graph object directly. This can be used to display the graph inline in a notebook. 2015-11-20 11:03:04 +01:00
François Chollet 6a231f1a24 Merge pull request #1041 from neggert/lambda_enhancements
Lambda layer enhancements
2015-11-19 22:39:28 -08:00
François Chollet b82223b2f2 Merge pull request #1037 from farizrahman4u/patch-9
Fix load_from_json for models with Lambda layer
2015-11-19 22:38:47 -08:00
François Chollet 0e69226546 Merge pull request #1039 from phreeza/patch-3
Update visualize_util.py to fix #1036
2015-11-19 22:38:33 -08:00
EderSantana 89132a6986 Fix typos and update docs 2015-11-19 23:46:55 -05:00
Francois Chollet 8b75182a17 Update backend 2015-11-19 20:14:48 -08:00
Francois Chollet bc5e993ae3 Update tests 2015-11-19 20:14:38 -08:00
Francois Chollet 8f2b5f0458 Continue Keras conversion to dual-backend version 2015-11-19 20:14:29 -08:00
Francois Chollet 34838cd369 Update examples 2015-11-19 20:13:49 -08:00
z001qdp 71b00324d8 Allow Lambda layer to pass arguments to Layer constructor.
Most importantly, the `input_shape` argument. This allows a Lambda
layer to be the first layer in a net, which was previously
impossible.
2015-11-19 16:35:26 -06:00
Nic Eggert 16590ccce5 Fix typo in Lambda layer 2015-11-19 16:17:48 -06:00
Thomas McColgan 2431764fed Update visualize_util.py to fix #1036 2015-11-19 14:53:51 +01:00
Fariz Rahman d444b9190f Update layer_utils.py 2015-11-19 16:15:26 +05:30
Francois Chollet 8ad18ce8f5 Update a number of tests. 2015-11-18 17:46:37 -08:00
Francois Chollet a744b600e9 Convert a number of layers. 2015-11-18 17:46:25 -08:00
Francois Chollet 52dac5e4b3 Update backends. 2015-11-18 17:45:29 -08:00
Francois Chollet e94f29cac4 Fix bug with validation data in Graph model 2015-11-18 13:32:06 -08:00
Francois Chollet 4e519f7aa7 Convert activations, constraints, noise, embedding 2015-11-17 21:39:15 -08:00
Francois Chollet fd05964135 Update TH / TF backends 2015-11-17 21:38:39 -08:00
Eder Santana 747d4a30b1 Update ntm.py
remove commented code
2015-11-17 21:03:06 -05:00
Eder Santana ab19cf7b07 Update ntm.py
clean up documentation
2015-11-17 21:00:51 -05:00
Eder Santana 6b8970abd3 Update neural_turing_machine_copy.py
Fix wrong import and train both models
2015-11-17 20:53:11 -05:00
Francois Chollet 5ed913da11 Convert constraints, initialization, activations 2015-11-15 15:01:58 -08:00
Francois Chollet 6ffa18e390 Convert objectives to Keras backend. 2015-11-15 14:33:20 -08:00
Francois Chollet 33ed943ad5 Convert optimizers to Keras backend. 2015-11-15 14:33:08 -08:00
Francois Chollet 368df8ef04 Convert regularizers to Keras backend. 2015-11-15 14:32:58 -08:00
Francois Chollet 24b5e80667 Fix axis specification in TF. 2015-11-15 11:30:07 -08:00
Francois Chollet 15fea0488a Style fixes 2015-11-14 22:17:13 -08:00
Francois Chollet cda6a998ef Add initial version of Theano/TensorFlow backends 2015-11-14 22:08:21 -08:00
François Chollet 653ee91d35 Merge pull request #999 from dbonadiman/patch-4
Update docs with go_backwards option
2015-11-14 11:04:50 -08:00
François Chollet eb8b37604c Merge pull request #1001 from dbonadiman/patch-5
Fixed error go_backward and return sequences.
2015-11-12 20:44:31 -08:00
Daniele Bonadiman e1bd779463 fixed an error in backward computation of recurrent layers on return sequences. 2015-11-12 13:25:47 +01:00
Daniele Bonadiman 62154fd6c6 Merge pull request #2 from fchollet/master
Up do date 2
2015-11-12 12:17:57 +01:00
Daniele Bonadiman f8b0c7e2e3 Update doc with go_backwards option 2015-11-12 11:48:32 +01:00
François Chollet 7df515b607 Merge pull request #995 from farizrahman4u/patch-9
Include samples dim in output_shape's argument
2015-11-11 10:33:24 -08:00
Fariz Rahman b65c665d2a Include samples dim in output_shape's argument 2015-11-11 23:58:12 +05:30
Francois Chollet dfa6b3a4c3 Merge branch 'farizrahman4u-patch-9' 2015-11-11 08:58:16 -08:00
Francois Chollet 2e6025d7cc Fix coding style in documentation for Lambda 2015-11-11 08:58:04 -08:00
Francois Chollet 1a721b42c7 Merge branch 'patch-9' of https://github.com/farizrahman4u/keras into farizrahman4u-patch-9 2015-11-11 08:47:08 -08:00
François Chollet d0677a1e1f Merge pull request #992 from tzachar/patch.02
Fix containers.graph sav/get_weights
2015-11-11 08:44:13 -08:00
Fariz Rahman f6f8bf643e Update core.md 2015-11-11 21:08:30 +05:30
Fariz Rahman d6aebff5b2 Added documentation for LambdaMerge layer 2015-11-11 21:07:36 +05:30
Fariz Rahman e60b7de064 Update core.md 2015-11-11 20:44:34 +05:30
Fariz Rahman cbd8eb7a55 Added documentation for Lambda layer with example 2015-11-11 20:39:53 +05:30
nir tzachar 20dc637cd6 Fix containers.graph sav/get_weights
As the graph container was not using each individual layer's get/set
weights, but rather the super class layer.get_weights, which works on
self.params(), it was missing some weights in the process, i.e., the
BatchNormalizationLayer has custom get_weights which allows to save the
running mean/std. However, these running computations are not added to
BatchNormalizationLayer.params(), resulting in losing these weights
after serializing a graph model utilizing a BatchNormalizationLayer.

Fixed to use each node's get/set weights.
2015-11-11 11:40:43 +02:00
François Chollet e037e17557 Merge pull request #950 from rushter/autoencoder-fix
Fix AutoEncoder's input_shape
2015-11-10 18:08:38 -08:00
François Chollet 9ad5bf3a7b Merge pull request #986 from tzachar/patch
Fix TimeDistributedMerge
2015-11-10 18:07:54 -08:00
EderSantana 9e4e317bcb Neural Turing Machines 2015-11-10 19:16:26 -05:00
nir tzachar db60707cb8 Fix TimeDistributedMerge
When mode='ave', and the dtype of the input is float32, dividing the sum
by shape[1], which is of dtype int64, results in an output of dtype
float64, which is wrong.

fixed to use theano.tensor.mean instead.
2015-11-10 09:40:37 +02:00
Francois Chollet 91ea495b56 MemNN Python3 compatibility 2015-11-09 18:47:29 -08:00
Francois Chollet d9596ae68d Add memory network example. 2015-11-09 18:47:29 -08:00
Francois Chollet 1dc1d25a58 Add memory network example. 2015-11-09 16:37:44 -08:00
François Chollet 527b1ed0dc Merge pull request #978 from dbonadiman/patch-3
Fix imdb bidirectional
2015-11-09 08:03:07 -08:00
Fariz Rahman 17d2f5f960 del instead of setting to None 2015-11-09 18:54:54 +05:30
Fariz Rahman 2ef4d698ef Whitespace fix 2015-11-09 18:50:52 +05:30
Fariz Rahman bde97055c0 Update core.py 2015-11-09 18:40:01 +05:30
Fariz Rahman 3b0e2b0c79 Del ndim arg,exclude samples dim from output shape 2015-11-09 18:37:32 +05:30
Daniele Bonadiman 3e3c43d3ee fix TypeError: fit() got an unexpected keyword argument 'show_accuracy' 2015-11-09 12:06:18 +01:00
Daniele Bonadiman cb60477548 Merge pull request #1 from fchollet/master
Up to date
2015-11-09 09:25:42 +00:00
Francois Chollet 3d25fae014 Merge branch 'dbonadiman-add-1' 2015-11-08 18:16:33 -08:00
Francois Chollet 4884595e4d Style fixes in bidirectional LSTM example. 2015-11-08 18:16:10 -08:00
Francois Chollet 1760ed6cd7 Merge branch 'add-1' of https://github.com/dbonadiman/keras into dbonadiman-add-1 2015-11-08 18:07:20 -08:00
François Chollet b1bbedfb46 Merge pull request #972 from dbonadiman/patch-1
[Patch] Fixing issue with dot output shape
2015-11-08 18:05:35 -08:00
Francois Chollet 227c300a0a Remove sudo from Travis CI config 2015-11-08 17:04:14 -08:00
Francois Chollet f5819a0d4e Update Travis CI config 2015-11-08 16:59:14 -08:00
Daniele Bonadiman 28882a868d fix https://github.com/fchollet/keras/pull/970#issuecomment-154886091 2015-11-09 00:29:14 +01:00
Daniele Bonadiman b32e60cfa0 fixing issues with dot output shape 2015-11-08 23:26:33 +01:00
Daniele Bonadiman ca360b0d15 bidirectional lstm example added. 2015-11-08 23:19:14 +01:00
Daniele Bonadiman 10852b2529 go_backwards added to recurrent layers. 2015-11-08 22:56:42 +01:00
rushter cc0108097c Fix AutoEncoder's input_shape 2015-11-04 10:12:39 +03:00
François Chollet fe14a845ab Merge pull request #942 from matsuyamax/master
Fixes and input checks for dot mode in merge.
2015-11-02 20:45:51 -08:00
Makoto Matsuyama 5964848bdf Fix Python3 compatibility 2015-11-02 20:14:33 -08:00
Makoto Matsuyama 002a9d5d2b Fixes and input checks for dot mode in merge. 2015-11-02 19:37:00 -08:00
François Chollet eba8530e7b Merge pull request #941 from stephenroller/master
imported TimeDistributedMerge
2015-11-02 14:47:42 -08:00
Stephen Roller 7432034ada TimeDistributedMerge needed to be imported into layer_utils, so it could be serialized to to_json 2015-11-02 16:36:05 -06:00
François Chollet 99331b83f9 Merge pull request #938 from farizrahman4u/patch-12
Avoid recalculation of output in join merge.
2015-11-02 12:37:31 -08:00
François Chollet 0b326d9688 Merge pull request #939 from stephenroller/master
Fix merge concat mode
2015-11-02 11:58:22 -08:00
Stephen Roller 57612707c1 Fix merge concat mode; the assertion checked the opposite of what was desired. 2015-11-02 13:51:10 -06:00
Fariz Rahman 5352e46e09 Avoid recalculation of output in join merge. 2015-11-03 00:10:43 +05:30
François Chollet a5d93bfdc1 Merge pull request #935 from liormagen/patch-1
Handle an empty document
2015-11-02 08:18:05 -08:00
Lior Magen 742ccaa2cf Handle an empty document
In case of an empty sequence (as a result of clearing stop words for example), don't raise an error but continue to the next sequence.
2015-11-02 16:39:18 +02:00
François Chollet 284ef7b495 Merge pull request #927 from LeavesBreathe/patch-2
Update Docs for RMSE in objectives
2015-11-01 10:59:42 -08:00
LeavesBreathe 02180e881d Update Docs for RMSE in objectives 2015-10-31 13:13:21 -04:00
Francois Chollet 4a6b03403b Fix ParametricSoftplus 2015-10-31 10:12:27 -07:00
François Chollet ccdd5d147d Merge pull request #926 from rushter/small-fixes
Small fixes
2015-10-31 10:11:16 -07:00
François Chollet 3c95896415 Merge pull request #922 from LeavesBreathe/patch-2
Added Root Mean Square Error
2015-10-31 09:57:05 -07:00
rushter 66edb6aea0 Fix python 3 compatibility 2015-10-31 18:16:48 +03:00
rushter 5590dc7b0d FIx read-only property can't be changed 2015-10-31 18:11:51 +03:00
rushter 8f2810bfee Remove useless declaration 2015-10-31 17:32:01 +03:00
rushter 42e582b1ba FIx typos 2015-10-31 17:30:00 +03:00
LeavesBreathe 43bf884b5f Added Root Mean Square Error 2015-10-31 08:59:04 -04:00
François Chollet 234408e82e Merge pull request #920 from farizrahman4u/patch-2
Fix dot_axis API
2015-10-30 13:47:51 -07:00
François Chollet 41db741881 Merge pull request #917 from contextvision/dropout
Dropout: rescale data at training time (breaks bw compat.)
2015-10-30 13:47:21 -07:00
François Chollet 46bfa18a57 Merge pull request #911 from jpeg729/custom_objects
Change the custom_layer api to support custom_objects
2015-10-30 13:41:54 -07:00
Francois Chollet 7e85390d8e Merge branch 'master' of https://github.com/fchollet/keras 2015-10-30 13:14:03 -07:00
Francois Chollet a2d01238af Fix flaky Travis test 2015-10-30 13:13:50 -07:00
Fariz Rahman ba982e7ee0 Whitespace fix 2015-10-30 23:28:15 +05:30
Fariz Rahman 18f122e1d9 Fix dot_axis API
Make the default value of dot_axes more useful.
2015-10-30 23:26:52 +05:30
Mikael Rousson bae645b65e rescale data at training time (breaks bw compat.) 2015-10-30 09:38:10 +01:00
jpeg729 66ad0bf736 Change the custom_layer api to support custom_objects
A small change permitting the use of custom loss functions, custom
optimizers, custom activation functions, and so on.
2015-10-29 16:31:17 +01:00
Fariz Rahman 469640bd45 Fix serialization recursion problem 2015-10-29 08:57:05 +05:30
Fariz Rahman 2f8b351c95 Update core.py 2015-10-29 08:23:18 +05:30
Fariz Rahman 8ee2ffd7e1 Update core.py 2015-10-29 08:22:09 +05:30
Fariz Rahman fb24dc1904 Update core.py 2015-10-29 00:02:00 +05:30
Fariz Rahman 79e702ec53 Added test for Lambda layer 2015-10-28 23:42:43 +05:30
François Chollet bd005d66af Merge pull request #906 from farizrahman4u/patch-2
Add dot_axes argument to Graph
2015-10-28 10:57:26 -07:00
Fariz Rahman 0354e64521 Update test_sequential_model.py 2015-10-28 12:39:02 +05:30
Fariz Rahman a4552fb004 Use input shape instead of input layer 2015-10-28 12:38:09 +05:30
Fariz Rahman 455d7d10db Add dot_axes argument to Graph
Add dot_axes argument, used by the recently added dot merge mode.
2015-10-28 12:07:53 +05:30
Francois Chollet 1c7585a563 Fix failing test 2015-10-27 22:08:41 -07:00
Francois Chollet 22566c37ce Fix dot_axes API in Merge 2015-10-27 22:08:25 -07:00
Fariz Rahman 1f0178e793 Whitespace fix 2015-10-28 10:32:51 +05:30
Fariz Rahman fbe2ea6537 Update core.py 2015-10-28 10:31:16 +05:30
Fariz Rahman 7b0be64757 White space/style/comment fix 2015-10-28 10:28:54 +05:30
François Chollet 0edbdcc998 Merge pull request #905 from farizrahman4u/patch-10
Dot and cos merge modes
2015-10-27 21:50:11 -07:00
Fariz Rahman 21dcabb6e8 Update test_sequential_model.py 2015-10-28 09:55:34 +05:30
Fariz Rahman c34578aece Added test for dot merge with tuple and int axes 2015-10-28 09:48:42 +05:30
Fariz Rahman 01a3e298fb Dot and cos merge modes
Cleaner version of #891
2015-10-28 09:44:18 +05:30
Fariz Rahman 42a65d4b83 Update core.py 2015-10-28 08:43:48 +05:30
Fariz Rahman cb836091ec Update core.py 2015-10-28 08:28:16 +05:30
Fariz Rahman 6a05247711 Update core.py 2015-10-28 04:10:43 +05:30
Fariz Rahman c015acb413 Update core.py 2015-10-28 03:43:48 +05:30
Fariz Rahman feac8dba01 Update test_sequential_model.py 2015-10-28 03:38:01 +05:30
Fariz Rahman ba389ffb11 Added LambdaMerge 2015-10-28 03:30:32 +05:30
Fariz Rahman c6c3a0247c Add auto_name to config 2015-10-28 02:48:43 +05:30
Fariz Rahman c140939c5a Update core.py 2015-10-28 02:39:18 +05:30
François Chollet a9cecbbe43 Merge pull request #897 from amitbeka/load-name-consume
utils.layer_utils: don't consume 'name' when loading
2015-10-27 13:48:10 -07:00
François Chollet 0f0d264e55 Merge pull request #903 from EderSantana/patch-2
property input_shape for Sequential
2015-10-27 13:35:36 -07:00
Eder Santana a9d0905897 property input_shape for Sequential
Fix #902
2015-10-27 16:23:59 -04:00
Fariz Rahman c90d2dfc0c Update core.py 2015-10-28 01:36:47 +05:30
Fariz Rahman 315a12ac58 Pass value for auto_name argument 2015-10-28 01:19:11 +05:30
Fariz Rahman f5896236fa Added auto_name argument for merge layer 2015-10-28 01:16:36 +05:30
Fariz Rahman 29e788dc2e Update test_sequential_model.py 2015-10-27 21:49:58 +05:30
Fariz Rahman 07f8cef29c Update core.py 2015-10-27 19:59:35 +05:30
Fariz Rahman a069161d0f Update test_sequential_model.py 2015-10-27 19:58:16 +05:30
François Chollet 26b57a6cdd Merge pull request #860 from jeanpijon/monitor_directions
Monitor directions #2
2015-10-26 10:12:53 -07:00
Fariz Rahman 45577f7959 Added type checking for output_shape return value 2015-10-26 21:54:07 +05:30
Fariz Rahman 25aab5d405 Indentation fix 2015-10-26 21:16:48 +05:30
Fariz Rahman a58e037715 Added doc string 2015-10-26 21:02:34 +05:30
Fariz Rahman eb62075078 Roll back 2015-10-26 20:43:17 +05:30
Pesan Jan 3663f64bb4 Modification of ModelCheckpoint to allow monitoring of increasing
metrics
2015-10-26 11:58:08 +01:00
Amit Beka fcd54ac85b utils.layer_utils: don't consume 'name' when loading
When loading regularizers/constraints from config, and the object isn't
found, don't consume the 'name' key.

This enables expansions to keras to be saved/loaded with dictionaries as
some of their parameters.

Signed-off-by: Amit Beka <amit.beka@gmail.com>
2015-10-26 12:11:07 +02:00
Fariz Rahman fb8e80daf4 Consider the case where Lambda is input layer 2015-10-26 14:52:54 +05:30
Fariz Rahman ac3d135b84 Only allow named inputs to be merged by join mode 2015-10-26 14:46:51 +05:30
Fariz Rahman d876dae965 Named layers before join merging 2015-10-26 14:45:06 +05:30
Fariz Rahman 345d78e27d Added default value for output shape 2015-10-26 08:41:34 +05:30
Fariz Rahman d5827c8917 Whitespace fix 2015-10-26 07:51:27 +05:30
Fariz Rahman 779bf2a8d2 Made compatible with Python 3 2015-10-26 07:50:55 +05:30
Fariz Rahman 0fab8ac373 Update test_sequential_model.py 2015-10-26 07:26:47 +05:30
Fariz Rahman b3594ccd5e Added test for serializing model with Lambda layer 2015-10-26 07:18:20 +05:30
Fariz Rahman 15b84d375f Update core.py 2015-10-26 07:00:02 +05:30
Fariz Rahman 312120272f Add Python3 support 2015-10-26 06:54:46 +05:30
Fariz Rahman 97b27bfd1e Update test_sequential_model.py 2015-10-26 06:24:59 +05:30
Fariz Rahman a0c5f5743c Update core.py 2015-10-26 06:19:18 +05:30
Fariz Rahman 688b898dc8 Update test_sequential_model.py 2015-10-26 05:50:19 +05:30
Fariz Rahman 7def993fe2 Update test_sequential_model.py 2015-10-26 05:40:56 +05:30
Fariz Rahman c33a551f97 Update test_sequential_model.py 2015-10-26 05:20:23 +05:30
Fariz Rahman 3f8bfd2b1c Added test for Lambda layer 2015-10-26 05:04:34 +05:30
Fariz Rahman c6cf4425d3 Update core.py 2015-10-26 04:21:56 +05:30
Fariz Rahman aa6cf91a18 White space/ style fix 2015-10-26 04:00:44 +05:30
Fariz Rahman 5faef2fc56 Changed order of inheritance 2015-10-26 03:58:41 +05:30
Fariz Rahman ad254f99eb Bug fix 2015-10-26 03:47:56 +05:30
Fariz Rahman e6cecb5d12 Separate Lambda and MaskedLambda layers 2015-10-26 03:29:57 +05:30
Fariz Rahman 6106d1fa30 Indentation fix 2015-10-26 02:30:00 +05:30
Fariz Rahman ab6b11d86e Lambda Layer
Lambda layer can be used to implement any arbitrary function when stacked on top of a join merge layer.
2015-10-26 02:20:24 +05:30
François Chollet 6e2e6eff89 Merge pull request #892 from amitbeka/fix-requirements
fix setup.py: add six as a requirement
2015-10-25 10:25:46 -07:00
Amit Beka e60680b12c fix setup.py: add six as a requirement
Signed-off-by: Amit Beka <amit.beka@gmail.com>
2015-10-25 18:06:41 +02:00
Francois Chollet 47071f9303 Merge branch 'farizrahman4u-patch-8' 2015-10-24 21:08:12 -07:00
Francois Chollet 14486397c5 Whitespace / style fixes 2015-10-24 21:07:47 -07:00
Francois Chollet 0cd30480fb Merge branch 'patch-8' of https://github.com/farizrahman4u/keras into farizrahman4u-patch-8 2015-10-24 20:46:10 -07:00
Francois Chollet 74b590eff8 Whitespace / style fixes only 2015-10-24 20:39:06 -07:00
Francois Chollet 25a2a972b1 Merge branch 'patch-1' of https://github.com/farizrahman4u/keras into farizrahman4u-patch-1 2015-10-24 20:28:51 -07:00
François Chollet 01bb88513d Merge pull request #889 from trungnt13/master
fixed error in reading hdf5 dataset
2015-10-24 14:22:30 -07:00
farizrahman4u 0d233b2512 Update imdb_cnn_lstm.py 2015-10-25 02:43:02 +05:30
farizrahman4u e704e1578e Update imdb_cnn_lstm.py
Style fix
2015-10-25 02:37:47 +05:30
nick_artin 0c0d91df2e Fixed error in reading hdf5 dataset 2015-10-24 23:00:17 +02:00
François Chollet 52fd68f4c5 Merge pull request #886 from alvations/master
Added version information and docstring to __init__
2015-10-24 13:05:34 -07:00
alvations 7b0b324041 Merge pull request #2 from alvations/alvations-patch-1
Removed the unused import
2015-10-24 20:23:11 +02:00
alvations 8b24b3343f Removed the unused import 2015-10-24 20:20:32 +02:00
alvations 084b235c62 Merge pull request #1 from alvations/alvations-patch-1
Added version information and docstring to __init__
2015-10-24 15:29:40 +02:00
alvations 9a384888d7 Added version information and docstring to __init__ 2015-10-24 15:21:34 +02:00
farizrahman4u 6cc827ca55 Bug fix 2015-10-24 15:11:20 +05:30
farizrahman4u d2051a5df1 Added shape checking for concat merge 2015-10-24 14:53:36 +05:30
François Chollet e7c6d598a9 Merge pull request #839 from mmmikael/trainable
added possibility to freeze layers during training
2015-10-23 16:40:38 -07:00
farizrahman4u 1526d81ab3 Faster and better Sentiment Analysis example.
Faster and more accurate sentiment analysis using combination of convolutional and recurrent layers. Better and faster results when compared to using either convnet or rnn alone.

Comparison with other sentiment analysis examples (run on a slow machine so that the time differences are visible):

imdb_lstm.py

Train...
Train on 20000 samples, validate on 5000 samples
Epoch 1/4
20000/20000 [==============================] - 784s - loss: 0.4773 - acc: 0.7769 - val_loss: 0.3613 - val_acc: 0.8396
Epoch 2/4
20000/20000 [==============================] - 788s - loss: 0.2691 - acc: 0.8946 - val_loss: 0.3644 - val_acc: 0.8376
Epoch 3/4
20000/20000 [==============================] - 791s - loss: 0.1770 - acc: 0.9351 - val_loss: 0.3913 - val_acc: 0.8370
Epoch 4/4
20000/20000 [==============================] - 800s - loss: 0.1137 - acc: 0.9612 - val_loss: 0.4621 - val_acc: 0.8308
5000/5000 [==============================] - 48s
Test score: 0.46212145137
Test accuracy: 0.8308

imdb_cnn.py

Train on 20000 samples, validate on 5000 samples
Epoch 1/3
20000/20000 [==============================] - 1414s - loss: 0.6401 - acc: 0.5930 - val_loss: 0.5144 - val_acc: 0.7442
Epoch 2/3
20000/20000 [==============================] - 1411s - loss: 0.3908 - acc: 0.8255 - val_loss: 0.3615 - val_acc: 0.8344
Epoch 3/3
20000/20000 [==============================] - 1416s - loss: 0.3173 - acc: 0.8636 - val_loss: 0.3788 - val_acc: 0.8256



imdb_cnn_lstm.py

Train...
Train on 20000 samples, validate on 5000 samples
Epoch 1/2
20000/20000 [==============================] - 575s - loss: 0.4312 - acc: 0.7900 - val_loss: 0.3457 - val_acc: 0.8456
Epoch 2/2
20000/20000 [==============================] - 580s - loss: 0.2302 - acc: 0.9094 - val_loss: 0.3546 - val_acc: 0.8498
5000/5000 [==============================] - 26s
Test score: 0.354624111649
Test accuracy: 0.8498
2015-10-24 01:49:27 +05:30
farizrahman4u 73c0045815 Bug fix
The base Layer was not returning an output shape.
2015-10-24 01:08:40 +05:30
farizrahman4u 3981a87b31 Assert input shapes of Merge layer are equal
Make sure that only layers with same output_shape are merged using sum, ave and mul modes.
2015-10-23 20:52:43 +05:30
Mikael Rousson a78c43033e added possibility to freeze layers during training 2015-10-23 13:53:26 +02:00
François Chollet 80e85836c1 Merge pull request #876 from farizrahman4u/patch-2
Update comment to include new join merge mode
2015-10-22 15:35:04 -07:00
farizrahman4u 569bb74a08 Update comment to include new join merge mode 2015-10-23 00:04:22 +05:30
François Chollet a8eda69f3e Merge pull request #869 from EderSantana/join
add join to valid merge modes
2015-10-22 09:16:16 -07:00
EderSantana 6f620712b5 add join to valid merge modes 2015-10-21 21:41:34 -04:00
François Chollet a19c9ecfbd Merge pull request #865 from suixudongi8/patch-1
Update optimizers.py
2015-10-21 18:33:14 -07:00
Xsh Disney 11e4c4b90f Update optimizers.py
Bug:
float() argument must be a string or a number, not 'TensorSharedVariable'
fixed!
2015-10-21 21:30:44 +08:00
François Chollet 025cd16854 Merge pull request #859 from r9y9/patch-1
FIx `Exception: Invalid layer: LRN2D`
2015-10-20 10:24:48 -07:00
Ryuichi YAMAMOTO 68f619b9f9 import LRN2D
This should fix the problem`Exception: Invalid layer: LRN2D` while loading a model that includes LRN2D.

```py
model = Sequential()
model.add(Convolution2D(30, 3, 3, input_shape=(1, 28, 28)))
model.add(LRN2D())

model_def = model.to_yaml()

# this line raises Exception: Invalid layer: LRN2D
model_from_yaml(model_def)
```

The code above could reproduce the problem.
2015-10-20 19:28:41 +09:00
Francois Chollet f1ef9895f5 Update README w/ warning about using latest Theano 2015-10-14 11:26:23 -07:00
Francois Chollet a86b381424 Update LICENSE with copyright information. 2015-10-14 09:02:22 -07:00
Francois Chollet 5691912701 Update RNN docs 2015-10-13 17:56:06 -07:00
François Chollet cc26bc24a9 Merge pull request #826 from jfsantos/patch-5
Fix #821
2015-10-13 11:41:15 -07:00
João Felipe Santos f62c03bdea Fix #821
`decay` in `SGD` is not a shared value, so it does not have a `get_value` method.
2015-10-13 14:19:50 -04:00
François Chollet 40a9bd7c2f Merge pull request #819 from xingdi-eric-yuan/master
Bug fixes:
2015-10-12 20:15:13 -07:00
Xingdi (Eric) Yuan 38a3228999 Bug fixes:
“TypeError: Cannot cast ufunc subtract output from dtype('float64') to
dtype('uint8') with casting rule 'same_kind'” in
keras/preprocessing/image.py, line 239, when using data augmentation.
2015-10-12 15:09:25 +08:00
88 arquivos alterados com 5417 adições e 3356 exclusões
+30 -10
Ver Arquivo
@@ -1,22 +1,42 @@
sudo: false
sudo: required
dist: trusty
language: python
# Setup anaconda
before_install:
- wget http://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh
- chmod +x miniconda.sh
- ./miniconda.sh -b
- export PATH=/home/travis/miniconda/bin:$PATH
- conda update --yes conda
python:
- "2.7"
- "3.4"
# command to install dependencies
install:
- conda install --yes python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib pandas pytest h5py
# code below is taken from http://conda.pydata.org/docs/travis.html
# We do this conditionally because it saves us some downloading if the
# version is the same.
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
wget https://repo.continuum.io/miniconda/Miniconda-latest-Linux-x86_64.sh -O miniconda.sh;
else
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh;
fi
- bash miniconda.sh -b -p $HOME/miniconda
- export PATH="$HOME/miniconda/bin:$PATH"
- hash -r
- conda config --set always_yes yes --set changeps1 no
- conda update -q conda
# Useful for debugging any issues with conda
- conda info -a
- conda create -q -n test-environment python=$TRAVIS_PYTHON_VERSION numpy scipy matplotlib pandas pytest h5py
- source activate test-environment
- pip install pytest-cov python-coveralls
- pip install git+git://github.com/Theano/Theano.git
- python setup.py install
# install TensorFlow
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.5.0-cp27-none-linux_x86_64.whl;
fi
# command to run tests
script:
- PYTHONPATH=$PWD:$PYTHONPATH py.test -v --cov-report term-missing --cov keras tests/
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
sed -i -e 's/theano/tensorflow/g' ~/.keras/keras.json;
PYTHONPATH=$PWD:$PYTHONPATH py.test -v --cov-report term-missing --cov keras tests/;
fi
after_success:
- coveralls
+19 -2
Ver Arquivo
@@ -1,6 +1,23 @@
The MIT License (MIT)
COPYRIGHT
Copyright (c) 2015
All contributions by François Chollet:
Copyright (c) 2015, François Chollet.
All rights reserved.
All contributions by Google:
Copyright (c) 2015, Google, Inc.
All rights reserved.
All other contributions:
Copyright (c) 2015, the respective contributors.
All rights reserved.
Each contributor holds copyright over their respective contributions.
The project versioning (Git) records all such contribution source information.
LICENSE
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+106 -168
Ver Arquivo
@@ -1,8 +1,8 @@
# Keras: Theano-based Deep Learning library
# Keras: Deep Learning library for Theano and TensorFlow
## You have just found Keras.
Keras is a minimalist, highly modular neural network library in the spirit of Torch, written in Python / Theano so as not to have to deal with the dearth of ecosystem in Lua. It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.
Keras is a minimalist, highly modular neural networks library, written in Python and capable of running either on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.
Use Keras if you need a deep learning library that:
- allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
@@ -12,200 +12,92 @@ Use Keras if you need a deep learning library that:
Read the documentation at [Keras.io](http://keras.io).
Keras is compatible with __Python 2.7-3.4__.
Keras is compatible with:
- __Python 2.7-3.5__ with the Theano backend
- __Python 2.7__ with the TensorFlow backend
------------------
## Guiding principles
- __Modularity.__ A model is understood as a sequence or a graph of standalone, fully-configurable modules that can be plugged together with as little restrictions as possible. In particular, neural layers, cost functions, optimizers, initialization schemes, activation functions, regularization schemes are all standalone modules that you can combine to create new models.
- __Minimalism.__ Each module should be kept short and simple (<100 lines of code). Every piece of code should be transparent upon first reading. No black magic: it hurts iteration speed and ability to innovate.
- __Minimalism.__ Each module should be kept short and simple. Every piece of code should be transparent upon first reading. No black magic: it hurts iteration speed and ability to innovate.
- __Easy extensibility.__ New modules are dead simple to add (as new classes/functions), and existing modules provide ample examples. To be able to easily create new modules allows for total expressiveness, making Keras suitable for advanced research.
- __Easy extensibility.__ New modules are dead simple to add (as new classes and functions), and existing modules provide ample examples. To be able to easily create new modules allows for total expressiveness, making Keras suitable for advanced research.
- __Work with Python__. No separate models configuration files in a declarative format (like in Caffe or PyLearn2). Models are described in Python code, which is compact, easier to debug, and allows for ease of extensibility.
- __Work with Python__. No separate models configuration files in a declarative format. Models are described in Python code, which is compact, easier to debug, and allows for ease of extensibility.
## Examples
### Multilayer Perceptron (MLP):
------------------
## Getting started: 30 seconds to Keras
The core datastructure of Keras is a __model__, a way to organize layers. There are two types of models: [`Sequential`](/models/#sequential) and [`Graph`](/models/#graph).
Here's the `Sequential` model (a linear pile of layers):
```python
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
model = Sequential()
```
Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100, init="glorot_uniform"))
model.add(Activation("relu"))
model.add(Dense(output_dim=10, init="glorot_uniform"))
model.add(Activation("softmax"))
```
Once your model looks good, configure its learning process with `.compile()`:
```python
model.compile(loss='categorical_crossentropy', optimizer='sgd')
```
If you need to, you can further configure your optimizer. A core principle of Keras is to make things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).
```python
from keras.optimizers import SGD
model = Sequential()
# Dense(64) is a fully-connected layer with 64 hidden units.
# in the first layer, you must specify the expected input data shape:
# here, 20-dimensional vectors.
model.add(Dense(64, input_dim=20, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform'))
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform'))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
model.fit(X_train, y_train, nb_epoch=20, batch_size=16)
score = model.evaluate(X_test, y_test, batch_size=16)
model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True))
```
### Alternative implementation of MLP:
You can now iterate on your training data in batches:
```python
model = Sequential()
model.add(Dense(64, input_dim=20, init='uniform', activation='tanh'))
model.add(Dropout(0.5))
model.add(Dense(64, init='uniform', activation='tanh'))
model.add(Dropout(0.5))
model.add(Dense(2, init='uniform', activation='softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mean_squared_error', optimizer=sgd)
model.fit(X_train, Y_train, nb_epoch=5, batch_size=32)
```
### VGG-like convnet:
Alternatively, you can feed batches to your model manually:
```python
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.optimizers import SGD
model = Sequential()
# input: 100x100 images with 3 channels -> (3, 100, 100) tensors.
# this applies 32 convolution filters of size 3x3 each.
model.add(Convolution2D(32, 3, 3, border_mode='full', input_shape=(3, 100, 100)))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, border_mode='valid'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
# Note: Keras does automatic shape inference.
model.add(Dense(256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(10))
model.add(Activation('softmax'))
sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
model.fit(X_train, Y_train, batch_size=32, nb_epoch=1)
model.train_on_batch(X_batch, Y_batch)
```
### Sequence classification with LSTM:
Evaluate your performance in one line:
```python
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
model = Sequential()
model.add(Embedding(max_features, 256, input_length=maxlen))
model.add(LSTM(output_dim=128, activation='sigmoid', inner_activation='hard_sigmoid'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop')
model.fit(X_train, Y_train, batch_size=16, nb_epoch=10)
score = model.evaluate(X_test, Y_test, batch_size=16)
objective_score = model.evaluate(X_test, Y_test, batch_size=32)
```
### Architecture for learning image captions with a convnet and a Gated Recurrent Unit:
(word-level embedding, caption of maximum length 16 words).
Note that getting this to work well will require using a bigger convnet, initialized with pre-trained weights.
Or generate predictions on new data:
```python
max_caption_len = 16
vocab_size = 10000
# first, let's define an image model that
# will encode pictures into 128-dimensional vectors.
# it should be initialized with pre-trained weights.
image_model = Sequential()
image_model.add(Convolution2D(32, 3, 3, border_mode='full', input_shape=(3, 100, 100)))
image_model.add(Activation('relu'))
image_model.add(Convolution2D(32, 3, 3))
image_model.add(Activation('relu'))
image_model.add(MaxPooling2D(pool_size=(2, 2)))
image_model.add(Convolution2D(64, 3, 3, border_mode='full'))
image_model.add(Activation('relu'))
image_model.add(Convolution2D(64, 3, 3))
image_model.add(Activation('relu'))
image_model.add(MaxPooling2D(pool_size=(2, 2)))
image_model.add(Flatten())
image_model.add(Dense(128))
# let's load the weights from a save file.
image_model.load_weights('weight_file.h5')
# next, let's define a RNN model that encodes sequences of words
# into sequences of 128-dimensional word vectors.
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(Dense(128))
# let's repeat the image vector to turn it into a sequence.
image_model.add(RepeatVector(max_caption_len))
# the output of both models will be tensors of shape (samples, max_caption_len, 128).
# let's concatenate these 2 vector sequences.
model = Merge([image_model, language_model], mode='concat', concat_axis=-1)
# let's encode this vector sequence into a single vector
model.add(GRU(256, 256, return_sequences=False))
# which will be used to compute a probability
# distribution over what the next word in the caption should be!
model.add(Dense(vocab_size))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
# "images" is a numpy float array of shape (nb_samples, nb_channels=3, width, height).
# "captions" is a numpy integer array of shape (nb_samples, max_caption_len)
# containing word index sequences representing partial captions.
# "next_words" is a numpy float array of shape (nb_samples, vocab_size)
# containing a categorical encoding (0s and 1s) of the next word in the corresponding
# partial caption.
model.fit([images, partial_captions], next_words, batch_size=16, nb_epoch=100)
classes = model.predict_classes(X_test, batch_size=32)
proba = model.predict_proba(X_test, batch_size=32)
```
In the examples folder, you will find example models for real datasets:
- CIFAR10 small images classification: Convolutional Neural Network (CNN) with realtime data augmentation
- IMDB movie review sentiment classification: LSTM over sequences of words
- Reuters newswires topic classification: Multilayer Perceptron (MLP)
- MNIST handwritten digits classification: MLP & CNN
- Character-level text generation with LSTM
Building a network of LSTMs, a deep CNN, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
...and more.
Have a look at these [starter examples](http://keras.io/examples/).
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repo, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, neural turing machines, etc.
## Current capabilities
------------------
For complete coverage of the API, check out [the Keras documentation](http://keras.io).
A few highlights: convnets, LSTM, GRU, word2vec-style embeddings, PReLU, BatchNormalization...
## Installation
@@ -213,11 +105,22 @@ Keras uses the following dependencies:
- numpy, scipy
- pyyaml
- Theano
- See installation instructions: http://deeplearning.net/software/theano/install.html#install
- HDF5 and h5py (optional, required if you use model saving/loading functions)
- Optional but recommended if you use CNNs: cuDNN.
When using the Theano backend:
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
**Note**: You should use the latest version of Theano, not the PyPI version. Install it with:
```
sudo pip install git+git://github.com/Theano/Theano.git
```
When using the TensorFlow backend:
- TensorFlow
- [See installation instructions](https://github.com/tensorflow/tensorflow#download-and-setup).
To install, `cd` to the Keras folder and run the install command:
```
sudo python setup.py install
@@ -228,10 +131,45 @@ You can also install Keras from PyPI:
sudo pip install keras
```
------------------
## Switching from Theano to TensorFlow
By default, Keras will use Theano as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
------------------
## Support
You can ask questions and join the development discussion on the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
------------------
## Contribution Guidelines
Keras welcomes all contributions from the community.
- Keep a pragmatic mindset and avoid bloat. Only add to the source if that is the only path forward.
- New features should be documented. Make sure you update the documentation along with your Pull Request.
- Any new function or class should have a proper docstring.
- The documentation for every new feature should include a usage example in the form of a code snippet.
- All changes should be tested. Make sure any new feature you add has a corresponding unit test.
- Please no Pull Requests about coding style.
- Even if you don't contribute to the Keras source code, if you have an application of Keras that is concise and powerful, please consider adding it to our collection of [examples](https://github.com/fchollet/keras/tree/master/examples).
------------------
## Why this name, Keras?
Keras (κέρας) means _horn_ in Greek. It is a reference to a literary image from ancient Greek and Latin literature, first found in the _Odyssey_, where dream spirits (_Oneiroi_, singular _Oneiros_) are divided between those who deceive men with false visions, who arrive to Earth through a gate of ivory, and those who announce a future that will come to pass, who arrive through a gate of horn. It's a play on the words κέρας (horn) / κραίνω (fulfill), and ἐλέφας (ivory) / ἐλεφαίρομαι (deceive).
Keras was developed as part of the research effort of project ONEIROS (Open-ended Neuro-Electronic Intelligent Robot Operating System).
Keras was initially developed as part of the research effort of project ONEIROS (Open-ended Neuro-Electronic Intelligent Robot Operating System).
>_"Oneiroi are beyond our unravelling --who can be sure what tale they tell? Not all that men look for comes to pass. Two gates there are that give passage to fleeting Oneiroi; one is made of horn, one of ivory. The Oneiroi that pass through sawn ivory are deceitful, bearing a message that will not be fulfilled; those that come out through polished horn have truth behind them, to be accomplished for men who see them."_ Homer, Odyssey 19. 562 ff (Shewring translation).
------------------
+1
Ver Arquivo
@@ -24,6 +24,7 @@ pages:
- Constraints: constraints.md
- Callbacks: callbacks.md
- Datasets: datasets.md
- Visualization: visualization.md
- Layers:
- Core Layers: layers/core.md
- Convolutional Layers: layers/convolutional.md
+74
Ver Arquivo
@@ -0,0 +1,74 @@
# Keras backends
## What is a "backend"?
Keras is a model-level library, providing high-level building blocks for developing deep learning models. It does not handle itself low-level operations such as tensor products, convolutions and so on. Instead, it relies on a specialized, well-optimized tensor manipulation library to do so, serving as the "backend engine" of Keras. Rather than picking one single tensor library and making the implementation of Keras tied to that library, Keras handles the problem in a modular way, and several different backend engines can be plugged seamlessly into Keras.
At this time, Keras has two backend implementations available: the **Theano** backend and the **TensorFlow** backend.
- [Theano](http://deeplearning.net/software/theano/) is an open-source symbolic tensor manipulation framework developed by LISA/MILA Lab at Université de Montréal.
- [TensorFlow](http://www.tensorflow.org/) is an open-source symbolic tensor manipulation framework developed by Google, Inc.
## Switching from one backend to another
If you have run Keras at least once, you will find the Keras configuration file at:
`~/.keras/keras.json`
If it isn't there, you can create it.
It probably looks like this:
`{"epsilon": 1e-07, "floatx": "float32", "backend": "theano"}`
Simply change the field `backend` to either `"theano"` or `"tensorflow"`, and Keras will use the new configuration next time you run any Keras code.
## Using the abstract Keras backend to write new code
If you want the Keras modules you write to be compatible with both Theano and TensorFlow, you have to write them via the abstract Keras backend API. Here's an intro.
You can import the backend module via:
```python
from keras import backend as K
```
This instantiates an input placeholder. It's equivalent to `tf.placeholder()` or `T.matrix()`, `T.tensor3()`, etc.
```python
input = K.placeholder(shape=(2, 4, 5))
# also works:
input = K.placeholder(shape=(None, 4, 5))
# also works:
input = K.placeholder(ndim=3)
```
This instantiates a shared variable. It's equivalent to `tf.variable()` or `theano.shared()`.
```python
val = np.random.random((3, 4, 5))
var = K.variable(value=val)
# all-zeros variable:
var = K.ones(shape=(3, 4, 5))
# all-ones:
var = K.zeros(shape=(3, 4, 5))
```
Most tensor operations you will need can be done as you would in TensorFlow or Theano:
```python
a = b + c * K.abs(d)
c = K.dot(a, K.transpose(b))
a = K.sum(b, axis=2)
a = K.softmax(b)
a = concatenate([b, c], axis=-1)
# etc...
```
For more information, see the code at `keras/backend/theano_backend.py` and `keras/backend/tensorflow_backend.py`.
+1
Ver Arquivo
@@ -6,6 +6,7 @@
- [Index](documentation.md)
- [Examples](examples.md)
- [FAQ](faq.md)
- [Backend](backend.md)
---
+1 -1
Ver Arquivo
@@ -140,7 +140,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(Dense(128))
language_model.add(TimeDistributedDense(128))
# let's repeat the image vector to turn it into a sequence.
image_model.add(RepeatVector(max_caption_len))
+64 -29
Ver Arquivo
@@ -1,33 +1,38 @@
# Keras: Theano-based Deep Learning library
# Keras: Deep Learning library for Theano and TensorFlow
## Overview
## You have just found Keras.
Keras is a minimalist, highly modular neural network library in the spirit of Torch, written in Python, that uses [Theano](http://deeplearning.net/software/theano/) under the hood for optimized tensor manipulation on GPU and CPU. It was developed with a focus on enabling fast experimentation.
Keras is a minimalist, highly modular neural networks library, written in Python and capable of running either on top of either [TensorFlow](https://github.com/tensorflow/tensorflow) or [Theano](https://github.com/Theano/Theano). It was developed with a focus on enabling fast experimentation. Being able to go from idea to result with the least possible delay is key to doing good research.
Use Keras if you need a deep learning library that:
- allows for easy and fast prototyping (through total modularity, minimalism, and extensibility).
- supports both convolutional networks and recurrent networks, as well as combinations of the two.
- supports arbitrary connectivity schemes (including multi-input and multi-output training).
- runs seamlessly on CPU and GPU.
Read the documentation at [Keras.io](http://keras.io).
Keras is compatible with:
- __Python 2.7-3.5__ with the Theano backend
- __Python 2.7__ with the TensorFlow backend
------------------
## Guiding principles
- __Modularity.__ A model is understood as a sequence or a graph of standalone, fully-configurable modules that can be plugged together with as little restrictions as possible. In particular, neural layers, cost functions, optimizers, initialization schemes, activation functions, regularization schemes are all standalone modules that you can combine to create new models.
- __Minimalism.__ Each module should be kept short and simple (<100 lines of code). Every piece of code should be transparent upon first reading. No black magic: it hurts iteration speed and ability to innovate.
- __Minimalism.__ Each module should be kept short and simple. Every piece of code should be transparent upon first reading. No black magic: it hurts iteration speed and ability to innovate.
- __Easy extensibility.__ New modules are dead simple to add (as new classes/functions), and existing modules provide ample examples. To be able to easily create new modules allows for total expressiveness, making Keras suitable for advanced research.
- __Easy extensibility.__ New modules are dead simple to add (as new classes and functions), and existing modules provide ample examples. To be able to easily create new modules allows for total expressiveness, making Keras suitable for advanced research.
- __Work with Python__. No separate models configuration files in a declarative format (like in Caffe or PyLearn2). Models are described in Python code, which is compact, easier to debug, and allows for ease of extensibility.
- __Work with Python__. No separate models configuration files in a declarative format. Models are described in Python code, which is compact, easier to debug, and allows for ease of extensibility.
## Code
Find the code on Github: [fchollet/keras](https://github.com/fchollet/keras).
------------------
## License
Keras is licensed under the [MIT license](http://opensource.org/licenses/MIT).
## Getting started: 30 seconds to Keras
@@ -57,7 +62,7 @@ Once your model looks good, configure its learning process with `.compile()`:
model.compile(loss='categorical_crossentropy', optimizer='sgd')
```
If you need to, you can further configure your optimizer. A core principle of Keras is make things things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).
If you need to, you can further configure your optimizer. A core principle of Keras is to make things reasonably simple, while allowing the user to be fully in control when they need to (the ultimate control being the easy extensibility of the source code).
```python
from keras.optimizers import SGD
model.compile(loss='categorical_crossentropy', optimizer=SGD(lr=0.01, momentum=0.9, nesterov=True))
@@ -86,55 +91,85 @@ proba = model.predict_proba(X_test, batch_size=32)
Building a network of LSTMs, a deep CNN, a Neural Turing Machine, a word2vec embedder or any other model is just as fast. The ideas behind deep learning are simple, so why should their implementation be painful?
Have a look at the [examples](examples.md).
Have a look at these [starter examples](http://keras.io/examples/).
In the [examples folder](https://github.com/fchollet/keras/tree/master/examples) of the repo, you will find more advanced models: question-answering with memory networks, text generation with stacked LSTMs, neural turing machines, etc.
------------------
## Installation
Keras uses the following dependencies:
- __numpy__, __scipy__
- __pyyaml__
- __Theano__
- See [installation instructions](http://deeplearning.net/software/theano/install.html#install).
- __HDF5__ and __h5py__ (optional, required if you use model saving/loading functions)
- Optional but recommended if you use CNNs: __cuDNN__.
- numpy, scipy
- pyyaml
- HDF5 and h5py (optional, required if you use model saving/loading functions)
- Optional but recommended if you use CNNs: cuDNN.
Once you have the dependencies installed, clone the repo:
```bash
git clone https://github.com/fchollet/keras.git
When using the Theano backend:
- Theano
- [See installation instructions](http://deeplearning.net/software/theano/install.html#install).
**Note**: You should use the latest version of Theano, not the PyPI version. Install it with:
```
sudo pip install git+git://github.com/Theano/Theano.git
```
When using the TensorFlow backend:
- TensorFlow
- [See installation instructions](https://github.com/tensorflow/tensorflow#download-and-setup).
To install, `cd` to the Keras folder and run the install command:
```
Go to the Keras folder and run the install command:
```bash
cd keras
sudo python setup.py install
```
You can also install Keras from PyPI:
```
sudo pip install keras
```
------------------
## Switching from Theano to TensorFlow
By default, Keras will use Theano as its tensor manipulation library. [Follow these instructions](http://keras.io/backend/) to configure the Keras backend.
------------------
## Support
You can ask questions and join the development discussion on the [Keras Google group](https://groups.google.com/forum/#!forum/keras-users).
------------------
## Contribution Guidelines
Keras welcomes all contributions from the community.
- Keep a pragmatic mindset and avoid bloat. Only add to the source if that is the only path forward.
- New features should be documented. Make sure you update the documentation along with your Pull Request.
- Any new function or class should have a proper docstring.
- The documentation for every new feature should include a usage example in the form of a code snippet.
- All changes should be tested. Make sure any new feature you add has a corresponding unit test.
- Please no Pull Requests about coding style.
- Even if you don't contribute to the Keras source code, if you have an application of Keras that is concise and powerful, please consider adding it to our collection of [examples](https://github.com/fchollet/keras/tree/master/examples).
------------------
## Why this name, Keras?
Keras (κέρας) means _horn_ in Greek. It is a reference to a literary image from ancient Greek and Latin literature, first found in the _Odyssey_, where dream spirits (_Oneiroi_, singular _Oneiros_) are divided between those who deceive men with false visions, who arrive to Earth through a gate of ivory, and those who announce a future that will come to pass, who arrive through a gate of horn. It's a play on the words κέρας (horn) / κραίνω (fulfill), and ἐλέφας (ivory) / ἐλεφαίρομαι (deceive).
Keras was developed as part of the research effort of project __ONEIROS__ (*Open-ended Neuro-Electronic Intelligent Robot Operating System*).
Keras was initially developed as part of the research effort of project ONEIROS (Open-ended Neuro-Electronic Intelligent Robot Operating System).
> _"Oneiroi are beyond our unravelling --who can be sure what tale they tell? Not all that men look for comes to pass. Two gates there are that give passage to fleeting Oneiroi; one is made of horn, one of ivory. The Oneiroi that pass through sawn ivory are deceitful, bearing a message that will not be fulfilled; those that come out through polished horn have truth behind them, to be accomplished for men who see them."_
>_"Oneiroi are beyond our unravelling --who can be sure what tale they tell? Not all that men look for comes to pass. Two gates there are that give passage to fleeting Oneiroi; one is made of horn, one of ivory. The Oneiroi that pass through sawn ivory are deceitful, bearing a message that will not be fulfilled; those that come out through polished horn have truth behind them, to be accomplished for men who see them."_ Homer, Odyssey 19. 562 ff (Shewring translation).
> -- Homer, Odyssey 19. 562 ff (Shewring translation).
------------------
+18
Ver Arquivo
@@ -35,6 +35,24 @@ Parametrized linear unit. Similar to a LeakyReLU, where each input unit has its
---
## ELU
```python
keras.layers.advanced_activations.ELU()
```
Exponential linear unit. Negative values pushes mean unit activations closer to zero, with the advantage of having a noise-robust deactivation state.
- __Input shape__: Arbitrary. Use the keyword argument `input_shape` (tuple of integers, does not include the samples axis) when using this layer as the first layer in a model.
- __Output shape__: Same as input.
- __References__:
- [Fast and Accurate Deep Network Learning by Exponential Linear Units (ELUs)](http://arxiv.org/pdf/1511.07289v1.pdf)
---
## ParametricSoftplus
```python
+121 -22
Ver Arquivo
@@ -3,17 +3,21 @@
```python
keras.layers.convolutional.Convolution1D(nb_filter, filter_length,
init='uniform', activation='linear', weights=None,
border_mode='valid', subsample_length=1,
W_regularizer=None, b_regularizer=None, W_constraint=None,
b_constraint=None, input_dim=None, input_length=None)
init='uniform',
activation='linear',
weights=None,
border_mode='valid',
subsample_length=1,
W_regularizer=None, b_regularizer=None,
W_constraint=None, b_constraint=None,
input_dim=None, input_length=None)
```
Convolution operator for filtering neighborhoods of one-dimensional inputs. 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).
- __Input shape__: 3D tensor with shape: `(nb_samples, steps, input_dim)`.
- __Input shape__: 3D tensor with shape: `(samples, steps, input_dim)`.
- __Output shape__: 3D tensor with shape: `(nb_samples, steps, nb_filter)`. `steps` value might have changed due to padding.
- __Output shape__: 3D tensor with shape: `(samples, new_steps, nb_filter)`. `steps` value might have changed due to padding.
- __Arguments__:
- __nb_filter__: Number of convolution kernels to use (dimensionality of the output).
@@ -21,7 +25,7 @@ Convolution operator for filtering neighborhoods of one-dimensional inputs. When
- __init__: name of initialization function for the weights of the layer (see: [initializations](../initializations.md)), or alternatively, Theano function to use for weights initialization. This parameter is only relevant if you don't pass a `weights` argument.
- __activation__: name of activation function to use (see: [activations](../activations.md)), or alternatively, elementwise Theano function. If you don't specify anything, no activation is applied (ie. "linear" activation: a(x) = x).
- __weights__: list of numpy arrays to set as initial weights.
- __border_mode__: 'valid' or 'full'. see scipy.signal.convolve2d.
- __border_mode__: 'valid' or 'same'.
- __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.
@@ -37,16 +41,23 @@ Convolution operator for filtering neighborhoods of one-dimensional inputs. When
```python
keras.layers.convolutional.Convolution2D(nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
W_regularizer=None, b_regularizer=None, W_constraint=None)
init='glorot_uniform',
activation='linear',
weights=None,
border_mode='valid',
subsample=(1, 1),
W_regularizer=None, b_regularizer=None,
W_constraint=None,
dim_ordering='th')
```
Convolution operator for filtering windows of two-dimensional inputs. 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.
- __Input shape__: 4D tensor with shape: `(nb_samples, channels, rows, cols)`.
- __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, nb_filter, rows, cols)`. `rows`, `cols` might have changed due to padding.
- __Output shape__: 4D tensor with shape: `(samples, nb_filter, nb_row, nb_col)` if dim_ordering='th'
or 4D tensor with shape: `(samples, nb_row, nb_col, nb_filter)` if dim_ordering='tf'.
- __Arguments__:
@@ -57,13 +68,14 @@ Convolution operator for filtering windows of two-dimensional inputs. When using
- __init__: name of initialization function for the weights of the layer (see: [initializations](../initializations.md)), or alternatively, Theano function to use for weights initialization. This parameter is only relevant if you don't pass a `weights` argument.
- __activation__: name of activation function to use (see: [activations](../activations.md)), or alternatively, elementwise Theano function. If you don't specify anything, no activation is applied (ie. "linear" activation: a(x) = x).
- __weights__: list of numpy arrays to set as initial weights.
- __border_mode__: 'valid', 'full', or 'same'. [See scipy.signal.convolve2d](http://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.convolve2d.html).
- __border_mode__: 'valid' or 'same'.
- __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.
---
@@ -71,33 +83,120 @@ Convolution operator for filtering windows of two-dimensional inputs. When using
## MaxPooling1D
```python
keras.layers.convolutional.MaxPooling1D(pool_length=2, stride=None, ignore_border=True)
keras.layers.convolutional.MaxPooling1D(pool_length=2, stride=None, border_mode='valid')
```
- __Input shape__: 3D tensor with shape: `(nb_samples, steps, dim)`.
Max pooling operation for temporal data.
- __Output shape__: 3D tensor with shape: `(nb_samples, downsampled_steps, dim)`.
- __Input shape__: 3D tensor with shape: `(samples, steps, features)`.
- __Output shape__: 3D tensor with shape: `(samples, downsampled_steps, features)`.
- __Arguments__:
- __pool_length__: factor by which to downscale. 2 will halve the input.
- __stride__: integer or None. Stride value.
- __ignore_border__: boolean.
- __border_mode__: 'valid' or 'same'. **Note:** 'same' will only work with TensorFlow for the time being.
---
## MaxPooling2D
```python
keras.layers.convolutional.MaxPooling2D(pool_size=(2, 2), ignore_border=True)
keras.layers.convolutional.MaxPooling2D(pool_size=(2, 2), border_mode='valid', dim_ordering='th')
```
- __Input shape__: 4D tensor with shape: `(nb_samples, stack_size, nb_row, nb_col)`.
Max pooling operation for spatial data.
- __Output shape__: 4D tensor with shape: `(nb_samples, stack_size, new_nb_row, new_nb_col)`.
- __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'.
- __Arguments__:
- __pool_size__: factor by which to downscale (vertical ds, horizontal ds). (2, 2) will halve the image in each dimension.
- __ignore_border__: boolean. When True, (5, 5) input with pool_size=(2, 2) will generate a (2, 2) output, (3, 3) otherwise.
- __pool_size__: tuple of 2 integers, factors by which to downscale (vertical, horizontal). (2, 2) will halve the image in each dimension.
- __strides__: tuple of 2 integers, or None. Strides values.
- __border_mode__: 'valid' or 'same'. **Note:** 'same' will only work with TensorFlow for the time being.
- __dim_ordering__: 'th' or 'tf'. In 'th' mode, the channels dimension (the depth) is at index 1, in 'tf' mode is it at index 3.
---
## UpSampling1D
```python
keras.layers.convolutional.UpSampling1D(length=2)
```
Repeats each temporal step `length` times along the time axis.
- __Input shape__: 3D tensor with shape: `(samples, steps, features)`.
- __Output shape__: 3D tensor with shape: `(samples, upsampled_steps, features)`.
- __Arguments__:
- __length__: integer. Upsampling factor.
---
## UpSampling2D
```python
keras.layers.convolutional.UpSampling2D(size=(2, 2), dim_ordering='th')
```
Repeats the rows and columns of the data by size[0] and size[1] respectively.
- __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, channels, upsampled_rows, upsampled_cols)` if dim_ordering='th'
or 4D tensor with shape: `(samples, upsampled_rows, upsampled_cols, channels)` if dim_ordering='tf'.
- __Arguments__:
- __size__: tuple of 2 integers. The upsampling factors for rows and columns.
- __dim_ordering__: 'th' or 'tf'. In 'th' mode, the channels dimension (the depth) is at index 1, in 'tf' mode is it at index 3.
---
## ZeroPadding1D
```python
keras.layers.convolutional.ZeroPaddding1D(padding=1)
```
Pads the input with zeros left and right along the time axis.
- __Input shape__: 3D tensor with shape: `(nb_samples, steps, dim)`.
- __Output shape__: 3D tensor with shape: `(nb_samples, padded_steps, dim)`.
- __Arguments__:
- __padding__: integer, the size of the padding.
---
## ZeroPadding2D
```python
keras.layers.convolutional.ZeroPaddding2D(padding=(1, 1), dim_ordering='th')
```
Pads the rows and columns of the input with zeros, left and right.
- __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, channels, padded_rows, padded_cols)` if dim_ordering='th'
or 4D tensor with shape: `(samples, padded_rows, padded_cols, channels)` if dim_ordering='tf'.
- __Arguments__:
- __padding__: tuple of 2 integers, the size of the padding for rows and columns respectively.
- __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.
---
+112 -11
Ver Arquivo
@@ -76,9 +76,13 @@ get_config()
## Dense
```python
keras.layers.core.Dense(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)
keras.layers.core.Dense(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)
```
Standard 1D fully-connect layer.
@@ -104,9 +108,13 @@ Standard 1D fully-connect layer.
## TimeDistributedDense
```python
keras.layers.core.TimeDistributedDense(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)
keras.layers.core.TimeDistributedDense(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)
```
Fully-connected layer distributed over the time dimension. Useful after a recurrent network set to `return_sequences=True`.
@@ -300,9 +308,12 @@ This layer can be used, for instance, to induce activation sparsity in the previ
## MaxoutDense
```python
keras.layers.core.MaxoutDense(output_dim, nb_feature=4, init='glorot_uniform', weights=None,
keras.layers.core.MaxoutDense(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)
W_constraint=None, b_constraint=None,
input_dim=None)
```
A dense maxout layer. A `MaxoutDense` layer takes the element-wise maximum of `nb_feature` `Dense(input_dim, output_dim)` linear layers. This allows the layer to learn a convex, piecewise linear activation function over the inputs. See [this paper](http://arxiv.org/pdf/1302.4389.pdf) for more details. Note that this is a *linear* layer -- if you wish to apply activation function (you shouldn't need to -- they are universal function approximators), an `Activation` layer must be added after.
@@ -332,14 +343,20 @@ model.add(MaxoutDense(50, nb_feature=10)) # output shape: (nb_samples, 50)
## Merge
```python
keras.layers.core.Merge(models, mode='sum')
keras.layers.core.Merge(layers, mode='sum', concat_axis=-1, dot_axes=-1)
```
Merge the output of a list of layers (or containers) into a single tensor, following one of three modes: `sum`, `mul` or `concat`.
Merge the output of a list of layers (or containers) into a single tensor.
- __Arguments__:
- __layers__: List of layers or [containers](/layers/containers/).
- __mode__: String, one of `{'sum', 'mul', 'concat'}`. `sum` and `mul` will simply sum/multiply the outputs of the layers (therefore all layers should have an output with the same shape). `concat` will concatenate the outputs along the last dimension (therefore all layers should have an output that only differ along the last dimension).
- __mode__: String, one of `{'sum', 'mul', 'concat', 'ave', 'dot'}`. `sum`, `mul` and `ave` will simply sum/multiply/average the outputs of the layers (therefore all layers should have an output with the same shape). `concat` will concatenate the outputs along the dimension specified by `concate_axis` (therefore all layers should have an output that only differ along this dimension). `dot` will dot tensor contraction on the axes specified by `dot_axes` (see [the Numpy documentation](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.tensordot.html) for more details).
- __concat_axis__: axis to use in `concat` mode.
- __dot_axes__: axis or axes to use in `dot` mode (see [the Numpy documentation](http://docs.scipy.org/doc/numpy-1.10.1/reference/generated/numpy.tensordot.html) for more details).
- __Notes__:
- `dot` mode only works with Theano for the time being.
- __Example__:
@@ -374,3 +391,87 @@ Given an input of dimensions `(nb_samples, timesteps, input_dim)`, return the in
- __Input shape__: 3D tensor with shape: `(nb_samples, timesteps, features)`.
- __Output shape__: 3D tensor with shape: `(nb_samples, timesteps, features)`.
- __Notes__: Masking only works in Theano for the time being.
## Lambda
```python
keras.layers.core.Lambda(function, output_shape=None)
```
Used for evaluating an arbitrary Theano expression on the output of the previous layer.
- __Input shape__: Arbitrary. Use the keyword argument input_shape (tuple of integers, does not include the samples axis) when using this layer as the first layer in a model.
- __Output shape__: Specified by the `output_shape` argument.
- __Arguments__:
- __function__: The expression to be evaluated. Takes one argument: the output of the previous layer.
- __output_shape__: Shape of the tensor returned by `function`. Should be a shape tuple (not including the samples dimension) or a function of the full input shape tuple (including samples dimension).
- __Example__:
```python
# custom softmax function
def sharp_softmax(X, beta=1.5):
return theano.tensor.nnet.softmax(X * beta)
def output_shape(input_shape):
# here input_shape includes the samples dimension
return input_shape # shape is unchanged
model = Sequential()
model.add(Dense(input_dim=10, output_dim=10))
model.add(Lambda(sharp_softmax, output_shape))
model.add(Dense(1))
model.add(Activation('sigmoid'))
```
## LambdaMerge
```python
keras.layers.core.LambdaMerge(layers, function, output_shape=None)
```
Merge the output of a list of layers (or containers) into a single tensor, using an arbitrary Theano expression.
- __Arguments__:
- __layers__: List of layers or [containers](/layers/containers/).
- __function__: The expression to be evaluated. Takes one argument: the list of input tensors.
- __output_shape__: Shape of the tensor returned by `function`. Should be a shape tuple (not including samples dimension) or a function of the list of input shape tuples (including samples dimension).
- __Example__:
```python
# root mean square function
def rms(inputs):
# inputs is a list of tensors
s = inputs[0] ** 2
for i in range(1, len(inputs)):
s += inputs[i] ** 2
s /= len(inputs)
s = theano.tensor.sqrt(s)
# return a single tensor
return s
def output_shape(input_shapes):
# return the shape of the first tensor
return input_shapes[0]
left = Sequential()
left.add(Dense(input_dim=10, output_dim=10))
left.add(Activation('sigmoid'))
right = Sequential()
right.add(Dense(input_dim=10, output_dim=10))
right.add(Activation('sigmoid'))
model = Sequential()
model.add(LambdaMerge([left, right], rms, output_shape))
model.add(Dense(1))
model.add(Activation('sigmoid'))
```
---
+8 -27
Ver Arquivo
@@ -2,7 +2,12 @@
## Embedding
```python
keras.layers.embeddings.Embedding(input_dim, output_dim, init='uniform', input_length=None, weights=None, W_regularizer=None, W_constraint=None, mask_zero=False)
keras.layers.embeddings.Embedding(input_dim, output_dim,
init='uniform',
weights=None,
W_regularizer=None, W_constraint=None,
mask_zero=False,
input_length=None)
```
Turn positive integers (indexes) into denses vectors of fixed size,
@@ -14,7 +19,7 @@ eg. `[[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]`
- __Arguments__:
- __input_dim__: int >= 0. Size of the vocabulary, ie. 1+maximum integer index occuring in the input data.
- __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. The list should have 1 element, of shape `(input_dim, output_dim)`.
@@ -23,28 +28,4 @@ eg. `[[4], [20]] -> [[0.25, 0.1], [0.6, -0.2]]`
- __mask_zero__: Whether or not the input value 0 is a special "padding" value that should be masked out. 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.
- __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).
## WordContextProduct
```python
keras.layers.embeddings.WordContextProduct(input_dim, proj_dim=128,
init='uniform', activation='sigmoid', weights=None)
```
This layer turns a pair of words (a pivot word + a context word, ie. a word from the same context as a pivot, or a random, out-of-context word), indentified by their indices in a vocabulary, into two dense reprensentations (word representation and context representation).
Then it returns `activation(dot(pivot_embedding, context_embedding))`, which can be trained to encode the probability of finding the context word in the context of the pivot word (or reciprocally depending on your training procedure).
For more context, see Mikolov et al.: [Efficient Estimation of Word reprensentations in Vector Space](http://arxiv.org/pdf/1301.3781v3.pdf)
- __Input shape__: 2D tensor with shape: `(nb_samples, 2)`.
- __Output shape__: 2D tensor with shape: `(nb_samples, 1)`.
- __Arguments__:
- __input_dim__: int >= 0. Size of the vocabulary, ie. 1+maximum integer index occuring in the input data.
- __proj_dim__: int >= 0. Dimension of the dense embedding used internally.
- __init__: name of initialization function for the embeddings (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.
- __weights__: list of numpy arrays to set as initial weights. The list should have 2 element, both of shape `(input_dim, proj_dim)`. The first element is the word embedding weights, the second one is the context embedding weights.
---
+34 -96
Ver Arquivo
@@ -2,9 +2,14 @@
## SimpleRNN
```python
keras.layers.recurrent.SimpleRNN(output_dim,
init='glorot_uniform', inner_init='orthogonal', activation='sigmoid', weights=None,
truncate_gradient=-1, return_sequences=False, input_dim=None, input_length=None)
keras.layers.recurrent.SimpleRNN(output_dim,
init='glorot_uniform', inner_init='orthogonal',
activation='sigmoid',
weights=None,
return_sequences=False,
go_backwards=False,
stateful=False,
input_dim=None, input_length=None)
```
Fully connected RNN where output is to fed back to input.
@@ -14,7 +19,9 @@ Fully connected RNN where output is to fed back to input.
- if `return_sequences`: 3D tensor with shape: `(nb_samples, timesteps, output_dim)`.
- else: 2D tensor with shape: `(nb_samples, output_dim)`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to `True`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to `True`. **Note:** for the time being, masking in only supported with Theano.
- __Notes__: When using the TensorFlow backend, the number of timesteps used must be fixed. Make sure to pass an `input_length` int argument or a complete `input_shape` tuple argument.
- __Arguments__:
@@ -22,50 +29,9 @@ Fully connected RNN where output is to fed back to input.
- __init__: weight initialization function. Can be the name of an existing function (str), or a Theano function (see: [initializations](../initializations.md)).
- __activation__: activation function. Can be the name of an existing function (str), or a Theano function (see: [activations](../activations.md)).
- __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,)]`.
- __truncate_gradient__: Number of steps to use in truncated BPTT. See: [Theano "scan"](http://deeplearning.net/software/theano/library/scan.html).
- __return_sequences__: Boolean. Whether to return the last output in the output sequence, or the full sequence.
- __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 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).
---
## SimpleDeepRNN
```python
keras.layers.recurrent.SimpleDeepRNN(output_dim, depth=3,
init='glorot_uniform', inner_init='orthogonal',
activation='sigmoid', inner_activation='hard_sigmoid',
weights=None, truncate_gradient=-1, return_sequences=False,
input_dim=None, input_length=None)
```
Fully connected RNN where the output of multiple timesteps (up to "depth" steps in the past) is fed back to the input:
```
output = activation( W.x_t + b + inner_activation(U_1.h_tm1) + inner_activation(U_2.h_tm2) + ... )
```
Not a particularly useful model, included for demonstration purposes.
- __Input shape__: 3D tensor with shape: `(nb_samples, timesteps, input_dim)`.
- __Output shape__:
- if `return_sequences`: 3D tensor with shape: `(nb_samples, timesteps, output_dim)`.
- else: 2D tensor with shape: `(nb_samples, output_dim)`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to `True`.
- __Arguments__:
- __input_dim__: dimension of the input.
- __output_dim__: dimension of the internal projections and the final output.
- __depth__: int >= 1. Lookback depth (eg. depth=1 is equivalent to SimpleRNN).
- __init__: weight initialization function for the output cell. Can be the name of an existing function (str), or a Theano function (see: [initializations](../initializations.md)).
- __inner_init__: weight initialization function for the inner cells.
- __activation__: activation function for the output. Can be the name of an existing function (str), or a Theano function (see: [activations](../activations.md)).
- __inner_activation__: activation function for the inner cells.
- __weights__: list of numpy arrays to set as initial weights. The list should have depth+2 elements.
- __truncate_gradient__: Number of steps to use in truncated BPTT. See: [Theano "scan"](http://deeplearning.net/software/theano/library/scan.html).
- __return_sequences__: Boolean. Whether to return the last output in the output sequence, or the full sequence.
- __go_backwards__: Boolean (default False). If True, rocess the input sequence backwards.
- __stateful__: Boolean (default False). If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch.
- __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 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).
@@ -75,10 +41,12 @@ Not a particularly useful model, included for demonstration purposes.
## GRU
```python
keras.layers.recurrent.GRU(input_dim, output_dim=128,
keras.layers.recurrent.GRU(output_dim,
init='glorot_uniform', inner_init='orthogonal',
activation='sigmoid', inner_activation='hard_sigmoid',
weights=None, truncate_gradient=-1, return_sequences=False,
return_sequences=False,
go_backwards=False,
stateful=False,
input_dim=None, input_length=None)
```
@@ -90,21 +58,24 @@ Gated Recurrent Unit - Cho et al. 2014.
- if `return_sequences`: 3D tensor with shape: `(nb_samples, timesteps, output_dim)`.
- else: 2D tensor with shape: `(nb_samples, output_dim)`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to true.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to true. **Note:** for the time being, masking in only supported with Theano.
- __Notes__: When using the TensorFlow backend, the number of timesteps used must be fixed. Make sure to pass an `input_length` int argument or a complete `input_shape` tuple argument.
- __Arguments__:
- __input_dim__: dimension of the input.
- __output_dim__: dimension of the internal projections and the final output.
- __init__: weight initialization function for the output cell. Can be the name of an existing function (str), or a Theano function (see: [initializations](../initializations.md)).
- __inner_init__: weight initialization function for the inner cells.
- __activation__: activation function for the output. Can be the name of an existing function (str), or a Theano function (see: [activations](../activations.md)).
- __inner_activation__: activation function for the inner cells.
- __weights__: list of numpy arrays to set as initial weights. The list should have 9 elements.
- __truncate_gradient__: Number of steps to use in truncated BPTT. See: [Theano "scan"](http://deeplearning.net/software/theano/library/scan.html).
- __return_sequences__: Boolean. Whether to return the last output in the output sequence, or the full sequence.
- __go_backwards__: Boolean (default False). If True, rocess the input sequence backwards.
- __stateful__: Boolean (default False). If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch.
- __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 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).
- __References__:
- [On the Properties of Neural Machine Translation: Encoder–Decoder Approaches](http://www.aclweb.org/anthology/W14-4012)
- [Empirical Evaluation of Gated Recurrent Neural Networks on Sequence Modeling](http://arxiv.org/pdf/1412.3555v1.pdf)
@@ -114,10 +85,13 @@ Gated Recurrent Unit - Cho et al. 2014.
## LSTM
```python
keras.layers.recurrent.LSTM(input_dim, output_dim=128,
keras.layers.recurrent.LSTM(output_dim,
init='glorot_uniform', inner_init='orthogonal', forget_bias_init='one',
activation='tanh', inner_activation='hard_sigmoid',
weights=None, truncate_gradient=-1, return_sequences=False,
weights=None,
return_sequences=False,
go_backwards=False,
stateful=False,
input_dim=None, input_length=None)
```
@@ -129,10 +103,11 @@ Long-Short Term Memory unit - Hochreiter 1997.
- if `return_sequences`: 3D tensor with shape: `(nb_samples, timesteps, output_dim)`.
- else: 2D tensor with shape: `(nb_samples, output_dim)`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to true.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to true. **Note:** for the time being, masking in only supported with Theano.
- __Notes__: When using the TensorFlow backend, the number of timesteps used must be fixed. Make sure to pass an `input_length` int argument or a complete `input_shape` tuple argument.
- __Arguments__:
- __input_dim__: dimension of the input.
- __output_dim__: dimension of the internal projections and the final output.
- __init__: weight initialization function for the output cell. Can be the name of an existing function (str), or a Theano function (see: [initializations](../initializations.md)).
- __inner_init__: weight initialization function for the inner cells.
@@ -140,53 +115,16 @@ Long-Short Term Memory unit - Hochreiter 1997.
- __activation__: activation function for the output. Can be the name of an existing function (str), or a Theano function (see: [activations](../activations.md)).
- __inner_activation__: activation function for the inner cells.
- __weights__: list of numpy arrays to set as initial weights. The list should have 12 elements.
- __truncate_gradient__: Number of steps to use in truncated BPTT. See: [Theano "scan"](http://deeplearning.net/software/theano/library/scan.html).
- __return_sequences__: Boolean. Whether to return the last output in the output sequence, or the full sequence.
- __go_backwards__: Boolean (default False). If True, rocess the input sequence backwards.
- __stateful__: Boolean (default False). If True, the last state for each sample at index i in a batch will be used as initial state for the sample of index i in the following batch.
- __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 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).
- __References__:
- [Long short-term memory](http://deeplearning.cs.cmu.edu/pdfs/Hochreiter97_lstm.pdf) (original 1997 paper)
- [Learning to forget: Continual prediction with LSTM](http://www.mitpressjournals.org/doi/pdf/10.1162/089976600300015015)
- [Supervised sequence labelling with recurrent neural networks](http://www.cs.toronto.edu/~graves/preprint.pdf)
---
## JZS1, JZS2, JZS3
```python
keras.layers.recurrent.JZS1(input_dim, output_dim=128,
init='glorot_uniform', inner_init='orthogonal',
activation='tanh', inner_activation='sigmoid',
weights=None, truncate_gradient=-1, return_sequences=False,
input_dim=None, input_length=None)
```
Top 3 RNN architectures evolved from the evaluation of thousands of models. Serves as alternatives to LSTMs and GRUs. Corresponds to `MUT1`, `MUT2`, and `MUT3` architectures described in the paper: An Empirical Exploration of Recurrent Network Architectures, Jozefowicz et al. 2015.
- __Input shape__: 3D tensor with shape: `(nb_samples, timesteps, input_dim)`.
- __Output shape__:
- if `return_sequences`: 3D tensor with shape: `(nb_samples, timesteps, output_dim)`.
- else: 2D tensor with shape: `(nb_samples, output_dim)`.
- __Masking__: This layer supports masking for input data with a variable number of timesteps To introduce masks to your data, use an [Embedding](embeddings.md) layer with the `mask_zero` parameter set to true.
- __Arguments__:
- __input_dim__: dimension of the input.
- __output_dim__: dimension of the internal projections and the final output.
- __init__: weight initialization function for the output cell. Can be the name of an existing function (str), or a Theano function (see: [initializations](../initializations.md)).
- __inner_init__: weight initialization function for the inner cells.
- __activation__: activation function for the output. Can be the name of an existing function (str), or a Theano function (see: [activations](../activations.md)).
- __inner_activation__: activation function for the inner cells.
- __weights__: list of numpy arrays to set as initial weights. The list should have 9 elements.
- __truncate_gradient__: Number of steps to use in truncated BPTT. See: [Theano "scan"](http://deeplearning.net/software/theano/library/scan.html).
- __return_sequences__: Boolean. Whether to return the last output in the output sequence, or the full sequence.
- __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 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).
- __References__:
- [An Empirical Exploration of Recurrent Network Architectures](http://www.jmlr.org/proceedings/papers/v37/jozefowicz15.pdf)
+9 -3
Ver Arquivo
@@ -12,9 +12,8 @@ model = keras.models.Sequential()
- __optimizer__: str (name of optimizer) or optimizer object. See [optimizers](optimizers.md).
- __loss__: str (name of objective function) or objective function. See [objectives](objectives.md).
- __class_mode__: one of "categorical", "binary". This is only used for computing classification accuracy or using the predict_classes method.
- __theano_mode__: A `theano.compile.mode.Mode` ([reference](http://deeplearning.net/software/theano/library/compile/mode.html)) instance controlling specifying compilation options.
- __fit__(X, y, batch_size=128, nb_epoch=100, verbose=1, validation_split=0., validation_data=None, shuffle=True, show_accuracy=False, callbacks=[], class_weight=None, sample_weight=None): Train a model for a fixed number of epochs.
- __Return__: a history dictionary with a record of training loss values at successive epochs, as well as validation loss values (if applicable), accuracy (if applicable), etc.
- __Return__: a history object. It `history` attribute is a record of training loss values at successive epochs, as well as validation loss values (if applicable).
- __Arguments__:
- __X__: data.
- __y__: labels.
@@ -142,12 +141,19 @@ model = keras.models.Graph()
- __input__: str name of the node/input that the node is connected to. Only specify *one* of either `input` or `inputs`.
- __inputs__: list of str names of the node that the node is connected to.
- __merge_mode__: "sum" or "concat". Only applicable if `inputs` list is specified. Merge mode for the different inputs.
- __add_shared_node__(layer, name, inputs=[], merge_mode=None, outputs=[]): Add a shared node connected to `inputs`. A shared node is a layer that will be applied separately to every incoming input, and that uses only one set of weights. The merging operation occurs on the outputs of the layer.
- __Arguments__:
- __layer__: Layer instance.
- __name__: str. unique identifier of the node.
- __inputs__: list of str names of the node that the node is connected to.
- __merge_mode__: Merge mode for the different inputs.
- __outputs__: Optional. List of names for outputs, when merge_mode = None.
- __compile__(optimizer, loss):
- __Arguments__:
- __optimizer__: str (name of optimizer) or optimizer object. See [optimizers](optimizers.md).
- __loss__: dictionary mapping the name(s) of the output(s) to a loss function (string name of objective function or objective function. See [objectives](objectives.md)).
- __fit__(data, batch_size=128, nb_epoch=100, verbose=1, validation_split=0., validation_data=None, shuffle=True, callbacks=[]): Train a model for a fixed number of epochs.
- __Return__: a history dictionary with a record of training loss values at successive epochs, as well as validation loss values (if applicable).
- __Return__: a history object. It `history` attribute is a record of training loss values at successive epochs, as well as validation loss values (if applicable).
- __Arguments__:
- __data__:dictionary mapping input names out outputs names to appropriate numpy arrays. All arrays should contain the same number of samples.
- __batch_size__: int. Number of samples per gradient update.
+1
Ver Arquivo
@@ -19,6 +19,7 @@ For a few examples of such functions, check out the [objectives source](https://
## Available objectives
- __mean_squared_error__ / __mse__
- __root_mean_squared_error__ / __rmse__
- __mean_absolute_error__ / __mae__
- __mean_absolute_percentage_error__ / __mape__
- __mean_squared_logarithmic_error__ / __msle__
+20
Ver Arquivo
@@ -0,0 +1,20 @@
## Model visualization
The `keras.utils.visualize_util` module provides utility functions to plot
a Keras model (using graphviz).
This will plot a graph of the model and save it to a file:
```python
from keras.utils.visualize_util import plot
plot(model, to_file='model.png')
```
You can also directly obtain the `pydot.Graph` object and render it yourself,
for example to show it in an ipython notebook :
```python
from IPython.display import SVG
from keras.utils.visualize_util import to_graph
SVG(to_graph(model).create(prog='dot', format='svg'))
```
+12 -15
Ver Arquivo
@@ -4,6 +4,7 @@ from keras.models import Sequential, slice_X
from keras.layers.core import Activation, TimeDistributedDense, RepeatVector
from keras.layers import recurrent
import numpy as np
from six.moves import range
"""
An implementation of sequence to sequence learning for performing addition
@@ -11,11 +12,6 @@ Input: "535+61"
Output: "596"
Padding is handled by using a repeated sentinel character (space)
By default, the JZS1 recurrent neural network is used
JZS1 was an "evolved" recurrent neural network performing well on arithmetic benchmark in:
"An Empirical Exploration of Recurrent Network Architectures"
http://jmlr.org/proceedings/papers/v37/jozefowicz15.pdf
Input may optionally be inverted, shown to increase performance in many tasks in:
"Learning to Execute"
http://arxiv.org/abs/1410.4615
@@ -25,16 +21,16 @@ http://papers.nips.cc/paper/5346-sequence-to-sequence-learning-with-neural-netwo
Theoretically it introduces shorter term dependencies between source and target.
Two digits inverted:
+ One layer JZS1 (128 HN), 5k training examples = 99% train/test accuracy in 55 epochs
+ One layer LSTM (128 HN), 5k training examples = 99% train/test accuracy in 55 epochs
Three digits inverted:
+ One layer JZS1 (128 HN), 50k training examples = 99% train/test accuracy in 100 epochs
+ One layer LSTM (128 HN), 50k training examples = 99% train/test accuracy in 100 epochs
Four digits inverted:
+ One layer JZS1 (128 HN), 400k training examples = 99% train/test accuracy in 20 epochs
+ One layer LSTM (128 HN), 400k training examples = 99% train/test accuracy in 20 epochs
Five digits inverted:
+ One layer JZS1 (128 HN), 550k training examples = 99% train/test accuracy in 30 epochs
+ One layer LSTM (128 HN), 550k training examples = 99% train/test accuracy in 30 epochs
"""
@@ -74,8 +70,8 @@ class colors:
TRAINING_SIZE = 50000
DIGITS = 3
INVERT = True
# Try replacing JZS1 with LSTM, GRU, or SimpleRNN
RNN = recurrent.JZS1
# Try replacing GRU, or SimpleRNN
RNN = recurrent.LSTM
HIDDEN_SIZE = 128
BATCH_SIZE = 128
LAYERS = 1
@@ -89,7 +85,7 @@ expected = []
seen = set()
print('Generating data...')
while len(questions) < TRAINING_SIZE:
f = lambda: int(''.join(np.random.choice(list('0123456789')) for i in xrange(np.random.randint(1, DIGITS + 1))))
f = lambda: int(''.join(np.random.choice(list('0123456789')) for i in range(np.random.randint(1, DIGITS + 1))))
a, b = f(), f()
# Skip any addition questions we've already seen
# Also skip any such that X+Y == Y+X (hence the sorting)
@@ -122,6 +118,7 @@ indices = np.arange(len(y))
np.random.shuffle(indices)
X = X[indices]
y = y[indices]
# Explicitly set apart 10% for validation data that we never train over
split_at = len(X) - len(X) / 10
(X_train, X_val) = (slice_X(X, 0, split_at), slice_X(X, split_at))
@@ -135,11 +132,11 @@ model = Sequential()
# "Encode" the input sequence using an RNN, producing an output of HIDDEN_SIZE
# note: in a situation where your input sequences have a variable length,
# use input_shape=(None, nb_feature).
model.add(RNN(HIDDEN_SIZE, input_shape=(None, len(chars))))
model.add(RNN(HIDDEN_SIZE, input_shape=(MAXLEN, len(chars))))
# For the decoder's input, we repeat the encoded input for each time step
model.add(RepeatVector(DIGITS + 1))
# The decoder RNN could be multiple layers stacked or a single layer
for _ in xrange(LAYERS):
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
@@ -156,7 +153,7 @@ for iteration in range(1, 200):
model.fit(X_train, y_train, batch_size=BATCH_SIZE, nb_epoch=1, validation_data=(X_val, y_val), show_accuracy=True)
###
# Select 10 samples from the validation set at random so we can visualize errors
for i in xrange(10):
for i in range(10):
ind = np.random.randint(0, len(X_val))
rowX, rowy = X_val[np.array([ind])], y_val[np.array([ind])]
preds = model.predict_classes(rowX, verbose=0)
+203
Ver Arquivo
@@ -0,0 +1,203 @@
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.datasets.data_utils import get_file
from keras.preprocessing.sequence import pad_sequences
from functools import reduce
import tarfile
import numpy as np
import re
"""
Train a memory network on the bAbI dataset.
References:
- Jason Weston, Antoine Bordes, Sumit Chopra, Tomas Mikolov, Alexander M. Rush,
"Towards AI-Complete Question Answering: A Set of Prerequisite Toy Tasks",
http://arxiv.org/abs/1503.08895
- Sainbayar Sukhbaatar, Arthur Szlam, Jason Weston, Rob Fergus,
"End-To-End Memory Networks",
http://arxiv.org/abs/1503.08895
Reaches 93% accuracy on task 'single_supporting_fact_10k' after 70 epochs.
Time per epoch: 3s on CPU (core i7).
"""
def tokenize(sent):
'''Return the tokens of a sentence including punctuation.
>>> tokenize('Bob dropped the apple. Where is the apple?')
['Bob', 'dropped', 'the', 'apple', '.', 'Where', 'is', 'the', 'apple', '?']
'''
return [x.strip() for x in re.split('(\W+)?', sent) if x.strip()]
def parse_stories(lines, only_supporting=False):
'''Parse stories provided in the bAbi tasks format
If only_supporting is true, only the sentences that support the answer are kept.
'''
data = []
story = []
for line in lines:
line = line.decode('utf-8').strip()
nid, line = line.split(' ', 1)
nid = int(nid)
if nid == 1:
story = []
if '\t' in line:
q, a, supporting = line.split('\t')
q = tokenize(q)
substory = None
if only_supporting:
# Only select the related substory
supporting = map(int, supporting.split())
substory = [story[i - 1] for i in supporting]
else:
# Provide all the substories
substory = [x for x in story if x]
data.append((substory, q, a))
story.append('')
else:
sent = tokenize(line)
story.append(sent)
return data
def get_stories(f, only_supporting=False, max_length=None):
'''Given a file name, read the file, retrieve the stories, and then convert the sentences into a single story.
If max_length is supplied, any stories longer than max_length tokens will be discarded.
'''
data = parse_stories(f.readlines(), only_supporting=only_supporting)
flatten = lambda data: reduce(lambda x, y: x + y, data)
data = [(flatten(story), q, answer) for story, q, answer in data if not max_length or len(flatten(story)) < max_length]
return data
def vectorize_stories(data, word_idx, story_maxlen, query_maxlen):
X = []
Xq = []
Y = []
for story, query, answer in data:
x = [word_idx[w] for w in story]
xq = [word_idx[w] for w in query]
y = np.zeros(len(word_idx) + 1) # let's not forget that index 0 is reserved
y[word_idx[answer]] = 1
X.append(x)
Xq.append(xq)
Y.append(y)
return (pad_sequences(X, maxlen=story_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')
tar = tarfile.open(path)
challenges = {
# QA1 with 10,000 samples
'single_supporting_fact_10k': 'tasks_1-20_v1-2/en-10k/qa1_single-supporting-fact_{}.txt',
# QA2 with 10,000 samples
'two_supporting_facts_10k': 'tasks_1-20_v1-2/en-10k/qa2_two-supporting-facts_{}.txt',
}
challenge_type = 'single_supporting_fact_10k'
challenge = challenges[challenge_type]
print('Extracting stories for the challenge:', challenge_type)
train_stories = get_stories(tar.extractfile(challenge.format('train')))
test_stories = get_stories(tar.extractfile(challenge.format('test')))
vocab = sorted(reduce(lambda x, y: x | y, (set(story + q + [answer]) for story, q, answer in train_stories + test_stories)))
# Reserve 0 for masking via pad_sequences
vocab_size = len(vocab) + 1
story_maxlen = max(map(len, (x for x, _, _ in train_stories + test_stories)))
query_maxlen = max(map(len, (x for _, x, _ in train_stories + test_stories)))
print('-')
print('Vocab size:', vocab_size, 'unique words')
print('Story max length:', story_maxlen, 'words')
print('Query max length:', query_maxlen, 'words')
print('Number of training stories:', len(train_stories))
print('Number of test stories:', len(test_stories))
print('-')
print('Here\'s what a "story" tuple looks like (input, query, answer):')
print(train_stories[0])
print('-')
print('Vectorizing the word sequences...')
word_idx = dict((c, i + 1) for i, c in enumerate(vocab))
inputs_train, queries_train, answers_train = vectorize_stories(train_stories, word_idx, story_maxlen, query_maxlen)
inputs_test, queries_test, answers_test = vectorize_stories(test_stories, word_idx, story_maxlen, query_maxlen)
print('-')
print('inputs: integer tensor of shape (samples, max_length)')
print('inputs_train shape:', inputs_train.shape)
print('inputs_test shape:', inputs_test.shape)
print('-')
print('queries: integer tensor of shape (samples, max_length)')
print('queries_train shape:', queries_train.shape)
print('queries_test shape:', queries_test.shape)
print('-')
print('answers: binary (1 or 0) tensor of shape (samples, vocab_size)')
print('answers_train shape:', answers_train.shape)
print('answers_test shape:', answers_test.shape)
print('-')
print('Compiling...')
# embed the input sequence into a sequence of vectors
input_encoder_m = Sequential()
input_encoder_m.add(Embedding(input_dim=vocab_size,
output_dim=64,
input_length=story_maxlen))
# output: (samples, story_maxlen, embedding_dim)
# embed the question into a sequence of vectors
question_encoder = Sequential()
question_encoder.add(Embedding(input_dim=vocab_size,
output_dim=64,
input_length=query_maxlen))
# output: (samples, query_maxlen, embedding_dim)
# compute a 'match' between input sequence elements (which are vectors)
# and the question vector sequence
match = Sequential()
match.add(Merge([input_encoder_m, question_encoder],
mode='dot',
dot_axes=[(2,), (2,)]))
# output: (samples, story_maxlen, query_maxlen)
# embed the input into a single vector with size = story_maxlen:
input_encoder_c = Sequential()
input_encoder_c.add(Embedding(input_dim=vocab_size,
output_dim=query_maxlen,
input_length=story_maxlen))
# output: (samples, story_maxlen, query_maxlen)
# sum the match vector with the input vector:
response = Sequential()
response.add(Merge([match, input_encoder_c], mode='sum'))
# output: (samples, story_maxlen, query_maxlen)
response.add(Permute((2, 1))) # output: (samples, query_maxlen, story_maxlen)
# concatenate the match vector with the question vector,
# and do logistic regression on top
answer = Sequential()
answer.add(Merge([response, question_encoder], mode='concat', concat_axis=-1))
# the original paper uses a matrix multiplication for this reduction step.
# we choose to use a RNN instead.
answer.add(LSTM(64))
# one regularization layer -- more would probably be needed.
answer.add(Dropout(0.25))
answer.add(Dense(vocab_size))
# we output a probability distribution over the vocabulary
answer.add(Activation('softmax'))
answer.compile(optimizer='rmsprop', loss='categorical_crossentropy')
# Note: you could use a Graph model to avoid repeat the input twice
answer.fit([inputs_train, queries_train, inputs_train], answers_train,
batch_size=32,
nb_epoch=70,
show_accuracy=True,
validation_data=([inputs_test, queries_test, inputs_test], answers_test))
+4 -4
Ver Arquivo
@@ -126,14 +126,14 @@ def get_stories(f, only_supporting=False, max_length=None):
return data
def vectorize_stories(data):
def vectorize_stories(data, word_idx, story_maxlen, query_maxlen):
X = []
Xq = []
Y = []
for story, query, answer in data:
x = [word_idx[w] for w in story]
xq = [word_idx[w] for w in query]
y = np.zeros(vocab_size)
y = np.zeros(len(word_idx) + 1) # let's not forget that index 0 is reserved
y[word_idx[answer]] = 1
X.append(x)
Xq.append(xq)
@@ -168,8 +168,8 @@ word_idx = dict((c, i + 1) for i, c in enumerate(vocab))
story_maxlen = max(map(len, (x for x, _, _ in train + test)))
query_maxlen = max(map(len, (x for _, x, _ in train + test)))
X, Xq, Y = vectorize_stories(train)
tX, tXq, tY = vectorize_stories(test)
X, Xq, Y = vectorize_stories(train, word_idx, story_maxlen, query_maxlen)
tX, tXq, tY = vectorize_stories(test, word_idx, story_maxlen, query_maxlen)
print('vocab = {}'.format(vocab))
print('X.shape = {}'.format(X.shape))
+8 -8
Ver Arquivo
@@ -33,7 +33,7 @@ img_rows, img_cols = 32, 32
# the CIFAR10 images are RGB
img_channels = 3
# the data, shuffled and split between tran and test sets
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
@@ -45,7 +45,7 @@ Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(32, 3, 3, border_mode='full',
model.add(Convolution2D(32, 3, 3, border_mode='same',
input_shape=(img_channels, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(32, 3, 3))
@@ -53,7 +53,7 @@ model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 3, 3, border_mode='full'))
model.add(Convolution2D(64, 3, 3, border_mode='same'))
model.add(Activation('relu'))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
@@ -71,13 +71,13 @@ model.add(Activation('softmax'))
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='categorical_crossentropy', optimizer=sgd)
X_train = X_train.astype("float32")
X_test = X_test.astype("float32")
X_train /= 255
X_test /= 255
if not data_augmentation:
print("Not using data augmentation or normalization")
X_train = X_train.astype("float32")
X_test = X_test.astype("float32")
X_train /= 255
X_test /= 255
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch)
score = model.evaluate(X_test, Y_test, batch_size=batch_size)
print('Test score:', score)
+63
Ver Arquivo
@@ -0,0 +1,63 @@
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.utils.np_utils import accuracy
from keras.models import Graph
from keras.layers.core import Dense, Dropout
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM
from keras.datasets import imdb
'''
Train a Bidirectional LSTM on the IMDB sentiment classification task.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_bidirectional_lstm.py
Output after 4 epochs on CPU: ~0.8146
Time per epoch on CPU (Core i7): ~150s.
'''
max_features = 20000
maxlen = 100 # cut texts after this number of words (among top max_features most common words)
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)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
print("Pad sequences (samples x time)")
X_train = sequence.pad_sequences(X_train, maxlen=maxlen)
X_test = sequence.pad_sequences(X_test, maxlen=maxlen)
print('X_train shape:', X_train.shape)
print('X_test shape:', X_test.shape)
y_train = np.array(y_train)
y_test = np.array(y_test)
print('Build model...')
model = Graph()
model.add_input(name='input', input_shape=(maxlen,), dtype=int)
model.add_node(Embedding(max_features, 128, input_length=maxlen),
name='embedding', input='input')
model.add_node(LSTM(64), name='forward', input='embedding')
model.add_node(LSTM(64, go_backwards=True), name='backward', input='embedding')
model.add_node(Dropout(0.5), name='dropout', inputs=['forward', 'backward'])
model.add_node(Dense(1, activation='sigmoid'), name='sigmoid', input='dropout')
model.add_output(name='output', input='sigmoid')
# try using different optimizers and different optimizer configs
model.compile('adam', {'output': 'binary_crossentropy'})
print("Train...")
model.fit({'input': X_train, 'output': y_train},
batch_size=batch_size,
nb_epoch=4)
acc = accuracy(y_test,
np.round(np.array(model.predict({'input': X_test},
batch_size=batch_size)['output'])))
print('Test accuracy:', acc)
+10 -6
Ver Arquivo
@@ -4,7 +4,6 @@ import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.optimizers import RMSprop
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.layers.embeddings import Embedding
@@ -17,7 +16,7 @@ from keras.datasets import imdb
Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_cnn.py
Get to 0.8330 test accuracy after 3 epochs. 100s/epoch on K520 GPU.
Get to 0.835 test accuracy after 2 epochs. 100s/epoch on K520 GPU.
'''
# set parameters:
@@ -28,7 +27,7 @@ embedding_dims = 100
nb_filter = 250
filter_length = 3
hidden_dims = 250
nb_epoch = 3
nb_epoch = 2
print("Loading data...")
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features,
@@ -60,7 +59,8 @@ model.add(Convolution1D(nb_filter=nb_filter,
# we use standard max pooling (halving the output of the previous layer):
model.add(MaxPooling1D(pool_length=2))
# We flatten the output of the conv layer, so that we can add a vanilla dense layer:
# We flatten the output of the conv layer,
# so that we can add a vanilla dense layer:
model.add(Flatten())
# We add a vanilla hidden layer:
@@ -72,5 +72,9 @@ model.add(Activation('relu'))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='rmsprop', class_mode="binary")
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, validation_data=(X_test, y_test))
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
class_mode="binary")
model.fit(X_train, y_train, batch_size=batch_size,
nb_epoch=nb_epoch, show_accuracy=True,
validation_data=(X_test, y_test))
+84
Ver Arquivo
@@ -0,0 +1,84 @@
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.optimizers import SGD, RMSprop, Adagrad
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, GRU, SimpleRNN
from keras.layers.convolutional import Convolution1D, MaxPooling1D
from keras.datasets import imdb
'''
Train a recurrent convolutional network on the IMDB sentiment classification task.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python imdb_lstm.py
Get to 0.8498 test accuracy after 2 epochs. 41s/epoch on K520 GPU.
'''
# Embedding
max_features = 20000
maxlen = 100
embedding_size = 128
# Convolution
filter_length = 3
nb_filter = 64
pool_length = 2
# LSTM
lstm_output_size = 70
# Training
batch_size = 30
nb_epoch = 2
'''
Note:
batch_size is highly sensitive.
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)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
print("Pad sequences (samples x time)")
X_train = sequence.pad_sequences(X_train, maxlen=maxlen)
X_test = sequence.pad_sequences(X_test, maxlen=maxlen)
print('X_train shape:', X_train.shape)
print('X_test shape:', X_test.shape)
print('Build model...')
model = Sequential()
model.add(Embedding(max_features, embedding_size, input_length=maxlen))
model.add(Dropout(0.25))
model.add(Convolution1D(nb_filter=nb_filter,
filter_length=filter_length,
border_mode="valid",
activation="relu",
subsample_length=1))
model.add(MaxPooling1D(pool_length=pool_length))
model.add(LSTM(lstm_output_size))
model.add(Dense(1))
model.add(Activation('sigmoid'))
model.compile(loss='binary_crossentropy',
optimizer='adam',
class_mode="binary")
print("Train...")
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,
validation_data=(X_test, y_test), show_accuracy=True)
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size,
show_accuracy=True)
print('Test score:', score)
print('Test accuracy:', acc)
+11 -6
Ver Arquivo
@@ -4,12 +4,11 @@ import numpy as np
np.random.seed(1337) # for reproducibility
from keras.preprocessing import sequence
from keras.optimizers import SGD, RMSprop, Adagrad
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, GRU
from keras.layers.recurrent import LSTM
from keras.datasets import imdb
'''
@@ -36,7 +35,8 @@ 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,
test_split=0.2)
print(len(X_train), 'train sequences')
print(len(X_test), 'test sequences')
@@ -55,10 +55,15 @@ model.add(Dense(1))
model.add(Activation('sigmoid'))
# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy', optimizer='adam', class_mode="binary")
model.compile(loss='binary_crossentropy',
optimizer='adam',
class_mode="binary")
print("Train...")
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=4, validation_data=(X_test, y_test), show_accuracy=True)
score, acc = model.evaluate(X_test, y_test, batch_size=batch_size, show_accuracy=True)
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=3,
validation_data=(X_test, y_test), show_accuracy=True)
score, acc = model.evaluate(X_test, y_test,
batch_size=batch_size,
show_accuracy=True)
print('Test score:', score)
print('Test accuracy:', acc)
+1 -1
Ver Arquivo
@@ -51,7 +51,7 @@ Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Convolution2D(nb_filters, nb_conv, nb_conv,
border_mode='full',
border_mode='same',
input_shape=(1, img_rows, img_cols)))
model.add(Activation('relu'))
model.add(Convolution2D(nb_filters, nb_conv, nb_conv))
+4 -6
Ver Arquivo
@@ -23,8 +23,8 @@ from keras.utils import np_utils
Optimizer is replaced with RMSprop which yields more stable and steady
improvement.
Reaches 0.93 train/test accuracy after 900 epochs (which roughly corresponds
to 1687500 steps in the original paper.)
Reaches 0.93 train/test accuracy after 900 epochs
(which roughly corresponds to 1687500 steps in the original paper.)
'''
batch_size = 32
@@ -34,7 +34,6 @@ hidden_units = 100
learning_rate = 1e-6
clip_norm = 1.0
BPTT_truncate = 28*28
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
@@ -58,8 +57,7 @@ model = Sequential()
model.add(SimpleRNN(output_dim=hidden_units,
init=lambda shape: normal(shape, scale=0.001),
inner_init=lambda shape: identity(shape, scale=1.0),
activation='relu', truncate_gradient=BPTT_truncate,
input_shape=(None, 1)))
activation='relu', input_shape=X_train.shape[1:]))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
rmsprop = RMSprop(lr=learning_rate)
@@ -74,7 +72,7 @@ print('IRNN test accuracy:', scores[1])
print('Compare to LSTM...')
model = Sequential()
model.add(LSTM(hidden_units, input_shape=(None, 1)))
model.add(LSTM(hidden_units, input_shape=X_train.shape[1:]))
model.add(Dense(nb_classes))
model.add(Activation('softmax'))
rmsprop = RMSprop(lr=learning_rate)
+11 -6
Ver Arquivo
@@ -12,8 +12,9 @@ from keras.utils import np_utils
'''
Train a simple deep NN on the MNIST dataset.
Get to 98.30% test accuracy after 20 epochs (there is *a lot* of margin for parameter tuning).
2 seconds per epoch on a GRID K520 GPU.
Get to 98.40% test accuracy after 20 epochs
(there is *a lot* of margin for parameter tuning).
2 seconds per epoch on a K520 GPU.
'''
batch_size = 128
@@ -37,10 +38,10 @@ Y_train = np_utils.to_categorical(y_train, nb_classes)
Y_test = np_utils.to_categorical(y_test, nb_classes)
model = Sequential()
model.add(Dense(128, input_shape=(784,)))
model.add(Dense(512, input_shape=(784,)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(128))
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(Dense(10))
@@ -49,7 +50,11 @@ model.add(Activation('softmax'))
rms = RMSprop()
model.compile(loss='categorical_crossentropy', optimizer=rms)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=2, validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=2,
validation_data=(X_test, Y_test))
score = model.evaluate(X_test, Y_test,
show_accuracy=True, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
+122
Ver Arquivo
@@ -0,0 +1,122 @@
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import datetime
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.utils import np_utils
'''
Transfer learning toy example:
1- Train a simple convnet on the MNIST dataset the first 5 digits [0..4].
2- Freeze convolutional layers and fine-tune dense layers
for the classification of digits [5..9].
Run on GPU: THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python mnist_cnn.py
Get to 99.8% test accuracy after 5 epochs
for the first five digits classifier
and 99.2% for the last five digits after transfer + fine-tuning.
'''
now = datetime.datetime.now
batch_size = 128
nb_classes = 5
nb_epoch = 5
# input image dimensions
img_rows, img_cols = 28, 28
# number of convolutional filters to use
nb_filters = 32
# size of pooling area for max pooling
nb_pool = 2
# convolution kernel size
nb_conv = 3
def train_model(model, train, test, nb_classes):
X_train = train[0].reshape(train[0].shape[0], 1, img_rows, img_cols)
X_test = test[0].reshape(test[0].shape[0], 1, img_rows, img_cols)
X_train = X_train.astype("float32")
X_test = X_test.astype("float32")
X_train /= 255
X_test /= 255
print('X_train shape:', X_train.shape)
print(X_train.shape[0], 'train samples')
print(X_test.shape[0], 'test samples')
# convert class vectors to binary class matrices
Y_train = np_utils.to_categorical(train[1], nb_classes)
Y_test = np_utils.to_categorical(test[1], nb_classes)
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
t = now()
model.fit(X_train, Y_train,
batch_size=batch_size, nb_epoch=nb_epoch,
show_accuracy=True, verbose=1,
validation_data=(X_test, Y_test))
print('Training time: %s' % (now() - t))
score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0)
print('Test score:', score[0])
print('Test accuracy:', score[1])
# the data, shuffled and split between train and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
# create two datasets one with digits below 5 and one with 5 and above
X_train_lt5 = X_train[y_train < 5]
y_train_lt5 = y_train[y_train < 5]
X_test_lt5 = X_test[y_test < 5]
y_test_lt5 = y_test[y_test < 5]
X_train_gte5 = X_train[y_train >= 5]
y_train_gte5 = y_train[y_train >= 5] - 5 # make classes start at 0 for
X_test_gte5 = X_test[y_test >= 5] # np_utils.to_categorical
y_test_gte5 = y_test[y_test >= 5] - 5
# define two groups of layers: feature (convolutions) and classification (dense)
feature_layers = [
Convolution2D(nb_filters, nb_conv, nb_conv,
border_mode='valid',
input_shape=(1, img_rows, img_cols)),
Activation('relu'),
Convolution2D(nb_filters, nb_conv, nb_conv),
Activation('relu'),
MaxPooling2D(pool_size=(nb_pool, nb_pool)),
Dropout(0.25),
Flatten(),
]
classification_layers = [
Dense(128),
Activation('relu'),
Dropout(0.5),
Dense(nb_classes),
Activation('softmax')
]
# create complete model
model = Sequential()
for l in feature_layers + classification_layers:
model.add(l)
# train model for 5-digit classification [0..4]
train_model(model,
(X_train_lt5, y_train_lt5),
(X_test_lt5, y_test_lt5), nb_classes)
# freeze feature layers and rebuild model
for l in feature_layers:
l.trainable = False
# transfer: train dense layers for new classification task [5..9]
train_model(model,
(X_train_gte5, y_train_gte5),
(X_test_gte5, y_test_gte5), nb_classes)
+168
Ver Arquivo
@@ -0,0 +1,168 @@
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
np.random.seed(123)
import matplotlib.pyplot as plt
from theano import function
from keras.models import Sequential
from keras.layers.core import TimeDistributedDense, Activation
from keras.layers.recurrent import LSTM
from keras.optimizers import Adam
from keras.utils import generic_utils
from keras.layers.ntm import NeuralTuringMachine as NTM
"""
Copy Problem defined in Graves et. al [0]
Training data is made of sequences with length 1 to 20.
Test data are sequences of length 100.
The model is tested every 500 weight updates.
After about 3500 updates, the accuracy jumps from around 50% to >90%.
Estimated compile time: 12 min
Estimated time to train Neural Turing Machine and 3 layer LSTM on an NVidia GTX 680: 2h
[0]: http://arxiv.org/pdf/1410.5401v2.pdf
"""
batch_size = 100
h_dim = 128
n_slots = 128
m_length = 20
input_dim = 8
lr = 1e-3
clipvalue = 10
##### Neural Turing Machine ######
ntm = NTM(h_dim, n_slots=n_slots, m_length=m_length, shift_range=3,
inner_rnn='lstm', return_sequences=True, input_dim=input_dim)
model = Sequential()
model.add(ntm)
model.add(TimeDistributedDense(input_dim))
model.add(Activation('sigmoid'))
sgd = Adam(lr=lr, clipvalue=clipvalue)
model.compile(loss='binary_crossentropy', optimizer=sgd)
# LSTM - Run this for comparison
sgd2 = Adam(lr=lr, clipvalue=clipvalue)
lstm = Sequential()
lstm.add(LSTM(input_dim=input_dim, output_dim=h_dim*2, return_sequences=True))
lstm.add(LSTM(output_dim=h_dim*2, return_sequences=True))
lstm.add(LSTM(output_dim=h_dim*2, return_sequences=True))
lstm.add(TimeDistributedDense(input_dim))
lstm.add(Activation('sigmoid'))
lstm.compile(loss='binary_crossentropy', optimizer=sgd)
###### DATASET ########
def get_sample(batch_size=128, n_bits=8, max_size=20, min_size=1):
# generate samples with random length
inp = np.zeros((batch_size, 2*max_size-1, n_bits))
out = np.zeros((batch_size, 2*max_size-1, n_bits))
sw = np.zeros((batch_size, 2*max_size-1, 1))
for i in range(batch_size):
t = np.random.randint(low=min_size, high=max_size)
x = np.random.uniform(size=(t, n_bits)) > .5
for j,f in enumerate(x.sum(axis=-1)): # remove fake flags
if f>=n_bits:
x[j, :] = 0.
del_flag = np.ones((1, n_bits))
inp[i, :t+1] = np.concatenate([x, del_flag], axis=0)
out[i, t+1:(2*t+1)] = x
sw[i, t+1:(2*t+1)] = 1
return inp, out, sw
def show_pattern(inp, out, sw, file_name='ntm_output.png'):
''' Helper function to visualize results '''
plt.figure(figsize=(10, 10))
plt.subplot(131)
plt.imshow(inp>.5)
plt.subplot(132)
plt.imshow(out>.5)
plt.subplot(133)
plt.imshow(sw>.5)
plt.savefig(file_name)
plt.close()
# Show data example:
inp, out, sw = get_sample(1, 8, 20)
plt.subplot(131)
plt.title('input')
plt.imshow(inp[0], cmap='gray')
plt.subplot(132)
plt.title('desired')
plt.imshow(out[0], cmap='gray')
plt.subplot(133)
plt.title('sample_weight')
plt.imshow(sw[0], cmap='gray')
# training uses sequences of length 1 to 20. Test uses series of length 100.
def test_model(model, file_name, min_size=100):
I, V, sw = get_sample(batch_size=500, n_bits=input_dim, max_size=min_size+1, min_size=min_size)
Y = np.asarray(model.predict(I, batch_size=100) > .5).astype('float64')
acc = (V[:, -min_size:, :] == Y[:, -min_size:, :]).mean() * 100
show_pattern(Y[0], V[0], sw[0], file_name)
return acc
##### TRAIN ######
nb_epoch = 4000
progbar = generic_utils.Progbar(nb_epoch)
for e in range(nb_epoch):
I, V, sw = get_sample(n_bits=input_dim, max_size=20, min_size=1, batch_size=100)
loss1 = model.train_on_batch(I, V, sample_weight=sw)
loss2 = lstm.train_on_batch(I, V, sample_weight=sw)
progbar.add(1, values=[("NTM", loss1), ("LSTM", loss2)])
if e % 500 == 0:
print("")
acc1 = test_model(model, 'ntm.png')
acc2 = test_model(lstm, 'lstm.png')
print("NTM test acc: {}".format(acc1))
print("LSTM test acc: {}".format(acc2))
##### VISUALIZATION #####
X = model.get_input()
Y = ntm.get_full_output()[0:3] # (memory over time, read_vectors, write_vectors)
F = function([X], Y, allow_input_downcast=True)
inp, out, sw = get_sample(1, 8, 21, 20)
mem, read, write = F(inp.astype('float32'))
Y = model.predict(inp)
plt.figure(figsize=(15, 12))
plt.subplot(221)
plt.imshow(write[0])
plt.xlabel('memory location')
plt.ylabel('time')
plt.title('write')
plt.subplot(222)
plt.imshow(read[0])
plt.title('read')
plt.subplot(223)
plt.title('desired')
plt.imshow(out[0])
plt.subplot(224)
plt.imshow(Y[0]>.5)
plt.title('output')
plt.figure(figsize=(15, 10))
plt.subplot(325)
plt.ylabel('time')
plt.xlabel('location')
plt.title('memory evolving in time (avg value per location)')
plt.imshow(mem[0].mean(axis=-1))
-221
Ver Arquivo
@@ -1,221 +0,0 @@
'''
We loop over words in a dataset, and for each word, we look at a context window around the word.
We generate pairs of (pivot_word, other_word_from_same_context) with label 1,
and pairs of (pivot_word, random_word) with label 0 (skip-gram method).
We use the layer WordContextProduct to learn embeddings for the word couples,
and compute a proximity score between the embeddings (= p(context|word)),
trained with our positive and negative labels.
We then use the weights computed by WordContextProduct to encode words
and demonstrate that the geometry of the embedding space
captures certain useful semantic properties.
Read more about skip-gram in this particularly gnomic paper by Mikolov et al.:
http://arxiv.org/pdf/1301.3781v3.pdf
Note: you should run this on GPU, otherwise training will be quite slow.
On a EC2 GPU instance, expect 3 hours per 10e6 comments (~10e8 words) per epoch with dim_proj=256.
Should be much faster on a modern GPU.
GPU command:
THEANO_FLAGS=mode=FAST_RUN,device=gpu,floatX=float32 python skipgram_word_embeddings.py
Dataset: 5,845,908 Hacker News comments.
Obtain the dataset at:
https://mega.co.nz/#F!YohlwD7R!wec0yNO86SeaNGIYQBOR0A
(HNCommentsAll.1perline.json.bz2)
'''
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import theano
from six.moves import cPickle
import os, re, json
from keras.preprocessing import sequence, text
from keras.optimizers import SGD, RMSprop, Adagrad
from keras.utils import np_utils, generic_utils
from keras.models import Sequential
from keras.layers.embeddings import WordContextProduct, Embedding
from six.moves import range
from six.moves import zip
max_features = 50000 # vocabulary size: top 50,000 most common words in data
skip_top = 100 # ignore top 100 most common words
nb_epoch = 1
dim_proj = 256 # embedding space dimension
save = True
load_model = False
load_tokenizer = False
train_model = True
save_dir = os.path.expanduser("~/.keras/models")
if not os.path.exists(save_dir):
os.makedirs(save_dir)
model_load_fname = "HN_skipgram_model.pkl"
model_save_fname = "HN_skipgram_model.pkl"
tokenizer_fname = "HN_tokenizer.pkl"
data_path = os.path.expanduser("~/")+"HNCommentsAll.1perline.json"
# text preprocessing utils
html_tags = re.compile(r'<.*?>')
to_replace = [('&#x27;', "'")]
hex_tags = re.compile(r'&.*?;')
def clean_comment(comment):
c = str(comment.encode("utf-8"))
c = html_tags.sub(' ', c)
for tag, char in to_replace:
c = c.replace(tag, char)
c = hex_tags.sub(' ', c)
return c
def text_generator(path=data_path):
f = open(path)
for i, l in enumerate(f):
comment_data = json.loads(l)
comment_text = comment_data["comment_text"]
comment_text = clean_comment(comment_text)
if i % 10000 == 0:
print(i)
yield comment_text
f.close()
# model management
if load_tokenizer:
print('Load tokenizer...')
tokenizer = cPickle.load(open(os.path.join(save_dir, tokenizer_fname), 'rb'))
else:
print("Fit tokenizer...")
tokenizer = text.Tokenizer(nb_words=max_features)
tokenizer.fit_on_texts(text_generator())
if save:
print("Save tokenizer...")
if not os.path.exists(save_dir):
os.makedirs(save_dir)
cPickle.dump(tokenizer, open(os.path.join(save_dir, tokenizer_fname), "wb"))
# training process
if train_model:
if load_model:
print('Load model...')
model = cPickle.load(open(os.path.join(save_dir, model_load_fname), 'rb'))
else:
print('Build model...')
model = Sequential()
model.add(WordContextProduct(max_features, proj_dim=dim_proj, init="uniform"))
model.compile(loss='mse', optimizer='rmsprop')
sampling_table = sequence.make_sampling_table(max_features)
for e in range(nb_epoch):
print('-'*40)
print('Epoch', e)
print('-'*40)
progbar = generic_utils.Progbar(tokenizer.document_count)
samples_seen = 0
losses = []
for i, seq in enumerate(tokenizer.texts_to_sequences_generator(text_generator())):
# get skipgram couples for one text in the dataset
couples, labels = sequence.skipgrams(seq, max_features, window_size=4, negative_samples=1., sampling_table=sampling_table)
if couples:
# one gradient update per sentence (one sentence = a few 1000s of word couples)
X = np.array(couples, dtype="int32")
loss = model.train_on_batch(X, labels)
losses.append(loss)
if len(losses) % 100 == 0:
progbar.update(i, values=[("loss", np.mean(losses))])
losses = []
samples_seen += len(labels)
print('Samples seen:', samples_seen)
print("Training completed!")
if save:
print("Saving model...")
if not os.path.exists(save_dir):
os.makedirs(save_dir)
cPickle.dump(model, open(os.path.join(save_dir, model_save_fname), "wb"))
print("It's test time!")
# recover the embedding weights trained with skipgram:
weights = model.layers[0].get_weights()[0]
# we no longer need this
del model
weights[:skip_top] = np.zeros((skip_top, dim_proj))
norm_weights = np_utils.normalize(weights)
word_index = tokenizer.word_index
reverse_word_index = dict([(v, k) for k, v in list(word_index.items())])
def embed_word(w):
i = word_index.get(w)
if (not i) or (i < skip_top) or (i >= max_features):
return None
return norm_weights[i]
def closest_to_point(point, nb_closest=10):
proximities = np.dot(norm_weights, point)
tups = list(zip(list(range(len(proximities))), proximities))
tups.sort(key=lambda x: x[1], reverse=True)
return [(reverse_word_index.get(t[0]), t[1]) for t in tups[:nb_closest]]
def closest_to_word(w, nb_closest=10):
i = word_index.get(w)
if (not i) or (i < skip_top) or (i >= max_features):
return []
return closest_to_point(norm_weights[i].T, nb_closest)
''' the resuls in comments below were for:
5.8M HN comments
dim_proj = 256
nb_epoch = 2
optimizer = rmsprop
loss = mse
max_features = 50000
skip_top = 100
negative_samples = 1.
window_size = 4
and frequency subsampling of factor 10e-5.
'''
words = [
"article", # post, story, hn, read, comments
"3", # 6, 4, 5, 2
"two", # three, few, several, each
"great", # love, nice, working, looking
"data", # information, memory, database
"money", # company, pay, customers, spend
"years", # ago, year, months, hours, week, days
"android", # ios, release, os, mobile, beta
"javascript", # js, css, compiler, library, jquery, ruby
"look", # looks, looking
"business", # industry, professional, customers
"company", # companies, startup, founders, startups
"after", # before, once, until
"own", # personal, our, having
"us", # united, country, american, tech, diversity, usa, china, sv
"using", # javascript, js, tools (lol)
"here", # hn, post, comments
]
for w in words:
res = closest_to_word(w)
print('====', w)
for r in res:
print(r)
+15
Ver Arquivo
@@ -0,0 +1,15 @@
"""
Keras: Theano-based Deep Learning library
==================================
Keras is a minimalist, highly modular neural network library in
the spirit of Torch, written in Python / Theano so as not to have
to deal with the dearth of ecosystem in Lua. It was developed with
a focus on enabling fast experimentation. Being able to go from
idea to result with the least possible delay is key to doing
good research.
See http://keras.io/
"""
__version__ = '0.2.0'
+19 -14
Ver Arquivo
@@ -1,35 +1,40 @@
from __future__ import absolute_import
import theano.tensor as T
from . import backend as K
def softmax(x):
return T.nnet.softmax(x.reshape((-1, x.shape[-1]))).reshape(x.shape)
def time_distributed_softmax(x):
import warnings
warnings.warn("time_distributed_softmax is deprecated. Just use softmax!", DeprecationWarning)
return softmax(x)
ndim = K.ndim(x)
if ndim == 2:
return K.softmax(x)
elif ndim == 3:
# apply softmax to each timestep
def step(x, states):
return K.softmax(x), []
last_output, outputs, states = K.rnn(step, x, [], masking=False)
return outputs
else:
raise Exception('Cannot apply softmax to a tensor that is not 2D or 3D. ' +
'Here, ndim=' + str(ndim))
def softplus(x):
return T.nnet.softplus(x)
return K.softplus(x)
def relu(x):
return T.nnet.relu(x)
def relu(x, alpha=0., max_value=None):
return K.relu(x, alpha=alpha, max_value=max_value)
def tanh(x):
return T.tanh(x)
return K.tanh(x)
def sigmoid(x):
return T.nnet.sigmoid(x)
return K.sigmoid(x)
def hard_sigmoid(x):
return T.nnet.hard_sigmoid(x)
return K.hard_sigmoid(x)
def linear(x):
+39
Ver Arquivo
@@ -0,0 +1,39 @@
from __future__ import absolute_import
from __future__ import print_function
import os
import json
from .common import epsilon, floatx, set_epsilon, set_floatx
_keras_dir = os.path.expanduser(os.path.join('~', '.keras'))
if not os.path.exists(_keras_dir):
os.makedirs(_keras_dir)
_BACKEND = 'theano'
_config_path = os.path.expanduser(os.path.join('~', '.keras', 'keras.json'))
if os.path.exists(_config_path):
_config = json.load(open(_config_path))
_floatx = _config.get('floatx', floatx())
assert _floatx in {'float32', 'float64'}
_epsilon = _config.get('epsilon', epsilon())
assert type(_epsilon) == float
_backend = _config.get('backend', _BACKEND)
assert _backend in {'theano', 'tensorflow'}
set_floatx(_floatx)
set_epsilon(_epsilon)
_BACKEND = _backend
else:
# save config file, for easy edition
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND}
json.dump(_config, open(_config_path, 'w'))
if _BACKEND == 'theano':
print('Using Theano backend.')
from .theano_backend import *
elif _BACKEND == 'tensorflow':
print('Using TensorFlow backend.')
from .tensorflow_backend import *
else:
raise Exception('Unknown backend: ' + str(backend))
+31
Ver Arquivo
@@ -0,0 +1,31 @@
import numpy as np
# the type of float to use throughout the session.
_FLOATX = 'float32'
_EPSILON = 10e-8
def epsilon():
return _EPSILON
def set_epsilon(e):
global _EPSILON
_EPSILON = e
def floatx():
return _FLOATX
def set_floatx(floatx):
global _FLOATX
if floatx not in {'float32', 'float64'}:
raise Exception('Unknown floatx type: ' + str(floatx))
_FLOATX = floatx
def cast_to_floatx(x):
'''Cast a Numpy array to floatx.
'''
return np.asarray(x, dtype=_FLOATX)
+602
Ver Arquivo
@@ -0,0 +1,602 @@
import tensorflow as tf
import numpy as np
from .common import _FLOATX, _EPSILON
# INTERNAL UTILS
_SESSION = None
def _get_session():
global _SESSION
if _SESSION is None:
_SESSION = tf.Session('')
return _SESSION
def _set_session(session):
global _SESSION
_SESSION = session
# VARIABLE MANIPULATION
def variable(value, dtype=_FLOATX, name=None):
v = tf.Variable(np.asarray(value, dtype=dtype), name=name)
_get_session().run(v.initializer)
return v
def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
if not shape:
if ndim:
shape = [None for _ in range(ndim)]
return tf.placeholder(dtype, shape=shape, name=name)
def shape(x):
return x.get_shape()
def ndim(x):
return len(x.get_shape())
def eval(x):
'''Run a graph.
'''
return x.eval(session=_get_session())
def zeros(shape, dtype=_FLOATX, name=None):
return variable(np.zeros(shape), dtype, name)
def ones(shape, dtype=_FLOATX, name=None):
return variable(np.ones(shape), dtype, name)
def ones_like(x, name=None):
return tf.ones_like(x)
def zeros_like(x, name=None):
return tf.zeros_like(x)
def count_params(x):
'''Return number of scalars in a tensor.
'''
shape = x.get_shape()
return np.prod([shape[i]._value for i in range(len(shape))])
def cast(x, dtype):
return tf.cast(x, dtype)
# LINEAR ALGEBRA
def dot(x, y):
return tf.matmul(x, y)
def transpose(x):
return tf.transpose(x)
def gather(reference, indices):
'''reference: a tensor.
indices: an int tensor of indices.
Return: a tensor of same type as reference.
'''
return tf.gather(reference, indices)
# ELEMENT-WISE OPERATIONS
def max(x, axis=None, keepdims=False):
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
return tf.reduce_max(x, reduction_indices=axis, keep_dims=keepdims)
def min(x, axis=None, keepdims=False):
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
return tf.reduce_min(x, reduction_indices=axis, keep_dims=keepdims)
def sum(x, axis=None, keepdims=False):
'''Sum of the values in a tensor, alongside the specified axis.
'''
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
return tf.reduce_sum(x, reduction_indices=axis, keep_dims=keepdims)
def prod(x, axis=None, keepdims=False):
'''Multiply the values in a tensor, alongside the specified axis.
'''
return tf.reduce_prod(x, reduction_indices=axis, keep_dims=keepdims)
def std(x, axis=None, keepdims=False):
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
if x.dtype.base_dtype == tf.bool:
x = tf.cast(x, _FLOATX)
m = tf.reduce_mean(x, reduction_indices=axis, keep_dims=keepdims)
devs_squared = tf.square(x - m)
return tf.sqrt(tf.reduce_mean(devs_squared,
reduction_indices=axis,
keep_dims=keepdims))
def mean(x, axis=None, keepdims=False):
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
if x.dtype.base_dtype == tf.bool:
x = tf.cast(x, _FLOATX)
return tf.reduce_mean(x, reduction_indices=axis, keep_dims=keepdims)
def any(x, axis=None, keepdims=False):
'''Bitwise reduction (logical OR).
Return array of int8 (0s and 1s).
'''
if axis is not None and axis < 0:
axis = axis % len(x.get_shape())
x = tf.cast(x, tf.bool)
x = tf.reduce_any(x, reduction_indices=axis, keep_dims=keepdims)
return tf.cast(x, tf.int8)
def argmax(x, axis=-1):
if axis < 0:
axis = axis % len(x.get_shape())
return tf.argmax(x, axis)
def argmin(x, axis=-1):
if axis < 0:
axis = axis % len(x.get_shape())
return tf.argmin(x, axis)
def square(x):
return tf.square(x)
def abs(x):
return tf.abs(x)
def sqrt(x):
x = tf.clip_by_value(x, tf.cast(0., dtype=_FLOATX),
tf.cast(np.inf, dtype=_FLOATX))
return tf.sqrt(x)
def exp(x):
return tf.exp(x)
def log(x):
return tf.log(x)
def round(x):
return tf.round(x)
def pow(x, a):
return tf.pow(x, a)
def clip(x, min_value, max_value):
if max_value < min_value:
max_value = min_value
return tf.clip_by_value(x, tf.cast(min_value, dtype=_FLOATX),
tf.cast(max_value, dtype=_FLOATX))
def equal(x, y):
return tf.equal(x, y)
def maximum(x, y):
return tf.maximum(x, y)
def minimum(x, y):
return tf.minimum(x, y)
# SHAPE OPERATIONS
def concatenate(tensors, axis=-1):
if axis < 0:
axis = axis % len(tensors[0].get_shape())
return tf.concat(axis, tensors)
def reshape(x, shape):
return tf.reshape(x, shape)
def permute_dimensions(x, pattern):
'''Transpose dimensions.
pattern should be a tuple or list of
dimension indices, e.g. [0, 2, 1].
'''
return tf.transpose(x, perm=pattern)
def repeat(x, n):
'''Repeat a 2D tensor:
if x has shape (samples, dim) and n=2,
the output will have shape (samples, 2, dim)
'''
tensors = [x] * n
stacked = tf.pack(tensors)
return tf.transpose(stacked, (1, 0, 2))
def tile(x, n):
return tf.tile(x, n)
def flatten(x):
'''Turn a n-D tensor into a 2D tensor where
the first dimension is conserved.
'''
x = tf.reshape(x, [-1, np.prod(x.get_shape()[1:].as_list())])
return x
def expand_dims(x, dim=-1):
'''Add a 1-sized dimension at index "dim".
'''
return tf.expand_dims(x, dim)
def squeeze(x, axis):
'''Remove a 1-dimension from the tensor at index "axis".
'''
return tf.squeeze(x, [axis])
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
really hard.
'''
pattern = [[0, 0], [padding, padding], [0, 0]]
return tf.pad(x, pattern)
def spatial_2d_padding(x, padding=(1, 1), dim_ordering='th'):
'''Pad the 2nd and 3rd dimensions of a 4D tensor
with "padding[0]" and "padding[1]" (resp.) zeros left and right.
'''
if dim_ordering == 'th':
pattern = [[0, 0], [0, 0],
[padding[0], padding[0]], [padding[1], padding[1]]]
else:
pattern = [[0, 0],
[padding[0], padding[0]], [padding[1], padding[1]],
[0, 0]]
return tf.pad(x, pattern)
# VALUE MANIPULATION
def get_value(x):
'''Technically the same as eval() for TF.
'''
return x.eval(session=_get_session())
def set_value(x, value):
tf.assign(x, np.asarray(value)).op.run(session=_get_session())
# GRAPH MANIPULATION
class Function(object):
def __init__(self, inputs, outputs, updates=[]):
self.inputs = list(inputs)
self.outputs = list(outputs)
with tf.control_dependencies(self.outputs):
self.updates = [tf.assign(p, new_p) for (p, new_p) in updates]
def __call__(self, inputs):
names = [v.name for v in self.inputs]
feed_dict = dict(zip(names, inputs))
session = _get_session()
updated = session.run(self.outputs + self.updates, feed_dict=feed_dict)
return updated[:len(self.outputs)]
def function(inputs, outputs, updates=[]):
return Function(inputs, outputs, updates=updates)
def gradients(loss, variables):
return tf.gradients(loss, variables)
# CONTROL FLOW
def rnn(step_function, inputs, initial_states,
go_backwards=False, masking=True):
'''Iterates over the time dimension of a tensor.
Parameters
----------
inputs: tensor of temporal data of shape (samples, time, ...)
(at least 3D).
step_function:
Parameters:
input: tensor with shape (samples, ...) (no time dimension),
representing input for the batch of samples at a certain
time step.
states: list of tensors.
Returns:
output: tensor with shape (samples, ...) (no time dimension),
new_states: list of tensors, same length and shapes
as 'states'.
initial_states: tensor with shape (samples, ...) (no time dimension),
containing the initial values for the states used in
the step function.
go_backwards: boolean. If True, do the iteration over
the time dimension in reverse order.
masking: boolean. If true, any input timestep inputs[s, i]
that is all-zeros will be skipped (states will be passed to
the next step unchanged) and the corresponding output will
be all zeros.
Returns
-------
A tuple (last_output, outputs, new_states).
last_output: the latest output of the rnn, of shape (samples, ...)
outputs: tensor with shape (samples, time, ...) where each
entry outputs[s, t] is the output of the step function
at time t for sample s.
new_states: list of tensors, latest states returned by
the step function, of shape (samples, ...).
'''
inputs = tf.transpose(inputs, (1, 0, 2))
input_list = tf.unpack(inputs)
states = initial_states
successive_states = []
successive_outputs = []
if go_backwards:
input_list.reverse()
for input in input_list:
output, new_states = step_function(input, states)
if masking:
# for now we raise an exception because tf.reduce_any will not work
raise Exception("Masking is Theano-only for the time being.")
# if all-zero input timestep, return
# all-zero output and unchanged states
switch = tf.reduce_any(input)
output = tf.control_flow_ops.cond(switch,
lambda: output,
lambda: 0. * output)
return_states = []
for state, new_state in zip(states, new_states):
return_states.append(tf.control_flow_ops.cond(switch,
lambda: new_state,
lambda: state))
states = return_states
else:
states = new_states
successive_outputs.append(output)
successive_states.append(states)
last_output = successive_outputs[-1]
outputs = tf.pack(successive_outputs)
new_states = successive_states[-1]
outputs = tf.transpose(outputs, (1, 0, 2))
return last_output, outputs, states
def switch(condition, then_expression, else_expression):
'''condition: scalar tensor.
'''
return tf.control_flow_ops.cond(condition,
lambda: then_expression,
lambda: else_expression)
# NN OPERATIONS
def relu(x, alpha=0., max_value=None):
'''ReLU.
alpha: slope of negative section.
'''
negative_part = tf.nn.relu(-x)
x = tf.nn.relu(x)
if max_value is not None:
x = tf.clip_by_value(x, tf.cast(0., dtype=_FLOATX),
tf.cast(max_value, dtype=_FLOATX))
x -= tf.constant(alpha, dtype=_FLOATX) * negative_part
return x
def softmax(x):
return tf.nn.softmax(x)
def softplus(x):
return tf.nn.softplus(x)
def categorical_crossentropy(output, target, from_logits=False):
'''Note: tf.nn.softmax_cross_entropy_with_logits
expects logits, Keras expects probabilities.
'''
if not from_logits:
# scale preds so that the class probas of each sample sum to 1
output /= tf.reduce_sum(output,
reduction_indices=len(output.get_shape())-1,
keep_dims=True)
# manual computation of crossentropy
output = tf.clip_by_value(output, tf.cast(_EPSILON, dtype=_FLOATX),
tf.cast(1.-_EPSILON, dtype=_FLOATX))
return - tf.reduce_sum(target * tf.log(output),
reduction_indices=len(output.get_shape())-1)
else:
return tf.nn.softmax_cross_entropy_with_logits(output, target)
def binary_crossentropy(output, target, from_logits=False):
'''Note: tf.nn.sigmoid_cross_entropy_with_logits
expects logits, Keras expects probabilities.
'''
if not from_logits:
# transform back to logits
output = tf.clip_by_value(output, tf.cast(_EPSILON, dtype=_FLOATX),
tf.cast(1.-_EPSILON, dtype=_FLOATX))
output = tf.log(output / (1 - output))
return tf.nn.sigmoid_cross_entropy_with_logits(output, target)
def sigmoid(x):
return tf.nn.sigmoid(x)
def hard_sigmoid(x):
x = (0.2 * x) + 0.5
x = tf.clip_by_value(x, tf.cast(0., dtype=_FLOATX),
tf.cast(1., dtype=_FLOATX))
return x
def tanh(x):
return tf.nn.tanh(x)
def dropout(x, level, seed=None):
retain_prob = 1. - level
if seed is None:
seed = np.random.randint(10e6)
# the dummy 1. works around a TF bug
# (float32_ref vs. float32 incomptability)
return tf.nn.dropout(x * 1., retain_prob, seed=seed)
# CONVOLUTIONS
def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th'):
'''
Run on cuDNN if available.
border_mode: string, "same" or "valid".
dim_ordering: whether to use Theano or TensorFlow dimension ordering
in inputs/kernels/ouputs.
'''
if border_mode == 'same':
padding = 'SAME'
elif border_mode == 'valid':
padding = 'VALID'
else:
raise Exception('Invalid border mode: ' + str(border_mode))
strides = (1,) + strides + (1,)
if _FLOATX == 'float64':
# tf conv2d only supports float32
x = tf.cast(x, 'float32')
kernel = tf.cast(kernel, 'float32')
if dim_ordering == 'th':
# TF uses the last dimension as channel dimension,
# instead of the 2nd one.
# TH input shape: (samples, input_depth, rows, cols)
# TF input shape: (samples, rows, cols, input_depth)
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
x = tf.transpose(x, (0, 2, 3, 1))
kernel = tf.transpose(kernel, (2, 3, 1, 0))
x = tf.nn.conv2d(x, kernel, strides, padding=padding)
x = tf.transpose(x, (0, 3, 1, 2))
elif dim_ordering == 'tf':
x = tf.nn.conv2d(x, kernel, strides, padding=padding)
else:
raise Exception('Unknown dim_ordering: ' + str(dim_ordering))
if _FLOATX == 'float64':
x = tf.cast(x, 'float64')
return x
def maxpool2d(x, pool_size, strides=(1, 1),
border_mode='valid', dim_ordering='th'):
'''
pool_size: tuple of 2 integers.
strides: tuple of 2 integers.
border_mode: one of "valid", "same".
dim_ordering: one of "th", "tf".
'''
if border_mode == 'same':
padding = 'SAME'
elif border_mode == 'valid':
padding = 'VALID'
else:
raise Exception('Invalid border mode: ' + str(border_mode))
strides = (1,) + strides + (1,)
pool_size = (1,) + pool_size + (1,)
if _FLOATX == 'float64':
# tf max_pool only supports float32
x = tf.cast(x, 'float32')
if dim_ordering == 'th':
# TF uses the last dimension as channel dimension,
# instead of the 2nd one.
# TH input shape: (samples, input_depth, rows, cols)
# TF input shape: (samples, rows, cols, input_depth)
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
x = tf.transpose(x, (0, 2, 3, 1))
x = tf.nn.max_pool(x, pool_size, strides, padding=padding)
x = tf.transpose(x, (0, 3, 1, 2))
elif dim_ordering == 'tf':
x = tf.nn.max_pool(x, pool_size, strides, padding=padding)
else:
raise Exception('Unknown dim_ordering: ' + str(dim_ordering))
if _FLOATX == 'float64':
x = tf.cast(x, 'float64')
return x
# RANDOMNESS
def random_normal(shape, mean=0.0, std=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
return tf.random_normal(shape, mean=mean, stddev=std,
dtype=dtype, seed=seed)
def random_uniform(shape, low=0.0, high=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
return tf.random_uniform(shape, minval=low, maxval=high,
dtype=dtype, seed=seed)
+622
Ver Arquivo
@@ -0,0 +1,622 @@
import theano
from theano import tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
from theano.tensor.signal import downsample
import numpy as np
from .common import _FLOATX, _EPSILON
# INTERNAL UTILS
theano.config.floatX = _FLOATX
def _on_gpu():
'''Returns whether the session is set to
run on GPU or not (i.e. on CPU).
'''
return theano.config.device[:3] == 'gpu'
if _on_gpu():
'''Import cuDNN only if running on GPU:
not having Cuda install should not
prevent from running the present code.
'''
from theano.sandbox.cuda import dnn
# VARIABLE MANIPULATION
def variable(value, dtype=_FLOATX, name=None):
'''Instantiate a tensor variable.
'''
value = np.asarray(value, dtype=dtype)
return theano.shared(value=value, name=name, strict=False)
def placeholder(shape=None, ndim=None, dtype=_FLOATX, name=None):
'''Instantiate an input data placeholder variable.
'''
if shape is None and ndim is None:
raise Exception('Specify either a shape or ndim value.')
if shape is not None:
ndim = len(shape)
if ndim == 0:
return T.scalar(name=name, dtype=dtype)
elif ndim == 1:
return T.vector(name=name, dtype=dtype)
elif ndim == 2:
return T.matrix(name=name, dtype=dtype)
elif ndim == 3:
return T.tensor3(name=name, dtype=dtype)
elif ndim == 4:
return T.tensor4(name=name, dtype=dtype)
else:
raise Exception('ndim too large: ' + str(ndim))
def shape(x):
'''Return the shape of a tensor.
Warning: type returned will be different for
Theano backend (Theano tensor type) and TF backend (TF TensorShape).
'''
return x.shape
def ndim(x):
return x.ndim
def eval(x):
'''Run a graph.
'''
return x.eval()
def zeros(shape, dtype=_FLOATX, name=None):
'''Instantiate an all-zeros variable.
'''
return variable(np.zeros(shape), dtype, name)
def ones(shape, dtype=_FLOATX, name=None):
'''Instantiate an all-ones variable.
'''
return variable(np.ones(shape), dtype, name)
def ones_like(x):
return T.ones_like(x)
def zeros_like(x):
return T.zeros_like(x)
def count_params(x):
'''Return number of scalars in a tensor.
Return: numpy integer.
'''
return np.prod(x.shape.eval())
def cast(x, dtype):
return T.cast(x, dtype)
# LINEAR ALGEBRA
'''
Assumed overridden:
+, -, /, *, +=, -=, *=, /=
'''
def dot(x, y):
return T.dot(x, y)
def transpose(x):
return T.transpose(x)
def gather(reference, indices):
'''reference: a tensor.
indices: an int tensor of indices.
Return: a tensor of same type as reference.
'''
return reference[indices]
# ELEMENT-WISE OPERATIONS
def max(x, axis=None, keepdims=False):
return T.max(x, axis=axis, keepdims=keepdims)
def min(x, axis=None, keepdims=False):
return T.min(x, axis=axis, keepdims=keepdims)
def sum(x, axis=None, keepdims=False):
'''Sum of the values in a tensor, alongside the specified axis.
'''
return T.sum(x, axis=axis, keepdims=keepdims)
def prod(x, axis=None, keepdims=False):
'''Multiply the values in a tensor, alongside the specified axis.
'''
return T.prod(x, axis=axis, keepdims=keepdims)
def mean(x, axis=None, keepdims=False):
return T.mean(x, axis=axis, keepdims=keepdims)
def std(x, axis=None, keepdims=False):
return T.std(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 argmax(x, axis=-1):
return T.argmax(x, axis=axis, keepdims=False)
def argmin(x, axis=-1):
return T.argmin(x, axis=axis, keepdims=False)
def square(x):
return T.sqr(x)
def abs(x):
return T.abs_(x)
def sqrt(x):
x = T.clip(x, 0., np.inf)
return T.sqrt(x)
def exp(x):
return T.exp(x)
def log(x):
return T.log(x)
def round(x):
return T.round(x)
def pow(x, a):
return T.pow(x, a)
def clip(x, min_value, max_value):
if max_value < min_value:
max_value = min_value
return T.clip(x, min_value, max_value)
def equal(x, y):
return T.eq(x, y)
def maximum(x, y):
return T.maximum(x, y)
def minimum(x, y):
return T.minimum(x, y)
# SHAPE OPERATIONS
def concatenate(tensors, axis=-1):
return T.concatenate(tensors, axis=axis)
def reshape(x, shape):
return T.reshape(x, shape)
def permute_dimensions(x, pattern):
'''Transpose dimensions.
pattern should be a tuple or list of
dimension indices, e.g. [0, 2, 1].
'''
pattern = tuple(pattern)
return x.dimshuffle(pattern)
def repeat(x, n):
'''Repeat a 2D tensor:
if x has shape (samples, dim) and n=2,
the output will have shape (samples, 2, dim)
'''
tensors = [x] * n
stacked = T.stack(*tensors)
return stacked.dimshuffle((1, 0, 2))
def tile(x, n):
return T.tile(x, n)
def flatten(x):
'''Turn a n-D tensor into a 2D tensor where
the first dimension is conserved.
'''
x = T.reshape(x, (x.shape[0], T.prod(x.shape) // x.shape[0]))
return x
def expand_dims(x, dim=-1):
'''Add a 1-sized dimension at index "dim".
'''
pattern = [i for i in range(x.type.ndim)]
if dim < 0:
if x.type.ndim == 0:
dim = 0
else:
dim = dim % x.type.ndim + 1
pattern.insert(dim, 'x')
return x.dimshuffle(pattern)
def squeeze(x, axis):
'''Remove a 1-dimension from the tensor at index "axis".
'''
x = T.addbroadcast(x, axis)
return T.squeeze(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
really hard.
'''
input_shape = x.shape
output_shape = (input_shape[0],
input_shape[1] + 2 * padding,
input_shape[2])
output = T.zeros(output_shape)
return T.set_subtensor(output[:, padding:x.shape[1] + padding, :], x)
def spatial_2d_padding(x, padding=(1, 1), dim_ordering='th'):
'''Pad the 2nd and 3rd dimensions of a 4D tensor
with "padding[0]" and "padding[1]" (resp.) zeros left and right.
'''
input_shape = x.shape
if dim_ordering == 'th':
output_shape = (input_shape[0],
input_shape[1],
input_shape[2] + 2 * padding[0],
input_shape[3] + 2 * padding[1])
output = T.zeros(output_shape)
indices = (slice(None),
slice(None),
slice(padding[0], input_shape[2] + padding[0]),
slice(padding[1], input_shape[3] + padding[1]))
elif dim_ordering == 'tf':
output_shape = (input_shape[0],
input_shape[1] + 2 * padding[0],
input_shape[2] + 2 * padding[1],
input_shape[3])
output = T.zeros(output_shape)
indices = (slice(None),
slice(padding[0], input_shape[1] + padding[0]),
slice(padding[1], input_shape[2] + padding[1]),
slice(None))
else:
raise Exception('Invalid dim_ordering: ' + dim_ordering)
return T.set_subtensor(output[indices], x)
# VALUE MANIPULATION
def get_value(x):
if not hasattr(x, 'get_value'):
raise Exception("'get_value() can only be called on a variable. " +
"If you have an expression instead, use eval().")
return x.get_value()
def set_value(x, value):
x.set_value(np.asarray(value, dtype=x.dtype))
# GRAPH MANIPULATION
class Function(object):
def __init__(self, inputs, outputs, updates=[], **kwargs):
self.function = theano.function(inputs, outputs, updates=updates,
allow_input_downcast=True, **kwargs)
def __call__(self, inputs):
return self.function(*inputs)
def function(inputs, outputs, updates=[]):
return Function(inputs, outputs, updates=updates)
def gradients(loss, variables):
return T.grad(loss, variables)
# CONTROL FLOW
def rnn(step_function, inputs, initial_states,
go_backwards=False, masking=True):
'''Iterates over the time dimension of a tensor.
Parameters
----------
inputs: tensor of temporal data of shape (samples, time, ...)
(at least 3D).
step_function:
Parameters:
input: tensor with shape (samples, ...) (no time dimension),
representing input for the batch of samples at a certain
time step.
states: list of tensors.
Returns:
output: tensor with shape (samples, ...) (no time dimension),
new_states: list of tensors, same length and shapes
as 'states'.
initial_states: tensor with shape (samples, ...) (no time dimension),
containing the initial values for the states used in
the step function.
go_backwards: boolean. If True, do the iteration over
the time dimension in reverse order.
masking: boolean. If true, any input timestep inputs[s, i]
that is all-zeros will be skipped (states will be passed to
the next step unchanged) and the corresponding output will
be all zeros.
Returns
-------
A tuple (last_output, outputs, new_states).
last_output: the latest output of the rnn, of shape (samples, ...)
outputs: tensor with shape (samples, time, ...) where each
entry outputs[s, t] is the output of the step function
at time t for sample s.
new_states: list of tensors, latest states returned by
the step function, of shape (samples, ...).
'''
inputs = inputs.dimshuffle((1, 0, 2))
def _step(*args):
global single_result
input = args[0]
states = args[1:]
output, new_states = step_function(input, states)
if masking:
# if all-zero input timestep, return
# all-zero output and unchanged states
switch = T.any(input)
output = T.switch(switch, output, 0. * output)
return_states = []
for state, new_state in zip(states, new_states):
return_states.append(T.switch(switch, new_state, state))
return [output] + return_states
else:
return [output] + new_states
results, _ = theano.scan(
_step,
sequences=inputs,
outputs_info=[None] + initial_states,
go_backwards=go_backwards)
# deal with Theano API inconsistency
if type(results) is list:
outputs = results[0]
states = results[1:]
else:
outputs = results
states = []
outputs = T.squeeze(outputs)
last_output = outputs[-1]
outputs = outputs.dimshuffle((1, 0, 2))
states = [T.squeeze(state[-1]) for state in states]
return last_output, outputs, states
def switch(condition, then_expression, else_expression):
'''condition: scalar tensor.
'''
return T.switch(condition, then_expression, else_expression)
# NN OPERATIONS
def relu(x, alpha=0., max_value=None):
x = T.nnet.relu(x, alpha)
if max_value is not None:
x = T.minimum(x, max_value)
return x
def softmax(x):
return T.nnet.softmax(x)
def softplus(x):
return T.nnet.softplus(x)
def categorical_crossentropy(output, target, from_logits=False):
if from_logits:
output = T.nnet.softmax(output)
else:
# scale preds so that the class probas of each sample sum to 1
output /= output.sum(axis=-1, keepdims=True)
# avoid numerical instability with _EPSILON clipping
output = T.clip(output, _EPSILON, 1.0 - _EPSILON)
return T.nnet.categorical_crossentropy(output, target)
def binary_crossentropy(output, target, from_logits=False):
if from_logits:
output = T.nnet.sigmoid(output)
# avoid numerical instability with _EPSILON clipping
output = T.clip(output, _EPSILON, 1.0 - _EPSILON)
return T.nnet.binary_crossentropy(output, target)
def sigmoid(x):
return T.nnet.sigmoid(x)
def hard_sigmoid(x):
return T.nnet.hard_sigmoid(x)
def tanh(x):
return T.tanh(x)
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)
rng = RandomStreams(seed=seed)
retain_prob = 1. - level
x *= rng.binomial(x.shape, p=retain_prob, dtype=x.dtype)
x /= retain_prob
return x
# CONVOLUTIONS
def conv2d(x, kernel, strides=(1, 1), border_mode='valid', dim_ordering='th'):
'''
Run on cuDNN if available.
border_mode: string, "same" or "valid".
'''
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
if dim_ordering == 'tf':
# TF uses the last dimension as channel dimension,
# instead of the 2nd one.
# TH input shape: (samples, input_depth, rows, cols)
# TF input shape: (samples, rows, cols, input_depth)
# TH kernel shape: (depth, input_depth, rows, cols)
# TF kernel shape: (rows, cols, input_depth, depth)
x = x.dimshuffle((0, 3, 1, 2))
kernel = kernel.dimshuffle((3, 2, 0, 1))
if _on_gpu() and dnn.dnn_available():
if border_mode == 'same':
assert(strides == (1, 1))
pad_x = (kernel.shape[2] - strides[0]) // 2
pad_y = (kernel.shape[3] - strides[1]) // 2
conv_out = dnn.dnn_conv(img=x,
kerns=kernel,
border_mode=(pad_x, pad_y))
else:
conv_out = dnn.dnn_conv(img=x,
kerns=kernel,
border_mode=border_mode,
subsample=strides)
else:
if border_mode == 'same':
th_border_mode = 'full'
assert(strides == (1, 1))
elif border_mode == 'valid':
th_border_mode = 'valid'
else:
raise Exception('Border mode not supported: ' + str(border_mode))
conv_out = T.nnet.conv.conv2d(x, kernel,
border_mode=th_border_mode,
subsample=strides)
if border_mode == 'same':
shift_x = (kernel.shape[2] - 1) // 2
shift_y = (kernel.shape[3] - 1) // 2
conv_out = conv_out[:, :,
shift_x:x.shape[2] + shift_x,
shift_y:x.shape[3] + shift_y]
if dim_ordering == 'tf':
conv_out = conv_out.dimshuffle((0, 2, 3, 1))
return conv_out
def maxpool2d(x, pool_size, strides=(1, 1), border_mode='valid',
dim_ordering='th'):
if border_mode == 'same':
# TODO: add implementation for border_mode="same"
raise Exception('border_mode="same" not supported with Theano.')
elif border_mode == 'valid':
ignore_border = True
padding = (0, 0)
else:
raise Exception('Invalid border mode: ' + str(border_mode))
if dim_ordering not in {'th', 'tf'}:
raise Exception('Unknown dim_ordering ' + str(dim_ordering))
if dim_ordering == 'tf':
x = x.dimshuffle((0, 3, 1, 2))
pool_out = downsample.max_pool_2d(x,
ds=pool_size,
st=strides,
ignore_border=ignore_border,
padding=padding,
mode='average_exc_pad')
if dim_ordering == 'tf':
pool_out = pool_out.dimshuffle((0, 2, 3, 1))
return pool_out
# RANDOMNESS
def random_normal(shape, mean=0.0, std=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(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)
rng = RandomStreams(seed=seed)
return rng.uniform(shape, low=low, high=high, dtype=dtype)
'''
more TODO:
tensordot -> soon to be introduced in TF
batched_tensordot -> reimplement
'''
+23 -4
Ver Arquivo
@@ -2,7 +2,9 @@ from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import time, json, warnings
import time
import json
import warnings
from collections import deque
from .utils.generic_utils import Progbar
@@ -173,14 +175,31 @@ class History(Callback):
class ModelCheckpoint(Callback):
def __init__(self, filepath, monitor='val_loss', verbose=0, save_best_only=False):
def __init__(self, filepath, monitor='val_loss', verbose=0, save_best_only=False, mode='auto'):
super(Callback, self).__init__()
self.monitor = monitor
self.verbose = verbose
self.filepath = filepath
self.save_best_only = save_best_only
self.best = np.Inf
if mode not in ['auto', 'min', 'max']:
warnings.warn("ModelCheckpoint mode %s is unknown, 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_epoch_end(self, epoch, logs={}):
filepath = self.filepath.format(epoch=epoch, **logs)
@@ -189,7 +208,7 @@ class ModelCheckpoint(Callback):
if current is None:
warnings.warn("Can save best model only with %s available, skipping." % (self.monitor), RuntimeWarning)
else:
if current < self.best:
if self.monitor_op(current, self.best):
if self.verbose > 0:
print("Epoch %05d: %s improved from %0.5f to %0.5f, saving model to %s"
% (epoch, self.monitor, self.best, current, filepath))
+5 -8
Ver Arquivo
@@ -1,7 +1,5 @@
from __future__ import absolute_import
import theano
import theano.tensor as T
import numpy as np
from . import backend as K
class Constraint(object):
@@ -17,8 +15,8 @@ class MaxNorm(Constraint):
self.m = m
def __call__(self, p):
norms = T.sqrt(T.sum(T.sqr(p), axis=0))
desired = T.clip(norms, 0, self.m)
norms = K.sqrt(K.sum(K.square(p), axis=0))
desired = K.clip(norms, 0, self.m)
p = p * (desired / (1e-7 + norms))
return p
@@ -29,14 +27,13 @@ class MaxNorm(Constraint):
class NonNeg(Constraint):
def __call__(self, p):
p = theano.shared(p)
p *= T.ge(p, 0.)
p *= K.cast(p >= 0., K.floatx())
return p
class UnitNorm(Constraint):
def __call__(self, p):
return p / T.sqrt(T.sum(p**2, axis=-1, keepdims=True))
return p / K.sqrt(K.sum(K.square(p), axis=-1, keepdims=True))
identity = Constraint
maxnorm = MaxNorm
+7 -7
Ver Arquivo
@@ -1,14 +1,17 @@
from __future__ import absolute_import
from __future__ import print_function
import tarfile, inspect, os
import tarfile
import os
from six.moves.urllib.request import FancyURLopener
from ..utils.generic_utils import Progbar
class ParanoidURLopener(FancyURLopener):
def http_error_default(self, url, fp, errcode, errmsg, headers):
raise Exception('URL fetch failure on {}: {} -- {}'.format(url, errcode, errmsg))
def http_error_default(self, url, fp, errcode, errmsg, headers):
raise Exception('URL fetch failure on {}: {} -- {}'.format(url, errcode, errmsg))
def get_file(fname, origin, untar=False):
datadir = os.path.expanduser(os.path.join('~', '.keras', 'datasets'))
@@ -21,11 +24,8 @@ def get_file(fname, origin, untar=False):
else:
fpath = os.path.join(datadir, fname)
try:
f = open(fpath)
except:
if not os.path.exists(fpath):
print('Downloading data from', origin)
global progbar
progbar = None
+7 -10
Ver Arquivo
@@ -1,9 +1,6 @@
from __future__ import absolute_import
import theano
import theano.tensor as T
import numpy as np
from .utils.theano_utils import sharedX, shared_zeros, shared_ones
from . import backend as K
def get_fans(shape):
@@ -13,11 +10,11 @@ def get_fans(shape):
def uniform(shape, scale=0.05):
return sharedX(np.random.uniform(low=-scale, high=scale, size=shape))
return K.variable(np.random.uniform(low=-scale, high=scale, size=shape))
def normal(shape, scale=0.05):
return sharedX(np.random.randn(*shape) * scale)
return K.variable(np.random.randn(*shape) * scale)
def lecun_uniform(shape):
@@ -66,22 +63,22 @@ def orthogonal(shape, scale=1.1):
# pick the one with the correct shape
q = u if u.shape == flat_shape else v
q = q.reshape(shape)
return sharedX(scale * q[:shape[0], :shape[1]])
return K.variable(scale * q[:shape[0], :shape[1]])
def identity(shape, scale=1):
if len(shape) != 2 or shape[0] != shape[1]:
raise Exception("Identity matrix initialization can only be used for 2D square matrices")
else:
return sharedX(scale * np.identity(shape[0]))
return K.variable(scale * np.identity(shape[0]))
def zero(shape):
return shared_zeros(shape)
return K.zeros(shape)
def one(shape):
return shared_ones(shape)
return K.ones(shape)
from .utils.generic_utils import get_from_module
+30 -12
Ver Arquivo
@@ -1,7 +1,6 @@
from .. import initializations
from ..layers.core import Layer, MaskedLayer
from ..utils.theano_utils import shared_zeros, shared_ones, sharedX
import theano.tensor as T
from .. import backend as K
import numpy as np
@@ -12,7 +11,7 @@ class LeakyReLU(MaskedLayer):
def get_output(self, train):
X = self.get_input(train)
return T.nnet.relu(X, self.alpha)
return K.relu(X, alpha=self.alpha)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -24,7 +23,8 @@ class LeakyReLU(MaskedLayer):
class PReLU(MaskedLayer):
'''
Reference:
Delving Deep into Rectifiers: Surpassing Human-Level Performance on ImageNet Classification
Delving Deep into Rectifiers: Surpassing Human-Level
Performance on ImageNet Classification
http://arxiv.org/pdf/1502.01852v1.pdf
'''
def __init__(self, init='zero', weights=None, **kwargs):
@@ -43,7 +43,7 @@ class PReLU(MaskedLayer):
def get_output(self, train):
X = self.get_input(train)
pos = T.nnet.relu(X)
pos = K.relu(X)
neg = self.alphas * (X - abs(X)) * 0.5
return pos + neg
@@ -54,12 +54,31 @@ class PReLU(MaskedLayer):
return dict(list(base_config.items()) + list(config.items()))
class ELU(MaskedLayer):
def __init__(self, alpha=1.0, **kwargs):
super(ELU, self).__init__(**kwargs)
self.alpha = alpha
def get_output(self, train):
X = self.get_input(train)
pos = K.relu(X)
neg = (X - abs(X)) * 0.5
return pos + self.alpha * (K.exp(neg) - 1.)
def get_config(self):
config = {"name": self.__class__.__name__,
"alpha": self.alpha}
base_config = super(ELU, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class ParametricSoftplus(MaskedLayer):
'''
Parametric Softplus of the form: alpha * log(1 + exp(beta * X))
Reference:
Inferring Nonlinear Neuronal Computation Based on Physiologically Plausible Inputs
Inferring Nonlinear Neuronal Computation
Based on Physiologically Plausible Inputs
http://journals.plos.org/ploscompbiol/article?id=10.1371/journal.pcbi.1003143
'''
def __init__(self, alpha_init=0.2, beta_init=5.0,
@@ -71,10 +90,9 @@ class ParametricSoftplus(MaskedLayer):
def build(self):
input_shape = self.input_shape[1:]
self.alphas = sharedX(self.alpha_init * np.ones(input_shape))
self.betas = sharedX(self.beta_init * np.ones(input_shape))
self.alphas = K.variable(self.alpha_init * np.ones(input_shape))
self.betas = K.variable(self.beta_init * np.ones(input_shape))
self.params = [self.alphas, self.betas]
self.input_shape = input_shape
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
@@ -82,7 +100,7 @@ class ParametricSoftplus(MaskedLayer):
def get_output(self, train):
X = self.get_input(train)
return T.nnet.softplus(self.betas * X) * self.alphas
return K.softplus(self.betas * X) * self.alphas
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -106,7 +124,7 @@ class ThresholdedLinear(MaskedLayer):
def get_output(self, train):
X = self.get_input(train)
return T.switch(abs(X) < self.theta, 0, X)
return K.switch(K.abs(X) < self.theta, 0, X)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -129,7 +147,7 @@ class ThresholdedReLU(MaskedLayer):
def get_output(self, train):
X = self.get_input(train)
return T.switch(X > self.theta, X, 0)
return K.switch(X > self.theta, X, 0)
def get_config(self):
config = {"name": self.__class__.__name__,
+175 -39
Ver Arquivo
@@ -2,9 +2,9 @@
from __future__ import absolute_import
from __future__ import print_function
import theano.tensor as T
from ..layers.core import Layer, Merge
from ..utils.theano_utils import ndim_tensor
from collections import OrderedDict
from .. import backend as K
from ..layers.core import Layer, Merge, Siamese, SiameseHead
from six.moves import range
@@ -20,11 +20,6 @@ class Sequential(Layer):
def __init__(self, layers=[]):
self.layers = []
self.params = []
self.regularizers = []
self.constraints = []
self.updates = []
for layer in layers:
self.add(layer)
@@ -38,11 +33,37 @@ class Sequential(Layer):
if not hasattr(self.layers[0], 'input'):
self.set_input()
params, regularizers, constraints, updates = layer.get_params()
self.params += params
self.regularizers += regularizers
self.constraints += constraints
self.updates += updates
@property
def params(self):
params = []
for l in self.layers:
if l.trainable:
params += l.get_params()[0]
return params
@property
def regularizers(self):
regularizers = []
for l in self.layers:
if l.trainable:
regularizers += l.get_params()[1]
return regularizers
@property
def constraints(self):
constraints = []
for l in self.layers:
if l.trainable:
constraints += l.get_params()[2]
return constraints
@property
def updates(self):
updates = []
for l in self.layers:
if l.trainable:
updates += l.get_params()[3]
return updates
@property
def output_shape(self):
@@ -54,8 +75,8 @@ class Sequential(Layer):
def set_input(self):
for l in self.layers:
if hasattr(l, 'input'):
ndim = l.input.ndim
self.layers[0].input = ndim_tensor(ndim)
ndim = len(K.get_shape(l.input))
self.layers[0].input = K.placeholder(ndim=ndim)
break
def get_input(self, train=False):
@@ -63,6 +84,10 @@ class Sequential(Layer):
self.set_input()
return self.layers[0].get_input(train)
@property
def input_shape(self):
return self.layers[0].input_shape
@property
def input(self):
return self.get_input()
@@ -97,7 +122,6 @@ class Graph(Layer):
when it has exactly one input and one output.
inherited from Layer:
- get_params
- get_output_mask
- supports_masked_input
- get_weights
@@ -105,7 +129,7 @@ class Graph(Layer):
'''
def __init__(self):
self.namespace = set() # strings
self.nodes = {} # layer-like
self.nodes = OrderedDict() # layer-like
self.inputs = {} # layer-like
self.input_order = [] # strings
self.outputs = {} # layer-like
@@ -114,11 +138,6 @@ class Graph(Layer):
self.output_config = [] # dicts
self.node_config = [] # dicts
self.params = []
self.regularizers = []
self.constraints = []
self.updates = []
@property
def nb_input(self):
return len(self.inputs)
@@ -127,6 +146,38 @@ class Graph(Layer):
def nb_output(self):
return len(self.outputs)
@property
def params(self):
params = []
for l in self.nodes.values():
if l.trainable:
params += l.get_params()[0]
return params
@property
def regularizers(self):
regularizers = []
for l in self.nodes.values():
if l.trainable:
regularizers += l.get_params()[1]
return regularizers
@property
def constraints(self):
constraints = []
for l in self.nodes.values():
if l.trainable:
constraints += l.get_params()[2]
return constraints
@property
def updates(self):
updates = []
for l in self.nodes.values():
if l.trainable:
updates += l.get_params()[3]
return updates
def set_previous(self, layer, connection_map={}):
if self.nb_input != layer.nb_output:
raise Exception('Cannot connect layers: input count does not match output count.')
@@ -173,24 +224,23 @@ class Graph(Layer):
self.input_order.append(name)
layer = Layer() # empty layer
layer.set_input_shape(input_shape)
ndim = len(input_shape) + 1
if dtype == 'float':
layer.input = ndim_tensor(ndim)
layer.input = K.placeholder(shape=layer.input_shape, name=name)
else:
if ndim == 2:
layer.input = T.imatrix()
if len(input_shape) == 1:
layer.input = K.placeholder(shape=layer.input_shape,
dtype='int32',
name=name)
else:
raise Exception('Type "int" can only be used with ndim==2 (Embedding).')
layer.input.name = name
self.inputs[name] = layer
self.input_config.append({'name': name,
'input_shape': input_shape,
'dtype': dtype})
def add_node(self, layer, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1, create_output=False):
if hasattr(layer, 'set_name'):
layer.set_name(name)
merge_mode='concat', concat_axis=-1, dot_axes=-1,
create_output=False):
if name in self.namespace:
raise Exception('Duplicate node identifier: ' + name)
if input:
@@ -209,7 +259,8 @@ class Graph(Layer):
to_merge.append(self.inputs[n])
else:
raise Exception('Unknown identifier: ' + n)
merge = Merge(to_merge, mode=merge_mode, concat_axis=concat_axis)
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes)
layer.set_previous(merge)
self.namespace.add(name)
@@ -219,18 +270,89 @@ class Graph(Layer):
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'create_output': create_output})
params, regularizers, constraints, updates = layer.get_params()
self.params += params
self.regularizers += regularizers
self.constraints += constraints
self.updates += updates
if create_output:
self.add_output(name, input=name)
def add_shared_node(self, layer, name, inputs=[], merge_mode=None,
concat_axis=-1, dot_axes=-1, outputs=[],
create_output=False):
'''
Used to shared / multi input-multi output node
Arguments
------------
layer - The layer to be shared across multiple inputs
name - Name of the shared layer
inputs - List of names of input nodes
merge_mode - Similar to merge_mode argument of add_node()
concat_axis - Similar to concat_axis argument of add_node()
dot_axes - Similar to dot_axes argument of add_node()
outputs - Names for output nodes. Used when merge_mode = None
create_output - Similar to create_output argument of add_node().
Output will be created only if merge_mode is given
'''
if name in self.namespace:
raise Exception('Duplicate node identifier: ' + name)
for o in outputs:
if o in self.namespace:
raise Exception('Duplicate node identifier: ' + o)
if merge_mode:
if merge_mode not in {'sum', 'ave', 'mul', 'dot', 'cos', 'concat', 'join'}:
raise Eception("Invalid merge mode")
layers = []
for i in range(len(inputs)):
input = inputs[i]
if input in self.nodes:
n = self.nodes[input]
if n.__class__.__name__ == 'Siamese':
if n.merge_mode is None:
for j in range(len(n.inputs)):
sh = SiameseHead(j)
sh.previous = n
layers.append(sh)
else:
layers.append(n)
else:
layers.append(n)
elif input in self.inputs:
n = self.inputs[input]
layers.append(n)
else:
raise Exception('Unknown identifier: ' + input)
s = Siamese(layer, layers, merge_mode, concat_axis=concat_axis, dot_axes=dot_axes)
s.set_name(name)
self.namespace.add(name)
self.nodes[name] = s
self.node_config.append({'name': name,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis,
'dot_axes': dot_axes,
'create_output': create_output if merge_mode else False})
if not merge_mode:
for i in range(len(outputs)):
sh = SiameseHead(i)
sh.previous = s
sh_name = outputs[i]
sh.set_name(sh_name)
self.namespace.add(sh_name)
self.nodes[sh_name] = sh
self.node_config.append({'name': sh_name,
'inputs': [s],
'create_output': create_output})
if create_output:
self.add_output(sh_name, input=sh_name)
if create_output and merge_mode:
if merge_mode == 'join':
raise Exception("Output can not be of type OrderedDict")
self.add_output(name, input=name)
def add_output(self, name, input=None, inputs=[],
merge_mode='concat', concat_axis=-1):
merge_mode='concat', concat_axis=-1, dot_axes=-1):
if name in self.output_order:
raise Exception('Duplicate output identifier: ' + name)
if input:
@@ -246,7 +368,8 @@ class Graph(Layer):
if n not in self.nodes:
raise Exception('Unknown identifier: ' + n)
to_merge.append(self.nodes[n])
merge = Merge(to_merge, mode=merge_mode, concat_axis=concat_axis)
merge = Merge(to_merge, mode=merge_mode,
concat_axis=concat_axis, dot_axes=dot_axes)
self.outputs[name] = merge
self.output_order.append(name)
@@ -254,7 +377,8 @@ class Graph(Layer):
'input': input,
'inputs': inputs,
'merge_mode': merge_mode,
'concat_axis': concat_axis})
'concat_axis': concat_axis,
'dot_axes': dot_axes})
def get_config(self):
return {"name": self.__class__.__name__,
@@ -267,3 +391,15 @@ class Graph(Layer):
def count_params(self):
return sum([layer.count_params() for layer in self.nodes.values()])
def get_weights(self):
weights = []
for layer in self.nodes.values():
weights += layer.get_weights()
return weights
def set_weights(self, weights):
for layer in self.nodes.values():
nb_param = len(layer.get_weights())
layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
+174 -173
Ver Arquivo
@@ -1,53 +1,22 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
import theano
import theano.tensor as T
from theano.tensor.signal import downsample
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..utils.theano_utils import shared_zeros, on_gpu
from ..layers.core import Layer
if on_gpu():
from theano.sandbox.cuda import dnn
def conv_output_length(input_length, filter_size, border_mode, stride):
if input_length is None:
return None
assert border_mode in {'same', 'full', 'valid'}
assert border_mode in {'same', 'valid'}
if border_mode == 'same':
output_length = input_length
elif border_mode == 'full':
output_length = input_length + filter_size - 1
elif border_mode == 'valid':
output_length = input_length - filter_size + 1
return (output_length + stride - 1) // stride
def pool_output_length(input_length, pool_size, ignore_border, stride):
if input_length is None:
return None
if ignore_border:
output_length = input_length - pool_size + 1
output_length = (output_length + stride - 1) // stride
else:
if pool_size == input_length:
output_length = min(input_length, stride - stride % 2)
if output_length <= 0:
output_length = 1
elif stride >= pool_size:
output_length = (input_length + stride - 1) // stride
else:
output_length = (input_length - pool_size + stride - 1) // stride
if output_length <= 0:
output_length = 1
else:
output_length += 1
return output_length
class Convolution1D(Layer):
input_ndim = 3
@@ -55,14 +24,16 @@ class Convolution1D(Layer):
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, input_dim=None, input_length=None, **kwargs):
W_constraint=None, b_constraint=None,
input_dim=None, input_length=None, **kwargs):
if border_mode not in {'valid', 'full', 'same'}:
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for Convolution1D:', border_mode)
self.nb_filter = nb_filter
self.filter_length = filter_length
self.init = initializations.get(init)
self.activation = activations.get(activation)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
self.subsample_length = subsample_length
@@ -82,14 +53,14 @@ class Convolution1D(Layer):
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
self.input = K.placeholder(ndim=3)
super(Convolution1D, self).__init__(**kwargs)
def build(self):
input_dim = self.input_shape[2]
self.input = T.tensor3()
self.W_shape = (self.nb_filter, input_dim, self.filter_length, 1)
self.W = self.init(self.W_shape)
self.b = shared_zeros((self.nb_filter,))
self.b = K.zeros((self.nb_filter,))
self.params = [self.W, self.b]
self.regularizers = []
@@ -111,44 +82,23 @@ class Convolution1D(Layer):
@property
def output_shape(self):
length = conv_output_length(self.input_shape[1], self.filter_length, self.border_mode, self.subsample[0])
length = conv_output_length(self.input_shape[1],
self.filter_length,
self.border_mode,
self.subsample[0])
return (self.input_shape[0], length, self.nb_filter)
def get_output(self, train=False):
X = self.get_input(train)
X = T.reshape(X, (X.shape[0], X.shape[1], X.shape[2], 1)).dimshuffle(0, 2, 1, 3)
X = K.expand_dims(X, -1) # add a dimension of the right
X = K.permute_dimensions(X, (0, 2, 1, 3))
conv_out = K.conv2d(X, self.W, strides=self.subsample,
border_mode=self.border_mode, dim_ordering='th')
border_mode = self.border_mode
if on_gpu() and dnn.dnn_available():
if border_mode == 'same':
assert(self.subsample_length == 1)
pad_x = (self.filter_length - self.subsample_length) // 2
conv_out = dnn.dnn_conv(img=X,
kerns=self.W,
border_mode=(pad_x, 0))
else:
conv_out = dnn.dnn_conv(img=X,
kerns=self.W,
border_mode=border_mode,
subsample=self.subsample)
else:
if border_mode == 'same':
assert(self.subsample_length == 1)
border_mode = 'full'
input_shape = self.input_shape
image_shape = (input_shape[0], input_shape[2], input_shape[1], 1)
conv_out = T.nnet.conv.conv2d(X, self.W,
border_mode=border_mode,
subsample=self.subsample,
image_shape=image_shape,
filter_shape=self.W_shape)
if self.border_mode == 'same':
shift_x = (self.filter_length - 1) // 2
conv_out = conv_out[:, :, shift_x:X.shape[2] + shift_x, :]
output = self.activation(conv_out + self.b.dimshuffle('x', 0, 'x', 'x'))
output = T.reshape(output, (output.shape[0], output.shape[1], output.shape[2])).dimshuffle(0, 2, 1)
output = conv_out + K.reshape(self.b, (1, self.nb_filter, 1, 1))
output = self.activation(output)
output = K.squeeze(output, 3) # remove the dummy 3rd dimension
output = K.permute_dimensions(output, (0, 2, 1))
return output
def get_config(self):
@@ -175,19 +125,22 @@ class Convolution2D(Layer):
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1),
border_mode='valid', subsample=(1, 1), dim_ordering='th',
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None, **kwargs):
if border_mode not in {'valid', 'full', 'same'}:
if border_mode not in {'valid', 'same'}:
raise Exception('Invalid border mode for Convolution2D:', border_mode)
self.nb_filter = nb_filter
self.nb_row = nb_row
self.nb_col = nb_col
self.init = initializations.get(init)
self.activation = activations.get(activation)
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
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)
@@ -198,14 +151,20 @@ class Convolution2D(Layer):
self.constraints = [self.W_constraint, self.b_constraint]
self.initial_weights = weights
self.input = K.placeholder(ndim=4)
super(Convolution2D, self).__init__(**kwargs)
def build(self):
stack_size = self.input_shape[1]
self.input = T.tensor4()
self.W_shape = (self.nb_filter, stack_size, self.nb_row, self.nb_col)
if self.dim_ordering == 'th':
stack_size = self.input_shape[1]
self.W_shape = (self.nb_filter, stack_size, self.nb_row, self.nb_col)
elif self.dim_ordering == 'tf':
stack_size = self.input_shape[3]
self.W_shape = (self.nb_row, self.nb_col, stack_size, self.nb_filter)
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
self.W = self.init(self.W_shape)
self.b = shared_zeros((self.nb_filter,))
self.b = K.zeros((self.nb_filter,))
self.params = [self.W, self.b]
self.regularizers = []
@@ -228,44 +187,36 @@ class Convolution2D(Layer):
@property
def output_shape(self):
input_shape = self.input_shape
rows = input_shape[2]
cols = input_shape[3]
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])
return (input_shape[0], self.nb_filter, rows, cols)
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 get_output(self, train=False):
X = self.get_input(train)
border_mode = self.border_mode
if on_gpu() and dnn.dnn_available():
if border_mode == 'same':
assert(self.subsample == (1, 1))
pad_x = (self.nb_row - self.subsample[0]) // 2
pad_y = (self.nb_col - self.subsample[1]) // 2
conv_out = dnn.dnn_conv(img=X,
kerns=self.W,
border_mode=(pad_x, pad_y))
else:
conv_out = dnn.dnn_conv(img=X,
kerns=self.W,
border_mode=border_mode,
subsample=self.subsample)
else:
if border_mode == 'same':
border_mode = 'full'
assert(self.subsample == (1, 1))
conv_out = K.conv2d(X, self.W, strides=self.subsample,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
conv_out = T.nnet.conv.conv2d(X, self.W,
border_mode=border_mode,
subsample=self.subsample,
image_shape=self.input_shape,
filter_shape=self.W_shape)
if self.border_mode == 'same':
shift_x = (self.nb_row - 1) // 2
shift_y = (self.nb_col - 1) // 2
conv_out = conv_out[:, :, shift_x:X.shape[2] + shift_x, shift_y:X.shape[3] + shift_y]
return self.activation(conv_out + self.b.dimshuffle('x', 0, 'x', 'x'))
output = conv_out + K.reshape(self.b, (1, self.nb_filter, 1, 1))
output = self.activation(output)
return output
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -276,6 +227,7 @@ class Convolution2D(Layer):
"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,
@@ -288,36 +240,41 @@ class Convolution2D(Layer):
class MaxPooling1D(Layer):
input_ndim = 3
def __init__(self, pool_length=2, stride=None, ignore_border=True, **kwargs):
def __init__(self, pool_length=2, stride=None,
border_mode='valid', **kwargs):
super(MaxPooling1D, self).__init__(**kwargs)
if stride is None:
stride = pool_length
self.pool_length = pool_length
self.stride = stride
self.st = (self.stride, 1)
self.input = T.tensor3()
self.input = K.placeholder(ndim=3)
self.pool_size = (pool_length, 1)
self.ignore_border = ignore_border
assert border_mode in {'valid', 'same'}, 'border_mode must be in {valid, same}'
self.border_mode = border_mode
@property
def output_shape(self):
input_shape = self.input_shape
length = pool_output_length(input_shape[1], self.pool_length, self.ignore_border, self.stride)
length = conv_output_length(input_shape[1], self.pool_length,
self.border_mode, self.stride)
return (input_shape[0], length, input_shape[2])
def get_output(self, train=False):
X = self.get_input(train)
X = T.reshape(X, (X.shape[0], X.shape[1], X.shape[2], 1)).dimshuffle(0, 2, 1, 3)
output = downsample.max_pool_2d(X, ds=self.pool_size, st=self.st, ignore_border=self.ignore_border)
output = output.dimshuffle(0, 2, 1, 3)
return T.reshape(output, (output.shape[0], output.shape[1], output.shape[2]))
X = K.expand_dims(X, -1) # add dummy last dimension
X = K.permute_dimensions(X, (0, 2, 1, 3))
output = K.maxpool2d(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 = {"name": self.__class__.__name__,
"stride": self.stride,
"pool_length": self.pool_length,
"ignore_border": self.ignore_border}
"border_mode": self.border_mode}
base_config = super(MaxPooling1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -325,43 +282,68 @@ class MaxPooling1D(Layer):
class MaxPooling2D(Layer):
input_ndim = 4
def __init__(self, pool_size=(2, 2), stride=None, ignore_border=True, **kwargs):
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
super(MaxPooling2D, self).__init__(**kwargs)
self.input = T.tensor4()
self.input = K.placeholder(ndim=4)
self.pool_size = tuple(pool_size)
if stride is None:
stride = self.pool_size
self.stride = tuple(stride)
self.ignore_border = ignore_border
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
@property
def output_shape(self):
input_shape = self.input_shape
rows = pool_output_length(input_shape[2], self.pool_size[0], self.ignore_border, self.stride[0])
cols = pool_output_length(input_shape[3], self.pool_size[1], self.ignore_border, self.stride[1])
return (input_shape[0], input_shape[1], rows, cols)
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 get_output(self, train=False):
X = self.get_input(train)
output = downsample.max_pool_2d(X, ds=self.pool_size, st=self.stride, ignore_border=self.ignore_border)
output = K.maxpool2d(X, pool_size=self.pool_size,
strides=self.strides,
border_mode=self.border_mode,
dim_ordering=self.dim_ordering)
return output
def get_config(self):
config = {"name": self.__class__.__name__,
"pool_size": self.pool_size,
"ignore_border": self.ignore_border,
"stride": self.stride}
"border_mode": self.border_mode,
"strides": self.strides,
"dim_ordering": self.dim_ordering}
base_config = super(MaxPooling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class UpSample1D(Layer):
class UpSampling1D(Layer):
input_ndim = 3
def __init__(self, length=2, **kwargs):
super(UpSample1D, self).__init__(**kwargs)
super(UpSampling1D, self).__init__(**kwargs)
self.length = length
self.input = T.tensor3()
self.input = K.placeholder(ndim=3)
@property
def output_shape(self):
@@ -370,39 +352,58 @@ class UpSample1D(Layer):
def get_output(self, train=False):
X = self.get_input(train)
output = theano.tensor.extra_ops.repeat(X, self.length, axis=1)
output = K.concatenate([X] * self.length, axis=1)
return output
def get_config(self):
config = {"name": self.__class__.__name__,
"length": self.length}
base_config = super(UpSample1D, self).get_config()
base_config = super(UpSampling1D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class UpSample2D(Layer):
class UpSampling2D(Layer):
input_ndim = 4
def __init__(self, size=(2, 2), **kwargs):
super(UpSample2D, self).__init__(**kwargs)
self.input = T.tensor4()
def __init__(self, size=(2, 2), dim_ordering='th', **kwargs):
super(UpSampling2D, self).__init__(**kwargs)
self.input = K.placeholder(ndim=4)
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
@property
def output_shape(self):
input_shape = self.input_shape
return (input_shape[0], input_shape[1], self.size[0] * input_shape[2], self.size[1] * input_shape[3])
if self.dim_ordering == 'th':
return (input_shape[0],
input_shape[1],
self.size[0] * input_shape[2],
self.size[1] * input_shape[3])
elif self.dim_ordering == 'tf':
return (input_shape[0],
self.size[0] * input_shape[1],
self.size[1] * input_shape[2],
input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
Y = theano.tensor.extra_ops.repeat(X, self.size[0], axis=2)
output = theano.tensor.extra_ops.repeat(Y, self.size[1], axis=3)
if self.dim_ordering == 'th':
output = K.concatenate([X] * self.size[0], axis=2)
output = K.concatenate([output] * self.size[1], axis=3)
elif self.dim_ordering == 'tf':
output = K.concatenate([X] * self.size[0], axis=1)
output = K.concatenate([output] * self.size[1], axis=2)
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
return output
def get_config(self):
config = {"name": self.__class__.__name__,
"size": self.size}
base_config = super(UpSample2D, self).get_config()
base_config = super(UpSampling2D, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -428,21 +429,18 @@ class ZeroPadding1D(Layer):
def __init__(self, padding=1, **kwargs):
super(ZeroPadding1D, self).__init__(**kwargs)
self.padding = padding
self.input = T.tensor3()
self.input = K.placeholder(ndim=3)
@property
def output_shape(self):
input_shape = self.input_shape
return (input_shape[0], input_shape[1] + self.padding * 2, input_shape[2])
return (input_shape[0],
input_shape[1] + self.padding * 2,
input_shape[2])
def get_output(self, train=False):
X = self.get_input(train)
input_shape = X.shape
output_shape = (input_shape[0],
input_shape[1] + 2 * self.padding,
input_shape[2])
output = T.zeros(output_shape)
return T.set_subtensor(output[:, self.padding:X.shape[1] + self.padding, :], X)
return K.temporal_padding(X, padding=self.padding)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -452,15 +450,17 @@ class ZeroPadding1D(Layer):
class ZeroPadding2D(Layer):
"""Zero-padding layer for 1D input (e.g. temporal sequence).
"""Zero-padding layer for 2D input (e.g. picture).
Input shape
-----------
4D tensor with shape (samples, depth, first_axis_to_pad, second_axis_to_pad)
4D tensor with shape:
(samples, depth, first_axis_to_pad, second_axis_to_pad)
Output shape
------------
4D tensor with shape (samples, depth, first_padded_axis, second_padded_axis)
4D tensor with shape:
(samples, depth, first_padded_axis, second_padded_axis)
Arguments
---------
@@ -470,32 +470,33 @@ class ZeroPadding2D(Layer):
"""
input_ndim = 4
def __init__(self, padding=(1, 1), **kwargs):
def __init__(self, padding=(1, 1), dim_ordering='th', **kwargs):
super(ZeroPadding2D, self).__init__(**kwargs)
self.padding = tuple(padding)
self.input = T.tensor4()
self.input = K.placeholder(ndim=4)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
@property
def output_shape(self):
input_shape = self.input_shape
return (input_shape[0],
input_shape[1],
input_shape[2] + 2 * self.padding[0],
input_shape[3] + 2 * self.padding[1])
if self.dim_ordering == 'th':
return (input_shape[0],
input_shape[1],
input_shape[2] + 2 * self.padding[0],
input_shape[3] + 2 * self.padding[1])
elif self.dim_ordering == 'tf':
return (input_shape[0],
input_shape[1] + 2 * self.padding[0],
input_shape[2] + 2 * self.padding[1],
input_shape[3])
else:
raise Exception('Invalid dim_ordering: ' + self.dim_ordering)
def get_output(self, train=False):
X = self.get_input(train)
input_shape = X.shape
output_shape = (input_shape[0],
input_shape[1],
input_shape[2] + 2 * self.padding[0],
input_shape[3] + 2 * self.padding[1])
output = T.zeros(output_shape)
indices = (slice(None),
slice(None),
slice(self.padding[0], input_shape[2] + self.padding[0]),
slice(self.padding[1], input_shape[3] + self.padding[1]))
return T.set_subtensor(output[indices], X)
return K.spatial_2d_padding(X, padding=self.padding,
dim_ordering=self.dim_ordering)
def get_config(self):
config = {"name": self.__class__.__name__,
+623 -67
Ver Arquivo
@@ -1,28 +1,30 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import, division
from __future__ import absolute_import
from __future__ import division
import theano
import theano.tensor as T
import numpy as np
from collections import OrderedDict
import copy
from .. import activations, initializations, regularizers, constraints
from ..utils.theano_utils import shared_zeros, floatX, ndim_tensor
from ..utils.generic_utils import make_tuple
from ..regularizers import ActivityRegularizer, Regularizer
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
from six.moves import zip
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..regularizers import ActivityRegularizer
import marshal
import types
import sys
class Layer(object):
def __init__(self, **kwargs):
for kwarg in kwargs:
assert kwarg in {'input_shape'}, "Keyword argument not understood: " + kwarg
assert kwarg in {'input_shape', 'trainable'}, "Keyword argument not understood: " + kwarg
if 'input_shape' in kwargs:
self.set_input_shape(kwargs['input_shape'])
if 'trainable' in kwargs:
self._trainable = kwargs['trainable']
if not hasattr(self, 'params'):
self.params = []
@@ -45,6 +47,17 @@ class Layer(object):
'''
pass
@property
def trainable(self):
if hasattr(self, '_trainable'):
return self._trainable
else:
return True
@trainable.setter
def trainable(self, value):
self._trainable = value
@property
def nb_input(self):
return 1
@@ -73,7 +86,7 @@ class Layer(object):
raise Exception('Invalid input shape - Layer expects input ndim=' +
str(self.input_ndim) + ', was provided with input shape ' + str(input_shape))
self._input_shape = input_shape
self.input = ndim_tensor(len(self._input_shape))
self.input = K.placeholder(shape=self._input_shape)
self.build()
@property
@@ -119,20 +132,22 @@ class Layer(object):
assert len(self.params) == len(weights), 'Provided weight array does not match layer weights (' + \
str(len(self.params)) + ' layer params vs. ' + str(len(weights)) + ' provided weights)'
for p, w in zip(self.params, weights):
if p.eval().shape != w.shape:
raise Exception("Layer shape %s not compatible with weight shape %s." % (p.eval().shape, w.shape))
p.set_value(floatX(w))
if K.get_value(p).shape != w.shape:
raise Exception("Layer shape %s not compatible with weight shape %s." % (K.get_value(p).shape, w.shape))
K.set_value(p, w)
def get_weights(self):
weights = []
for p in self.params:
weights.append(p.get_value())
weights.append(K.get_value(p))
return weights
def get_config(self):
config = {"name": self.__class__.__name__}
if hasattr(self, '_input_shape'):
config['input_shape'] = self._input_shape[1:]
if hasattr(self, '_trainable'):
config['trainable'] = self._trainable
return config
def get_params(self):
@@ -160,18 +175,17 @@ class Layer(object):
return self.params, regularizers, consts, updates
def set_name(self, name):
for i in range(len(self.params)):
self.params[i].name = '%s_p%d' % (name, i)
def count_params(self):
return sum([np.prod(p.shape.eval()) for p in self.params])
return sum([K.count_params(p) for p in self.params])
class MaskedLayer(Layer):
'''
If your layer trivially supports masking (by simply copying the input mask to the output), then subclass MaskedLayer
instead of Layer, and make sure that you incorporate the input mask into your calculation of get_output()
If your layer trivially supports masking
(by simply copying the input mask to the output),
then subclass MaskedLayer instead of Layer,
and make sure that you incorporate the input mask
into your calculation of get_output()
'''
def supports_masked_input(self):
return True
@@ -183,8 +197,9 @@ class MaskedLayer(Layer):
return None
def get_output_mask(self, train=False):
''' The default output mask is just the input mask unchanged. Override this in your own
implementations if, for instance, you are reshaping the input'''
''' The default output mask is just the input mask unchanged.
Override this in your own implementations if,
for instance, you are reshaping the input'''
return self.get_input_mask(train)
@@ -202,15 +217,19 @@ class Masking(MaskedLayer):
def __init__(self, mask_value=0., **kwargs):
super(Masking, self).__init__(**kwargs)
self.mask_value = mask_value
self.input = T.tensor3()
self.input = K.placeholder(ndim=3)
def get_output_mask(self, train=False):
if K._BACKEND == "tensorflow":
raise Exception("Masking is Theano-only for the time being.")
X = self.get_input(train)
return T.any(T.ones_like(X) * (1. - T.eq(X, self.mask_value)), axis=-1)
return K.any(K.ones_like(X) * (1. - K.equal(X, self.mask_value)),
axis=-1)
def get_output(self, train=False):
X = self.get_input(train)
return X * T.shape_padright(T.any((1. - T.eq(X, self.mask_value)), axis=-1))
return X * K.any((1. - K.equal(X, self.mask_value)),
axis=-1, keepdims=True)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -221,7 +240,6 @@ class Masking(MaskedLayer):
class TimeDistributedMerge(Layer):
'''Sum/multiply/average over the outputs of a TimeDistributed layer.
mode: {'sum', 'mul', 'ave'}
Tensor input dimensions: (nb_sample, time, features)
Tensor output dimensions: (nb_sample, features)
@@ -242,13 +260,14 @@ class TimeDistributedMerge(Layer):
def get_output(self, train=False):
X = self.get_input(train)
if self.mode == 'sum' or self.mode == 'ave':
s = theano.tensor.sum(X, axis=1)
if self.mode == 'ave':
s /= X.shape[1]
if self.mode == 'ave':
s = K.mean(X, axis=1)
return s
if self.mode == 'sum':
s = K.sum(X, axis=1)
return s
elif self.mode == 'mul':
s = theano.tensor.mul(X, axis=1)
s = K.prod(X, axis=1)
return s
else:
raise Exception('Unknown merge mode')
@@ -261,16 +280,63 @@ class TimeDistributedMerge(Layer):
class Merge(Layer):
def __init__(self, layers, mode='sum', concat_axis=-1):
def __init__(self, layers, mode='sum', concat_axis=-1, dot_axes=-1):
''' Merge the output of a list of layers or containers into a single tensor.
mode: {'sum', 'mul', 'concat', 'ave'}
mode: {'sum', 'mul', 'concat', 'ave', 'join'}
'''
if len(layers) < 2:
raise Exception("Please specify two or more input layers (or containers) to merge")
if mode not in {'sum', 'mul', 'concat', 'ave'}:
if mode not in {'sum', 'mul', 'concat', 'ave', 'join', 'cos', 'dot'}:
raise Exception("Invalid merge mode: " + str(mode))
if mode in {'sum', 'mul', 'ave', 'cos'}:
input_shapes = set([l.output_shape for l in layers])
if len(input_shapes) > 1:
raise Exception("Only layers of same output shape can be merged using " + mode + " mode. " +
"Layer shapes: %s" % ([l.output_shape for l in layers]))
if mode in {'cos', 'dot'}:
if K._BACKEND != 'theano':
raise Exception('"' + mode + '" merge mode will only work with Theano.')
if len(layers) > 2:
raise Exception(mode + " merge takes exactly 2 layers")
shape1 = layers[0].output_shape
shape2 = layers[1].output_shape
n1 = len(shape1)
n2 = len(shape2)
if mode == 'dot':
if type(dot_axes) == int:
if dot_axes < 0:
dot_axes = [range(dot_axes % n1, n1), range(dot_axes % n2, n2)]
else:
dot_axes = [range(n1 - dot_axes, n2), range(1, dot_axes + 1)]
if type(dot_axes) not in [list, tuple]:
raise Exception("Invalid type for dot_axes - should be a list.")
if len(dot_axes) != 2:
raise Exception("Invalid format for dot_axes - should contain two elements.")
if type(dot_axes[0]) not in [list, tuple, range] or type(dot_axes[1]) not in [list, tuple, range]:
raise Exception("Invalid format for dot_axes - list elements should have type 'list' or 'tuple'.")
for i in range(len(dot_axes[0])):
if shape1[dot_axes[0][i]] != shape2[dot_axes[1][i]]:
raise Exception("Dimension incompatibility using dot mode: " +
"%s != %s. " % (shape1[dot_axes[0][i]], shape2[dot_axes[1][i]]) +
"Layer shapes: %s, %s" % (shape1, shape2))
elif mode == 'concat':
input_shapes = set()
for l in layers:
oshape = list(l.output_shape)
oshape.pop(concat_axis)
oshape = tuple(oshape)
input_shapes.add(oshape)
if len(input_shapes) > 1:
raise Exception("'concat' mode can only merge layers with matching " +
"output shapes except for the concat axis. " +
"Layer shapes: %s" % ([l.output_shape for l in layers]))
self.mode = mode
self.concat_axis = concat_axis
self.dot_axes = dot_axes
self.layers = layers
self.params = []
self.regularizers = []
@@ -296,6 +362,24 @@ class Merge(Layer):
for shape in input_shapes[1:]:
output_shape[self.concat_axis] += shape[self.concat_axis]
return tuple(output_shape)
elif self.mode == 'join':
return None
elif self.mode == 'dot':
shape1 = list(input_shapes[0])
shape2 = list(input_shapes[1])
dot_axes = []
for axes in self.dot_axes:
dot_axes.append([index-1 for index in axes])
tensordot_output = np.tensordot(np.zeros(tuple(shape1[1:])),
np.zeros(tuple(shape2[1:])),
axes=dot_axes)
if len(tensordot_output.shape) == 0:
shape = (1,)
else:
shape = tensordot_output.shape
return (shape1[0],) + shape
elif self.mode == 'cos':
return tuple(input_shapes[0][0], 1)
def get_params(self):
return self.params, self.regularizers, self.constraints, self.updates
@@ -310,7 +394,7 @@ class Merge(Layer):
return s
elif self.mode == 'concat':
inputs = [self.layers[i].get_output(train) for i in range(len(self.layers))]
return T.concatenate(inputs, axis=self.concat_axis)
return K.concatenate(inputs, axis=self.concat_axis)
elif self.mode == 'join':
inputs = OrderedDict()
for i in range(len(self.layers)):
@@ -318,13 +402,34 @@ class Merge(Layer):
if X.name is None:
raise ValueError("merge_mode='join' only works with named inputs")
else:
inputs[X.name] = self.layers[i].get_output(train)
inputs[X.name] = X
return inputs
elif self.mode == 'mul':
s = self.layers[0].get_output(train)
for i in range(1, len(self.layers)):
s *= self.layers[i].get_output(train)
return s
elif self.mode == 'dot':
if K._BACKEND != 'theano':
raise Exception('"dot" merge mode will only work with Theano.')
from theano import tensor as T
l1 = self.layers[0].get_output(train)
l2 = self.layers[1].get_output(train)
output = T.batched_tensordot(l1, l2, self.dot_axes)
output_shape = list(self.output_shape)
output_shape[0] = l1.shape[0]
output = output.reshape(tuple(output_shape))
return output
elif self.mode == 'cos':
if K._BACKEND != 'theano':
raise Exception('"dot" merge mode will only work with Theano.')
import theano
l1 = self.layers[0].get_output(train)
l2 = self.layers[1].get_output(train)
output, _ = theano.scan(lambda v1, v2: K.dot(v1, v2) / K.sqrt(K.dot(v1, v1) * K.dot(v2, v2)),
sequences=[l1, l2],
outputs_info=None)
return output
else:
raise Exception('Unknown merge mode')
@@ -365,7 +470,8 @@ class Merge(Layer):
config = {"name": self.__class__.__name__,
"layers": [l.get_config() for l in self.layers],
"mode": self.mode,
"concat_axis": self.concat_axis}
"concat_axis": self.concat_axis,
"dot_axes": self.dot_axes}
base_config = super(Merge, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
@@ -377,16 +483,12 @@ class Dropout(MaskedLayer):
def __init__(self, p, **kwargs):
super(Dropout, self).__init__(**kwargs)
self.p = p
self.srng = RandomStreams(seed=np.random.randint(10e6))
def get_output(self, train=False):
X = self.get_input(train)
if self.p > 0.:
retain_prob = 1. - self.p
if train:
X *= self.srng.binomial(X.shape, p=retain_prob, dtype=theano.config.floatX)
else:
X *= retain_prob
X = K.dropout(X, level=self.p)
return X
def get_config(self):
@@ -435,8 +537,7 @@ class Reshape(Layer):
def get_output(self, train=False):
X = self.get_input(train)
new_shape = (X.shape[0],) + self.dims
return theano.tensor.reshape(X, new_shape)
return K.reshape(X, (-1,) + self.dims)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -464,7 +565,7 @@ class Permute(Layer):
def get_output(self, train=False):
X = self.get_input(train)
return X.dimshuffle((0,) + self.dims)
return K.permute_dimensions(X, (0,) + self.dims)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -488,9 +589,7 @@ class Flatten(Layer):
def get_output(self, train=False):
X = self.get_input(train)
size = theano.tensor.prod(X.shape) // X.shape[0]
nshape = (X.shape[0], size)
return theano.tensor.reshape(X, nshape)
return K.flatten(X)
class RepeatVector(Layer):
@@ -511,9 +610,7 @@ class RepeatVector(Layer):
def get_output(self, train=False):
X = self.get_input(train)
tensors = [X]*self.n
stacked = theano.tensor.stack(*tensors)
return stacked.dimshuffle((1, 0, 2))
return K.repeat(X, self.n)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -548,14 +645,14 @@ class Dense(Layer):
self.input_dim = input_dim
if self.input_dim:
kwargs['input_shape'] = (self.input_dim,)
self.input = K.placeholder(ndim=2)
super(Dense, self).__init__(**kwargs)
def build(self):
input_dim = self.input_shape[1]
self.input = T.matrix()
self.W = self.init((input_dim, self.output_dim))
self.b = shared_zeros((self.output_dim,))
self.b = K.zeros((self.output_dim,))
self.params = [self.W, self.b]
@@ -582,7 +679,7 @@ class Dense(Layer):
def get_output(self, train=False):
X = self.get_input(train)
output = self.activation(T.dot(X, self.W) + self.b)
output = self.activation(K.dot(X, self.W) + self.b)
return output
def get_config(self):
@@ -635,9 +732,11 @@ class TimeDistributedDense(MaskedLayer):
'''
input_ndim = 3
def __init__(self, output_dim, init='glorot_uniform', activation='linear', weights=None,
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):
W_constraint=None, b_constraint=None,
input_dim=None, input_length=None, **kwargs):
self.output_dim = output_dim
self.init = initializations.get(init)
self.activation = activations.get(activation)
@@ -656,14 +755,14 @@ class TimeDistributedDense(MaskedLayer):
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
self.input = K.placeholder(ndim=3)
super(TimeDistributedDense, self).__init__(**kwargs)
def build(self):
input_dim = self.input_shape[2]
self.input = T.tensor3()
self.W = self.init((input_dim, self.output_dim))
self.b = shared_zeros((self.output_dim))
self.b = K.zeros((self.output_dim))
self.params = [self.W, self.b]
self.regularizers = []
@@ -691,8 +790,14 @@ class TimeDistributedDense(MaskedLayer):
def get_output(self, train=False):
X = self.get_input(train)
output = self.activation(T.dot(X.dimshuffle(1, 0, 2), self.W) + self.b)
return output.dimshuffle(1, 0, 2)
def step(x, states):
output = K.dot(x, self.W) + self.b
return output, []
last_output, outputs, states = K.rnn(step, X, [], masking=False)
outputs = self.activation(outputs)
return outputs
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -771,7 +876,7 @@ class AutoEncoder(Layer):
@property
def input_shape(self):
self.encoder.previous.output_shape
return self.encoder.input_shape
@property
def output_shape(self):
@@ -819,14 +924,14 @@ class MaxoutDense(Layer):
self.input_dim = input_dim
if self.input_dim:
kwargs['input_shape'] = (self.input_dim,)
self.input = K.placeholder(ndim=2)
super(MaxoutDense, self).__init__(**kwargs)
def build(self):
input_dim = self.input_shape[1]
self.input = T.matrix()
self.W = self.init((self.nb_feature, input_dim, self.output_dim))
self.b = shared_zeros((self.nb_feature, self.output_dim))
self.b = K.zeros((self.nb_feature, self.output_dim))
self.params = [self.W, self.b]
self.regularizers = []
@@ -854,7 +959,7 @@ class MaxoutDense(Layer):
def get_output(self, train=False):
X = self.get_input(train)
# -- don't need activation since it's just linear.
output = T.max(T.dot(X, self.W) + self.b, axis=1)
output = K.max(K.dot(X, self.W) + self.b, axis=1)
return output
def get_config(self):
@@ -870,3 +975,454 @@ class MaxoutDense(Layer):
"input_dim": self.input_dim}
base_config = super(MaxoutDense, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Lambda(Layer):
"""Lambda layer for evaluating arbitrary function
Input shape
-----------
output_shape of previous layer
Output shape
------------
Specified by output_shape argument
Arguments
---------
function - The function to be evaluated. Takes one argument : output of previous layer
output_shape - Expected output shape from function. Could be a tuple or a function of the shape of the input
"""
def __init__(self, function, output_shape=None, **kwargs):
super(Lambda, self).__init__(**kwargs)
py3 = sys.version_info[0] == 3
if py3:
self.function = marshal.dumps(function.__code__)
else:
self.function = marshal.dumps(function.func_code)
if output_shape is None:
self._output_shape = None
elif type(output_shape) in {tuple, list} :
self._output_shape = tuple(output_shape)
else:
if py3:
self._output_shape = marshal.dumps(output_shape.__code__)
else:
self._output_shape = marshal.dumps(output_shape.func_code)
@property
def output_shape(self):
if self._output_shape is None:
return self.input_shape
elif type(self._output_shape) == tuple:
return (self.input_shape[0], ) + self._output_shape
else:
output_shape_func = marshal.loads(self._output_shape)
output_shape_func = types.FunctionType(output_shape_func, globals())
shape = output_shape_func(self.previous.output_shape)
if type(shape) not in {list, tuple}:
raise Exception("output_shape function must return a tuple")
return tuple(shape)
def get_output(self, train=False):
func = marshal.loads(self.function)
func = types.FunctionType(func, globals())
if hasattr(self, 'previous'):
return func(self.previous.get_output(train))
else:
return func(self.input)
class MaskedLambda(MaskedLayer, Lambda):
pass
class LambdaMerge(Lambda):
"""LambdaMerge layer for evaluating arbitrary function over multiple inputs
Input shape
-----------
None
Output shape
------------
Specified by output_shape argument
Arguments
---------
layers - Input layers. Similar to layers argument of Merge
function - The function to be evaluated. Takes one argument:
list of outputs from input layers
output_shape - Expected output shape from function.
Could be a tuple or a function of list of input shapes
"""
def __init__(self, layers, function, output_shape=None):
if len(layers) < 2:
raise Exception("Please specify two or more input layers (or containers) to merge")
self.layers = layers
self.params = []
self.regularizers = []
self.constraints = []
self.updates = []
for l in self.layers:
params, regs, consts, updates = l.get_params()
self.regularizers += regs
self.updates += updates
# params and constraints have the same size
for p, c in zip(params, consts):
if p not in self.params:
self.params.append(p)
self.constraints.append(c)
py3 = sys.version_info[0] == 3
if py3:
self.function = marshal.dumps(function.__code__)
else:
self.function = marshal.dumps(function.func_code)
if output_shape is None:
self._output_shape = None
elif type(output_shape) in {tuple, list}:
self._output_shape = tuple(output_shape)
else:
if py3:
self._output_shape = marshal.dumps(output_shape.__code__)
else:
self._output_shape = marshal.dumps(output_shape.func_code)
@property
def output_shape(self):
input_shapes = [layer.output_shape for layer in self.layers]
if self._output_shape is None:
return input_shapes[0]
elif type(self._output_shape) == tuple:
return (input_shapes[0][0], ) + self._output_shape
else:
output_shape_func = marshal.loads(self._output_shape)
output_shape_func = types.FunctionType(output_shape_func, globals())
shape = output_shape_func(input_shapes)
if type(shape) not in {list, tuple}:
raise Exception("output_shape function must return a tuple")
return tuple(shape)
def get_params(self):
return self.params, self.regularizers, self.constraints, self.updates
def get_output(self, train=False):
func = marshal.loads(self.function)
func = types.FunctionType(func, globals())
inputs = [layer.get_output(train) for layer in self.layers]
return func(inputs)
def get_input(self, train=False):
res = []
for i in range(len(self.layers)):
o = self.layers[i].get_input(train)
if not type(o) == list:
o = [o]
for output in o:
if output not in res:
res.append(output)
return res
@property
def input(self):
return self.get_input()
def supports_masked_input(self):
return False
def get_output_mask(self, train=None):
return None
def get_weights(self):
weights = []
for l in self.layers:
weights += l.get_weights()
return weights
def set_weights(self, weights):
for i in range(len(self.layers)):
nb_param = len(self.layers[i].params)
self.layers[i].set_weights(weights[:nb_param])
weights = weights[nb_param:]
def get_config(self):
config = {"name": self.__class__.__name__,
"layers": [l.get_config() for l in self.layers],
"function": self.function,
"output_shape": self._output_shape
}
base_config = super(LambdaMerge, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class Siamese(Layer):
'''Shared layer with multiple inputs
Output shape
------------
Depends on merge_mode argument
Arguments
---------
layer - The layer to be shared across multiple inputs
inputs - inputs to the shared layer
merge_mode - Similar to mode argument of Merge layer
concat_axis - Similar to concat_axis argument of Merge layer
dot_axes - Similar to dot_axes argument of Merge layer
'''
def __init__(self, layer, inputs, merge_mode='concat',
concat_axis=1, dot_axes=-1):
if merge_mode not in ['sum', 'mul', 'concat', 'ave',
'join', 'cos', 'dot', None]:
raise Exception("Invalid merge mode: " + str(merge_mode))
if merge_mode in {'cos', 'dot'}:
if len(inputs) > 2:
raise Exception(merge_mode + " merge takes exactly 2 layers")
self.layer = layer
self.inputs = inputs
self.params = []
self.merge_mode = merge_mode
self.concat_axis = concat_axis
self.dot_axes = dot_axes
layer.set_previous(inputs[0])
self.regularizers = []
self.constraints = []
self.updates = []
layers = [layer]
if merge_mode:
layers += inputs
for l in layers:
params, regs, consts, updates = l.get_params()
self.regularizers += regs
self.updates += updates
# params and constraints have the same size
for p, c in zip(params, consts):
if p not in self.params:
self.params.append(p)
self.constraints.append(c)
@property
def output_shape(self):
if self.merge_mode is None:
return self.layer.output_shape
input_shapes = [self.get_output_shape(i) for i in range(len(self.inputs))]
if self.merge_mode in ['sum', 'mul', 'ave']:
return input_shapes[0]
elif self.merge_mode == 'concat':
output_shape = list(input_shapes[0])
for shape in input_shapes[1:]:
output_shape[self.concat_axis] += shape[self.concat_axis]
return tuple(output_shape)
elif self.merge_mode == 'join':
return None
elif self.merge_mode == 'dot':
shape1 = list(input_shapes[0])
shape2 = list(input_shapes[1])
for i in self.dot_axes[0]:
shape1.pop(i)
for i in self.dot_axes[1]:
shape2.pop(i)
shape = shape1 + shape2[1:]
if len(shape) == 1:
shape.append(1)
return tuple(shape)
elif self.merge_mode == 'cos':
return tuple(input_shapes[0][0], 1)
def get_params(self):
return self.params, self.regularizers, self.constraints, self.updates
def set_layer_input(self, index):
l = self.layer
while not hasattr(l, 'previous'):
l = l.layers[0]
l.previous = self.inputs[index]
def get_output_at(self, head, train=False):
self.set_layer_input(head)
return self.layer.get_output(train)
def get_output_shape(self, head, train=False):
self.set_layer_input(head)
return self.layer.output_shape
def get_output_join(self, train=False):
o = OrderedDict()
for i in range(len(self.inputs)):
X = self.get_output_at(i, train)
if X.name is None:
raise ValueError("merge_mode='join' only works with named inputs")
o[X.name] = X
return o
def get_output_sum(self, train=False):
s = self.get_output_at(0, train)
for i in range(1, len(self.inputs)):
s += self.get_output_at(i, train)
return s
def get_output_ave(self, train=False):
n = len(self.inputs)
s = self.get_output_at(0, train)
for i in range(1, n):
s += self.get_output_at(i, train)
s /= n
return s
def get_output_concat(self, train=False):
inputs = [self.get_output_at(i, train) for i in range(len(self.inputs))]
return K.concatenate(inputs, axis=self.concat_axis)
def get_output_mul(self, train=False):
s = self.get_output_at(0, train)
for i in range(1, len(self.inputs)):
s *= self.get_output_at(i, train)
return s
def get_output_dot(self, train=False):
if K._BACKEND != 'theano':
raise Exception('"dot" merge mode will only work with Theano.')
from theano import tensor as T
l1 = self.get_output_at(0, train)
l2 = self.get_output_at(1, train)
output = T.batched_tensordot(l1, l2, self.dot_axes)
output = output.dimshuffle((0, 'x'))
return output
def get_output_cos(self, train=False):
if K._BACKEND != 'theano':
raise Exception('"cos" merge mode will only work with Theano.')
import theano
from theano import tensor as T
l1 = self.get_output_at(0, train)
l2 = self.get_output_at(1, train)
cos = lambda v1, v2: T.dot(v1, v2) / T.sqrt(T.dot(v1, v1) * T.dot(v2, v2))
output, _ = theano.scan(cos, sequences=[l1, l2], outputs_info=None)
output = output.dimshuffle((0, 'x'))
return output
def get_output(self, train=False):
mode = self.merge_mode
if mode == 'join':
return self.get_output_join(train)
elif mode == 'concat':
return self.get_output_concat(train)
elif mode == 'sum':
return self.get_output_sum(train)
elif mode == 'ave':
return self.get_output_ave(train)
elif mode == 'mul':
return self.get_output_mul(train)
elif mode == 'dot':
return self.get_output_dot(train)
elif mode == 'cos':
return self.get_output_dot(train)
def get_input(self, train=False):
res = []
for i in range(len(self.inputs)):
o = self.inputs[i].get_input(train)
if type(o) != list:
o = [o]
for output in o:
if output not in res:
res.append(output)
return res
@property
def input(self):
return self.get_input()
def supports_masked_input(self):
return False
def get_output_mask(self, train=None):
return None
def get_weights(self):
weights = self.layer.get_weights()
if self.merge_mode:
for m in self.inputs:
weights += m.get_weights()
return weights
def set_weights(self, weights):
nb_param = len(self.layer.params)
self.layer.set_weights(weights[:nb_param])
weights = weights[nb_param:]
if self.merge_mode:
for i in range(len(self.inputs)):
nb_param = len(self.inputs[i].params)
self.inputs[i].set_weights(weights[:nb_param])
weights = weights[nb_param:]
def get_config(self):
config = {"name": self.__class__.__name__,
"layer": self.layer.get_config,
"inputs": [m.get_config() for m in self.inputs],
"merge_mode": self.merge_mode,
"concat_axis": self.concat_axis,
"dot_axes": self.dot_axes
}
base_config = super(Siamese, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class SiameseHead(Layer):
'''This layer should be added only on top of a Siamese layer
with merge_mode = None
Outputs the output of the Siamese layer at a given index,
specified by the head argument
Arguments
---------
head - The index at which the output of the Siamese layer
should be obtained
'''
def __init__(self, head):
self.head = head
self.params = []
def get_output(self, train=False):
return self.get_input(train)
@property
def input_shape(self):
return self.previous.get_output_shape(self.head)
def get_input(self, train=False):
return self.previous.get_output_at(self.head, train)
def get_config(self):
config = {"name": self.__class__.__name__,
"head": self.head}
base_config = super(SiameseHead, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
def set_previous(self, layer):
self.previous = layer
def add_shared_layer(layer, inputs):
'''
Use this function to add a shared layer across multiple Sequential models
without merging the outputs
'''
input_layers = [l.layers[-1] for l in inputs]
s = Siamese(layer, input_layers, merge_mode=None)
for i in range(len(inputs)):
sh = SiameseHead(i)
inputs[i].add(s)
inputs[i].add(sh)
+13 -78
Ver Arquivo
@@ -1,10 +1,8 @@
from __future__ import absolute_import
import theano
import theano.tensor as T
from .. import backend as K
from .. import activations, initializations, regularizers, constraints
from ..layers.core import Layer, MaskedLayer
from ..utils.theano_utils import sharedX
from ..constraints import unitnorm
@@ -19,9 +17,12 @@ class Embedding(Layer):
'''
input_ndim = 2
def __init__(self, input_dim, output_dim, init='uniform', input_length=None,
W_regularizer=None, activity_regularizer=None, W_constraint=None,
mask_zero=False, weights=None, **kwargs):
def __init__(self, input_dim, output_dim,
init='uniform', input_length=None,
W_regularizer=None, activity_regularizer=None,
W_constraint=None,
mask_zero=False,
weights=None, **kwargs):
self.input_dim = input_dim
self.output_dim = output_dim
self.init = initializations.get(init)
@@ -39,7 +40,8 @@ class Embedding(Layer):
super(Embedding, self).__init__(**kwargs)
def build(self):
self.input = T.imatrix()
self.input = K.placeholder(shape=(None, self.input_length),
dtype='int32')
self.W = self.init((self.input_dim, self.output_dim))
self.params = [self.W]
self.regularizers = []
@@ -59,7 +61,9 @@ class Embedding(Layer):
if not self.mask_zero:
return None
else:
return T.ones_like(X) * (1 - T.eq(X, 0))
if K._BACKEND == "tensorflow":
raise Exception("Masking is Theano-only for the time being.")
return K.ones_like(X) * (1 - K.equal(X, 0))
@property
def output_shape(self):
@@ -67,7 +71,7 @@ class Embedding(Layer):
def get_output(self, train=False):
X = self.get_input(train)
out = self.W[X]
out = K.gather(self.W, X)
return out
def get_config(self):
@@ -82,72 +86,3 @@ class Embedding(Layer):
"W_constraint": self.W_constraint.get_config() if self.W_constraint else None}
base_config = super(Embedding, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
class WordContextProduct(Layer):
'''
This layer turns a pair of words (a pivot word + a context word,
ie. a word from the same context, or a random, out-of-context word),
indentified by their index in a vocabulary, into two dense reprensentations
(word representation and context representation).
Then it returns activation(dot(pivot_embedding, context_embedding)),
which can be trained to encode the probability
of finding the context word in the context of the pivot word
(or reciprocally depending on your training procedure).
The layer ingests integer tensors of shape:
(nb_samples, 2)
and outputs a float tensor of shape
(nb_samples, 1)
The 2nd dimension encodes (pivot, context).
input_dim is the size of the vocabulary.
For more context, see Mikolov et al.:
Efficient Estimation of Word reprensentations in Vector Space
http://arxiv.org/pdf/1301.3781v3.pdf
'''
input_ndim = 2
def __init__(self, input_dim, proj_dim=128,
init='uniform', activation='sigmoid', weights=None, **kwargs):
super(WordContextProduct, self).__init__(**kwargs)
self.input_dim = input_dim
self.proj_dim = proj_dim
self.init = initializations.get(init)
self.activation = activations.get(activation)
self.input = T.imatrix()
# two different embeddings for pivot word and its context
# because p(w|c) != p(c|w)
self.W_w = self.init((input_dim, proj_dim))
self.W_c = self.init((input_dim, proj_dim))
self.params = [self.W_w, self.W_c]
if weights is not None:
self.set_weights(weights)
@property
def output_shape(self):
return (self.input_shape[0], 1)
def get_output(self, train=False):
X = self.get_input(train)
w = self.W_w[X[:, 0]] # nb_samples, proj_dim
c = self.W_c[X[:, 1]] # nb_samples, proj_dim
dot = T.sum(w * c, axis=1)
dot = theano.tensor.reshape(dot, (X.shape[0], 1))
return self.activation(dot)
def get_config(self):
config = {"name": self.__class__.__name__,
"input_dim": self.input_dim,
"proj_dim": self.proj_dim,
"init": self.init.__name__,
"activation": self.activation.__name__}
base_config = super(WordContextProduct, self).get_config()
return dict(list(base_config.items()) + list(config.items()))
+8 -10
Ver Arquivo
@@ -1,9 +1,6 @@
from __future__ import absolute_import
import numpy as np
from .core import MaskedLayer
import theano
import theano.tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
from .. import backend as K
class GaussianNoise(MaskedLayer):
@@ -13,15 +10,15 @@ class GaussianNoise(MaskedLayer):
def __init__(self, sigma, **kwargs):
super(GaussianNoise, self).__init__(**kwargs)
self.sigma = sigma
self.srng = RandomStreams(seed=np.random.randint(10e6))
def get_output(self, train=False):
X = self.get_input(train)
if not train or self.sigma == 0:
return X
else:
return X + self.srng.normal(size=X.shape, avg=0.0, std=self.sigma,
dtype=theano.config.floatX)
return X + K.random_normal(shape=K.shape(X),
mean=0.,
std=self.sigma)
def get_config(self):
config = {"name": self.__class__.__name__,
@@ -41,13 +38,14 @@ class GaussianDropout(MaskedLayer):
def __init__(self, p, **kwargs):
super(GaussianDropout, self).__init__(**kwargs)
self.p = p
self.srng = RandomStreams(seed=np.random.randint(10e6))
def get_output(self, train):
X = self.get_input(train)
if train:
# self.p refers to drop probability rather than retain probability (as in paper) to match Dropout layer syntax
X *= self.srng.normal(size=X.shape, avg=1.0, std=T.sqrt(self.p / (1.0 - self.p)), dtype=theano.config.floatX)
# self.p refers to drop probability rather than
# retain probability (as in paper), for consistency
X *= K.random_normal(shape=K.shape(X), mean=1.0,
std=self.p / (1.0 - self.p))
return X
def get_config(self):
+34 -28
Ver Arquivo
@@ -1,22 +1,24 @@
from ..layers.core import Layer
from ..utils.theano_utils import shared_zeros, shared_ones, ndim_tensor, floatX
from .. import initializations
import theano.tensor as T
from .. import backend as K
class BatchNormalization(Layer):
'''
Reference:
Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift
Batch Normalization: Accelerating Deep Network Training
by Reducing Internal Covariate Shift
http://arxiv.org/pdf/1502.03167v3.pdf
mode: 0 -> featurewise normalization
1 -> samplewise normalization (may sometimes outperform featurewise mode)
1 -> samplewise normalization
(may sometimes outperform featurewise mode)
momentum: momentum term in the computation of a running estimate of the mean and std of the data
momentum: momentum term in the computation
of a running estimate of the mean and std of the data
'''
def __init__(self, epsilon=1e-6, mode=0, momentum=0.9, weights=None, **kwargs):
def __init__(self, epsilon=1e-6, mode=0, momentum=0.9,
weights=None, **kwargs):
self.init = initializations.get("uniform")
self.epsilon = epsilon
self.mode = mode
@@ -27,46 +29,47 @@ class BatchNormalization(Layer):
def build(self):
input_shape = self.input_shape # starts with samples axis
input_shape = input_shape[1:]
self.input = ndim_tensor(len(input_shape) + 1)
self.gamma = self.init((input_shape))
self.beta = shared_zeros(input_shape)
self.beta = K.zeros(input_shape)
self.params = [self.gamma, self.beta]
self.running_mean = shared_zeros(input_shape)
self.running_std = shared_ones((input_shape))
self.running_mean = K.zeros(input_shape)
self.running_std = K.ones((input_shape))
# initialize self.updates: batch mean/std computation
X = self.get_input(train=True)
m = X.mean(axis=0)
std = T.mean((X - m) ** 2 + self.epsilon, axis=0) ** 0.5
m = K.mean(X, axis=0)
std = K.mean(K.square(X - m) + self.epsilon, axis=0)
std = K.sqrt(std)
mean_update = self.momentum * self.running_mean + (1-self.momentum) * m
std_update = self.momentum * self.running_std + (1-self.momentum) * std
self.updates = [(self.running_mean, mean_update), (self.running_std, std_update)]
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
def get_weights(self):
return super(BatchNormalization, self).get_weights() + [self.running_mean.get_value(), self.running_std.get_value()]
super_weights = super(BatchNormalization, self).get_weights()
return super_weights + [K.get_value(self.running_mean),
K.get_value(self.running_std)]
def set_weights(self, weights):
self.running_mean.set_value(floatX(weights[-2]))
self.running_std.set_value(floatX(weights[-1]))
K.set_value(self.running_mean, weights[-2])
K.set_value(self.running_std, weights[-1])
super(BatchNormalization, self).set_weights(weights[:-2])
def get_output(self, train):
X = self.get_input(train)
if self.mode == 0:
X_normed = (X - self.running_mean) / (self.running_std + self.epsilon)
X_normed = ((X - self.running_mean) /
(self.running_std + self.epsilon))
elif self.mode == 1:
m = X.mean(axis=-1, keepdims=True)
std = X.std(axis=-1, keepdims=True)
m = K.mean(X, axis=-1, keepdims=True)
std = K.std(X, axis=-1, keepdims=True)
X_normed = (X - m) / (std + self.epsilon)
out = self.gamma * X_normed + self.beta
return out
@@ -96,14 +99,17 @@ class LRN2D(Layer):
def get_output(self, train):
X = self.get_input(train)
b, ch, r, c = X.shape
b, ch, r, c = K.shape(X)
half_n = self.n // 2
input_sqr = T.sqr(X)
extra_channels = T.alloc(0., b, ch + 2*half_n, r, c)
input_sqr = T.set_subtensor(extra_channels[:, half_n:half_n+ch, :, :], input_sqr)
input_sqr = K.square(X)
extra_channels = K.zeros((b, ch + 2 * half_n, r, c))
input_sqr = K.concatenate([extra_channels[:, :half_n, :, :],
input_sqr,
extra_channels[:, half_n + ch:, :, :]],
axis=1)
scale = self.k
for i in range(self.n):
scale += self.alpha * input_sqr[:, i:i+ch, :, :]
scale += self.alpha * input_sqr[:, i:i + ch, :, :]
scale = scale ** self.beta
return X / scale
+326
Ver Arquivo
@@ -0,0 +1,326 @@
import numpy as np
from scipy.linalg import circulant
from .. import backend as K
import theano
import theano.tensor as T
floatX = theano.config.floatX
from keras.layers.recurrent import Recurrent, GRU, LSTM
from keras.utils.theano_utils import shared_zeros, alloc_zeros_matrix, shared_scalar
tol = 1e-4
def _update_controller(self, inp, h_tm1, M, mask):
""" Update inner RNN controler
We have to update the inner RNN inside the Neural Turing Machine, this
is an almost literal copy of keras.layers.recurrent.GRU and
keras.layers.recurrent.LSTM see these clases for further details.
"""
x = T.concatenate([inp, M], axis=-1)
# get inputs
if self.inner_rnn == 'gru':
x_z = T.dot(x, self.rnn.W_z) + self.rnn.b_z
x_r = T.dot(x, self.rnn.W_r) + self.rnn.b_r
x_h = T.dot(x, self.rnn.W_h) + self.rnn.b_h
elif self.inner_rnn == 'lstm':
xi = T.dot(x, self.rnn.W_i) + self.rnn.b_i
xf = T.dot(x, self.rnn.W_f) + self.rnn.b_f
xc = T.dot(x, self.rnn.W_c) + self.rnn.b_c
xo = T.dot(x, self.rnn.W_o) + self.rnn.b_o
elif self.inner_rnn == 'simple':
x = T.dot(x, self.rnn.W) + self.rnn.b
# update state
if self.inner_rnn == 'gru':
h = self.rnn._step(x_z, x_r, x_h, 1., h_tm1[0],
self.rnn.U_z,
self.rnn.U_r,
self.rnn.U_h)
h = mask[:, None] * h + (1-mask[:, None])*h_tm1[0]
h = (h, )
elif self.inner_rnn == 'lstm':
h = self.rnn._step(xi, xf, xo, xc, 1.,
h_tm1[1], h_tm1[0],
self.rnn.U_i, self.rnn.U_f,
self.rnn.U_o, self.rnn.U_c)
h = h[::-1]
h = tuple([mask[:, None]*h[i] +
(1-mask[:, None])*h_tm1[i] for i in range(len(h))])
elif self.inner_rnn == 'simple':
h = self.rnn._step(x, 1, h_tm1[0], self.rnn.U)
h = mask[:, None] * h + (1-mask[:, None])*h_tm1[0]
h = (h, )
return h
def _circulant(leng, n_shifts):
""" Generate circulant copies of a vector.
This will generate a tensor with `n_shifts` of rotated versions the
identity matrix. When this tensor is multiplied by a vector
the result are `n_shifts` shifted versions of that vector. Since
everything is done with inner products, this operation is differentiable.
Paramters:
----------
leng: int > 0, number of memory locations
n_shifts: int > 0, number of allowed shifts (if 1, no shift)
Returns:
--------
shift operation, a tensor with dimensions (n_shifts, leng, leng)
"""
eye = np.eye(leng)
shifts = range(n_shifts//2, -n_shifts//2, -1)
C = np.asarray([np.roll(eye, s, axis=1) for s in shifts])
return theano.shared(C.astype(theano.config.floatX))
def _renorm(x):
return x / (x.sum(axis=1, keepdims=True))
def _softmax(x):
wt = x.flatten(ndim=2)
w = T.nnet.softmax(wt)
return w.reshape(x.shape) # T.clip(s, 0, 1)
def _cosine_distance(M, k):
dot = (M * k[:, None, :]).sum(axis=-1)
nM = T.sqrt((M**2).sum(axis=-1))
nk = T.sqrt((k**2).sum(axis=-1, keepdims=True))
return dot / (nM * nk)
class NeuralTuringMachine(Recurrent):
""" Neural Turing Machines
Parameters:
-----------
shift_range: int, number of available shifts, ex. if 3, avilable shifts are
(-1, 0, 1)
n_slots: number of memory locations
m_length: memory length at each location
inner_rnn: str, supported values are 'gru' and 'lstm'
output_dim: hidden state size (RNN controller output_dim)
Known issues and TODO:
----------------------
Theano may complain when n_slots == 1.
Add multiple reading and writing heads.
"""
def __init__(self, output_dim, n_slots, m_length, shift_range=3,
inner_rnn='gru', truncate_gradient=-1, return_sequences=False,
init='glorot_uniform', inner_init='orthogonal',
input_dim=None, input_length=None, **kwargs):
if K._BACKEND != 'theano':
raise Exception('NeuralTuringMachine is only available for Theano for the time being. ' +
'It will be adapted to TensorFlow soon.')
self.output_dim = output_dim
self.n_slots = n_slots
self.m_length = m_length
self.shift_range = shift_range
self.init = init
self.inner_init = inner_init
self.inner_rnn = inner_rnn
self.return_sequences = return_sequences
self.truncate_gradient = truncate_gradient
self.input_dim = input_dim
self.input_length = input_length
if self.input_dim:
kwargs['input_shape'] = (self.input_length, self.input_dim)
super(NeuralTuringMachine, self).__init__(**kwargs)
def build(self):
input_leng, input_dim = self.input_shape[1:]
self.input = T.tensor3()
if self.inner_rnn == 'gru':
self.rnn = GRU(
input_dim=input_dim+self.m_length,
input_length=input_leng,
output_dim=self.output_dim, init=self.init,
inner_init=self.inner_init)
elif self.inner_rnn == 'lstm':
self.rnn = LSTM(
input_dim=input_dim+self.m_length,
input_length=input_leng,
output_dim=self.output_dim, init=self.init,
inner_init=self.inner_init)
else:
raise ValueError('this inner_rnn is not implemented yet.')
self.rnn.build()
# initial memory, state, read and write vecotrs
self.M = theano.shared((.001*np.ones((1,)).astype(floatX)))
self.init_h = shared_zeros((self.output_dim))
self.init_wr = self.rnn.init((self.n_slots,))
self.init_ww = self.rnn.init((self.n_slots,))
# write
self.W_e = self.rnn.init((self.output_dim, self.m_length)) # erase
self.b_e = shared_zeros((self.m_length))
self.W_a = self.rnn.init((self.output_dim, self.m_length)) # add
self.b_a = shared_zeros((self.m_length))
# get_w parameters for reading operation
self.W_k_read = self.rnn.init((self.output_dim, self.m_length))
self.b_k_read = self.rnn.init((self.m_length, ))
self.W_c_read = self.rnn.init((self.output_dim, 3)) # 3 = beta, g, gamma see eq. 5, 7, 9 in Graves et. al 2014
self.b_c_read = shared_zeros((3))
self.W_s_read = self.rnn.init((self.output_dim, self.shift_range))
self.b_s_read = shared_zeros((self.shift_range))
# get_w parameters for writing operation
self.W_k_write = self.rnn.init((self.output_dim, self.m_length))
self.b_k_write = self.rnn.init((self.m_length, ))
self.W_c_write = self.rnn.init((self.output_dim, 3)) # 3 = beta, g, gamma see eq. 5, 7, 9
self.b_c_write = shared_zeros((3))
self.W_s_write = self.rnn.init((self.output_dim, self.shift_range))
self.b_s_write = shared_zeros((self.shift_range))
self.C = _circulant(self.n_slots, self.shift_range)
self.params = self.rnn.params + [
self.W_e, self.b_e,
self.W_a, self.b_a,
self.W_k_read, self.b_k_read,
self.W_c_read, self.b_c_read,
self.W_s_read, self.b_s_read,
self.W_k_write, self.b_k_write,
self.W_s_write, self.b_s_write,
self.W_c_write, self.b_c_write,
self.M,
self.init_h, self.init_wr, self.init_ww]
if self.inner_rnn == 'lstm':
self.init_c = shared_zeros((self.output_dim))
self.params = self.params + [self.init_c, ]
def _read(self, w, M):
return (w[:, :, None]*M).sum(axis=1)
def _write(self, w, e, a, M, mask):
Mtilda = M * (1 - w[:, :, None]*e[:, None, :])
Mout = Mtilda + w[:, :, None]*a[:, None, :]
return mask[:, None, None]*Mout + (1-mask[:, None, None])*M
def _get_content_w(self, beta, k, M):
num = beta[:, None] * _cosine_distance(M, k)
return _softmax(num)
def _get_location_w(self, g, s, C, gamma, wc, w_tm1, mask):
wg = g[:, None] * wc + (1-g[:, None])*w_tm1
Cs = (C[None, :, :, :] * wg[:, None, None, :]).sum(axis=3)
wtilda = (Cs * s[:, :, None]).sum(axis=1)
wout = _renorm(wtilda ** gamma[:, None])
return mask[:, None] * wout + (1-mask[:, None])*w_tm1
def _get_controller_output(self, h, W_k, b_k, W_c, b_c, W_s, b_s):
k = T.tanh(T.dot(h, W_k) + b_k) # + 1e-6
c = T.dot(h, W_c) + b_c
beta = T.nnet.relu(c[:, 0]) + 1e-6
g = T.nnet.sigmoid(c[:, 1])
gamma = T.nnet.relu(c[:, 2]) + 1
s = T.nnet.softmax(T.dot(h, W_s) + b_s)
return k, beta, g, gamma, s
def _get_initial_states(self, batch_size):
init_M = self.M.dimshuffle(0, 'x', 'x').repeat(
batch_size, axis=0).repeat(self.n_slots, axis=1).repeat(
self.m_length, axis=2)
init_h = self.init_h.dimshuffle(('x', 0)).repeat(batch_size, axis=0)
init_wr = self.init_wr.dimshuffle(('x', 0)).repeat(batch_size, axis=0)
init_ww = self.init_ww.dimshuffle(('x', 0)).repeat(batch_size, axis=0)
if self.inner_rnn == 'lstm':
init_c = self.init_c.dimshuffle(('x', 0)).repeat(batch_size, axis=0)
return init_M, T.nnet.softmax(init_wr), T.nnet.softmax(init_ww), init_h, init_c
else:
return init_M, T.nnet.softmax(init_wr), T.nnet.softmax(init_ww), init_h
def _step(self, x, mask, M_tm1, wr_tm1, ww_tm1, *args):
# read
if self.inner_rnn == 'lstm':
h_tm1 = args[0:2][::-1] # (cell_tm1, h_tm1)
else:
h_tm1 = args[0:1] # (h_tm1, )
k_read, beta_read, g_read, gamma_read, s_read = self._get_controller_output(
h_tm1[-1], self.W_k_read, self.b_k_read, self.W_c_read, self.b_c_read,
self.W_s_read, self.b_s_read)
wc_read = self._get_content_w(beta_read, k_read, M_tm1)
wr_t = self._get_location_w(g_read, s_read, self.C, gamma_read,
wc_read, wr_tm1, mask)
M_read = self._read(wr_t, M_tm1)
# update controller
h_t = _update_controller(self, x, h_tm1, M_read, mask)
# write
k_write, beta_write, g_write, gamma_write, s_write = self._get_controller_output(
h_t[-1], self.W_k_write, self.b_k_write, self.W_c_write,
self.b_c_write, self.W_s_write, self.b_s_write)
wc_write = self._get_content_w(beta_write, k_write, M_tm1)
ww_t = self._get_location_w(g_write, s_write, self.C, gamma_write,
wc_write, ww_tm1, mask)
e = T.nnet.sigmoid(T.dot(h_t[-1], self.W_e) + self.b_e)
a = T.tanh(T.dot(h_t[-1], self.W_a) + self.b_a)
M_t = self._write(ww_t, e, a, M_tm1, mask)
return (M_t, wr_t, ww_t) + h_t
def get_output(self, train=False):
outputs = self.get_full_output(train)
if self.return_sequences:
return outputs[-1]
else:
return outputs[-1][:, -1]
@property
def output_shape(self):
input_shape = self.input_shape
if self.return_sequences:
return input_shape[0], input_shape[1], self.output_dim
else:
return input_shape[0], self.output_dim
def get_full_output(self, train=False):
"""
This method is for research and visualization purposes. Use it as:
X = model.get_input() # full model
Y = ntm.get_output() # this layer
F = theano.function([X], Y, allow_input_downcast=True)
[memory, read_address, write_address, rnn_state] = F(x)
if inner_rnn == "lstm" use it as:
[memory, read_address, write_address, rnn_cell, rnn_state] = F(x)
"""
X = self.get_input(train)
padded_mask = self.get_padded_shuffled_mask(train, X, pad=1)[:, :, 0]
X = X.dimshuffle((1, 0, 2))
init_states = self._get_initial_states(X.shape[1])
outputs, updates = theano.scan(self._step,
sequences=[X, padded_mask],
outputs_info=init_states,
non_sequences=self.params,
truncate_gradient=self.truncate_gradient)
out = [outputs[0].dimshuffle((1, 0, 2, 3)),
outputs[1].dimshuffle(1, 0, 2),
outputs[2].dimshuffle((1, 0, 2)),
outputs[3].dimshuffle((1, 0, 2))]
if self.inner_rnn == 'lstm':
out + [outputs[4].dimshuffle((1, 0, 2))]
return out
Diferenças do arquivo suprimidas por serem muito extensas Carregar Diff
+115 -100
Ver Arquivo
@@ -1,12 +1,14 @@
from __future__ import absolute_import
from __future__ import print_function
import theano
import theano.tensor as T
import numpy as np
import warnings, time, copy, pprint
import warnings
import time
import copy
import pprint
from six.moves import range
import six
from . import backend as K
from . import optimizers
from . import objectives
from . import regularizers
@@ -26,11 +28,11 @@ def standardize_y(y):
def batch_shuffle(index_array, batch_size):
batch_count = int(len(index_array)/batch_size)
batch_count = int(len(index_array) / batch_size)
# to reshape we need to be cleanly divisible by batch size
# we stash extra items and reappend them after shuffling
last_batch = index_array[batch_count*batch_size:]
index_array = index_array[:batch_count*batch_size]
last_batch = index_array[batch_count * batch_size:]
index_array = index_array[:batch_count * batch_size]
index_array = index_array.reshape((batch_count, batch_size))
np.random.shuffle(index_array)
index_array = index_array.flatten()
@@ -38,8 +40,8 @@ def batch_shuffle(index_array, batch_size):
def make_batches(size, batch_size):
nb_batch = int(np.ceil(size/float(batch_size)))
return [(i*batch_size, min(size, (i+1)*batch_size)) for i in range(0, nb_batch)]
nb_batch = int(np.ceil(size / float(batch_size)))
return [(i * batch_size, min(size, (i + 1) * batch_size)) for i in range(0, nb_batch)]
def standardize_X(X):
@@ -52,11 +54,16 @@ def standardize_X(X):
def slice_X(X, start=None, stop=None):
if type(X) == list:
if hasattr(start, '__len__'):
# hdf5 dataset only support list object as indices
if hasattr(start, 'shape'):
start = start.tolist()
return [x[start] for x in X]
else:
return [x[start:stop] for x in X]
else:
if hasattr(start, '__len__'):
if hasattr(start, 'shape'):
start = start.tolist()
return X[start]
else:
return X[start:stop]
@@ -64,65 +71,71 @@ def slice_X(X, start=None, stop=None):
def weighted_objective(fn):
def weighted(y_true, y_pred, weights, mask=None):
# it's important that 0 * Inf == 0, not NaN, so we need to filter
# those out first
filtered_y_true = y_true[weights.nonzero()[:-1]]
filtered_y_pred = y_pred[weights.nonzero()[:-1]]
filtered_weights = weights[weights.nonzero()]
obj_output = fn(filtered_y_true, filtered_y_pred)
weighted = filtered_weights * obj_output
if mask is None:
# Instead of calling mean() here, we divide by the sum of filtered_weights.
return weighted.sum() / filtered_weights.sum()
else:
filtered_mask = mask[weights.nonzero()[:-1]]
return weighted.sum() / (filtered_mask * filtered_weights).sum()
'''To be called only with non-zero weights.
mask: binary
'''
score_array = fn(y_true, y_pred)
if mask is not None:
score_array *= mask
# the loss per batch should be proportional
# to the number of unmasked sampled.
score_array /= K.mean(mask)
# reduce score_array to 1D
ndim = K.ndim(score_array)
for d in range(ndim-1):
score_array = K.mean(score_array, axis=-1)
if weights is not None:
score_array *= weights
return K.mean(score_array)
return weighted
def standardize_weights(y, sample_weight=None, class_weight=None):
if sample_weight is not None:
return standardize_y(sample_weight)
assert len(sample_weight) == len(y)
return sample_weight.flatten()
elif isinstance(class_weight, dict):
if len(y.shape) > 3:
raise Exception('class_weight not supported for 4+ dimensional targets.')
yshape = y.shape
y = np.reshape(y, (-1, yshape[-1])) # for time-distributed data, collapse time and sample
if len(y.shape) > 2:
raise Exception('class_weight not supported for 3+ dimensional targets.')
if y.shape[1] > 1:
y_classes = y.argmax(axis=1)
elif y.shape[1] == 1:
y_classes = np.reshape(y, y.shape[0])
else:
y_classes = y
class_weights = np.asarray([class_weight[cls] for cls in y_classes])
return np.reshape(class_weights, yshape[:-1] + (1,)) # uncollapse initial dimensions
weights = np.asarray([class_weight[cls] for cls in y_classes])
return weights
else:
return np.ones(y.shape[:-1] + (1,))
return np.ones((y.shape[0],))
def model_from_yaml(yaml_string, custom_layers={}):
def model_from_yaml(yaml_string, custom_objects={}):
'''
Returns a model generated from a local yaml file,
which is either created by hand or from to_yaml method of Sequential or Graph
which is either created by hand or from to_yaml method
of Sequential or Graph
'''
import yaml
config = yaml.load(yaml_string)
return model_from_config(config, custom_layers=custom_layers)
return model_from_config(config, custom_objects=custom_objects)
def model_from_json(json_string, custom_layers={}):
def model_from_json(json_string, custom_objects={}):
import json
config = json.loads(json_string)
return model_from_config(config, custom_layers=custom_layers)
return model_from_config(config, custom_objects=custom_objects)
def model_from_config(config, custom_layers={}):
def model_from_config(config, custom_objects={}):
model_name = config.get('name')
if model_name not in {'Graph', 'Sequential'}:
raise Exception('Unrecognized model:', model_name)
# Create a container then set class to appropriate model
model = container_from_config(config, custom_layers=custom_layers)
model = container_from_config(config, custom_objects=custom_objects)
if model_name == 'Graph':
model.__class__ = Graph
elif model_name == 'Sequential':
@@ -139,10 +152,11 @@ def model_from_config(config, custom_layers={}):
optimizer = optimizers.get(optimizer_name, optimizer_params)
if model_name == 'Sequential':
model.compile(loss=loss, optimizer=optimizer, class_mode=class_mode, theano_mode=theano_mode)
model.compile(loss=loss, optimizer=optimizer,
class_mode=class_mode, theano_mode=theano_mode)
elif model_name == 'Graph':
model.compile(loss=loss, optimizer=optimizer, theano_mode=theano_mode)
model.compile(loss=loss, optimizer=optimizer,
theano_mode=theano_mode)
return model
@@ -154,10 +168,12 @@ def get_function_name(o):
class Model(object):
def _fit(self, f, ins, out_labels=[], batch_size=128, nb_epoch=100, verbose=1, callbacks=[],
def _fit(self, f, ins, out_labels=[], batch_size=128,
nb_epoch=100, verbose=1, callbacks=[],
val_f=None, val_ins=None, shuffle=True, metrics=[]):
'''
Abstract fit function for f(*ins). Assume that f returns a list, labelled by out_labels.
Abstract fit function for f(ins).
Assume that f returns a list, labelled by out_labels.
'''
do_validation = False
if val_f and val_ins:
@@ -199,7 +215,7 @@ class Model(object):
batch_ids = index_array[batch_start:batch_end]
try:
ins_batch = slice_X(ins, batch_ids)
except TypeError as err:
except TypeError:
raise Exception('TypeError while preparing batch. \
If using HDF5 input data, pass shuffle="batch".\n')
@@ -207,7 +223,7 @@ class Model(object):
batch_logs['batch'] = batch_index
batch_logs['size'] = len(batch_ids)
callbacks.on_batch_begin(batch_index, batch_logs)
outs = f(*ins_batch)
outs = f(ins_batch)
if type(outs) != list:
outs = [outs]
for l, o in zip(out_labels, outs):
@@ -220,7 +236,9 @@ class Model(object):
# validation
if do_validation:
# replace with self._evaluate
val_outs = self._test_loop(val_f, val_ins, batch_size=batch_size, verbose=0)
val_outs = self._test_loop(val_f, val_ins,
batch_size=batch_size,
verbose=0)
if type(val_outs) != list:
val_outs = [val_outs]
# same labels assumed
@@ -248,7 +266,7 @@ class Model(object):
batch_ids = index_array[batch_start:batch_end]
ins_batch = slice_X(ins, batch_ids)
batch_outs = f(*ins_batch)
batch_outs = f(ins_batch)
if type(batch_outs) != list:
batch_outs = [batch_outs]
if batch_index == 0:
@@ -276,7 +294,7 @@ class Model(object):
batch_ids = index_array[batch_start:batch_end]
ins_batch = slice_X(ins, batch_ids)
batch_outs = f(*ins_batch)
batch_outs = f(ins_batch)
if type(batch_outs) == list:
if batch_index == 0:
for batch_out in enumerate(batch_outs):
@@ -340,7 +358,8 @@ class Sequential(Model, containers.Sequential):
- set_weights
'''
def compile(self, optimizer, loss, class_mode="categorical", theano_mode=None):
def compile(self, optimizer, loss,
class_mode="categorical", theano_mode=None):
self.optimizer = optimizers.get(optimizer)
self.loss = objectives.get(loss)
@@ -354,9 +373,9 @@ class Sequential(Model, containers.Sequential):
self.y_test = self.get_output(train=False)
# target of model
self.y = T.zeros_like(self.y_train)
self.weights = T.ones_like(self.y_train)
self.y = K.placeholder(ndim=K.ndim(self.y_train))
# weights: one scalar per sample
self.weights = K.placeholder(ndim=1)
if hasattr(self.layers[-1], "get_output_mask"):
mask = self.layers[-1].get_output_mask()
@@ -365,17 +384,15 @@ class Sequential(Model, containers.Sequential):
train_loss = weighted_loss(self.y, self.y_train, self.weights, mask)
test_loss = weighted_loss(self.y, self.y_test, self.weights, mask)
train_loss.name = 'train_loss'
test_loss.name = 'test_loss'
self.y.name = 'y'
if class_mode == "categorical":
train_accuracy = T.mean(T.eq(T.argmax(self.y, axis=-1), T.argmax(self.y_train, axis=-1)))
test_accuracy = T.mean(T.eq(T.argmax(self.y, axis=-1), T.argmax(self.y_test, axis=-1)))
train_accuracy = K.mean(K.equal(K.argmax(self.y, axis=-1),
K.argmax(self.y_train, axis=-1)))
test_accuracy = K.mean(K.equal(K.argmax(self.y, axis=-1),
K.argmax(self.y_test, axis=-1)))
elif class_mode == "binary":
train_accuracy = T.mean(T.eq(self.y, T.round(self.y_train)))
test_accuracy = T.mean(T.eq(self.y, T.round(self.y_test)))
train_accuracy = K.mean(K.equal(self.y, K.round(self.y_train)))
test_accuracy = K.mean(K.equal(self.y, K.round(self.y_test)))
else:
raise Exception("Invalid class mode:" + str(class_mode))
self.class_mode = class_mode
@@ -383,39 +400,38 @@ class Sequential(Model, containers.Sequential):
for r in self.regularizers:
train_loss = r(train_loss)
updates = self.optimizer.get_updates(self.params, self.constraints, train_loss)
updates = self.optimizer.get_updates(self.params,
self.constraints,
train_loss)
updates += self.updates
if type(self.X_train) == list:
train_ins = self.X_train + [self.y, self.weights]
test_ins = self.X_test + [self.y, self.weights]
assert type(self.X_test) == list
predict_ins = self.X_test
else:
train_ins = [self.X_train, self.y, self.weights]
test_ins = [self.X_test, self.y, self.weights]
predict_ins = [self.X_test]
self._train = theano.function(train_ins, train_loss, updates=updates,
allow_input_downcast=True, mode=theano_mode)
self._train_with_acc = theano.function(train_ins, [train_loss, train_accuracy], updates=updates,
allow_input_downcast=True, mode=theano_mode)
self._predict = theano.function(predict_ins, self.y_test,
allow_input_downcast=True, mode=theano_mode)
self._test = theano.function(test_ins, test_loss,
allow_input_downcast=True, mode=theano_mode)
self._test_with_acc = theano.function(test_ins, [test_loss, test_accuracy],
allow_input_downcast=True, mode=theano_mode)
self._train = K.function(train_ins, [train_loss], updates=updates)
self._train_with_acc = K.function(train_ins, [train_loss, train_accuracy], updates=updates)
self._predict = K.function(predict_ins, [self.y_test])
self._test = K.function(test_ins, [test_loss])
self._test_with_acc = K.function(test_ins, [test_loss, test_accuracy])
def train_on_batch(self, X, y, accuracy=False, class_weight=None, sample_weight=None):
def train_on_batch(self, X, y, accuracy=False,
class_weight=None, sample_weight=None):
X = standardize_X(X)
y = standardize_y(y)
sample_weight = standardize_weights(y, class_weight=class_weight, sample_weight=sample_weight)
sample_weight = standardize_weights(y, class_weight=class_weight,
sample_weight=sample_weight)
ins = X + [y, sample_weight]
if accuracy:
return self._train_with_acc(*ins)
return self._train_with_acc(ins)
else:
return self._train(*ins)
return self._train(ins)
def test_on_batch(self, X, y, accuracy=False, sample_weight=None):
X = standardize_X(X)
@@ -424,17 +440,17 @@ class Sequential(Model, containers.Sequential):
ins = X + [y, sample_weight]
if accuracy:
return self._test_with_acc(*ins)
return self._test_with_acc(ins)
else:
return self._test(*ins)
return self._test(ins)
def predict_on_batch(self, X):
ins = standardize_X(X)
return self._predict(*ins)
return self._predict(ins)
def fit(self, X, y, batch_size=128, nb_epoch=100, verbose=1, callbacks=[],
validation_split=0., validation_data=None, shuffle=True, show_accuracy=False,
class_weight=None, sample_weight=None):
validation_split=0., validation_data=None, shuffle=True,
show_accuracy=False, class_weight=None, sample_weight=None):
X = standardize_X(X)
y = standardize_y(y)
@@ -451,12 +467,13 @@ class Sequential(Model, containers.Sequential):
X_val, y_val = validation_data
X_val = standardize_X(X_val)
y_val = standardize_y(y_val)
sample_weight_val = np.ones(y_val.shape[:-1] + (1,))
sample_weight_val = standardize_weights(y_val)
elif len(validation_data) == 3:
X_val, y_val, sample_weight_val = validation_data
X_val = standardize_X(X_val)
y_val = standardize_y(y_val)
sample_weight_val = standardize_weights(y_val, sample_weight=sample_weight_val)
sample_weight_val = standardize_weights(y_val,
sample_weight=sample_weight_val)
else:
raise Exception("Invalid format for validation data; provide a tuple (X_val, y_val) or (X_val, y_val, sample_weight). \
X_val may be a numpy array or a list of numpy arrays depending on your model input.")
@@ -470,7 +487,7 @@ class Sequential(Model, containers.Sequential):
sample_weight, sample_weight_val = (slice_X(sample_weight, 0, split_at), slice_X(sample_weight, split_at))
sample_weight_val = standardize_weights(y_val, sample_weight=sample_weight_val)
else:
sample_weight_val = np.ones(y_val.shape[:-1] + (1,))
sample_weight_val = standardize_weights(y_val)
val_ins = X_val + [y_val, sample_weight_val]
if show_accuracy:
@@ -483,7 +500,8 @@ class Sequential(Model, containers.Sequential):
sample_weight = standardize_weights(y, class_weight=class_weight, sample_weight=sample_weight)
ins = X + [y, sample_weight]
metrics = ['loss', 'acc', 'val_loss', 'val_acc']
return self._fit(f, ins, out_labels=out_labels, batch_size=batch_size, nb_epoch=nb_epoch,
return self._fit(f, ins, out_labels=out_labels,
batch_size=batch_size, nb_epoch=nb_epoch,
verbose=verbose, callbacks=callbacks,
val_f=val_f, val_ins=val_ins,
shuffle=shuffle, metrics=metrics)
@@ -505,7 +523,8 @@ class Sequential(Model, containers.Sequential):
else:
return (proba > 0.5).astype('int32')
def evaluate(self, X, y, batch_size=128, show_accuracy=False, verbose=1, sample_weight=None):
def evaluate(self, X, y, batch_size=128, show_accuracy=False,
verbose=1, sample_weight=None):
X = standardize_X(X)
y = standardize_y(y)
sample_weight = standardize_weights(y, sample_weight=sample_weight)
@@ -580,7 +599,7 @@ class Graph(Model, containers.Graph):
output = self.outputs[output_name]
y_train = output.get_output(True)
y_test = output.get_output(False)
y = T.zeros_like(y_test)
y = K.placeholder(ndim=K.ndim(y_train))
ys.append(y)
ys_train.append(y_train)
ys_test.append(y_test)
@@ -590,15 +609,12 @@ class Graph(Model, containers.Graph):
else:
mask = None
weight = T.ones_like(y_test)
weight = K.placeholder(ndim=1)
weights.append(weight)
weighted_loss = weighted_objective(objectives.get(loss_fn))
train_loss += weighted_loss(y, y_train, weight, mask)
test_loss += weighted_loss(y, y_test, weight, mask)
train_loss.name = 'train_loss'
test_loss.name = 'test_loss'
ins = [self.inputs[name].input for name in self.input_order]
train_ins = ins + ys + weights
test_ins = ins + ys + weights
@@ -611,12 +627,9 @@ class Graph(Model, containers.Graph):
self.theano_mode = theano_mode
self.loss = loss
self._train = theano.function(train_ins, train_loss, updates=updates,
allow_input_downcast=True, mode=theano_mode)
self._test = theano.function(test_ins, test_loss,
allow_input_downcast=True, mode=theano_mode)
self._predict = theano.function(inputs=ins, outputs=ys_test,
allow_input_downcast=True, mode=theano_mode)
self._train = K.function(train_ins, [train_loss], updates=updates)
self._test = K.function(test_ins, [test_loss])
self._predict = K.function(inputs=ins, outputs=ys_test)
def train_on_batch(self, data, class_weight={}, sample_weight={}):
# data is a dictionary mapping output and input names to arrays
@@ -624,22 +637,23 @@ class Graph(Model, containers.Graph):
sample_weight=sample_weight.get(name),
class_weight=class_weight.get(name)) for name in self.output_order]
ins = [data[name] for name in self.input_order] + [standardize_y(data[name]) for name in self.output_order] + sample_weight
return self._train(*ins)
return self._train(ins)
def test_on_batch(self, data, sample_weight={}):
# data is a dictionary mapping input names to arrays
sample_weight = [standardize_weights(data[name],
sample_weight=sample_weight.get(name)) for name in self.output_order]
ins = [data[name] for name in self.input_order] + [standardize_y(data[name]) for name in self.output_order] + sample_weight
return self._test(*ins)
return self._test(ins)
def predict_on_batch(self, data):
# data is a dictionary mapping input names to arrays
ins = [data[name] for name in self.input_order]
return self._predict(*ins)
return self._predict(ins)
def fit(self, data, batch_size=128, nb_epoch=100, verbose=1, callbacks=[],
validation_split=0., validation_data=None, shuffle=True, class_weight={}, sample_weight={}):
validation_split=0., validation_data=None, shuffle=True,
class_weight={}, sample_weight={}):
X = [data[name] for name in self.input_order]
y = [standardize_y(data[name]) for name in self.output_order]
@@ -653,7 +667,8 @@ class Graph(Model, containers.Graph):
val_f = self._test
if validation_data:
# can't use sample weights with validation data at this point
sample_weight = [standardize_weights(validation_data[name]) for name in self.output_order]
y_val = [standardize_y(data[name]) for name in self.output_order]
sample_weight = [standardize_weights(y_val[i]) for i in range(len(y_val))]
val_ins = [validation_data[name] for name in self.input_order] + [standardize_y(validation_data[name]) for name in self.output_order] + sample_weight
elif 0 < validation_split < 1:
+18 -23
Ver Arquivo
@@ -1,60 +1,55 @@
from __future__ import absolute_import
import theano
import theano.tensor as T
import numpy as np
from six.moves import range
if theano.config.floatX == 'float64':
epsilon = 1.0e-9
else:
epsilon = 1.0e-7
from . import backend as K
def mean_squared_error(y_true, y_pred):
return T.sqr(y_pred - y_true).mean(axis=-1)
return K.mean(K.square(y_pred - y_true), axis=-1)
def root_mean_squared_error(y_true, y_pred):
return K.sqrt(K.mean(K.square(y_pred - y_true), axis=-1))
def mean_absolute_error(y_true, y_pred):
return T.abs_(y_pred - y_true).mean(axis=-1)
return K.mean(K.abs(y_pred - y_true), axis=-1)
def mean_absolute_percentage_error(y_true, y_pred):
return T.abs_((y_true - y_pred) / T.clip(T.abs_(y_true), epsilon, np.inf)).mean(axis=-1) * 100.
diff = K.abs((y_true - y_pred) / K.clip(K.abs(y_true), K._EPSILON, np.inf))
return 100. * K.mean(diff, axis=-1)
def mean_squared_logarithmic_error(y_true, y_pred):
return T.sqr(T.log(T.clip(y_pred, epsilon, np.inf) + 1.) - T.log(T.clip(y_true, epsilon, np.inf) + 1.)).mean(axis=-1)
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), axis=-1)
def squared_hinge(y_true, y_pred):
return T.sqr(T.maximum(1. - y_true * y_pred, 0.)).mean(axis=-1)
return K.mean(K.square(K.maximum(1. - y_true * y_pred, 0.)), axis=-1)
def hinge(y_true, y_pred):
return T.maximum(1. - y_true * y_pred, 0.).mean(axis=-1)
return K.mean(K.maximum(1. - y_true * y_pred, 0.), axis=-1)
def categorical_crossentropy(y_true, y_pred):
'''Expects a binary class matrix instead of a vector of scalar classes
'''
y_pred = T.clip(y_pred, epsilon, 1.0 - epsilon)
# scale preds so that the class probas of each sample sum to 1
y_pred /= y_pred.sum(axis=-1, keepdims=True)
cce = T.nnet.categorical_crossentropy(y_pred, y_true)
return cce
return K.mean(K.categorical_crossentropy(y_pred, y_true), axis=-1)
def binary_crossentropy(y_true, y_pred):
y_pred = T.clip(y_pred, epsilon, 1.0 - epsilon)
bce = T.nnet.binary_crossentropy(y_pred, y_true).mean(axis=-1)
return bce
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
def poisson_loss(y_true, y_pred):
return T.mean(y_pred - y_true * T.log(y_pred + epsilon), axis=-1)
return K.mean(y_pred - y_true * K.log(y_pred + K._EPSILON), axis=-1)
# aliases
mse = MSE = mean_squared_error
rmse = RMSE = root_mean_squared_error
mae = MAE = mean_absolute_error
mape = MAPE = mean_absolute_percentage_error
msle = MSLE = mean_squared_logarithmic_error
+59 -58
Ver Arquivo
@@ -1,20 +1,18 @@
from __future__ import absolute_import
import theano
import theano.tensor as T
from .utils.theano_utils import shared_zeros, shared_scalar, floatX
from . import backend as K
import numpy as np
from .utils.generic_utils import get_from_module
from six.moves import zip
def clip_norm(g, c, n):
if c > 0:
g = T.switch(T.ge(n, c), g * c / n, g)
g = K.switch(n >= c, g * c / n, g)
return g
def kl_divergence(p, p_hat):
return p_hat - p + p * T.log(p / p_hat)
return p_hat - p + p * K.log(p / p_hat)
class Optimizer(object):
@@ -23,27 +21,23 @@ class Optimizer(object):
self.updates = []
def get_state(self):
return [u[0].get_value() for u in self.updates]
return [K.get_value(u[0]) for u in self.updates]
def set_state(self, value_list):
assert len(self.updates) == len(value_list)
for u, v in zip(self.updates, value_list):
u[0].set_value(floatX(v))
K.set_value(u[0], v)
def get_updates(self, params, constraints, loss):
raise NotImplementedError
def get_gradients(self, loss, params):
grads = T.grad(loss, params)
grads = K.gradients(loss, params)
if hasattr(self, 'clipnorm') and self.clipnorm > 0:
norm = T.sqrt(sum([T.sum(g ** 2) for g in grads]))
norm = K.sqrt(sum([K.sum(K.square(g)) for g in grads]))
grads = [clip_norm(g, self.clipnorm, norm) for g in grads]
if hasattr(self, 'clipvalue') and self.clipvalue > 0:
grads = [T.clip(g, -self.clipvalue, self.clipvalue) for g in grads]
grads = [K.clip(g, -self.clipvalue, self.clipvalue) for g in grads]
return grads
def get_config(self):
@@ -52,13 +46,14 @@ class Optimizer(object):
class SGD(Optimizer):
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,
*args, **kwargs):
super(SGD, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = shared_scalar(0)
self.lr = shared_scalar(lr)
self.momentum = shared_scalar(momentum)
self.decay = shared_scalar(decay)
self.iterations = K.variable(0.)
self.lr = K.variable(lr)
self.momentum = K.variable(momentum)
self.decay = K.variable(decay)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
@@ -66,7 +61,7 @@ class SGD(Optimizer):
self.updates = [(self.iterations, self.iterations + 1.)]
for p, g, c in zip(params, grads, constraints):
m = shared_zeros(p.get_value().shape) # momentum
m = K.variable(np.zeros(K.get_value(p).shape)) # momentum
v = self.momentum * m - lr * g # velocity
self.updates.append((m, v))
@@ -80,9 +75,9 @@ class SGD(Optimizer):
def get_config(self):
return {"name": self.__class__.__name__,
"lr": float(self.lr.get_value()),
"momentum": float(self.momentum.get_value()),
"decay": float(self.decay.get_value()),
"lr": float(K.get_value(self.lr)),
"momentum": float(K.get_value(self.momentum)),
"decay": float(K.get_value(self.decay)),
"nesterov": self.nesterov}
@@ -90,26 +85,27 @@ class RMSprop(Optimizer):
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-6, *args, **kwargs):
super(RMSprop, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = shared_scalar(lr)
self.rho = shared_scalar(rho)
self.lr = K.variable(lr)
self.rho = K.variable(rho)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [shared_zeros(p.get_value().shape) for p in params]
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.updates = []
for p, g, a, c in zip(params, grads, accumulators, constraints):
new_a = self.rho * a + (1 - self.rho) * g ** 2 # update accumulator
# 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 / T.sqrt(new_a + self.epsilon)
new_p = p - self.lr * g / K.sqrt(new_a + self.epsilon)
self.updates.append((p, c(new_p))) # apply constraints
return self.updates
def get_config(self):
return {"name": self.__class__.__name__,
"lr": float(self.lr.get_value()),
"rho": float(self.rho.get_value()),
"lr": float(K.get_value(self.lr)),
"rho": float(K.get_value(self.rho)),
"epsilon": self.epsilon}
@@ -117,23 +113,23 @@ class Adagrad(Optimizer):
def __init__(self, lr=0.01, epsilon=1e-6, *args, **kwargs):
super(Adagrad, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = shared_scalar(lr)
self.lr = K.variable(lr)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [shared_zeros(p.get_value().shape) for p in params]
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.updates = []
for p, g, a, c in zip(params, grads, accumulators, constraints):
new_a = a + g ** 2 # update accumulator
new_a = a + K.square(g) # update accumulator
self.updates.append((a, new_a))
new_p = p - self.lr * g / T.sqrt(new_a + self.epsilon)
new_p = p - self.lr * g / K.sqrt(new_a + self.epsilon)
self.updates.append((p, c(new_p))) # apply constraints
return self.updates
def get_config(self):
return {"name": self.__class__.__name__,
"lr": float(self.lr.get_value()),
"lr": float(K.get_value(self.lr)),
"epsilon": self.epsilon}
@@ -144,35 +140,35 @@ class Adadelta(Optimizer):
def __init__(self, lr=1.0, rho=0.95, epsilon=1e-6, *args, **kwargs):
super(Adadelta, self).__init__(**kwargs)
self.__dict__.update(locals())
self.lr = shared_scalar(lr)
self.lr = K.variable(lr)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
accumulators = [shared_zeros(p.get_value().shape) for p in params]
delta_accumulators = [shared_zeros(p.get_value().shape) for p in params]
accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
delta_accumulators = [K.variable(np.zeros(K.get_value(p).shape)) for p in params]
self.updates = []
for p, g, a, d_a, c in zip(params, grads, accumulators,
delta_accumulators, constraints):
new_a = self.rho * a + (1 - self.rho) * g ** 2 # update accumulator
# update accumulator
new_a = self.rho * a + (1 - self.rho) * K.square(g)
self.updates.append((a, new_a))
# use the new accumulator and the *old* delta_accumulator
update = g * T.sqrt(d_a + self.epsilon) / T.sqrt(new_a +
self.epsilon)
update = g * K.sqrt(d_a + self.epsilon) / K.sqrt(new_a + self.epsilon)
new_p = p - self.lr * update
self.updates.append((p, c(new_p))) # apply constraints
# update delta_accumulator
new_d_a = self.rho * d_a + (1 - self.rho) * update ** 2
new_d_a = self.rho * d_a + (1 - self.rho) * K.square(update)
self.updates.append((d_a, new_d_a))
return self.updates
def get_config(self):
return {"name": self.__class__.__name__,
"lr": float(self.lr.get_value()),
"rho": self.rho,
"lr": float(K.get_value(self.lr)),
"rho": float(K.get_value(self.rho)),
"epsilon": self.epsilon}
@@ -182,26 +178,31 @@ class Adam(Optimizer):
Default parameters follow those provided in the original paper.
'''
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,
*args, **kwargs):
super(Adam, self).__init__(**kwargs)
self.__dict__.update(locals())
self.iterations = shared_scalar(0)
self.lr = shared_scalar(lr)
self.iterations = K.variable(0)
self.lr = K.variable(lr)
self.beta_1 = K.variable(beta_1)
self.beta_2 = K.variable(beta_2)
def get_updates(self, params, constraints, loss):
grads = self.get_gradients(loss, params)
self.updates = [(self.iterations, self.iterations+1.)]
t = self.iterations + 1
lr_t = self.lr * T.sqrt(1-self.beta_2**t)/(1-self.beta_1**t)
lr_t = self.lr * K.sqrt(1 - K.pow(self.beta_2, t)) / (1 - K.pow(self.beta_1, t))
for p, g, c in zip(params, grads, constraints):
m = theano.shared(p.get_value() * 0.) # zero init of moment
v = theano.shared(p.get_value() * 0.) # zero init of velocity
# zero init of moment
m = K.variable(np.zeros(K.get_value(p).shape))
# zero init of velocity
v = K.variable(np.zeros(K.get_value(p).shape))
m_t = (self.beta_1 * m) + (1 - self.beta_1) * g
v_t = (self.beta_2 * v) + (1 - self.beta_2) * (g**2)
p_t = p - lr_t * m_t / (T.sqrt(v_t) + self.epsilon)
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))
@@ -210,9 +211,9 @@ class Adam(Optimizer):
def get_config(self):
return {"name": self.__class__.__name__,
"lr": float(self.lr.get_value()),
"beta_1": self.beta_1,
"beta_2": self.beta_2,
"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}
# aliases
@@ -224,5 +225,5 @@ adam = Adam
def get(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'optimizer', instantiate=True,
kwargs=kwargs)
return get_from_module(identifier, globals(), 'optimizer',
instantiate=True, kwargs=kwargs)
+4 -9
Ver Arquivo
@@ -214,17 +214,14 @@ class ImageDataGenerator(object):
# channel shifting
return x
def fit(self, X,
augment=False, # fit on randomly augmented samples
rounds=1, # if augment, how many augmentation passes over the data do we use
seed=None
):
def fit(self, X,
augment=False, # fit on randomly augmented samples
rounds=1, # if augment, how many augmentation passes over the data do we use
seed=None):
'''
Required for featurewise_center, featurewise_std_normalization and zca_whitening.
'''
X = np.copy(X)
if augment:
aX = np.zeros(tuple([rounds*X.shape[0]]+list(X.shape)[1:]))
for r in range(rounds):
@@ -247,5 +244,3 @@ class ImageDataGenerator(object):
sigma = np.dot(flatX.T, flatX) / flatX.shape[1]
U, S, V = linalg.svd(sigma)
self.principal_components = np.dot(np.dot(U, np.diag(1. / np.sqrt(S + fudge))), U.T)
+2
Ver Arquivo
@@ -24,6 +24,8 @@ def pad_sequences(sequences, maxlen=None, dtype='int32', padding='pre', truncati
x = (np.ones((nb_samples, maxlen)) * value).astype(dtype)
for idx, s in enumerate(sequences):
if len(s) == 0:
continue # empty list was found
if truncating == 'pre':
trunc = s[-maxlen:]
elif truncating == 'post':
+8 -6
Ver Arquivo
@@ -1,5 +1,5 @@
from __future__ import absolute_import
import theano.tensor as T
from . import backend as K
class Regularizer(object):
@@ -25,8 +25,8 @@ class WeightRegularizer(Regularizer):
self.p = p
def __call__(self, loss):
loss += T.sum(abs(self.p)) * self.l1
loss += T.sum(self.p ** 2) * self.l2
loss += K.sum(K.abs(self.p)) * self.l1
loss += K.sum(K.square(self.p)) * self.l2
return loss
def get_config(self):
@@ -44,8 +44,9 @@ class ActivityRegularizer(Regularizer):
self.layer = layer
def __call__(self, loss):
loss += self.l1 * T.sum(T.mean(abs(self.layer.get_output(True)), axis=0))
loss += self.l2 * T.sum(T.mean(self.layer.get_output(True) ** 2, axis=0))
output = self.layer.get_output(True)
loss += self.l1 * K.sum(K.mean(K.abs(output), axis=0))
loss += self.l2 * K.sum(K.mean(K.square(output), axis=0))
return loss
def get_config(self):
@@ -81,4 +82,5 @@ identity = Regularizer
from .utils.generic_utils import get_from_module
def get(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'regularizer', instantiate=True, kwargs=kwargs)
return get_from_module(identifier, globals(), 'regularizer',
instantiate=True, kwargs=kwargs)
+27 -65
Ver Arquivo
@@ -1,32 +1,35 @@
from __future__ import print_function
import inspect
import numpy as np
import theano
import copy
from ..layers.advanced_activations import LeakyReLU, PReLU
from ..layers.core import Dense, Merge, Dropout, Activation, Reshape, Flatten, RepeatVector, Layer, AutoEncoder, Masking, Permute
from ..layers.core import ActivityRegularization, TimeDistributedDense, AutoEncoder, MaxoutDense
from ..layers.convolutional import Convolution1D, Convolution2D, MaxPooling1D, MaxPooling2D, ZeroPadding2D
from ..layers.embeddings import Embedding, WordContextProduct
from ..layers.noise import GaussianNoise, GaussianDropout
from ..layers.normalization import BatchNormalization
from ..layers.recurrent import SimpleRNN, SimpleDeepRNN, GRU, LSTM, JZS1, JZS2, JZS3
from ..layers.advanced_activations import *
from ..layers.core import *
from ..layers.convolutional import *
from ..layers.embeddings import *
from ..layers.noise import *
from ..layers.normalization import *
from ..layers.recurrent import *
from ..layers import containers
from .. import regularizers
from .. import constraints
def container_from_config(original_layer_dict, custom_layers={}):
def container_from_config(original_layer_dict, custom_objects={}):
layer_dict = copy.deepcopy(original_layer_dict)
name = layer_dict.get('name')
# Insert custom layers into globals so they can
# be accessed by `get_from_module`.
for cls_key in custom_objects:
globals()[cls_key] = custom_objects[cls_key]
if name == 'Merge':
mode = layer_dict.get('mode')
layers = layer_dict.get('layers')
layer_list = []
for layer in layers:
init_layer = container_from_config(layer, custom_layers=custom_layers)
init_layer = container_from_config(layer)
layer_list.append(init_layer)
merge_layer = Merge(layer_list, mode)
return merge_layer
@@ -35,7 +38,7 @@ def container_from_config(original_layer_dict, custom_layers={}):
layers = layer_dict.get('layers')
layer_list = []
for layer in layers:
init_layer = container_from_config(layer, custom_layers=custom_layers)
init_layer = container_from_config(layer)
layer_list.append(init_layer)
seq_layer = containers.Sequential(layer_list)
return seq_layer
@@ -49,8 +52,7 @@ def container_from_config(original_layer_dict, custom_layers={}):
nodes = layer_dict.get('node_config')
for node in nodes:
layer = container_from_config(layer_dict['nodes'].get(node['name']),
custom_layers=custom_layers)
layer = container_from_config(layer_dict['nodes'].get(node['name']))
node['layer'] = layer
graph_layer.add_node(**node)
@@ -60,10 +62,8 @@ def container_from_config(original_layer_dict, custom_layers={}):
return graph_layer
elif name == 'AutoEncoder':
kwargs = {'encoder': container_from_config(layer_dict.get('encoder_config'),
custom_layers=custom_layers),
'decoder': container_from_config(layer_dict.get('decoder_config'),
custom_layers=custom_layers)}
kwargs = {'encoder': container_from_config(layer_dict.get('encoder_config')),
'decoder': container_from_config(layer_dict.get('decoder_config'))}
for kwarg in ['output_reconstruction', 'weights']:
if kwarg in layer_dict:
kwargs[kwarg] = layer_dict[kwarg]
@@ -73,59 +73,21 @@ def container_from_config(original_layer_dict, custom_layers={}):
layer_dict.pop('name')
for k, v in layer_dict.items():
# For now, this can only happen for regularizers and constraints
if isinstance(v, dict):
vname = v.get('name')
v.pop('name')
vname = v.pop('name')
if vname in [x for x, y in inspect.getmembers(constraints, predicate=inspect.isclass)]:
layer_dict[k] = constraints.get(vname, v)
if vname in [x for x, y in inspect.getmembers(regularizers, predicate=inspect.isclass)]:
elif vname in [x for x, y in inspect.getmembers(regularizers, predicate=inspect.isclass)]:
layer_dict[k] = regularizers.get(vname, v)
else:
# not a regularizer of constraint, don't touch it
v['name'] = vname
base_layer = get_layer(name, layer_dict, custom_layers=custom_layers)
base_layer = get_layer(name, layer_dict)
return base_layer
def print_layer_shapes(model, input_shapes):
"""
Utility function to print the shape of the output at each layer of a Model
Arguments:
model: instance of Model / Merge
input_shapes: dict (Graph), list of tuples (Merge) or tuple (Sequential)
"""
if model.__class__.__name__ in ['Sequential', 'Merge']:
# in this case input_shapes is a tuple, or a list [shape1, shape2]
if not isinstance(input_shapes[0], tuple):
input_shapes = [input_shapes]
inputs = model.get_input(train=False)
if not isinstance(inputs, list):
inputs = [inputs]
input_dummy = [np.zeros(shape, dtype=np.float32)
for shape in input_shapes]
layers = model.layers
elif model.__class__.__name__ == 'Graph':
# in this case input_shapes is a dictionary
inputs = [model.inputs[name].input
for name in model.input_order]
input_dummy = [np.zeros(input_shapes[name], dtype=np.float32)
for name in model.input_order]
layers = [model.nodes[c['name']] for c in model.node_config]
print("input shapes : ", input_shapes)
for l in layers:
shape_f = theano.function(inputs, l.get_output(train=False).shape,
on_unused_input='ignore')
out_shape = tuple(shape_f(*input_dummy))
config = l.get_config()
print('shape after %s: %s' % (config['name'], out_shape))
from .generic_utils import get_from_module
def get_layer(identifier, kwargs=None, custom_layers={}):
# Insert custom layers into globals so they can be accessed by `get_from_module`.
for cls_key in custom_layers:
globals()[cls_key] = custom_layers[cls_key]
return get_from_module(identifier, globals(), 'layer', instantiate=True, kwargs=kwargs)
def get_layer(identifier, kwargs=None):
return get_from_module(identifier, globals(), 'layer',
instantiate=True, kwargs=kwargs)
-1
Ver Arquivo
@@ -34,7 +34,6 @@ def binary_logloss(p, y):
def multiclass_logloss(P, Y):
score = 0.
npreds = [P[i][Y[i]-1] for i in range(len(Y))]
score = -(1. / len(Y)) * np.sum(np.log(npreds))
return score
-44
Ver Arquivo
@@ -1,44 +0,0 @@
from __future__ import absolute_import
import numpy as np
import theano
import theano.tensor as T
def floatX(X):
return np.asarray(X, dtype=theano.config.floatX)
def sharedX(X, dtype=theano.config.floatX, name=None):
return theano.shared(np.asarray(X, dtype=dtype), name=name)
def shared_zeros(shape, dtype=theano.config.floatX, name=None):
return sharedX(np.zeros(shape), dtype=dtype, name=name)
def shared_scalar(val=0., dtype=theano.config.floatX, name=None):
return theano.shared(np.cast[dtype](val))
def shared_ones(shape, dtype=theano.config.floatX, name=None):
return sharedX(np.ones(shape), dtype=dtype, name=name)
def alloc_zeros_matrix(*dims):
return T.alloc(np.cast[theano.config.floatX](0.), *dims)
def ndim_tensor(ndim):
if ndim == 1:
return T.vector()
elif ndim == 2:
return T.matrix()
elif ndim == 3:
return T.tensor3()
elif ndim == 4:
return T.tensor4()
return T.matrix()
def on_gpu():
return theano.config.device[:3] == 'gpu'
+6 -6
Ver Arquivo
@@ -1,10 +1,9 @@
import pydot
# old pydot will not work with python3, must use one
# that works with python3 such as pydot2 or pydot
from keras.models import Sequential, Graph
def plot(model, to_file='model.png'):
def to_graph(model):
graph = pydot.Dot(graph_type='digraph')
if type(model) == Sequential:
previous_node = None
@@ -20,8 +19,6 @@ def plot(model, to_file='model.png'):
if previous_node:
graph.add_edge(pydot.Edge(previous_node, current_node))
previous_node = current_node
graph.write_png(to_file)
elif type(model) == Graph:
# don't need to append number for names since all nodes labeled
for input_node in model.input_config:
@@ -37,5 +34,8 @@ def plot(model, to_file='model.png'):
graph.add_edge(pydot.Edge(e, node['name']))
else:
graph.add_edge(pydot.Edge(node['input'], node['name']))
return graph
graph.write_png(to_file)
def plot(model, to_file='model.png'):
graph = to_graph(model)
graph.write_png(to_file)
+1 -1
Ver Arquivo
@@ -10,7 +10,7 @@ setup(name='Keras',
url='https://github.com/fchollet/keras',
download_url='https://github.com/fchollet/keras/tarball/0.2.0',
license='MIT',
install_requires=['theano', 'pyyaml'],
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
'h5py': ['h5py'],
},
Ver Arquivo
-106
Ver Arquivo
@@ -1,106 +0,0 @@
import math
import keras
import theano
import theano.tensor as T
import numpy
def list_assert_equal(a, b, round_to=7):
'''
This will do a pairwise, rounded equality test across two lists of
numbers.
'''
pairs = zip(a, b)
for i, j in pairs:
assert round(i, round_to) == round(j, round_to)
def get_standard_values():
'''
These are just a set of floats used for testing the activation
functions, and are useful in multiple tests.
'''
return [0, 0.1, 0.5, 0.9, 1.0]
def test_softmax():
from keras.activations import softmax as s
# Test using a reference implementation of softmax
def softmax(values):
m = max(values)
values = numpy.array(values)
e = numpy.exp(values - m)
dist = list(e / numpy.sum(e))
return dist
x = T.vector()
exp = s(x)
f = theano.function([x], exp)
test_values = get_standard_values()
result = f(test_values)
expected = softmax(test_values)
print(str(result))
print(str(expected))
list_assert_equal(result, expected)
def test_relu():
'''
Relu implementation doesn't depend on the value being
a theano variable. Testing ints, floats and theano tensors.
'''
from keras.activations import relu as r
assert r(5) == 5
assert r(-5) == 0
assert r(-0.1) == 0
assert r(0.1) == 0.1
x = T.vector()
exp = r(x)
f = theano.function([x], exp)
test_values = get_standard_values()
result = f(test_values)
list_assert_equal(result, test_values) # because no negatives in test values
def test_tanh():
from keras.activations import tanh as t
test_values = get_standard_values()
x = T.vector()
exp = t(x)
f = theano.function([x], exp)
result = f(test_values)
expected = [math.tanh(v) for v in test_values]
print(result)
print(expected)
list_assert_equal(result, expected)
def test_linear():
'''
This function does no input validation, it just returns the thing
that was passed in.
'''
from keras.activations import linear as l
xs = [1, 5, True, None, 'foo']
for x in xs:
assert x == l(x)
+335
Ver Arquivo
@@ -0,0 +1,335 @@
import sys
import unittest
from numpy.testing import assert_allclose
import numpy as np
import pytest
if sys.version_info.major == 2:
from keras.backend import theano_backend as KTH
from keras.backend import tensorflow_backend as KTF
def check_single_tensor_operation(function_name, input_shape, **kwargs):
val = np.random.random(input_shape) - 0.5
xth = KTH.variable(val)
xtf = KTF.variable(val)
zth = KTH.eval(getattr(KTH, function_name)(xth, **kwargs))
ztf = KTF.eval(getattr(KTF, function_name)(xtf, **kwargs))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-06)
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)
zth = KTH.eval(getattr(KTH, function_name)(xth, yth, **kwargs))
ztf = KTF.eval(getattr(KTF, function_name)(xtf, ytf, **kwargs))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-06)
@pytest.mark.skipif(sys.version_info.major != 2, reason="Requires Python 2.7")
class TestBackend(unittest.TestCase):
def test_linear_operations(self):
check_two_tensor_operation('dot', (4, 2), (2, 4))
check_single_tensor_operation('transpose', (4, 2))
def test_shape_operations(self):
# concatenate
xval = np.random.random((4, 3))
xth = KTH.variable(xval)
xtf = KTF.variable(xval)
yval = np.random.random((4, 2))
yth = KTH.variable(yval)
ytf = KTF.variable(yval)
zth = KTH.eval(KTH.concatenate([xth, yth], axis=-1))
ztf = KTF.eval(KTF.concatenate([xtf, ytf], axis=-1))
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-06)
check_single_tensor_operation('reshape', (4, 2), shape=(8, 1))
check_single_tensor_operation('permute_dimensions', (4, 2, 3),
pattern=(2, 0, 1))
check_single_tensor_operation('repeat', (4, 1), n=3)
check_single_tensor_operation('flatten', (4, 1))
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)
def test_value_manipulation(self):
val = np.random.random((4, 2))
xth = KTH.variable(val)
xtf = KTF.variable(val)
# get_value
valth = KTH.get_value(xth)
valtf = KTF.get_value(xtf)
assert valtf.shape == valth.shape
assert_allclose(valth, valtf, atol=1e-06)
# set_value
val = np.random.random((4, 2))
KTH.set_value(xth, val)
KTF.set_value(xtf, val)
valth = KTH.get_value(xth)
valtf = KTF.get_value(xtf)
assert valtf.shape == valth.shape
assert_allclose(valth, valtf, atol=1e-06)
# count_params
assert KTH.count_params(xth) == KTF.count_params(xtf)
def test_elementwise_operations(self):
check_single_tensor_operation('max', (4, 2))
check_single_tensor_operation('max', (4, 2), axis=1, keepdims=True)
check_single_tensor_operation('min', (4, 2))
check_single_tensor_operation('min', (4, 2), axis=1, keepdims=True)
check_single_tensor_operation('mean', (4, 2))
check_single_tensor_operation('mean', (4, 2), axis=1, keepdims=True)
check_single_tensor_operation('mean', (4, 2, 3), axis=-1, keepdims=True)
check_single_tensor_operation('std', (4, 2))
check_single_tensor_operation('std', (4, 2), axis=1, keepdims=True)
check_single_tensor_operation('prod', (4, 2))
check_single_tensor_operation('prod', (4, 2), axis=1, keepdims=True)
# 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('argmax', (4, 2))
check_single_tensor_operation('argmax', (4, 2), axis=1)
check_single_tensor_operation('argmin', (4, 2))
check_single_tensor_operation('argmin', (4, 2), axis=1)
check_single_tensor_operation('square', (4, 2))
check_single_tensor_operation('abs', (4, 2))
check_single_tensor_operation('sqrt', (4, 2))
check_single_tensor_operation('exp', (4, 2))
check_single_tensor_operation('log', (4, 2))
check_single_tensor_operation('round', (4, 2))
check_single_tensor_operation('pow', (4, 2), a=3)
check_single_tensor_operation('clip', (4, 2), min_value=0.4,
max_value=0.6)
# two-tensor ops
check_two_tensor_operation('equal', (4, 2), (4, 2))
check_two_tensor_operation('maximum', (4, 2), (4, 2))
check_two_tensor_operation('minimum', (4, 2), (4, 2))
def test_gradient(self):
val = np.random.random((4, 2))
xth = KTH.variable(val)
xtf = KTF.variable(val)
expth = xth * KTH.exp(xth)
exptf = xtf * KTF.exp(xtf)
lossth = KTH.sum(expth)
losstf = KTF.sum(exptf)
gradth = KTH.gradients(lossth, [expth])
gradtf = KTF.gradients(losstf, [exptf])
zth = KTH.eval(gradth[0])
ztf = KTF.eval(gradtf[0])
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-06)
def test_function(self):
val = np.random.random((4, 2))
input_val = np.random.random((4, 2))
xth = KTH.variable(val)
xtf = KTF.variable(val)
yth = KTH.placeholder(ndim=2)
ytf = KTF.placeholder(ndim=2)
exp_th = KTH.square(xth) + yth
exp_tf = KTF.square(xtf) + ytf
update_th = xth * 2
update_tf = xtf * 2
fth = KTH.function([yth], [exp_th], updates=[(xth, update_th)])
ftf = KTF.function([ytf], [exp_tf], updates=[(xtf, update_tf)])
function_outputs_th = fth([input_val])[0]
function_outputs_tf = ftf([input_val])[0]
assert function_outputs_th.shape == function_outputs_tf.shape
assert_allclose(function_outputs_th, function_outputs_tf, atol=1e-06)
new_val_th = KTH.get_value(xth)
new_val_tf = KTF.get_value(xtf)
assert new_val_th.shape == new_val_tf.shape
assert_allclose(new_val_th, new_val_tf, atol=1e-06)
def test_rnn(self):
# implement a simple RNN
input_dim = 8
output_dim = 4
timesteps = 5
input_val = np.random.random((32, timesteps, input_dim))
init_state_val = np.random.random((32, output_dim))
W_i_val = np.random.random((input_dim, output_dim))
W_o_val = np.random.random((output_dim, output_dim))
def rnn_step_fn(input_dim, output_dim, K):
W_i = K.variable(W_i_val)
W_o = K.variable(W_o_val)
def step_function(x, states):
assert len(states) == 1
prev_output = states[0]
output = K.dot(x, W_i) + K.dot(prev_output, W_o)
return output, [output]
return step_function
th_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTH)
inputs = KTH.variable(input_val)
initial_states = [KTH.variable(init_state_val)]
last_output, outputs, new_states = KTH.rnn(th_rnn_step_fn, inputs,
initial_states,
go_backwards=False,
masking=False)
th_last_output = KTH.eval(last_output)
th_outputs = KTH.eval(outputs)
assert len(new_states) == 1
th_state = KTH.eval(new_states[0])
tf_rnn_step_fn = rnn_step_fn(input_dim, output_dim, KTF)
inputs = KTF.variable(input_val)
initial_states = [KTF.variable(init_state_val)]
last_output, outputs, new_states = KTF.rnn(tf_rnn_step_fn, inputs,
initial_states,
go_backwards=False,
masking=False)
tf_last_output = KTF.eval(last_output)
tf_outputs = KTF.eval(outputs)
assert len(new_states) == 1
tf_state = KTF.eval(new_states[0])
assert_allclose(tf_last_output, th_last_output, atol=1e-06)
assert_allclose(tf_outputs, th_outputs, atol=1e-06)
assert_allclose(tf_state, th_state, atol=1e-06)
def test_switch(self):
val = np.random.random()
xth = KTH.variable(val)
xth = KTH.switch(xth >= 0.5, xth * 0.1, xth * 0.2)
xtf = KTF.variable(val)
xtf = KTF.switch(xtf >= 0.5, xtf * 0.1, xtf * 0.2)
zth = KTH.eval(xth)
ztf = KTF.eval(xtf)
assert zth.shape == ztf.shape
assert_allclose(zth, ztf, atol=1e-06)
def test_nn_operations(self):
check_single_tensor_operation('relu', (4, 2), alpha=0.1, max_value=0.5)
check_single_tensor_operation('softmax', (4, 10))
check_single_tensor_operation('softplus', (4, 10))
check_single_tensor_operation('sigmoid', (4, 2))
check_single_tensor_operation('hard_sigmoid', (4, 2))
check_single_tensor_operation('tanh', (4, 2))
# dropout
val = np.random.random((20, 20))
xth = KTH.variable(val)
xtf = KTF.variable(val)
zth = KTH.eval(KTH.dropout(xth, level=0.2))
ztf = KTF.eval(KTF.dropout(xtf, level=0.2))
assert zth.shape == ztf.shape
# dropout patterns are different, only check mean
assert np.abs(zth.mean() - ztf.mean()) < 0.05
check_two_tensor_operation('binary_crossentropy', (4, 2), (4, 2), from_logits=True)
check_two_tensor_operation('categorical_crossentropy', (4, 2), (4, 2), from_logits=True)
check_two_tensor_operation('binary_crossentropy', (4, 2), (4, 2), from_logits=False)
check_two_tensor_operation('categorical_crossentropy', (4, 2), (4, 2), from_logits=False)
# 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')
# # 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')
# 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')
# check_two_tensor_operation('conv2d', (5, 3, 10, 12), (4, 3, 3, 3),
# strides=(2, 2), border_mode='valid')
# def test_maxpool2d(self):
# '''maxpool2d works "properly" with Theano and TF but outputs different
# values in each case. Cause unclear (input shape format?)
# '''
# check_single_tensor_operation('maxpool2d', (5, 3, 10, 12), pool_size=(2, 2),
# strides=(1, 1), border_mode='valid')
# check_single_tensor_operation('maxpool2d', (5, 3, 9, 11), pool_size=(2, 2),
# strides=(1, 1), border_mode='valid')
# check_single_tensor_operation('maxpool2d', (5, 3, 9, 11), pool_size=(2, 3),
# strides=(1, 1), border_mode='valid')
def test_random_normal(self):
mean = 0.
std = 1.
rand = KTF.get_value(KTF.random_normal((1000, 1000), mean=mean, std=std))
assert(rand.shape == (1000, 1000))
assert(np.abs(np.mean(rand) - mean) < 0.01)
assert(np.abs(np.std(rand) - std) < 0.01)
rand = KTF.get_value(KTF.random_normal((1000, 1000), mean=mean, std=std))
assert(rand.shape == (1000, 1000))
assert(np.abs(np.mean(rand) - mean) < 0.01)
assert(np.abs(np.std(rand) - std) < 0.01)
def test_random_uniform(self):
mean = 0.
std = 1.
rand = KTF.get_value(KTF.random_normal((1000, 1000), mean=mean, std=std))
assert(rand.shape == (1000, 1000))
assert(np.abs(np.mean(rand) - mean) < 0.01)
assert(np.abs(np.std(rand) - std) < 0.01)
rand = KTF.get_value(KTF.random_normal((1000, 1000), mean=mean, std=std))
assert(rand.shape == (1000, 1000))
assert(np.abs(np.mean(rand) - mean) < 0.01)
assert(np.abs(np.std(rand) - std) < 0.01)
if __name__ == '__main__':
unittest.main()
@@ -1,8 +1,8 @@
import unittest
import numpy as np
from numpy.testing import assert_allclose
import theano
from keras import backend as K
from keras.layers import convolutional
@@ -14,31 +14,35 @@ class TestConvolutions(unittest.TestCase):
filter_length = 6
nb_filter = 5
weights_in = [np.ones((nb_filter, input_dim, filter_length, 1)), np.ones(nb_filter)]
weights_in = [np.ones((nb_filter, input_dim, filter_length, 1)),
np.ones(nb_filter)]
input = np.ones((nb_samples, nb_steps, input_dim))
for weight in [None, weights_in]:
for border_mode in ['valid', 'full', 'same']:
for subsample_length in [1, 3]:
for border_mode in ['valid', 'same']:
for subsample_length in [1]:
if border_mode == 'same' and subsample_length != 1:
continue
for W_regularizer in [None, 'l2']:
for b_regularizer in [None, 'l2']:
for act_regularizer in [None, 'l2']:
layer = convolutional.Convolution1D(
nb_filter, filter_length, weights=weight,
border_mode=border_mode, W_regularizer=W_regularizer,
b_regularizer=b_regularizer, activity_regularizer=act_regularizer,
subsample_length=subsample_length, input_shape=(None, input_dim))
nb_filter, filter_length,
weights=weight,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
activity_regularizer=act_regularizer,
subsample_length=subsample_length,
input_shape=(None, input_dim))
layer.input = theano.shared(value=input)
layer.input = K.variable(input)
for train in [True, False]:
out = layer.get_output(train).eval()
out = K.eval(layer.get_output(train))
assert input.shape[0] == out.shape[0]
if border_mode == 'same' and subsample_length == 1:
assert input.shape[1] == out.shape[1]
config = layer.get_config()
layer.get_config()
def test_maxpooling_1d(self):
nb_samples = 9
@@ -46,14 +50,13 @@ class TestConvolutions(unittest.TestCase):
input_dim = 10
input = np.ones((nb_samples, nb_steps, input_dim))
for ignore_border in [True, False]:
for stride in [1, 2]:
layer = convolutional.MaxPooling1D(stride=stride, ignore_border=ignore_border)
layer.input = theano.shared(value=input)
for train in [True, False]:
layer.get_output(train).eval()
config = layer.get_config()
for stride in [1, 2]:
layer = convolutional.MaxPooling1D(stride=stride,
border_mode='valid')
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
def test_convolution_2d(self):
nb_samples = 8
@@ -69,26 +72,29 @@ class TestConvolutions(unittest.TestCase):
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
for weight in [None, weights_in]:
for border_mode in ['valid', 'full', 'same']:
for subsample in [(1, 1), (2, 3)]:
for border_mode in ['valid', 'same']:
for subsample in [(1, 1), (2, 2)]:
if border_mode == 'same' and subsample != (1, 1):
continue
for W_regularizer in [None, 'l2']:
for b_regularizer in [None, 'l2']:
for act_regularizer in [None, 'l2']:
layer = convolutional.Convolution2D(
nb_filter, nb_row, nb_col, weights=weight,
border_mode=border_mode, W_regularizer=W_regularizer,
b_regularizer=b_regularizer, activity_regularizer=act_regularizer,
subsample=subsample, input_shape=(stack_size, None, None))
nb_filter, nb_row, nb_col,
weights=weight,
border_mode=border_mode,
W_regularizer=W_regularizer,
b_regularizer=b_regularizer,
activity_regularizer=act_regularizer,
subsample=subsample,
input_shape=(stack_size, None, None))
layer.input = theano.shared(value=input)
layer.input = K.variable(input)
for train in [True, False]:
out = layer.get_output(train).eval()
out = K.eval(layer.get_output(train))
if border_mode == 'same' and subsample == (1, 1):
assert out.shape[2:] == input.shape[2:]
config = layer.get_config()
layer.get_config()
def test_maxpooling_2d(self):
nb_samples = 9
@@ -98,14 +104,14 @@ class TestConvolutions(unittest.TestCase):
pool_size = (3, 3)
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
for ignore_border in [True, False]:
for stride in [(1, 1), (2, 2)]:
layer = convolutional.MaxPooling2D(stride=stride, ignore_border=ignore_border, pool_size=pool_size)
layer.input = theano.shared(value=input)
for train in [True, False]:
layer.get_output(train).eval()
config = layer.get_config()
for strides in [(1, 1), (2, 2)]:
layer = convolutional.MaxPooling2D(strides=strides,
border_mode='valid',
pool_size=pool_size)
layer.input = K.variable(input)
for train in [True, False]:
K.eval(layer.get_output(train))
layer.get_config()
def test_zero_padding_2d(self):
nb_samples = 9
@@ -115,32 +121,30 @@ class TestConvolutions(unittest.TestCase):
input = np.ones((nb_samples, stack_size, input_nb_row, input_nb_col))
layer = convolutional.ZeroPadding2D(padding=(2, 2))
layer.input = theano.shared(value=input)
layer.input = K.variable(input)
for train in [True, False]:
out = layer.get_output(train).eval()
out = K.eval(layer.get_output(train))
for offset in [0, 1, -1, -2]:
assert_allclose(out[:, :, offset, :], 0.)
assert_allclose(out[:, :, :, offset], 0.)
assert_allclose(out[:, :, 2:-2, 2:-2], 1.)
layer.get_config()
config = layer.get_config()
def test_upsample_1d(self):
def test_upsampling_1d(self):
nb_samples = 9
nb_steps = 7
input_dim = 10
input = np.ones((nb_samples, nb_steps, input_dim))
for length in [2, 3, 9]:
layer = convolutional.UpSample1D(length=length)
layer.input = theano.shared(value=input)
layer = convolutional.UpSampling1D(length=length)
layer.input = K.variable(input)
for train in [True, False]:
out = layer.get_output(train).eval()
assert out.shape[1] == length*nb_steps
out = K.eval(layer.get_output(train))
assert out.shape[1] == length * nb_steps
layer.get_config()
config = layer.get_config()
def test_upsample_2d(self):
def test_upsampling_2d(self):
nb_samples = 9
stack_size = 7
input_nb_row = 11
@@ -150,14 +154,13 @@ class TestConvolutions(unittest.TestCase):
for length_row in [2, 3, 9]:
for length_col in [2, 3, 9]:
layer = convolutional.UpSample2D(size=(length_row, length_col))
layer.input = theano.shared(value=input)
layer = convolutional.UpSampling2D(size=(length_row, length_col))
layer.input = K.variable(input)
for train in [True, False]:
out = layer.get_output(train).eval()
assert out.shape[2] == length_row*input_nb_row
assert out.shape[3] == length_col*input_nb_col
config = layer.get_config()
out = K.eval(layer.get_output(train))
assert out.shape[2] == length_row * input_nb_row
assert out.shape[3] == length_col * input_nb_col
layer.get_config()
if __name__ == '__main__':
unittest.main()
@@ -1,8 +1,8 @@
import unittest
import numpy as np
from numpy.testing import assert_allclose
import theano
from keras import backend as K
from keras.layers import core
@@ -15,10 +15,10 @@ class TestLayerBase(unittest.TestCase):
# Once an input is provided, it should be reachable through the
# appropriate getters
input = np.ones((nb_samples, input_dim))
layer.input = theano.shared(value=input)
layer.input = K.variable(input)
for train in [True, False]:
assert_allclose(layer.get_input(train).eval(), input)
assert_allclose(layer.get_output(train).eval(), input)
assert_allclose(K.eval(layer.get_input(train)), input)
assert_allclose(K.eval(layer.get_output(train)), input)
def test_connections(self):
nb_samples = 10
@@ -27,13 +27,13 @@ class TestLayerBase(unittest.TestCase):
layer2 = core.Layer()
input = np.ones((nb_samples, input_dim))
layer1.input = theano.shared(value=input)
layer1.input = K.variable(input)
# After connecting, input of layer1 should be passed through
layer2.set_previous(layer1)
for train in [True, False]:
assert_allclose(layer2.get_input(train).eval(), input)
assert_allclose(layer2.get_output(train).eval(), input)
assert_allclose(K.eval(layer2.get_input(train)), input)
assert_allclose(K.eval(layer2.get_output(train)), input)
class TestConfigParams(unittest.TestCase):
@@ -60,6 +60,8 @@ class TestConfigParams(unittest.TestCase):
def test_merge(self):
layer_1 = core.Layer()
layer_2 = core.Layer()
layer_1.set_input_shape((None,))
layer_2.set_input_shape((None,))
layer = core.Merge([layer_1, layer_2])
self._runner(layer)
@@ -116,38 +118,48 @@ class TestMasking(unittest.TestCase):
def test_sequences(self):
"""Test masking sequences with zeroes as padding"""
if K._BACKEND == "tensorflow":
return
# integer inputs, one per timestep, like embeddings
layer = core.Masking()
func = theano.function([layer.input], layer.get_output_mask())
self.assertTrue(np.all(
# get mask for this input
func(np.array([[[1], [2], [3], [0]],
[[0], [4], [5], [0]]], dtype=np.int32)) ==
# This is the expected output mask, one dimension less
np.array([[1, 1, 1, 0], [0, 1, 1, 0]])))
func = K.function([layer.input], [layer.get_output_mask()])
input_data = np.array([[[1], [2], [3], [0]],
[[0], [4], [5], [0]]], dtype=np.int32)
# This is the expected output mask, one dimension less
expected = np.array([[1, 1, 1, 0], [0, 1, 1, 0]])
# get mask for this input
output = func([input_data])[0]
self.assertTrue(np.all(output == expected))
def test_non_zero(self):
"""Test masking with non-zero mask value"""
if K._BACKEND == "tensorflow":
return
layer = core.Masking(5)
func = theano.function([layer.input], layer.get_output_mask())
self.assertTrue(np.all(
# get mask for this input, if not all the values are 5, shouldn't masked
func(np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]], dtype=np.int32)) ==
# This is the expected output mask, one dimension less
np.array([[1, 1, 1, 0], [1, 1, 1, 1]])))
func = K.function([layer.input], [layer.get_output_mask()])
input_data = np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]],
dtype=np.int32)
output = func([input_data])[0]
expected = np.array([[1, 1, 1, 0], [1, 1, 1, 1]])
self.assertTrue(np.all(output == expected))
def test_non_zero_output(self):
"""Test output of masking layer with non-zero mask value"""
if K._BACKEND == "tensorflow":
return
layer = core.Masking(5)
func = theano.function([layer.input], layer.get_output())
self.assertTrue(np.all(
# get output for this input, replace padding with 0
func(np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]], dtype=np.int32)) ==
# This is the expected output
np.array([[[1, 1], [2, 1], [3, 1], [0, 0]],
[[1, 5], [5, 0], [0, 0], [0, 0]]])))
func = K.function([layer.input], [layer.get_output()])
input_data = np.array([[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]],
dtype=np.int32)
output = func([input_data])[0]
expected = np.array([[[1, 1], [2, 1], [3, 1], [0, 0]],
[[1, 5], [5, 0], [0, 0], [0, 0]]])
self.assertTrue(np.all(output == expected))
if __name__ == '__main__':
@@ -1,24 +1,25 @@
import unittest
import numpy as np
import theano
from keras.layers import recurrent
from keras import backend as K
nb_samples, timesteps, input_dim, output_dim = 3, 3, 10, 5
def _runner(layer_class):
"""
All the recurrent layers share the same interface, so we can run through them with a single
function.
All the recurrent layers share the same interface,
so we can run through them with a single function.
"""
for ret_seq in [True, False]:
layer = layer_class(output_dim, return_sequences=ret_seq, weights=None, input_shape=(None, input_dim))
layer.input = theano.shared(value=np.ones((nb_samples, timesteps, input_dim)))
config = layer.get_config()
layer = layer_class(output_dim, return_sequences=ret_seq,
weights=None, input_shape=(timesteps, input_dim))
layer.input = K.variable(np.ones((nb_samples, timesteps, input_dim)))
layer.get_config()
for train in [True, False]:
out = layer.get_output(train).eval()
out = K.eval(layer.get_output(train))
# Make sure the output has the desired shape
if ret_seq:
assert(out.shape == (nb_samples, timesteps, output_dim))
@@ -35,24 +36,12 @@ class TestRNNS(unittest.TestCase):
def test_simple(self):
_runner(recurrent.SimpleRNN)
def test_simple_deep(self):
_runner(recurrent.SimpleDeepRNN)
def test_gru(self):
_runner(recurrent.GRU)
def test_lstm(self):
_runner(recurrent.LSTM)
def test_jzs1(self):
_runner(recurrent.JZS1)
def test_jzs2(self):
_runner(recurrent.JZS2)
def test_jzs3(self):
_runner(recurrent.JZS3)
if __name__ == '__main__':
unittest.main()
+76
Ver Arquivo
@@ -0,0 +1,76 @@
import unittest
from keras import backend as K
import numpy as np
from numpy.testing import assert_allclose
def get_standard_values():
'''
These are just a set of floats used for testing the activation
functions, and are useful in multiple tests.
'''
return np.array([[0, 0.1, 0.5, 0.9, 1.0]], dtype=K.floatx())
class TestActivations(unittest.TestCase):
def test_softmax(self):
from keras.activations import softmax as s
# Test using a reference implementation of softmax
def softmax(values):
m = np.max(values)
e = np.exp(values - m)
return e / np.sum(e)
x = K.placeholder(ndim=2)
exp = s(x)
f = K.function([x], [exp])
test_values = get_standard_values()
result = f([test_values])[0]
expected = softmax(test_values)
assert_allclose(result, expected, rtol=1e-05)
def test_relu(self):
'''
Relu implementation doesn't depend on the value being
a theano variable. Testing ints, floats and theano tensors.
'''
from keras.activations import relu as r
x = K.placeholder(ndim=2)
exp = r(x)
f = K.function([x], [exp])
test_values = get_standard_values()
result = f([test_values])[0]
# because no negatives in test values
assert_allclose(result, test_values, rtol=1e-05)
def test_tanh(self):
from keras.activations import tanh as t
test_values = get_standard_values()
x = K.placeholder(ndim=2)
exp = t(x)
f = K.function([x], [exp])
result = f([test_values])[0]
expected = np.tanh(test_values)
assert_allclose(result, expected, rtol=1e-05)
def test_linear(self):
'''
This function does no input validation, it just returns the thing
that was passed in.
'''
from keras.activations import linear as l
xs = [1, 5, True, None, 'foo']
for x in xs:
assert x == l(x)
if __name__ == '__main__':
unittest.main()
@@ -1,7 +1,7 @@
import unittest
import numpy as np
from numpy.testing import assert_allclose
from theano import tensor as T
from keras import backend as K
class TestConstraints(unittest.TestCase):
@@ -16,23 +16,25 @@ class TestConstraints(unittest.TestCase):
for m in self.some_values:
norm_instance = maxnorm(m)
normed = norm_instance(self.example_array)
assert (np.all(normed.eval() < m))
normed = norm_instance(K.variable(self.example_array))
assert (np.all(K.eval(normed) < m))
# a more explicit example
norm_instance = maxnorm(2.0)
x = np.array([[0, 0, 0], [1.0, 0, 0], [3, 0, 0], [3, 3, 3]]).T
x_normed_target = np.array([[0, 0, 0], [1.0, 0, 0], [2.0, 0, 0], [2./np.sqrt(3), 2./np.sqrt(3), 2./np.sqrt(3)]]).T
x_normed_actual = norm_instance(x).eval()
assert_allclose(x_normed_actual, x_normed_target)
x_normed_target = np.array([[0, 0, 0], [1.0, 0, 0],
[2.0, 0, 0],
[2. / np.sqrt(3), 2. / np.sqrt(3), 2. / np.sqrt(3)]]).T
x_normed_actual = K.eval(norm_instance(K.variable(x)))
assert_allclose(x_normed_actual, x_normed_target, rtol=1e-05)
def test_nonneg(self):
from keras.constraints import nonneg
nonneg_instance = nonneg()
normed = nonneg_instance(self.example_array)
assert (np.all(np.min(normed.eval(), axis=1) == 0.))
normed = nonneg_instance(K.variable(self.example_array))
assert (np.all(np.min(K.eval(normed), axis=1) == 0.))
def test_identity(self):
from keras.constraints import identity
@@ -58,12 +60,13 @@ class TestConstraints(unittest.TestCase):
from keras.constraints import unitnorm
unitnorm_instance = unitnorm()
normalized = unitnorm_instance(self.example_array)
normalized = unitnorm_instance(K.variable(self.example_array))
norm_of_normalized = np.sqrt(np.sum(normalized.eval()**2, axis=1))
difference = norm_of_normalized - 1. # in the unit norm constraint, it should be equal to 1.
norm_of_normalized = np.sqrt(np.sum(K.eval(normalized)**2, axis=1))
# in the unit norm constraint, it should be equal to 1.
difference = norm_of_normalized - 1.
largest_difference = np.max(np.abs(difference))
self.assertAlmostEqual(largest_difference, 0.)
assert np.abs(largest_difference) < 10e-5
if __name__ == '__main__':
unittest.main()
@@ -1,9 +1,9 @@
import unittest
import numpy as np
from numpy.testing import assert_allclose
from theano import tensor as T
from keras.layers import normalization
from keras.models import Sequential
from keras import backend as K
class TestBatchNormalization(unittest.TestCase):
@@ -19,7 +19,8 @@ class TestBatchNormalization(unittest.TestCase):
norm_m1 = normalization.BatchNormalization(input_shape=(10, 10), mode=1)
# mode 3 does not exist
self.assertRaises(Exception, normalization.BatchNormalization(input_shape=(10, 10), mode=3))
self.assertRaises(Exception,
normalization.BatchNormalization(input_shape=(10, 10), mode=3))
def test_mode_0(self):
model = Sequential()
@@ -30,23 +31,23 @@ class TestBatchNormalization(unittest.TestCase):
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 10))
model.fit(X, X, nb_epoch=5, verbose=0)
norm_m0.input = X
norm_m0.input = K.variable(X)
out = (norm_m0.get_output(train=True) - norm_m0.beta) / norm_m0.gamma
self.assertAlmostEqual(out.mean().eval(), 0.0, places=1)
self.assertAlmostEqual(out.std().eval(), 1.0, places=1)
self.assertAlmostEqual(K.eval(K.mean(out)), 0.0, places=1)
self.assertAlmostEqual(K.eval(K.std(out)), 1.0, places=1)
def test_mode_1(self):
norm_m1 = normalization.BatchNormalization(input_shape=(10,), mode=1)
for inp in [self.input_1, self.input_2, self.input_3]:
norm_m1.input = inp
norm_m1.input = K.variable(inp)
out = (norm_m1.get_output(train=True) - norm_m1.beta) / norm_m1.gamma
self.assertAlmostEqual(out.mean().eval(), 0.0)
self.assertAlmostEqual(K.eval(K.mean(out)), 0.0)
if inp.std() > 0.:
self.assertAlmostEqual(out.std().eval(), 1.0, places=2)
self.assertAlmostEqual(K.eval(K.std(out)), 1.0, places=2)
else:
self.assertAlmostEqual(out.std().eval(), 0.0, places=2)
self.assertAlmostEqual(K.eval(K.std(out)), 0.0, places=2)
def test_shapes(self):
"""
@@ -54,11 +55,11 @@ class TestBatchNormalization(unittest.TestCase):
"""
for inp in self.input_shapes:
norm_m0 = normalization.BatchNormalization(input_shape=inp.shape, mode=0)
norm_m0.input = inp
norm_m0.input = K.variable(inp)
out = (norm_m0.get_output(train=True) - norm_m0.beta) / norm_m0.gamma
norm_m1 = normalization.BatchNormalization(input_shape=inp.shape, mode=1)
norm_m1.input = inp
norm_m1.input = K.variable(inp)
out = (norm_m1.get_output(train=True) - norm_m1.beta) / norm_m1.gamma
def test_weight_init(self):
@@ -69,26 +70,29 @@ class TestBatchNormalization(unittest.TestCase):
weights=[np.ones(10), np.ones(10), np.zeros(10), np.zeros(10)])
for inp in [self.input_1, self.input_2, self.input_3]:
norm_m1.input = inp
norm_m1.input = K.variable(inp)
out = (norm_m1.get_output(train=True) - np.ones(10)) / 1.
self.assertAlmostEqual(out.mean().eval(), 0.0)
self.assertAlmostEqual(K.eval(K.mean(out)), 0.0)
if inp.std() > 0.:
self.assertAlmostEqual(out.std().eval(), 1.0, places=2)
self.assertAlmostEqual(K.eval(K.std(out)), 1.0, places=2)
else:
self.assertAlmostEqual(out.std().eval(), 0.0, places=2)
self.assertAlmostEqual(K.eval(K.std(out)), 0.0, places=2)
assert_allclose(norm_m1.gamma.eval(), np.ones(10))
assert_allclose(norm_m1.beta.eval(), np.ones(10))
assert_allclose(K.eval(norm_m1.gamma), np.ones(10))
assert_allclose(K.eval(norm_m1.beta), np.ones(10))
def test_config(self):
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1, epsilon=0.1, momentum=0.9)
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1,
epsilon=0.1, momentum=0.9)
conf = norm.get_config()
conf_target = {"input_shape": (10, 10), "name": normalization.BatchNormalization.__name__,
conf_target = {"input_shape": (10, 10),
"name": normalization.BatchNormalization.__name__,
"epsilon": 0.1, "mode": 1, "momentum": 0.9}
self.assertDictEqual(conf, conf_target)
def test_save_weights(self):
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1, epsilon=0.1)
norm = normalization.BatchNormalization(input_shape=(10, 10), mode=1,
epsilon=0.1)
weights = norm.get_weights()
assert(len(weights) == 4)
norm.set_weights(weights)
Ver Arquivo
-134
Ver Arquivo
@@ -1,134 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
from keras.datasets import mnist
from keras.models import Sequential, model_from_config
from keras.layers.core import AutoEncoder, Dense, Activation, TimeDistributedDense, Flatten
from keras.layers.recurrent import LSTM
from keras.layers.embeddings import Embedding
from keras.layers.core import Layer
from keras.layers import containers
from keras.utils import np_utils
import numpy as np
nb_classes = 10
batch_size = 128
nb_epoch = 5
activation = 'linear'
input_dim = 784
hidden_dim = 392
max_train_samples = 5000
max_test_samples = 1000
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, input_dim)[:max_train_samples]
X_test = X_test.reshape(10000, input_dim)[:max_test_samples]
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)[:max_train_samples]
Y_test = np_utils.to_categorical(y_test, nb_classes)[:max_test_samples]
print("X_train: ", X_train.shape)
print("X_test: ", X_test.shape)
##########################
# dense model test #
##########################
print("Training classical fully connected layer for classification")
model_classical = Sequential()
model_classical.add(Dense(input_dim, 10, activation=activation))
model_classical.add(Activation('softmax'))
model_classical.get_config(verbose=1)
model_classical.compile(loss='categorical_crossentropy', optimizer='adam')
model_classical.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=(X_test, Y_test))
classical_score = model_classical.evaluate(X_test, Y_test, verbose=0, show_accuracy=True)
print('\nclassical_score:', classical_score)
##########################
# autoencoder model test #
##########################
def build_lstm_autoencoder(autoencoder, X_train, X_test):
X_train = X_train[:, np.newaxis, :]
X_test = X_test[:, np.newaxis, :]
print("Modified X_train: ", X_train.shape)
print("Modified X_test: ", X_test.shape)
# The TimeDistributedDense isn't really necessary, however you need a lot of GPU memory to do 784x394-394x784
autoencoder.add(TimeDistributedDense(input_dim, 16))
autoencoder.add(AutoEncoder(encoder=LSTM(16, 8, activation=activation, return_sequences=True),
decoder=LSTM(8, input_dim, activation=activation, return_sequences=True),
output_reconstruction=False))
return autoencoder, X_train, X_test
def build_deep_classical_autoencoder(autoencoder):
encoder = containers.Sequential([Dense(input_dim, hidden_dim, activation=activation), Dense(hidden_dim, hidden_dim/2, activation=activation)])
decoder = containers.Sequential([Dense(hidden_dim/2, hidden_dim, activation=activation), Dense(hidden_dim, input_dim, activation=activation)])
autoencoder.add(AutoEncoder(encoder=encoder, decoder=decoder, output_reconstruction=False))
return autoencoder
# Try different things here: 'lstm' or 'classical' or 'denoising'
# or 'deep_denoising'
for autoencoder_type in ['classical', 'lstm']:
print(autoencoder_type)
print('-'*40)
# Build our autoencoder model
autoencoder = Sequential()
if autoencoder_type == 'lstm':
print("Training LSTM AutoEncoder")
autoencoder, X_train, X_test = build_lstm_autoencoder(autoencoder, X_train, X_test)
elif autoencoder_type == 'classical':
print("Training Classical AutoEncoder")
autoencoder = build_deep_classical_autoencoder(autoencoder)
else:
print("Error: unknown autoencoder type!")
exit(-1)
autoencoder.compile(loss='mean_squared_error', optimizer='adam')
# Do NOT use validation data with return output_reconstruction=True
autoencoder.fit(X_train, X_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=1)
# Do an inference pass
prefilter_train = autoencoder.predict(X_train, verbose=0)
prefilter_test = autoencoder.predict(X_test, verbose=0)
print("prefilter_train: ", prefilter_train.shape)
print("prefilter_test: ", prefilter_test.shape)
# Classify results from Autoencoder
print("Building classical fully connected layer for classification")
model = Sequential()
if autoencoder_type == 'lstm':
model.add(TimeDistributedDense(8, nb_classes, activation=activation))
model.add(Flatten())
elif autoencoder_type == 'classical':
model.add(Dense(prefilter_train.shape[1], nb_classes, activation=activation))
else:
model.add(Dense(prefilter_train.shape[1], nb_classes, activation=activation))
model.add(Activation('softmax'))
model.get_config(verbose=1)
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.fit(prefilter_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=(prefilter_test, Y_test))
score = model.evaluate(prefilter_test, Y_test, verbose=0, show_accuracy=True)
print('\nscore:', score)
print('Loss change:', (score[0] - classical_score[0])/classical_score[0], '%')
print('Accuracy change:', (score[1] - classical_score[1])/classical_score[1], '%')
# check serialization
config = autoencoder.get_config(verbose=1)
autoencoder = model_from_config(config)
-236
Ver Arquivo
@@ -1,236 +0,0 @@
import numpy as np
import random
import theano
from keras.models import Sequential
from keras.callbacks import Callback
from keras.layers.core import Dense, Dropout, Activation, Flatten
from keras.regularizers import l2
from keras.layers.convolutional import Convolution2D, MaxPooling2D
from keras.utils import np_utils
from keras.datasets import mnist
import keras.callbacks as cbks
from matplotlib import pyplot as plt
from matplotlib import animation
##############################
# model DrawActivations test #
##############################
print('Running DrawActivations test')
nb_classes = 10
batch_size = 128
nb_epoch = 10
max_train_samples = 512
max_test_samples = 1
np.random.seed(1337)
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(-1,1,28,28)[:max_train_samples]
X_train = X_train.astype("float32")
X_train /= 255
X_test = X_test.reshape(-1,1,28,28)[:max_test_samples]
X_test = X_test.astype("float32")
X_test /= 255
# convert class vectors to binary class matrices
Y_train = np_utils.to_categorical(y_train, nb_classes)[:max_train_samples]
class Frames(object):
def __init__(self, n_plots=16):
self._n_frames = 0
self._framedata = []
self._titles = []
for i in range(n_plots):
self._framedata.append([])
def add_frame(self, i, frame):
self._framedata[i].append(frame)
def set_title(self, title):
self._titles.append(title)
class SubplotTimedAnimation(animation.TimedAnimation):
def __init__(self, fig, frames, grid=(4, 4), interval=10, blit=False, **kwargs):
self.n_plots = grid[0] * grid[1]
self.axes = [fig.add_subplot(grid[0], grid[1], i + 1) for i in range(self.n_plots)]
for axis in self.axes:
axis.get_xaxis().set_ticks([])
axis.get_yaxis().set_ticks([])
self.frames = frames
self.imgs = [self.axes[i].imshow(frames._framedata[i][0], interpolation='nearest', cmap='bone') for i in range(self.n_plots)]
self.title = fig.suptitle('')
super(SubplotTimedAnimation, self).__init__(fig, interval=interval, blit=blit, **kwargs)
def _draw_frame(self, j):
for i in range(self.n_plots):
self.imgs[i].set_data(self.frames._framedata[i][j])
if len(self.frames._titles) > j:
self.title.set_text(self.frames._titles[j])
self._drawn_artists = self.imgs
def new_frame_seq(self):
return iter(range(len(self.frames._framedata[0])))
def _init_draw(self):
for img in self.imgs:
img.set_data([[]])
def combine_imgs(imgs, grid=(1,1)):
n_imgs, img_h, img_w = imgs.shape
if n_imgs != grid[0] * grid[1]:
raise ValueError()
combined = np.zeros((grid[0] * img_h, grid[1] * img_w))
for i in range(grid[0]):
for j in range(grid[1]):
combined[img_h*i:img_h*(i+1),img_w*j:img_w*(j+1)] = imgs[grid[0] * i + j]
return combined
class DrawActivations(Callback):
def __init__(self, figsize):
self.fig = plt.figure(figsize=figsize)
def on_train_begin(self, logs={}):
self.imgs = Frames(n_plots=5)
layers_0_ids = np.random.choice(32, 16, replace=False)
self.test_layer0 = theano.function([self.model.get_input()], self.model.layers[1].get_output(train=False)[0, layers_0_ids])
layers_1_ids = np.random.choice(64, 36, replace=False)
self.test_layer1 = theano.function([self.model.get_input()], self.model.layers[5].get_output(train=False)[0, layers_1_ids])
self.test_layer2 = theano.function([self.model.get_input()], self.model.layers[10].get_output(train=False)[0])
def on_epoch_begin(self, epoch, logs={}):
self.epoch = epoch
def on_batch_end(self, batch, logs={}):
if batch % 5 == 0:
self.imgs.add_frame(0, X_test[0,0])
self.imgs.add_frame(1, combine_imgs(self.test_layer0(X_test), grid=(4, 4)))
self.imgs.add_frame(2, combine_imgs(self.test_layer1(X_test), grid=(6, 6)))
self.imgs.add_frame(3, self.test_layer2(X_test).reshape((16,16)))
self.imgs.add_frame(4, self.model._predict(X_test)[0].reshape((1,10)))
self.imgs.set_title('Epoch #%d - Batch #%d' % (self.epoch, batch))
def on_train_end(self, logs={}):
anim = SubplotTimedAnimation(self.fig, self.imgs, grid=(1,5), interval=10, blit=False, repeat_delay=1000)
# anim.save('test_gif.gif', fps=15, writer='imagemagick')
plt.show()
# model = Sequential()
# model.add(Dense(784, 50))
# model.add(Activation('relu'))
# model.add(Dense(50, 10))
# model.add(Activation('softmax'))
model = Sequential()
model.add(Convolution2D(32, 1, 3, 3, border_mode='full'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Convolution2D(64, 32, 3, 3, border_mode='full'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(64*8*8, 256))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(256, 10, W_regularizer = l2(0.1)))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
# Fit the model
draw_weights = DrawActivations(figsize=(5.4, 1.35))
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=1, callbacks=[draw_weights])
##########################
# model checkpoint tests #
##########################
print('Running ModelCheckpoint test')
nb_classes = 10
batch_size = 128
nb_epoch = 20
# small sample size to overfit on training data
max_train_samples = 50
max_test_samples = 1000
np.random.seed(1337) # for reproducibility
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000,784)[:max_train_samples]
X_test = X_test.reshape(10000,784)[:max_test_samples]
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)[:max_train_samples]
Y_test = np_utils.to_categorical(y_test, nb_classes)[:max_test_samples]
# Create a slightly larger network than required to test best validation save only
model = Sequential()
model.add(Dense(784, 500))
model.add(Activation('relu'))
model.add(Dense(500, 10))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
# test file location
path = "/tmp"
filename = "model_weights.hdf5"
import os
f = os.path.join(path, filename)
print("Test model checkpointer")
# only store best validation model in checkpointer
checkpointer = cbks.ModelCheckpoint(filepath=f, verbose=1, save_best_only=True)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=(X_test, Y_test), callbacks =[checkpointer])
if not os.path.isfile(f):
raise Exception("Model weights were not saved to %s" % (f))
print("Test model checkpointer without validation data")
import warnings
warnings.filterwarnings('error')
try:
passed = False
# this should issue a warning
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, callbacks =[checkpointer])
except:
passed = True
if not passed:
raise Exception("Modelcheckpoint tests did not pass")
print("Test model checkpointer with pattern")
filename = "model_weights.{epoch:04d}.hdf5"
f = os.path.join(path, filename)
nb_epoch = 3
checkpointer = cbks.ModelCheckpoint(f)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, callbacks=[checkpointer])
for i in range(nb_epoch):
if not os.path.isfile(f.format(epoch=i)):
raise Exception("Model weights were not saved separately for each epoch")
print("Tests passed")
-100
Ver Arquivo
@@ -1,100 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
import keras
from keras.datasets import mnist
import keras.models
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.regularizers import l2, l1
from keras.constraints import maxnorm, nonneg
from keras.optimizers import SGD, Adam, RMSprop
from keras.utils import np_utils, generic_utils
import theano
import theano.tensor as T
import numpy as np
import scipy
batch_size = 100
nb_classes = 10
nb_epoch = 10
# the data, shuffled and split between tran and test sets
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train=X_train.reshape(60000,784)
X_test=X_test.reshape(10000,784)
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)
model = Sequential()
model.add(Dense(784, 20, W_constraint=maxnorm(1)))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(20, 20, W_constraint=nonneg()))
model.add(Activation('relu'))
model.add(Dropout(0.1))
model.add(Dense(20, 10, W_constraint=maxnorm(1)))
model.add(Activation('softmax'))
rms = RMSprop()
model.compile(loss='categorical_crossentropy', optimizer=rms)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0)
a=model.params[0].eval()
if np.isclose(np.max(np.sqrt(np.sum(a**2, axis=0))),1):
print('Maxnorm test passed')
else:
raise ValueError('Maxnorm test failed!')
b=model.params[2].eval()
if np.min(b)==0 and np.min(a)!=0:
print('Nonneg test passed')
else:
raise ValueError('Nonneg test failed!')
model = Sequential()
model.add(Dense(784, 20))
model.add(Activation('relu'))
model.add(Dense(20, 20, W_regularizer=l1(.01)))
model.add(Activation('relu'))
model.add(Dense(20, 10))
model.add(Activation('softmax'))
rms = RMSprop()
model.compile(loss='categorical_crossentropy', optimizer=rms)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=20, show_accuracy=True, verbose=0)
a=model.params[2].eval().reshape(400)
(D, p1) = scipy.stats.kurtosistest(a)
model = Sequential()
model.add(Dense(784, 20))
model.add(Activation('relu'))
model.add(Dense(20, 20, W_regularizer=l2(.01)))
model.add(Activation('relu'))
model.add(Dense(20, 10))
model.add(Activation('softmax'))
rms = RMSprop()
model.compile(loss='categorical_crossentropy', optimizer=rms)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=20, show_accuracy=True, verbose=0)
a=model.params[2].eval().reshape(400)
(D, p2) = scipy.stats.kurtosistest(a)
if p1<.01 and p2>.01:
print('L1 and L2 regularization tests passed')
else:
raise ValueError('L1 and L2 regularization tests failed!')
-130
Ver Arquivo
@@ -1,130 +0,0 @@
# Dummy test data as input to RNN. This input is 3 timesteps long where the third timestep always matches the
# first. Without masking it should be able to learn it, with masking it should fail.
import numpy as np
from keras.utils.theano_utils import sharedX
from keras.models import Sequential
from keras.layers.core import Dense, Activation, Merge, Dropout, TimeDistributedDense
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import SimpleRNN, SimpleDeepRNN, LSTM, GRU
import theano
theano.config.exception_verbosity = 'high'
# (nb_samples, timesteps, dimensions)
X = np.random.random_integers(1, 4, size=(500000, 15))
print("About to compile the first model")
model = Sequential()
model.add(Embedding(5, 4, mask_zero=True))
model.add(TimeDistributedDense(4, 4)) # obviously this is redundant. Just testing.
model.add(SimpleRNN(4, 4, activation='relu', return_sequences=True))
model.add(Dropout(0.5))
model.add(SimpleDeepRNN(4, 4, depth=2, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(4, 4, activation='softmax'))
model.compile(loss='categorical_crossentropy',
optimizer='rmsprop', theano_mode=theano.compile.mode.FAST_RUN)
print("Compiled model")
W = model.get_weights() # We'll save these so we can reset it later
X[:, : 10] = 0
Xmask0 = X.copy()
Xmask0[:, 10] = 0
Xmask12 = X.copy()
Xmask12[:, 11] = 0
Xmask12[:, 12] = 0
X0_onehot = np.zeros((X.shape[0], 4))
X1_onehot = np.zeros((X.shape[0], 4))
for i, row in enumerate(X):
X0_onehot[i, row[10] - 1] = 1
X1_onehot[i, row[11] - 1] = 1
# Uniform score: 4 options = ln(4) nats (2 bits)
# we should not do better than this when we mask out the part of the input
# that gives us the correct answer
uniform_score = np.log(4)
batch_size=512
# Train it to guess 0th dim
model.fit(X, X0_onehot, nb_epoch=1, batch_size=batch_size)
score = model.evaluate(X, X0_onehot, batch_size=batch_size)
if score > uniform_score * 0.9:
raise Exception('Failed to learn to copy timestep 0, score %f' % score)
model.set_weights(W)
# Train without showing it the 0th dim to learn 1st dim
model.fit(X[: , 1:], X1_onehot, nb_epoch=1, batch_size=batch_size)
score = model.evaluate(X[:, 1:], X1_onehot, batch_size=batch_size)
if score > uniform_score * 0.9:
raise Exception('Failed to learn to copy timestep 1, score %f' % score)
model.set_weights(W)
# Train to guess 0th dim when 0th dim has been masked (should fail)
model.fit(Xmask0, X0_onehot, nb_epoch=1, batch_size=batch_size)
score = model.evaluate(Xmask0, X0_onehot, batch_size=batch_size)
if score < uniform_score * 0.9:
raise Exception('Somehow learned to copy timestep 0 despite mask, score %f' % score)
model.set_weights(W)
# Train to guess 1st dim when 0th dim has been masked (should succeed)
model.fit(Xmask0, X1_onehot, nb_epoch=1, batch_size=batch_size)
score = model.evaluate(Xmask0, X1_onehot, batch_size=batch_size)
if score > uniform_score * 0.9:
raise Exception('Failed to learn to copy timestep 1 in masked model, score %f' % score)
model.set_weights(W)
# Finally, make sure the mask is actually blocking input, mask out timesteps 1 and 2, and see if
# it can learn timestep 0 (should fail)
model.fit(Xmask12, X0_onehot, nb_epoch=1, batch_size=batch_size)
score = model.evaluate(Xmask12, X0_onehot, batch_size=batch_size)
if score < uniform_score * 0.9:
raise Exception('Somehow learned to copy timestep 0 despite masking 1, score %f' % score)
# Another testing approach, just initialize models and make sure that prepending zeros doesn't affect
# their output
print("About to compile the second model")
model2 = Sequential()
model2.add(Embedding(5, 4, mask_zero=True))
model2.add(TimeDistributedDense(4, 4))
model2.add(Activation('time_distributed_softmax'))
model2.add(LSTM(4, 4, return_sequences=True))
model2.add(Activation('tanh'))
model2.add(GRU(4, 4, activation='softmax', return_sequences=True))
model2.add(SimpleDeepRNN(4, 4, depth=2, activation='relu', return_sequences=True))
model2.add(SimpleRNN(4, 4, activation='relu', return_sequences=True))
model2.compile(loss='categorical_crossentropy',
optimizer='rmsprop', theano_mode=theano.compile.mode.FAST_RUN)
print("Compiled model2")
X2 = np.random.random_integers(1, 4, size=(2, 5))
y2 = np.random.random((X2.shape[0], X2.shape[1], 4))
ref = model2.predict(X2)
ref_eval = model2.evaluate(X2, y2)
mask = np.ones((y2.shape[0], y2.shape[1], 1))
for pre_zeros in range(1, 10):
padded_X2 = np.concatenate((np.zeros((X2.shape[0], pre_zeros)), X2), axis=1)
padded_mask = np.concatenate((np.zeros((mask.shape[0], pre_zeros, mask.shape[2])), mask), axis=1)
padded_y2 = np.concatenate((np.zeros((y2.shape[0], pre_zeros, y2.shape[2])), y2), axis=1)
pred = model2.predict(padded_X2)
if not np.allclose(ref[:, -1, :], pred[:, -1, :]):
raise Exception("Different result after left-padding %d zeros. Ref: %s, Pred: %s" % (pre_zeros, ref, pred))
pad_eval = model2.evaluate(padded_X2, padded_y2, weights=padded_mask)
if not np.allclose([pad_eval], [ref_eval]):
raise Exception("Got dissimilar categorical_crossentropy after left-padding %d zeros. Ref: %f, Pred %f" %\
(pref_eval, pred_val))
-44
Ver Arquivo
@@ -1,44 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
from keras.models import Sequential, Graph
from keras.layers.core import Layer, Activation, Dense, Flatten, Reshape, Merge
from keras.layers.convolutional import Convolution2D, MaxPooling2D
import keras.utils.layer_utils as layer_utils
print('-- Sequential model')
left = Sequential()
left.add(Convolution2D(32, 1, 3, 3, border_mode='valid'))
left.add(MaxPooling2D(pool_size=(2, 2)))
left.add(Flatten())
left.add(Dense(32 * 13 * 13, 50))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(784, 30))
right.add(Activation('relu'))
model = Sequential()
model.add(Merge([left, right], mode='concat'))
model.add(Dense(80, 10))
model.add(Activation('softmax'))
layer_utils.print_layer_shapes(model, [(1, 1, 28, 28), (1, 784)])
print('-- Graph model')
graph = Graph()
graph.add_input(name='input1', ndim=2)
graph.add_input(name='input2', ndim=4)
graph.add_node(Dense(32, 16), name='dense1', input='input1')
graph.add_node(Dense(16, 4), name='dense3', input='dense1')
graph.add_node(Convolution2D(32, 1, 3, 3), name='conv1', input='input2')
graph.add_node(Flatten(), name='flatten1', input='conv1')
graph.add_node(Dense(32 * 13 * 13, 10), name='dense4', input='flatten1')
graph.add_output(name='output1', inputs=['dense1', 'dense3'], merge_mode='sum')
graph.add_output(name='output2', inputs=['dense1', 'dense4'], merge_mode='concat')
layer_utils.print_layer_shapes(graph, {'input1': (1, 32), 'input2': (1, 1, 28, 28)})
print('Test script complete')
-40
Ver Arquivo
@@ -1,40 +0,0 @@
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
import sys
sys.setrecursionlimit(10000) # to be able to pickle Theano compiled functions
import pickle, numpy
def create_model():
model = Sequential()
model.add(Dense(256, 2048, init='uniform', activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2048, 2048, init='uniform', activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2048, 2048, init='uniform', activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2048, 2048, init='uniform', activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(2048, 256, init='uniform', activation='linear'))
return model
model = create_model()
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True)
model.compile(loss='mse', optimizer=sgd)
pickle.dump(model, open('/tmp/model.pkl', 'wb'))
model.save_weights('/tmp/model_weights.hdf5')
model_loaded = create_model()
model_loaded.load_weights('/tmp/model_weights.hdf5')
for k in range(len(model.layers)):
weights_orig = model.layers[k].get_weights()
weights_loaded = model_loaded.layers[k].get_weights()
for x, y in zip(weights_orig, weights_loaded):
if numpy.any(x != y):
raise ValueError('Loaded weights are different from pickled weights!')
-126
Ver Arquivo
@@ -1,126 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers.core import Dense, Activation
from keras.utils import np_utils
from keras.wrappers.scikit_learn import *
import numpy as np
batch_size = 128
nb_epoch = 1
nb_classes = 10
max_train_samples = 5000
max_test_samples = 1000
np.random.seed(1337) # for reproducibility
############################################
# scikit-learn classification wrapper test #
############################################
print('Beginning scikit-learn classification wrapper test')
print('Loading data')
(X_train, y_train), (X_test, y_test) = mnist.load_data()
X_train = X_train.reshape(60000, 784)[:max_train_samples]
X_test = X_test.reshape(10000, 784)[:max_test_samples]
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255
Y_train = np_utils.to_categorical(y_train, nb_classes)[:max_train_samples]
Y_test = np_utils.to_categorical(y_test, nb_classes)[:max_test_samples]
print('Defining model')
model = Sequential()
model.add(Dense(784, 50))
model.add(Activation('relu'))
model.add(Dense(50, 10))
model.add(Activation('softmax'))
print('Creating wrapper')
classifier = KerasClassifier(model, train_batch_size=batch_size, nb_epoch=nb_epoch)
print('Fitting model')
classifier.fit(X_train, Y_train)
print('Testing score function')
score = classifier.score(X_train, Y_train)
print('Score: ', score)
print('Testing predict function')
preds = classifier.predict(X_test)
print('Preds.shape: ', preds.shape)
print('Testing predict proba function')
proba = classifier.predict_proba(X_test)
print('Proba.shape: ', proba.shape)
print('Testing get params')
print(classifier.get_params())
print('Testing set params')
classifier.set_params(optimizer='sgd', loss='binary_crossentropy')
print(classifier.get_params())
print('Testing attributes')
print('Classes')
print(classifier.classes_)
print('Config')
print(classifier.config_)
print('Weights')
print(classifier.weights_)
print('Compiled model')
print(classifier.compiled_model_)
########################################
# scikit-learn regression wrapper test #
########################################
print('Beginning scikit-learn regression wrapper test')
print('Generating data')
X_train = np.random.random((5000, 100))
X_test = np.random.random((1000, 100))
y_train = np.random.random(5000)
y_test = np.random.random(1000)
print('Defining model')
model = Sequential()
model.add(Dense(100, 50))
model.add(Activation('relu'))
model.add(Dense(50, 1))
model.add(Activation('linear'))
print('Creating wrapper')
regressor = KerasRegressor(model, train_batch_size=batch_size, nb_epoch=nb_epoch)
print('Fitting model')
regressor.fit(X_train, y_train)
print('Testing score function')
score = regressor.score(X_train, y_train)
print('Score: ', score)
print('Testing predict function')
preds = regressor.predict(X_test)
print('Preds.shape: ', preds.shape)
print('Testing get params')
print(regressor.get_params())
print('Testing set params')
regressor.set_params(optimizer='sgd', loss='mean_absolute_error')
print(regressor.get_params())
print('Testing attributes')
print('Config')
print(regressor.config_)
print('Weights')
print(regressor.weights_)
print('Compiled model')
print(regressor.compiled_model_)
print('Test script complete.')
-101
Ver Arquivo
@@ -1,101 +0,0 @@
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
from keras.utils.test_utils import get_test_data
from keras.preprocessing import sequence
from keras.optimizers import SGD, RMSprop, Adagrad
from keras.utils import np_utils
from keras.models import Sequential, Graph
from keras.layers.core import Dense, Dropout, Activation, Merge
from keras.layers.embeddings import Embedding
from keras.layers.recurrent import LSTM, GRU
from keras.datasets import imdb
from keras.models import model_from_yaml
'''
This is essentially the IMDB test. Deserialized models should yield
the same config as the original one.
'''
max_features = 10000
maxlen = 100
batch_size = 32
(X_train, y_train), (X_test, y_test) = imdb.load_data(nb_words=max_features, test_split=0.2)
X_train = sequence.pad_sequences(X_train, maxlen=maxlen)
X_test = sequence.pad_sequences(X_test, maxlen=maxlen)
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(LSTM(128, 128))
model.add(Dropout(0.5))
model.add(Dense(128, 1, W_regularizer='identity', b_constraint='maxnorm'))
model.add(Activation('sigmoid'))
model.get_config(verbose=1)
#####################################
# save model w/o parameters to yaml #
#####################################
yaml_no_params = model.to_yaml()
no_param_model = model_from_yaml(yaml_no_params)
no_param_model.get_config(verbose=1)
######################################
# save multi-branch sequential model #
######################################
seq = Sequential()
seq.add(Merge([model, model], mode='sum'))
seq.get_config(verbose=1)
merge_yaml = seq.to_yaml()
merge_model = model_from_yaml(merge_yaml)
large_model = Sequential()
large_model.add(Merge([seq,model], mode='concat'))
large_model.get_config(verbose=1)
large_model.to_yaml()
####################
# save graph model #
####################
X = np.random.random((100, 32))
X2 = np.random.random((100, 32))
y = np.random.random((100, 4))
y2 = np.random.random((100,))
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(32,),
classification=False, output_shape=(4,))
graph = Graph()
graph.add_input(name='input1', ndim=2)
graph.add_node(Dense(32, 16), name='dense1', input='input1')
graph.add_node(Dense(32, 4), name='dense2', input='input1')
graph.add_node(Dense(16, 4), name='dense3', input='dense1')
graph.add_output(name='output1', inputs=['dense2', 'dense3'], merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
graph.get_config(verbose=1)
history = graph.fit({'input1': X_train, 'output1': y_train}, nb_epoch=10)
original_pred = graph.predict({'input1': X_test})
graph_yaml = graph.to_yaml()
graph.save_weights('temp.h5', overwrite=True)
reloaded_graph = model_from_yaml(graph_yaml)
reloaded_graph.load_weights('temp.h5')
reloaded_graph.get_config(verbose=1)
reloaded_graph.compile('rmsprop', {'output1': 'mse'})
new_pred = reloaded_graph.predict({'input1': X_test})
assert(np.sum(new_pred['output1'] - original_pred['output1']) == 0)
@@ -1,10 +1,10 @@
import unittest
import numpy as np
from keras.models import Sequential
from keras.layers.core import Merge, Dense, Activation, Flatten
from keras.layers.core import Dense, Activation, Flatten
from keras.layers.embeddings import Embedding
from theano import function
from keras.constraints import unitnorm
from keras import backend as K
class TestEmbedding(unittest.TestCase):
@@ -14,13 +14,16 @@ class TestEmbedding(unittest.TestCase):
def test_unitnorm_constraint(self):
lookup = Sequential()
lookup.add(Embedding(3, 2, weights=[self.W1], W_constraint=unitnorm(), input_length=1))
lookup.add(Embedding(3, 2, weights=[self.W1],
W_constraint=unitnorm(),
input_length=1))
lookup.add(Flatten())
lookup.add(Dense(1))
lookup.add(Activation('sigmoid'))
lookup.compile(loss='binary_crossentropy', optimizer='sgd', class_mode='binary')
lookup.compile(loss='binary_crossentropy', optimizer='sgd',
class_mode='binary')
lookup.train_on_batch(self.X1, np.array([[1], [0]], dtype='int32'))
norm = np.linalg.norm(lookup.params[0].get_value(), axis=1)
norm = np.linalg.norm(K.get_value(lookup.params[0]), axis=1)
self.assertTrue(np.allclose(norm, np.ones_like(norm).astype('float32')))
if __name__ == '__main__':
@@ -13,10 +13,16 @@ X2 = np.random.random((100, 32))
y = np.random.random((100, 4))
y2 = np.random.random((100,))
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(32,),
classification=False, output_shape=(4,))
(X2_train, y2_train), (X2_test, y2_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(32,),
classification=False, output_shape=(1,))
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(32,),
classification=False,
output_shape=(4,))
(X2_train, y2_train), (X2_test, y2_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(32,),
classification=False,
output_shape=(1,))
class TestGraph(unittest.TestCase):
@@ -29,10 +35,13 @@ class TestGraph(unittest.TestCase):
graph.add_node(Dense(4), name='dense2', input='input1')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_output(name='output1', inputs=['dense2', 'dense3'], merge_mode='sum')
graph.add_output(name='output1',
inputs=['dense2', 'dense3'],
merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
history = graph.fit({'input1': X_train, 'output1': y_train}, nb_epoch=10)
history = graph.fit({'input1': X_train, 'output1': y_train},
nb_epoch=10)
out = graph.predict({'input1': X_test})
assert(type(out == dict))
assert(len(out) == 1)
@@ -42,6 +51,14 @@ class TestGraph(unittest.TestCase):
print(loss)
assert(loss < 2.5)
# test validation split
history = graph.fit({'input1': X_train, 'output1': y_train},
validation_split=0.2, nb_epoch=1)
# test validation data
history = graph.fit({'input1': X_train, 'output1': y_train},
validation_data={'input1': X_train, 'output1': y_train},
nb_epoch=1)
def test_1o_1i_2(self):
print('test a more complex non-sequential graph with 1 input and 1 output')
graph = Graph()
@@ -52,12 +69,15 @@ class TestGraph(unittest.TestCase):
graph.add_node(Activation('relu'), name='dense2', input='dense2-0')
graph.add_node(Dense(16), name='dense3', input='dense2')
graph.add_node(Dense(4), name='dense4', inputs=['dense1', 'dense3'], merge_mode='sum')
graph.add_node(Dense(4), name='dense4', inputs=['dense1', 'dense3'],
merge_mode='sum')
graph.add_output(name='output1', inputs=['dense2', 'dense4'], merge_mode='sum')
graph.add_output(name='output1', inputs=['dense2', 'dense4'],
merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
history = graph.fit({'input1': X_train, 'output1': y_train}, nb_epoch=10)
history = graph.fit({'input1': X_train, 'output1': y_train},
nb_epoch=10)
out = graph.predict({'input1': X_train})
assert(type(out == dict))
assert(len(out) == 1)
@@ -78,10 +98,12 @@ class TestGraph(unittest.TestCase):
graph.add_node(Dense(4), name='dense2', input='input2')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_output(name='output1', inputs=['dense2', 'dense3'], merge_mode='sum')
graph.add_output(name='output1', inputs=['dense2', 'dense3'],
merge_mode='sum')
graph.compile('rmsprop', {'output1': 'mse'})
history = graph.fit({'input1': X_train, 'input2': X2_train, 'output1': y_train}, nb_epoch=10)
history = graph.fit({'input1': X_train, 'input2': X2_train, 'output1': y_train},
nb_epoch=10)
out = graph.predict({'input1': X_test, 'input2': X2_test})
assert(type(out == dict))
assert(len(out) == 1)
@@ -105,7 +127,8 @@ class TestGraph(unittest.TestCase):
graph.add_output(name='output2', input='dense3')
graph.compile('rmsprop', {'output1': 'mse', 'output2': 'mse'})
history = graph.fit({'input1': X_train, 'output1': y_train, 'output2': y2_train}, nb_epoch=10)
history = graph.fit({'input1': X_train, 'output1': y_train, 'output2': y2_train},
nb_epoch=10)
out = graph.predict({'input1': X_test})
assert(type(out == dict))
assert(len(out) == 2)
@@ -149,7 +172,8 @@ class TestGraph(unittest.TestCase):
graph.compile('rmsprop', {'output1': 'mse', 'output2': 'mse'})
history = graph.fit({'input1': X_train, 'output1': y_train, 'output2': y2_train}, nb_epoch=10,
history = graph.fit({'input1': X_train, 'output1': y_train, 'output2': y2_train},
nb_epoch=10,
sample_weight={'output1': weights1, 'output2': weights2})
out = graph.predict({'input1': X_test})
assert(type(out == dict))
@@ -170,7 +194,8 @@ class TestGraph(unittest.TestCase):
graph.add_node(Dense(16), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense2', input='input1')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_output(name='output1', inputs=['dense2', 'dense3'], merge_mode='sum')
graph.add_output(name='output1', inputs=['dense2', 'dense3'],
merge_mode='sum')
seq = Sequential()
seq.add(Dense(32, input_shape=(32,)))
@@ -196,10 +221,12 @@ class TestGraph(unittest.TestCase):
graph.add_node(Dense(16), name='dense1', input='input1')
graph.add_node(Dense(4), name='dense2', input='input1')
graph.add_node(Dense(4), name='dense3', input='dense1')
graph.add_node(Dense(4), name='output1', inputs=['dense2', 'dense3'], merge_mode='sum', create_output=True)
graph.add_node(Dense(4), name='output1', inputs=['dense2', 'dense3'],
merge_mode='sum', create_output=True)
graph.compile('rmsprop', {'output1': 'mse'})
history = graph.fit({'input1': X_train, 'output1': y_train}, nb_epoch=10)
history = graph.fit({'input1': X_train, 'output1': y_train},
nb_epoch=10)
out = graph.predict({'input1': X_test})
assert(type(out == dict))
assert(len(out) == 1)
@@ -5,11 +5,14 @@ import unittest
from keras.models import Sequential, weighted_objective
from keras.layers.core import TimeDistributedDense, Masking
from keras import objectives
import theano
from keras import backend as K
class TestLossMasking(unittest.TestCase):
def test_loss_masking(self):
class TestMasking(unittest.TestCase):
def test_masking(self):
if K._BACKEND == 'tensorflow':
# skip this test for TF: not supported yet
return
X = np.array(
[[[1, 1], [2, 1], [3, 1], [5, 5]],
[[1, 5], [5, 0], [0, 0], [0, 0]]], dtype=np.int32)
@@ -18,29 +21,27 @@ class TestLossMasking(unittest.TestCase):
model.add(TimeDistributedDense(1, init='one'))
model.compile(loss='mse', optimizer='sgd')
y = model.predict(X)
loss = model.fit(X, 4*y, nb_epoch=1, batch_size=2, verbose=1).history['loss'][0]
assert loss == 285.
history = model.fit(X, 4 * y, nb_epoch=1, batch_size=2, verbose=1)
assert history.history['loss'][0] == 285.
def test_loss_masking_time(self):
theano.config.mode = 'FAST_COMPILE'
weighted_loss = weighted_objective(objectives.get('categorical_crossentropy'))
def test_loss_masking(self):
weighted_loss = weighted_objective(objectives.get('mae'))
shape = (3, 4, 2)
X = np.arange(24).reshape(shape)
Y = 2 * X
weights = np.ones((3, 4, 1)) # Normally the trailing 1 is added by standardize_weights
weights[0, 0] = 0
# Normally the trailing 1 is added by standardize_weights
weights = np.ones((3,))
mask = np.ones((3, 4))
mask[1, 0] = 0
out = weighted_loss(X, Y, weights, mask).eval()
weights[0, 0] = 1e-9 # so that nonzero() doesn't remove this weight
out2 = weighted_loss(X, Y, weights, mask).eval()
out = K.eval(weighted_loss(K.variable(X),
K.variable(Y),
K.variable(weights),
K.variable(mask)))
print(out)
print(out2)
assert abs(out - out2) < 1e-8
if __name__ == '__main__':
print('Test loss masking')
print('Test masking')
unittest.main()
@@ -12,7 +12,7 @@ import unittest
nb_classes = 10
batch_size = 128
nb_epoch = 8
nb_epoch = 10
weighted_class = 9
standard_weight = 1
high_weight = 5
@@ -60,20 +60,29 @@ def create_graph_model():
def _test_weights_sequential(model, class_weight=None, sample_weight=None):
if sample_weight is not None:
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch // 3, verbose=0,
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch // 3, verbose=0,
class_weight=class_weight, sample_weight=sample_weight)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch // 3, verbose=0,
class_weight=class_weight, sample_weight=sample_weight, validation_split=0.1)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch // 3, verbose=0,
class_weight=class_weight, sample_weight=sample_weight, validation_data=(X_train, Y_train, sample_weight))
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch // 3, verbose=0,
class_weight=class_weight, sample_weight=sample_weight,
validation_split=0.1)
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch // 3, verbose=0,
class_weight=class_weight, sample_weight=sample_weight,
validation_data=(X_train, Y_train, sample_weight))
else:
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch // 2, verbose=0,
class_weight=class_weight, sample_weight=sample_weight)
model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
class_weight=class_weight, sample_weight=sample_weight, validation_split=0.1)
model.fit(X_train, Y_train, batch_size=batch_size,
nb_epoch=nb_epoch // 2, verbose=0,
class_weight=class_weight, sample_weight=sample_weight,
validation_split=0.1)
model.train_on_batch(X_train[:32], Y_train[:32],
class_weight=class_weight, sample_weight=sample_weight[:32] if sample_weight is not None else None)
class_weight=class_weight,
sample_weight=sample_weight[:32] if sample_weight is not None else None)
model.test_on_batch(X_train[:32], Y_train[:32],
sample_weight=sample_weight[:32] if sample_weight is not None else None)
score = model.evaluate(X_test[test_ids, :], Y_test[test_ids, :], verbose=0)
@@ -81,27 +90,34 @@ def _test_weights_sequential(model, class_weight=None, sample_weight=None):
def _test_weights_graph(model, class_weight=None, sample_weight=None):
model.fit({'input': X_train, 'output': Y_train}, batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
class_weight={'output': class_weight}, sample_weight={'output': sample_weight})
model.fit({'input': X_train, 'output': Y_train}, batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
class_weight={'output': class_weight}, sample_weight={'output': sample_weight}, validation_split=0.1)
model.fit({'input': X_train, 'output': Y_train},
batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
class_weight={'output': class_weight},
sample_weight={'output': sample_weight})
model.fit({'input': X_train, 'output': Y_train},
batch_size=batch_size, nb_epoch=nb_epoch // 2, verbose=0,
class_weight={'output': class_weight},
sample_weight={'output': sample_weight}, validation_split=0.1)
model.train_on_batch({'input': X_train[:32], 'output': Y_train[:32]},
class_weight={'output': class_weight}, sample_weight={'output': sample_weight[:32] if sample_weight is not None else None})
class_weight={'output': class_weight},
sample_weight={'output': sample_weight[:32] if sample_weight is not None else None})
model.test_on_batch({'input': X_train[:32], 'output': Y_train[:32]},
sample_weight={'output': sample_weight[:32] if sample_weight is not None else None})
score = model.evaluate({'input': X_test[test_ids, :], 'output': Y_test[test_ids, :]}, verbose=0)
score = model.evaluate({'input': X_test[test_ids, :],
'output': Y_test[test_ids, :]},
verbose=0)
return score
class TestLossWeighting(unittest.TestCase):
def test_sequential(self):
for loss in ['mae', 'mse', 'categorical_crossentropy']:
for loss in ['mae', 'mse']:
print('loss:', loss)
print('sequential')
# no weights: reference point
model = create_sequential_model()
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.compile(loss=loss, optimizer='rmsprop')
standard_score = _test_weights_sequential(model)
# test class_weight
model = create_sequential_model()
@@ -117,22 +133,22 @@ class TestLossWeighting(unittest.TestCase):
self.assertTrue(score < standard_score)
def test_graph(self):
for loss in ['mae', 'mse', 'categorical_crossentropy']:
for loss in ['mae', 'mse']:
print('loss:', loss)
print('graph')
# no weights: reference point
model = create_graph_model()
model.compile(loss={'output': 'categorical_crossentropy'}, optimizer='rmsprop')
model.compile(loss={'output': loss}, optimizer='rmsprop')
standard_score = _test_weights_graph(model)
# test class_weight
model = create_graph_model()
model.compile(loss={'output': 'categorical_crossentropy'}, optimizer='rmsprop')
model.compile(loss={'output': loss}, optimizer='rmsprop')
score = _test_weights_graph(model, class_weight=class_weight)
print('score:', score, ' vs.', standard_score)
self.assertTrue(score < standard_score)
# test sample_weight
model = create_graph_model()
model.compile(loss={'output': 'categorical_crossentropy'}, optimizer='rmsprop')
model.compile(loss={'output': loss}, optimizer='rmsprop')
score = _test_weights_graph(model, sample_weight=sample_weight)
print('score:', score, ' vs.', standard_score)
self.assertTrue(score < standard_score)
@@ -4,10 +4,13 @@ import unittest
import numpy as np
np.random.seed(1337)
from keras import backend as K
from keras.models import Sequential, model_from_json, model_from_yaml
from keras.layers.core import Dense, Activation, Merge
from keras.layers.core import Dense, Activation, Merge, Lambda, LambdaMerge
from keras.utils import np_utils
from keras.utils.test_utils import get_test_data
import pickle
import sys
input_dim = 32
nb_hidden = 16
@@ -18,8 +21,11 @@ nb_epoch = 1
train_samples = 5000
test_samples = 1000
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples, nb_test=test_samples, input_shape=(input_dim,),
classification=True, nb_class=4)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
nb_test=test_samples,
input_shape=(input_dim,),
classification=True,
nb_class=4)
y_test = np_utils.to_categorical(y_test)
y_train = np_utils.to_categorical(y_train)
print(X_train.shape)
@@ -47,12 +53,12 @@ class TestSequential(unittest.TestCase):
loss = model.evaluate(X_train, y_train, verbose=0)
print('loss:', loss)
if loss > 0.6:
if loss > 0.7:
raise Exception('Score too low, learning issue.')
preds = model.predict(X_test, verbose=0)
classes = model.predict_classes(X_test, verbose=0)
probas = model.predict_proba(X_test, verbose=0)
print(model.get_config(verbose=1))
model.predict(X_test, verbose=0)
model.predict_classes(X_test, verbose=0)
model.predict_proba(X_test, verbose=0)
model.get_config(verbose=0)
print('test weight saving')
model.save_weights('temp.h5', overwrite=True)
@@ -65,7 +71,6 @@ class TestSequential(unittest.TestCase):
model.load_weights('temp.h5')
nloss = model.evaluate(X_train, y_train, verbose=0)
print(nloss)
assert(loss == nloss)
# test json serialization
@@ -88,10 +93,8 @@ class TestSequential(unittest.TestCase):
model = Sequential()
model.add(Merge([left, right], mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
@@ -105,10 +108,10 @@ class TestSequential(unittest.TestCase):
print('loss:', loss)
if loss > 0.7:
raise Exception('Score too low, learning issue.')
preds = model.predict([X_test, X_test], verbose=0)
classes = model.predict_classes([X_test, X_test], verbose=0)
probas = model.predict_proba([X_test, X_test], verbose=0)
print(model.get_config(verbose=1))
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
print('test weight saving')
model.save_weights('temp.h5', overwrite=True)
@@ -129,6 +132,46 @@ class TestSequential(unittest.TestCase):
print(nloss)
assert(loss == nloss)
def test_merge_dot1(self):
if K._BACKEND == 'tensorflow':
return
print('Test merge: dot')
left = Sequential()
left.add(Dense(input_dim=input_dim, output_dim=nb_hidden))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(input_dim=input_dim, output_dim=nb_hidden))
right.add(Activation('relu'))
model = Sequential()
model.add(Merge([left, right], mode='dot', dot_axes=1))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
def test_merge_dot2(self):
if K._BACKEND == 'tensorflow':
return
print('Test merge: dot')
left = Sequential()
left.add(Dense(input_dim=input_dim, output_dim=nb_hidden))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(input_dim=input_dim, output_dim=nb_hidden))
right.add(Activation('relu'))
model = Sequential()
model.add(Merge([left, right], mode='dot', dot_axes=([1], [1])))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
def test_merge_concat(self):
print('Test merge: concat')
left = Sequential()
@@ -141,10 +184,8 @@ class TestSequential(unittest.TestCase):
model = Sequential()
model.add(Merge([left, right], mode='concat'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
@@ -156,12 +197,12 @@ class TestSequential(unittest.TestCase):
loss = model.evaluate([X_train, X_train], y_train, verbose=0)
print('loss:', loss)
if loss > 0.6:
if loss > 0.7:
raise Exception('Score too low, learning issue.')
preds = model.predict([X_test, X_test], verbose=0)
classes = model.predict_classes([X_test, X_test], verbose=0)
probas = model.predict_proba([X_test, X_test], verbose=0)
print(model.get_config(verbose=1))
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
print('test weight saving')
model.save_weights('temp.h5', overwrite=True)
@@ -183,7 +224,6 @@ class TestSequential(unittest.TestCase):
model.load_weights('temp.h5')
nloss = model.evaluate([X_train, X_train], y_train, verbose=0)
print(nloss)
assert(loss == nloss)
def test_merge_recursivity(self):
@@ -208,10 +248,8 @@ class TestSequential(unittest.TestCase):
model = Sequential()
model.add(Merge([intermediate, righter], mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test, X_test], y_test))
@@ -223,12 +261,12 @@ class TestSequential(unittest.TestCase):
loss = model.evaluate([X_train, X_train, X_train], y_train, verbose=0)
print('loss:', loss)
if loss > 0.6:
if loss > 0.7:
raise Exception('Score too low, learning issue.')
preds = model.predict([X_test, X_test, X_test], verbose=0)
classes = model.predict_classes([X_test, X_test, X_test], verbose=0)
probas = model.predict_proba([X_test, X_test, X_test], verbose=0)
print(model.get_config(verbose=1))
model.predict([X_test, X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test, X_test], verbose=0)
model.get_config(verbose=0)
model.save_weights('temp.h5', overwrite=True)
model.load_weights('temp.h5')
@@ -245,10 +283,8 @@ class TestSequential(unittest.TestCase):
model = Sequential()
model.add(Merge([left, left], mode='sum'))
model.add(Dense(nb_class))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=1, validation_data=(X_test, y_test))
@@ -262,12 +298,12 @@ class TestSequential(unittest.TestCase):
loss = model.evaluate(X_train, y_train, verbose=0)
print('loss:', loss)
if loss > 0.6:
if loss > 0.7:
raise Exception('Score too low, learning issue.')
preds = model.predict(X_test, verbose=0)
classes = model.predict_classes(X_test, verbose=0)
probas = model.predict_proba(X_test, verbose=0)
print(model.get_config(verbose=1))
model.predict(X_test, verbose=0)
model.predict_classes(X_test, verbose=0)
model.predict_proba(X_test, verbose=0)
model.get_config(verbose=0)
model.save_weights('temp.h5', overwrite=True)
model.load_weights('temp.h5')
@@ -276,6 +312,71 @@ class TestSequential(unittest.TestCase):
print(nloss)
assert(loss == nloss)
def test_lambda(self):
print('Test lambda: sum')
def func(X):
s = X[0]
for i in range(1, len(X)):
s += X[i]
return s
def activation(X):
return K.softmax(X)
def output_shape(input_shapes):
return input_shapes[0]
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(LambdaMerge([left, right], function=func,
output_shape=output_shape))
model.add(Dense(nb_class))
model.add(Lambda(activation))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_data=([X_test, X_test], y_test))
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=True, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, show_accuracy=False, verbose=0, validation_split=0.1)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0)
model.fit([X_train, X_train], y_train, batch_size=batch_size, nb_epoch=nb_epoch, verbose=0, shuffle=False)
loss = model.evaluate([X_train, X_train], y_train, verbose=0)
print('loss:', loss)
if loss > 0.7:
raise Exception('Score too low, learning issue.')
model.predict([X_test, X_test], verbose=0)
model.predict_classes([X_test, X_test], verbose=0)
model.predict_proba([X_test, X_test], verbose=0)
model.get_config(verbose=0)
print('test weight saving')
model.save_weights('temp.h5', overwrite=True)
left = Sequential()
left.add(Dense(nb_hidden, input_shape=(input_dim,)))
left.add(Activation('relu'))
right = Sequential()
right.add(Dense(nb_hidden, input_shape=(input_dim,)))
right.add(Activation('relu'))
model = Sequential()
model.add(LambdaMerge([left, right], function=func,
output_shape=output_shape))
model.add(Dense(nb_class))
model.add(Lambda(activation))
model.load_weights('temp.h5')
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
nloss = model.evaluate([X_train, X_train], y_train, verbose=0)
assert(loss == nloss)
def test_count_params(self):
print('test count params')
input_dim = 20
@@ -1,7 +1,7 @@
import unittest
import numpy as np
import theano
from keras.utils.theano_utils import ndim_tensor
from keras import backend as K
from keras.layers.core import *
from keras.layers.convolutional import *
from keras.layers.recurrent import SimpleRNN
@@ -9,13 +9,13 @@ from keras.layers.recurrent import SimpleRNN
def check_layer_output_shape(layer, input_data):
ndim = len(input_data.shape)
layer.input = ndim_tensor(ndim)
layer.input = K.placeholder(ndim=ndim)
layer.set_input_shape(input_data.shape[1:])
expected_output_shape = layer.output_shape[1:]
function = theano.function([layer.input], [layer.get_output()])
output = function(input_data)[0]
assert output.shape[1:] == expected_output_shape
function = K.function([layer.input], [layer.get_output()])
output = function([input_data])[0]
assert output.shape[1:] == expected_output_shape, str(output.shape[1:]) + ' != ' + str(expected_output_shape)
class TestShapeInference(unittest.TestCase):
@@ -56,67 +56,102 @@ class TestShapeInference(unittest.TestCase):
# Convolutional #
#################
def test_Convolution1D(self):
for border_mode in ['same', 'full', 'valid']:
for border_mode in ['same', 'valid']:
for filter_length in [2, 3]:
for subsample_length in [1, 2]:
for subsample_length in [1]:
if subsample_length > 1 and border_mode == 'same':
continue
for input_data_shape in [(2, 3, 2), (2, 4, 2)]:
layer = Convolution1D(nb_filter=1, filter_length=filter_length,
border_mode=border_mode, subsample_length=subsample_length)
for input_data_shape in [(2, 3, 4), (2, 4, 4)]:
layer = Convolution1D(nb_filter=1,
filter_length=filter_length,
border_mode=border_mode,
subsample_length=subsample_length)
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_Convolution2D(self):
for border_mode in ['same', 'full', 'valid']:
for nb_row, nb_col in [(2, 1), (3, 2)]:
for border_mode in ['same', 'valid']:
for nb_row, nb_col in [(2, 2), (3, 3)]:
for subsample in [(1, 1), (2, 2)]:
if (subsample[0] > 1 or subsample[1] > 1) and border_mode == 'same':
continue
for input_data_shape in [(2, 1, 3, 3), (2, 1, 4, 4)]:
layer = Convolution2D(nb_filter=1, nb_row=nb_row, nb_col=nb_row,
border_mode=border_mode, subsample=subsample)
layer = Convolution2D(nb_filter=1, nb_row=nb_row,
nb_col=nb_row,
border_mode=border_mode,
subsample=subsample,
dim_ordering='th')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
for input_data_shape in [(2, 3, 3, 1)]:
layer = Convolution2D(nb_filter=1, nb_row=nb_row,
nb_col=nb_row,
border_mode=border_mode,
subsample=subsample,
dim_ordering='tf')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_MaxPooling1D(self):
for ignore_border in [True, False]:
for stride in [1, 2]:
for pool_length in [1, 2]:
for input_data_shape in [(2, 1, 3), (2, 1, 4)]:
layer = MaxPooling1D(pool_length=pool_length, stride=stride, ignore_border=ignore_border)
for pool_length in [1, 2]:
for stride in [1]:
for input_data_shape in [(2, 3, 4), (2, 4, 4)]:
layer = MaxPooling1D(pool_length=pool_length,
stride=stride,
border_mode='valid')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_MaxPooling2D(self):
for ignore_border in [True, False]:
for stride in [(1, 1), (2, 2)]:
for strides in [(1, 1), (2, 2)]:
for pool_size in [(2, 2), (3, 3), (4, 4)]:
for input_data_shape in [(2, 1, 3, 3), (2, 1, 4, 4), (2, 1, 5, 5), (2, 1, 6, 6)]:
layer = MaxPooling2D(pool_size=pool_size, stride=stride, ignore_border=ignore_border)
for input_data_shape in [(2, 1, 4, 4), (2, 1, 5, 5), (2, 1, 6, 6)]:
layer = MaxPooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='th')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_UpSample1D(self):
layer = UpSample1D(length=2)
for input_data_shape in [(2, 4, 4, 1)]:
layer = MaxPooling2D(pool_size=pool_size,
strides=strides,
border_mode='valid',
dim_ordering='tf')
input_data = np.random.random(input_data_shape)
check_layer_output_shape(layer, input_data)
def test_UpSampling1D(self):
layer = UpSampling1D(length=2)
input_data = np.random.random((2, 2, 3))
check_layer_output_shape(layer, input_data)
def test_UpSample2D(self):
layer = UpSample2D(size=(2, 2))
def test_UpSampling2D(self):
layer = UpSampling2D(size=(2, 2), dim_ordering='th')
input_data = np.random.random((2, 1, 2, 3))
check_layer_output_shape(layer, input_data)
layer = UpSampling2D(size=(2, 2), dim_ordering='tf')
input_data = np.random.random((2, 2, 3, 1))
check_layer_output_shape(layer, input_data)
def test_ZeroPadding1D(self):
layer = ZeroPadding1D(1)
input_data = np.random.random((2, 2, 1))
check_layer_output_shape(layer, input_data)
def test_ZeroPadding2D(self):
layer = ZeroPadding2D((1, 2))
layer = ZeroPadding2D((1, 2), dim_ordering='th')
input_data = np.random.random((2, 1, 2, 3))
check_layer_output_shape(layer, input_data)
layer = ZeroPadding2D((1, 2), dim_ordering='tf')
input_data = np.random.random((2, 2, 3, 1))
check_layer_output_shape(layer, input_data)
# #############
# # Recurrent #
# #############
+46 -20
Ver Arquivo
@@ -16,8 +16,11 @@ class TestTasks(unittest.TestCase):
nb_hidden = 10
print('vector classification data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(10,),
classification=True, nb_class=2)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(10,),
classification=True,
nb_class=2)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
print('y_train:', y_train.shape)
@@ -32,14 +35,18 @@ class TestTasks(unittest.TestCase):
model.add(Dense(y_train.shape[-1]))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), show_accuracy=True, verbose=2)
print(history.history)
self.assertTrue(history.history['val_acc'][-1] > 0.9)
history = model.fit(X_train, y_train, nb_epoch=15, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
self.assertTrue(history.history['val_acc'][-1] > 0.8)
def test_vector_reg(self):
nb_hidden = 10
print('vector regression data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(10,), output_shape=(2,),
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(10,),
output_shape=(2,),
classification=False)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
@@ -51,13 +58,17 @@ class TestTasks(unittest.TestCase):
model.add(Activation('tanh'))
model.add(Dense(y_train.shape[-1]))
model.compile(loss='hinge', optimizer='adagrad')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), verbose=2)
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test), verbose=0)
self.assertTrue(history.history['val_loss'][-1] < 0.9)
def test_temporal_clf(self):
print('temporal classification data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(3, 5),
classification=True, nb_class=2)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(3, 5),
classification=True,
nb_class=2)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
print('y_train:', y_train.shape)
@@ -67,15 +78,20 @@ class TestTasks(unittest.TestCase):
y_test = to_categorical(y_test)
model = Sequential()
model.add(GRU(y_train.shape[-1], input_shape=(None, X_train.shape[-1])))
model.add(GRU(y_train.shape[-1], input_shape=(X_train.shape[1], X_train.shape[2])))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adadelta')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), show_accuracy=True, verbose=2)
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
self.assertTrue(history.history['val_acc'][-1] > 0.9)
def test_temporal_reg(self):
print('temporal regression data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(3, 5), output_shape=(2,),
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(3, 5),
output_shape=(2,),
classification=False)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
@@ -83,14 +99,18 @@ class TestTasks(unittest.TestCase):
print('y_test:', y_test.shape)
model = Sequential()
model.add(GRU(y_train.shape[-1], input_shape=(None, X_train.shape[-1])))
model.add(GRU(y_train.shape[-1], input_shape=(X_train.shape[1], X_train.shape[2])))
model.compile(loss='hinge', optimizer='adam')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), verbose=2)
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test), verbose=0)
self.assertTrue(history.history['val_loss'][-1] < 0.8)
def test_seq_to_seq(self):
print('sequence to sequence data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(3, 5), output_shape=(3, 5),
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(3, 5),
output_shape=(3, 5),
classification=False)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
@@ -98,15 +118,19 @@ class TestTasks(unittest.TestCase):
print('y_test:', y_test.shape)
model = Sequential()
model.add(TimeDistributedDense(y_train.shape[-1], input_shape=(None, X_train.shape[-1])))
model.add(TimeDistributedDense(y_train.shape[-1], input_shape=(X_train.shape[1], X_train.shape[2])))
model.compile(loss='hinge', optimizer='rmsprop')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), verbose=2)
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test), verbose=0)
self.assertTrue(history.history['val_loss'][-1] < 0.8)
def test_img_clf(self):
print('image classification data:')
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000, nb_test=200, input_shape=(3, 8, 8),
classification=True, nb_class=2)
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=1000,
nb_test=200,
input_shape=(3, 8, 8),
classification=True,
nb_class=2)
print('X_train:', X_train.shape)
print('X_test:', X_test.shape)
print('y_train:', y_train.shape)
@@ -122,7 +146,9 @@ class TestTasks(unittest.TestCase):
model.add(Dense(y_test.shape[-1]))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd')
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16, validation_data=(X_test, y_test), show_accuracy=True, verbose=2)
history = model.fit(X_train, y_train, nb_epoch=12, batch_size=16,
validation_data=(X_test, y_test),
show_accuracy=True, verbose=0)
print(history.history['val_acc'][-1])
self.assertTrue(history.history['val_acc'][-1] > 0.9)