Comparar commits

..

52 Commits

Autor SHA1 Mensagem Data
Francois Chollet 97e31b6090 Cleanup docs autogen script 2016-06-06 10:18:09 -07:00
Francois Chollet 62053e68e2 Prepare 1.0.4 PyPI release 2016-06-06 10:17:47 -07:00
Francois Chollet 489c07e748 Docs adjustment 2016-06-06 10:15:22 -07:00
fchollet 604ea8d68a Fix PEP8 BS 2016-06-05 20:41:19 -07:00
fchollet fd3cfb196b Allow no layer names in plot() 2016-06-05 20:20:14 -07:00
fchollet b71f6ba864 Allow absence of labels in flow() 2016-06-05 20:19:55 -07:00
fchollet dfc128b89a Fix some py3 generator issue 2016-06-05 14:52:10 -07:00
fchollet 34b8b57c2f Update image preprocessing docs 2016-06-05 14:01:28 -07:00
fchollet 3bba409d9e Improve docstring in preprocessing/image 2016-06-05 14:01:11 -07:00
fchollet 7869cdccec Merge branch 'master' of ssh://github.com/fchollet/keras 2016-06-05 13:39:55 -07:00
fchollet 0e18e345b0 Refactor ImageDataGenerator, add directory support 2016-06-05 10:24:54 -07:00
fchollet e5b99c7512 Tiny fixes in Sequential methods 2016-06-05 10:24:20 -07:00
aaditya prakash 7d4c85018a MaxoutDense no activation; incorrect docs (#2895)
Since MaxoutDense does not have activation it might be misleading to include "activation" as one of the arguments in the function docs.
2016-06-03 23:45:24 -07:00
fchollet edbec2dbc9 Remove bit of deprecated code 2016-06-03 23:13:46 -07:00
fchollet 973ece9809 Make dim_ordering a global default 2016-06-03 23:13:11 -07:00
lorenzoritter 90f441a6a0 fixed formatting error in the docstring (#2797)
* fixed formatting error in the docstring

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

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

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

* Update theano_backend.py

changed style and numpy randint range

* Update theano_backend.py

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

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

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

* added test for conv layer initializations

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

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

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

* use backend epsilon
2016-05-15 20:16:46 -07:00
Mikhail Korobov e0ed174f2c Input: proper error message for missing "shape" argument (#2727) 2016-05-15 15:15:14 -07:00
37 arquivos alterados com 736 adições e 389 exclusões
+1 -1
Ver Arquivo
@@ -51,7 +51,7 @@ model = Sequential()
Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
from keras.layers import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
+2 -100
Ver Arquivo
@@ -82,6 +82,7 @@ from keras import constraints
from keras import activations
from keras import regularizers
EXCLUDE = {
'Optimizer',
'Wrapper',
@@ -334,6 +335,7 @@ def process_function_docstring(docstring):
print('Cleaning up existing sources directory.')
if os.path.exists('sources'):
shutil.rmtree('sources')
print('Populating sources directory with templates.')
for subdir, dirs, fnames in os.walk('templates'):
for fname in fnames:
@@ -418,103 +420,3 @@ for page_data in PAGES:
if not os.path.exists(subdir):
os.makedirs(subdir)
open(path, 'w').write(mkdown)
# covered_so_far = set()
# for module, module_name in MODULES:
# class_pages = []
# for name in dir(module):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# module_member = getattr(module, name)
# if module_member in covered_so_far:
# continue
# if inspect.isclass(module_member):
# cls = module_member
# if cls.__module__ == module_name:
# try:
# class_signature = get_function_signature(cls.__init__)
# class_signature = class_signature.replace('__init__', cls.__name__)
# except:
# # in case the class inherits from object and does not
# # define __init__
# class_signature = module_name + '.' + cls.__name__ + '()'
# functions = []
# functions_not_defined_here = []
# for name in dir(cls):
# if name in SKIP:
# continue
# if name[0] == '_':
# continue
# cls_member = getattr(cls, name)
# if inspect.isfunction(cls_member):
# function = cls_member
# signature = inspect.getargspec(function)
# defaults = signature.defaults
# args = signature.args[1:]
# if defaults:
# kwargs = zip(args[-len(defaults):], defaults)
# args = args[:-len(defaults)]
# else:
# kwargs = []
# defined_by = get_earliest_class_that_defined_member(function.__name__, cls)
# if cls == defined_by:
# functions.append(function)
# else:
# functions_not_defined_here.append((function, defined_by))
# blocks = []
# blocks.append('<span style="float:right;">' + class_to_source_link(cls) + '</span>')
# blocks.append('# ' + cls.__name__ + '\n')
# blocks.append(code_snippet(class_signature))
# docstring = cls.__doc__
# if docstring:
# blocks.append(process_class_docstring(docstring))
# if cls.__name__ in INCLUDE_functionS_FOR:
# if functions or functions_not_defined_here:
# blocks.append('### functions\n')
# for function in functions:
# signature = get_function_signature(function)
# signature = signature.replace(module_name + '.', '')
# blocks.append(code_snippet(signature))
# docstring = function.__doc__
# if docstring:
# blocks.append(process_function_docstring(docstring))
# for function, defined_by in functions_not_defined_here:
# signature = get_function_signature(function)
# function_module_name = function.__module__
# signature = signature.replace(function_module_name + '.', '')
# link = '[' + defined_by.__name__ + '](' + class_to_docs_link(defined_by) + ')'
# blocks.append(code_snippet(signature))
# blocks.append('Defined by ' + link + '.\n')
# mkdown = '\n'.join(blocks)
# class_pages.append((id(cls), mkdown))
# covered_so_far.add(module_member)
# class_pages.sort(key=lambda x: x[0])
# class_pages = [x[1] for x in class_pages]
# module_page = '\n----\n\n'.join(class_pages)
# # save module page.
# # Either insert content into existing page,
# # or create page otherwise
# path = 'sources/' + module_name.replace('.', '/')[6:] + '.md'
# if os.path.exists(path):
# template = open(path).read()
# assert '{{autogenerated}}' in template, ('Template found for ' + path +
# ' but missing {{autogenerated}} tag.')
# module_page = template.replace('{{autogenerated}}', module_page)
# print('...inserting autogenerated content into template:', path)
# else:
# print('...creating new page with autogenerated content:', path)
# subdir = os.path.dirname(path)
# if not os.path.exists(subdir):
# os.makedirs(subdir)
# open(path, 'w').write(module_page)
+40 -6
Ver Arquivo
@@ -10,6 +10,7 @@
- [How is the validation split computed?](#how-is-the-validation-split-computed)
- [Is the data shuffled during training?](#is-the-data-shuffled-during-training)
- [How can I record the training / validation loss / accuracy at each epoch?](#how-can-i-record-the-training-validation-loss-accuracy-at-each-epoch)
- [How can I "freeze" layers?](#how-can-i-freeze-keras-layers)
- [How can I use stateful RNNs?](#how-can-i-use-stateful-rnns)
---
@@ -20,12 +21,11 @@ Please cite Keras in your publications if it helps your research. Here is an exa
```
@misc{chollet2015keras,
author = {Chollet, Francois},
title = {Keras},
year = {2015},
publisher = {GitHub},
journal = {GitHub repository},
howpublished = {\url{https://github.com/fchollet/keras}}
title={Keras},
author={Chollet, Fran\c{c}ois},
year={2015},
publisher={GitHub},
howpublished={\url{https://github.com/fchollet/keras}},
}
```
@@ -215,6 +215,40 @@ print(hist.history)
---
### How can I "freeze" Keras layers?
To "freeze" a layer means to exclude it from training, i.e. its weights will never be updated. This is useful in the context of fine-tuning a model, or using fixed embeddings for a text input.
You can pass a `trainable` argument (boolean) to a layer constructor to set a layer to be non-trainable:
```python
frozen_layer = Dense(32, trainable=False)
```
Additionally, you can set the `trainable` property of a layer to `True` or `False` after instantiation. For this to take effect, you will need to call `compile()` on your model after modifying the `trainable` property. Here's an example:
```python
x = Input(shape=(32,))
layer = Dense(32)
layer.trainable = False
y = layer(x)
frozen_model = Model(x, y)
# in the model below, the weights of `layer` will not be updated during training
frozen_model.compile(optimizer='rmsprop', loss='mse')
layer.trainable = True
trainable_model = Model(x, y)
# with this model the weights of the layer will be updated during training
# (which will also affect the above model since it uses the same layer instance)
trainable_model.compile(optimizer='rmsprop', loss='mse')
frozen_model.fit(data, labels) # this does NOT update the weights of `layer`
trainable_model.fit(data, labels) # this updates the weights of `layer`
```
---
### How can I use stateful RNNs?
Making a RNN stateful means that the states for the samples of each batch will be reused as initial states for the samples in the next batch.
@@ -6,6 +6,7 @@ You can create a `Sequential` model by passing a list of layer instances to the
```python
from keras.models import Sequential
from keras.layers import Dense, Activation
model = Sequential([
Dense(32, input_dim=784),
+2 -2
Ver Arquivo
@@ -36,7 +36,7 @@ Keras is compatible with: __Python 2.7-3.5__.
## Getting started: 30 seconds to Keras
The core data structure of Keras is a __model__, a way to organize layers. The main type of model is the [`Sequential`](http://keras.io/getting-started/sequential-model-guide) model, a linear stack of layers. For more complex architectures, you should use the [Keras function API](http://keras.io/getting-started/functional-api-guide).
The core data structure of Keras is a __model__, a way to organize layers. The main type of model is the [`Sequential`](http://keras.io/getting-started/sequential-model-guide) model, a linear stack of layers. For more complex architectures, you should use the [Keras functional API](http://keras.io/getting-started/functional-api-guide).
Here's the `Sequential` model:
@@ -49,7 +49,7 @@ model = Sequential()
Stacking layers is as easy as `.add()`:
```python
from keras.layers.core import Dense, Activation
from keras.layers import Dense, Activation
model.add(Dense(output_dim=64, input_dim=100))
model.add(Activation("relu"))
+3 -2
Ver Arquivo
@@ -27,5 +27,6 @@ For a few examples of such functions, check out the [objectives source](https://
- __binary_crossentropy__: Also known as logloss.
- __categorical_crossentropy__: Also known as multiclass logloss. __Note__: using this objective requires that your labels are binary arrays of shape `(nb_samples, nb_classes)`.
- __sparse_categorical_crossentropy__: As above but accepts sparse labels. __Note__: this objective still requires that your labels have the same number of dimensions as your outputs; you may need to add a length-1 dimension to the shape of your labels, e.g with `np.expand_dims(y, -1)`.
- __poisson__: mean of `(predictions - targets * log(predictions))`
- __cosine_proximity__: the opposite (negative) of the mean cosine proximity between predictions and targets.
- __kullback_leibler_divergence__ / __kld__: Information gain from a predicted probability distribution Q to a true probability distribution P. Gives a measure of difference between both distributions.
- __poisson__: Mean of `(predictions - targets * log(predictions))`
- __cosine_proximity__: The opposite (negative) of the mean cosine proximity between predictions and targets.
+68 -9
Ver Arquivo
@@ -2,9 +2,9 @@
## ImageDataGenerator
```python
keras.preprocessing.image.ImageDataGenerator(featurewise_center=True,
keras.preprocessing.image.ImageDataGenerator(featurewise_center=False,
samplewise_center=False,
featurewise_std_normalization=True,
featurewise_std_normalization=False,
samplewise_std_normalization=False,
zca_whitening=False,
rotation_range=0.,
@@ -17,7 +17,8 @@ keras.preprocessing.image.ImageDataGenerator(featurewise_center=True,
cval=0.,
horizontal_flip=False,
vertical_flip=False,
dim_ordering='th')
rescale=None,
dim_ordering=K.image_dim_ordering())
```
Generate batches of tensor image data with real-time data augmentation. The data will be looped over (in batches) indefinitely.
@@ -38,27 +39,54 @@ Generate batches of tensor image data with real-time data augmentation. The data
- __cval__: Float or Int. Value used for points outside the boundaries when `fill_mode = "constant"`.
- __horizontal_flip__: Boolean. Randomly flip inputs horizontally.
- __vertical_flip__: Boolean. Randomly flip inputs vertically.
- __rescale__: rescaling factor. Defaults to None. If None or 0, no rescaling is applied,
otherwise we multiply the data by the value provided (before applying
any other transformation).
- __dim_ordering__: One of {"th", "tf"}.
"tf" mode means that the images should have shape `(samples, width, height, channels)`,
"th" mode means that the images should have shape `(samples, channels, width, height)`.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
- __Methods__:
- __fit(X)__: Required if featurewise_center or featurewise_std_normalization or zca_whitening. Compute necessary quantities on some sample data.
- __fit(X)__: Compute the internal data stats related to the data-dependent transformations, based on an array of sample data.
Only required if featurewise_center or featurewise_std_normalization or zca_whitening.
- __Arguments__:
- __X__: sample data.
- __augment__: Boolean (default: False). Whether to fit on randomly augmented samples.
- __rounds__: int (default: 1). If augment, how many augmentation passes over the data to use.
- __flow(X, y)__:
- __flow(X, y)__: Takes numpy data & label arrays, and generates batches of augmented/normalized data. Yields batches indefinitely, in an infinite loop.
- __Arguments__:
- __X__: data.
- __y__: labels.
- __batch_size__: int (default: 32).
- __shuffle__: boolean (defaut: False).
- __save_to_dir__: None or str. This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str. Prefix to use for filenames of saved pictures.
- __save_format__: one of "png", jpeg".
- __save_to_dir__: None or str (default: None). This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str (default: `''`). Prefix to use for filenames of saved pictures (only relevant if `save_to_dir` is set).
- __save_format__: one of "png", jpeg" (only relevant if `save_to_dir` is set). Default: "jpeg".
- ___yields__: Tuples of `(x, y)` where `x` is a numpy array of image data and `y` is a numpy array of corresponding labels.
The generator loops indefinitely.
- __flow_from_directory(directory)__: Takes the path to a directory, and generates batches of augmented/normalized data. Yields batches indefinitely, in an infinite loop.
- __Arguments__:
- __directory: path to the target directory. It should contain one subdirectory per class,
and the subdirectories should contain PNG or JPG images. See [this script](https://gist.github.com/fchollet/0830affa1f7f19fd47b06d4cf89ed44d) for more details.
- __target_size__: tuple of integers, default: `(256, 256)`. The dimensions to which all images found will be resized.
- __color_mode__: one of "grayscale", "rbg". Default: "rgb". Whether the images will be converted to have 1 or 3 color channels.
- __classes__: optional list of class subdirectories (e.g. `['dogs', 'cats']`). Default: None. If not provided, the list of classes will be automatically infered (and the order of the classes, which will map to the label indices, will be alphanumeral).
- __class_mode__: one of "categorical", "binary", "sparse" or None. Default: "categorical". Determines the type of label arrays that are returned: "categorical" will be 2D one-hot encoded labels, "binary" will be 1D binary labels, "sparse" will be 1D integer labels. If None, no labels are returned (the generator will only yield batches of image data, which is useful to use `model.predict_generator()`, `model.evaluate_generator()`, etc.).
- __batch_size__: size of the batches of data (default: 32).
- __shuffle__: whether to shuffle the data (default: True)
- __seed__: optional random seed for shuffling.
- __save_to_dir__: None or str (default: None). This allows you to optimally specify a directory to which to save the augmented pictures being generated (useful for visualizing what you are doing).
- __save_prefix__: str. Prefix to use for filenames of saved pictures (only relevant if `save_to_dir` is set).
- __save_format__: one of "png", jpeg" (only relevant if `save_to_dir` is set). Default: "jpeg".
- __Examples__:
Example of using `.flow(X, y)`:
- __Example__:
```python
(X_train, y_train), (X_test, y_test) = cifar10.load_data(test_split=0.1)
Y_train = np_utils.to_categorical(y_train, nb_classes)
@@ -92,3 +120,34 @@ for e in range(nb_epoch):
# the generator loops indefinitely
break
```
Example of using `.flow_from_directory(directory)`:
```python
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
'data/train',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
'data/validation',
target_size=(150, 150),
batch_size=32,
class_mode='binary')
model.fit_generator(
train_generator,
samples_per_epoch=2000,
nb_epoch=50,
validation_data=validation_generator,
nb_val_samples=800)
```
+2 -2
Ver Arquivo
@@ -1,4 +1,4 @@
# Wrappers for the Sciki-Learn API
# Wrappers for the Scikit-Learn API
You can use `Sequential` Keras models (single-input only) as part of your Scikit-Learn workflow via the wrappers found at `keras.wrappers.sklearn.py`.
@@ -42,4 +42,4 @@ fitting (predicting) parameters are selected in the following order:
When using scikit-learn's `grid_search` API, legal tunable parameters are
those you could pass to `sk_params`, including fitting parameters.
In other words, you could use `grid_search` to search for the best
`batch_size` or `nb_epoch` as well as the model parameters.
`batch_size` or `nb_epoch` as well as the model parameters.
+2 -2
Ver Arquivo
@@ -29,7 +29,7 @@ Five digits inverted:
from __future__ import print_function
from keras.models import Sequential
from keras.engine.training import slice_X
from keras.layers import Activation, TimeDistributedDense, RepeatVector, recurrent
from keras.layers import Activation, TimeDistributed, Dense, RepeatVector, recurrent
import numpy as np
from six.moves import range
@@ -139,7 +139,7 @@ for _ in range(LAYERS):
model.add(RNN(HIDDEN_SIZE, return_sequences=True))
# For each of step of the output sequence, decide which character should be chosen
model.add(TimeDistributedDense(len(chars)))
model.add(TimeDistributed(Dense(len(chars))))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy',
+7 -2
Ver Arquivo
@@ -94,8 +94,13 @@ def vectorize_stories(data, word_idx, story_maxlen, query_maxlen):
pad_sequences(Xq, maxlen=query_maxlen), np.array(Y))
path = get_file('babi-tasks-v1-2.tar.gz',
origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
except:
print('Error downloading dataset, please download it manually:\n'
'$ wget http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz\n'
'$ mv tasks_1-20_v1-2.tar.gz ~/.keras/datasets/babi-tasks-v1-2.tar.gz')
raise
tar = tarfile.open(path)
challenges = {
+7 -1
Ver Arquivo
@@ -146,7 +146,13 @@ BATCH_SIZE = 32
EPOCHS = 40
print('RNN / Embed / Sent / Query = {}, {}, {}, {}'.format(RNN, EMBED_HIDDEN_SIZE, SENT_HIDDEN_SIZE, QUERY_HIDDEN_SIZE))
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
try:
path = get_file('babi-tasks-v1-2.tar.gz', origin='http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz')
except:
print('Error downloading dataset, please download it manually:\n'
'$ wget http://www.thespermwhale.com/jaseweston/babi/tasks_1-20_v1-2.tar.gz\n'
'$ mv tasks_1-20_v1-2.tar.gz ~/.keras/datasets/babi-tasks-v1-2.tar.gz')
raise
tar = tarfile.open(path)
# Default QA1 with 1000 samples
# challenge = 'tasks_1-20_v1-2/en/qa1_single-supporting-fact_{}.txt'
+1 -1
Ver Arquivo
@@ -3,7 +3,7 @@ with pixel-by-pixel sequential MNIST in
"A Simple Way to Initialize Recurrent Networks of Rectified Linear Units"
by Quoc V. Le, Navdeep Jaitly, Geoffrey E. Hinton
arXiv:1504.00941v2 [cs.NE] 7 Apr 201
arXiv:1504.00941v2 [cs.NE] 7 Apr 2015
http://arxiv.org/pdf/1504.00941v2.pdf
Optimizer is replaced with RMSprop which yields more stable and steady
+6 -6
Ver Arquivo
@@ -21,17 +21,17 @@ nb_epoch = 40
x = Input(batch_shape=(batch_size, original_dim))
h = Dense(intermediate_dim, activation='relu')(x)
z_mean = Dense(latent_dim)(h)
z_log_sigma = Dense(latent_dim)(h)
z_log_std = Dense(latent_dim)(h)
def sampling(args):
z_mean, z_log_sigma = args
z_mean, z_log_std = args
epsilon = K.random_normal(shape=(batch_size, latent_dim),
mean=0., std=epsilon_std)
return z_mean + K.exp(z_log_sigma) * epsilon
return z_mean + K.exp(z_log_std) * epsilon
# note that "output_shape" isn't necessary with the TensorFlow backend
# so you could write `Lambda(sampling)([z_mean, z_log_sigma])`
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_sigma])
# so you could write `Lambda(sampling)([z_mean, z_log_std])`
z = Lambda(sampling, output_shape=(latent_dim,))([z_mean, z_log_std])
# we instantiate these layers separately so as to reuse them later
decoder_h = Dense(intermediate_dim, activation='relu')
@@ -41,7 +41,7 @@ x_decoded_mean = decoder_mean(h_decoded)
def vae_loss(x, x_decoded_mean):
xent_loss = objectives.binary_crossentropy(x, x_decoded_mean)
kl_loss = - 0.5 * K.mean(1 + z_log_sigma - K.square(z_mean) - K.exp(z_log_sigma), axis=-1)
kl_loss = - 0.5 * K.mean(1 + z_log_std - K.square(z_mean) - K.exp(z_log_std), axis=-1)
return xent_loss + kl_loss
vae = Model(x, x_decoded_mean)
+1 -1
Ver Arquivo
@@ -15,4 +15,4 @@ from . import objectives
from . import optimizers
from . import regularizers
__version__ = '1.0.3'
__version__ = '1.0.4'
+13 -8
Ver Arquivo
@@ -9,6 +9,8 @@ from .common import set_epsilon
from .common import set_floatx
from .common import get_uid
from .common import cast_to_floatx
from .common import image_dim_ordering
from .common import set_image_dim_ordering
_keras_base_dir = os.path.expanduser('~')
if not os.access(_keras_base_dir, os.W_OK):
@@ -28,24 +30,27 @@ if os.path.exists(_config_path):
assert type(_epsilon) == float
_backend = _config.get('backend', _BACKEND)
assert _backend in {'theano', 'tensorflow'}
_image_dim_ordering = _config.get('image_dim_ordering', image_dim_ordering())
assert _image_dim_ordering in {'tf', 'th'}
set_floatx(_floatx)
set_epsilon(_epsilon)
_BACKEND = _backend
else:
# save config file, for easy edition
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND}
with open(_config_path, 'w') as f:
# add new line in order for bash 'cat' display the content correctly
f.write(json.dumps(_config) + '\n')
# save config file
_config = {'floatx': floatx(),
'epsilon': epsilon(),
'backend': _BACKEND,
'image_dim_ordering': image_dim_ordering()}
with open(_config_path, 'w') as f:
f.write(json.dumps(_config, indent=4))
if 'KERAS_BACKEND' in os.environ:
_backend = os.environ['KERAS_BACKEND']
assert _backend in {'theano', 'tensorflow'}
_BACKEND = _backend
# import backend
if _BACKEND == 'theano':
sys.stderr.write('Using Theano backend.\n')
from .theano_backend import *
+25 -2
Ver Arquivo
@@ -4,13 +4,20 @@ import numpy as np
_FLOATX = 'float32'
_EPSILON = 10e-8
_UID_PREFIXES = {}
_IMAGE_DIM_ORDERING = 'th'
def epsilon():
'''Returns the value of the fuzz
factor used in numeric expressions.
'''
return _EPSILON
def set_epsilon(e):
'''Sets the value of the fuzz
factor used in numeric expressions.
'''
global _EPSILON
_EPSILON = e
@@ -26,8 +33,7 @@ def set_floatx(floatx):
global _FLOATX
if floatx not in {'float16', 'float32', 'float64'}:
raise Exception('Unknown floatx type: ' + str(floatx))
floatx = str(floatx)
_FLOATX = floatx
_FLOATX = str(floatx)
def cast_to_floatx(x):
@@ -36,6 +42,23 @@ def cast_to_floatx(x):
return np.asarray(x, dtype=_FLOATX)
def image_dim_ordering():
'''Returns the image dimension ordering
convention ('th' or 'tf').
'''
return _IMAGE_DIM_ORDERING
def set_image_dim_ordering(dim_ordering):
'''Sets the value of the image dimension
ordering convention ('th' or 'tf').
'''
global _IMAGE_DIM_ORDERING
if dim_ordering not in {'tf', 'th'}:
raise Exception('Unknown dim_ordering:', dim_ordering)
_IMAGE_DIM_ORDERING = str(dim_ordering)
def get_uid(prefix=''):
if prefix not in _UID_PREFIXES:
_UID_PREFIXES[prefix] = 1
+4 -4
Ver Arquivo
@@ -782,7 +782,7 @@ def dropout(x, level, seed=None):
if level < 0. or level >= 1:
raise Exception('Dropout level must be in interval [0, 1[.')
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
retain_prob = 1. - level
x *= rng.binomial(x.shape, p=retain_prob, dtype=x.dtype)
@@ -1027,20 +1027,20 @@ def pool3d(x, pool_size, strides=(1, 1, 1), border_mode='valid',
def random_normal(shape, mean=0.0, std=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.normal(size=shape, avg=mean, std=std, dtype=dtype)
def random_uniform(shape, low=0.0, high=1.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.uniform(shape, low=low, high=high, dtype=dtype)
def random_binomial(shape, p=0.0, dtype=_FLOATX, seed=None):
if seed is None:
seed = np.random.randint(10e6)
seed = np.random.randint(1, 10e6)
rng = RandomStreams(seed=seed)
return rng.binomial(shape, p=p, dtype=dtype)
+2 -3
Ver Arquivo
@@ -192,7 +192,7 @@ class ProgbarLogger(Callback):
if k in logs:
self.log_values.append((k, logs[k]))
if self.verbose:
self.progbar.update(self.seen, self.log_values)
self.progbar.update(self.seen, self.log_values, force=True)
class History(Callback):
@@ -462,8 +462,7 @@ class TensorBoard(Callback):
layer.output)
self.merged = tf.merge_all_summaries()
if self.write_graph:
tf_version = tuple(int(i) for i in tf.__version__.split('.'))
if tf_version >= (0, 8, 0):
if tf.__version__ >= '0.8.0':
self.writer = tf.train.SummaryWriter(self.log_dir,
self.sess.graph)
else:
+77 -43
Ver Arquivo
@@ -1015,9 +1015,9 @@ def Input(shape=None, batch_shape=None,
```
'''
if not batch_shape:
assert shape, ('Please provide to Input either an `input_shape`' +
' or `batch_input_shape` argument. Note that ' +
'`input_shape` does not include the batch '
assert shape, ('Please provide to Input either a `shape`' +
' or a `batch_shape` argument. Note that ' +
'`shape` does not include the batch '
'dimension.')
batch_shape = (None,) + tuple(shape)
input_layer = InputLayer(batch_input_shape=batch_shape,
@@ -1060,10 +1060,14 @@ class Merge(Layer):
and return a single tensor.
concat_axis: integer, axis to use in mode `concat`.
dot_axes: integer or tuple of integers, axes to use in mode `dot`.
output_shape: shape tuple (tuple of integers), or lambda/function
to compute output_shape (only if merge mode is a lambda/function).
If the latter case, it should take as input a list of shape tuples
(1:1 mapping to input tensors) and return a single shape tuple.
output_shape: either a shape tuple (tuple of integers), or a lambda/function
to compute `output_shape` (only if merge mode is a lambda/function).
If the argument is a tuple,
it should be expected output shape, *not* including the batch size
(same convention as the `input_shape` argument in layers).
If the argument is callable, it should take as input a list of shape tuples
(1:1 mapping to input tensors) and return a single shape tuple, including the
batch size (same convention as the `get_output_shape_for` method of layers).
node_indices: optional list of integers containing
the output node index for each input layer
(in case some input layers have multiple output nodes).
@@ -1110,7 +1114,6 @@ class Merge(Layer):
node_indices = [0 for _ in range(len(layers))]
self._arguments_validation(layers, mode,
concat_axis, dot_axes,
output_shape,
node_indices, tensor_indices)
self.built = True
self.add_inbound_node(layers, node_indices, tensor_indices)
@@ -1118,7 +1121,7 @@ class Merge(Layer):
self.built = False
def _arguments_validation(self, layers, mode, concat_axis, dot_axes,
output_shape, node_indices, tensor_indices):
node_indices, tensor_indices):
'''Validates user-passed arguments and raises exceptions
as appropriate.
'''
@@ -1220,6 +1223,7 @@ class Merge(Layer):
l2 = inputs[1]
denominator = K.sqrt(K.batch_dot(l1, l1, self.dot_axes) *
K.batch_dot(l2, l2, self.dot_axes))
denominator = K.maximum(denominator, K.epsilon())
output = K.batch_dot(l1, l2, self.dot_axes) / denominator
output = K.expand_dims(output, 1)
return output
@@ -1258,7 +1262,6 @@ class Merge(Layer):
tensor_indices.append(tensor_index)
self._arguments_validation(layers, self.mode,
self.concat_axis, self.dot_axes,
self._output_shape,
node_indices, tensor_indices)
self.built = True
self.add_inbound_node(layers, node_indices, tensor_indices)
@@ -1276,7 +1279,7 @@ class Merge(Layer):
output_shape = self._output_shape(input_shape)
return output_shape
elif self._output_shape is not None:
return self._output_shape
return (input_shape[0],) + tuple(self._output_shape)
else:
# TODO: consider shape auto-inference with TF
raise Exception('The Merge layer ' + self.name +
@@ -1301,7 +1304,7 @@ class Merge(Layer):
elif self.mode == 'dot':
shape1 = list(input_shapes[0])
shape2 = list(input_shapes[1])
dot_axes = [a-1 for a in self.dot_axes]
dot_axes = [a - 1 for a in self.dot_axes]
tensordot_output = np.tensordot(np.zeros(tuple(shape1[1:])),
np.zeros(tuple(shape2[1:])),
axes=dot_axes)
@@ -1326,9 +1329,9 @@ class Merge(Layer):
if isinstance(self.mode, python_types.LambdaType):
if py3:
mode = marshal.dumps(self.mode.__code__)
mode = marshal.dumps(self.mode.__code__).decode('raw_unicode_escape')
else:
mode = marshal.dumps(self.mode.func_code)
mode = marshal.dumps(self.mode.func_code).decode('raw_unicode_escape')
mode_type = 'lambda'
elif callable(self.mode):
mode = self.mode.__name__
@@ -1364,7 +1367,7 @@ class Merge(Layer):
if mode_type == 'function':
mode = globals()[config['mode']]
elif mode_type == 'lambda':
mode = marshal.loads(config['mode'])
mode = marshal.loads(config['mode'].encode('raw_unicode_escape'))
mode = python_types.FunctionType(mode, globals())
else:
mode = config['mode']
@@ -1566,12 +1569,28 @@ class Container(Layer):
raise Exception('Output tensors to a ' + cls_name + ' must be '
'Keras tensors. Found: ' + str(x))
# build self.output_layers:
masks = []
for x in self.outputs:
layer, node_index, tensor_index = x._keras_history
self.output_layers.append(layer)
self.output_layers_node_indices.append(node_index)
self.output_layers_tensor_indices.append(tensor_index)
# build self.output_layers:
# also fill in the output mask cache
node = layer.inbound_nodes[node_index]
mask = node.output_masks[tensor_index]
masks.append(mask)
# output mask cache
mask_cache_key = ','.join([str(id(x)) for x in self.inputs])
mask_cache_key += '_' + ','.join([str(id(x)) for x in masks])
if len(masks) == 1:
mask = masks[0]
else:
mask = masks
self._output_mask_cache[mask_cache_key] = mask
# build self.input_layers:
for x in self.inputs:
layer, node_index, tensor_index = x._keras_history
# it's supposed to be an input layer, so only one node
@@ -1599,7 +1618,7 @@ class Container(Layer):
nodes_depths = {} # map {node: depth value}
layers_depths = {} # map {layer: depth value}
def make_node_key(node, depth):
def make_node_marker(node, depth):
return str(id(node)) + '-' + str(depth)
def build_map_of_graph(tensor, seen_nodes=set(), depth=0,
@@ -1623,7 +1642,7 @@ class Container(Layer):
node = layer.inbound_nodes[node_index]
# prevent cycles
seen_nodes.add(make_node_key(node, depth))
seen_nodes.add(make_node_marker(node, depth))
node_key = layer.name + '_ib-' + str(node_index)
# update container_nodes
@@ -1635,11 +1654,12 @@ class Container(Layer):
else:
nodes_depths[node] = max(depth, node_depth)
# update layers_depths
layer_depth = layers_depths.get(layer)
if layer_depth is None:
layers_depths[layer] = depth
previously_seen_depth = layers_depths.get(layer)
if previously_seen_depth is None:
current_depth = depth
else:
layers_depths[layer] = max(depth, layer_depth)
current_depth = max(depth, previously_seen_depth)
layers_depths[layer] = current_depth
# propagate to all previous tensors connected to this node
for i in range(len(node.inbound_layers)):
@@ -1648,9 +1668,10 @@ class Container(Layer):
node_index = node.node_indices[i]
tensor_index = node.tensor_indices[i]
next_node = layer.inbound_nodes[node_index]
node_key = make_node_key(next_node, depth + 1)
if node_key not in seen_nodes:
build_map_of_graph(x, seen_nodes, depth + 1,
# use node_marker to prevent cycles
node_marker = make_node_marker(next_node, current_depth + 1)
if node_marker not in seen_nodes:
build_map_of_graph(x, seen_nodes, current_depth + 1,
layer, node_index, tensor_index)
for x in self.outputs:
@@ -2105,8 +2126,6 @@ class Container(Layer):
return output_tensors, output_masks, output_shapes
def get_config(self):
'''TODO: add keras version information
'''
config = {
'name': self.name,
}
@@ -2187,9 +2206,9 @@ class Container(Layer):
# the graph reconstruction process
created_layers = {}
# iterate over saved layers, instantiate them,
# then call them on appropriate inputs to create graph nodes
for layer_data in config['layers']:
def process_layer(layer_data):
# iterate over saved layers, instantiate them,
# then call them on appropriate inputs to create graph nodes
layer_name = layer_data['name']
# instantiate layer
@@ -2214,6 +2233,10 @@ class Container(Layer):
layer(input_tensors[0])
else:
layer(input_tensors)
for layer_data in config['layers']:
process_layer(layer_data)
name = config.get('name')
input_tensors = []
output_tensors = []
@@ -2346,6 +2369,26 @@ class Container(Layer):
K.batch_set_value(weight_value_tuples)
f.close()
def _updated_config(self):
'''shared between different serialization methods'''
from keras import __version__ as keras_version
config = self.get_config()
model_config = {
'class_name': self.__class__.__name__,
'config': config,
'keras_version': keras_version
}
if hasattr(self, 'optimizer'):
model_config['optimizer'] = self.optimizer.get_config()
model_config['loss'] = getattr(self.loss, '__name__', self.loss)
model_config['sample_weight_mode'] = self.sample_weight_mode
if hasattr(self, 'loss_weights'):
model_config['loss_weights'] = self.loss_weights
return model_config
def to_json(self, **kwargs):
'''Returns a JSON string containing the network configuration.
@@ -2365,11 +2408,7 @@ class Container(Layer):
raise TypeError('Not JSON Serializable')
config = self.get_config()
model_config = {
'class_name': self.__class__.__name__,
'config': config,
}
model_config = self._updated_config()
return json.dumps(model_config, default=get_json_type, **kwargs)
def to_yaml(self, **kwargs):
@@ -2383,14 +2422,9 @@ class Container(Layer):
functions / classes.
'''
import yaml
config = self.get_config()
model_config = {
'class_name': self.__class__.__name__,
'config': config,
}
return yaml.dump(model_config, **kwargs)
return yaml.dump(self._updated_config(), **kwargs)
def summary(self):
def summary(self, line_length=100, positions=[.33, .55, .67, 1.]):
from keras.utils.layer_utils import print_summary
if hasattr(self, 'flattened_layers'):
@@ -2399,7 +2433,7 @@ class Container(Layer):
else:
flattened_layers = self.layers
print_summary(flattened_layers, getattr(self, 'container_nodes', None))
print_summary(flattened_layers, getattr(self, 'container_nodes', None), line_length=line_length, positions=positions)
def get_source_inputs(tensor, layer=None, node_index=None):
+5 -4
Ver Arquivo
@@ -84,9 +84,6 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
# check shapes compatibility
if shapes:
for i in range(len(names)):
if not i and not check_batch_dim:
# skip the first axis
continue
array = arrays[i]
if len(array.shape) != len(shapes[i]):
raise Exception('Error when checking ' + exception_prefix +
@@ -94,7 +91,10 @@ def standardize_input_data(data, names, shapes=None, check_batch_dim=True,
' to have ' + str(len(shapes[i])) +
' dimensions, but got array with shape ' +
str(array.shape))
for dim, ref_dim in zip(array.shape, shapes[i]):
for j, (dim, ref_dim) in enumerate(zip(array.shape, shapes[i])):
if not j and not check_batch_dim:
# skip the first axis
continue
if ref_dim:
if ref_dim != dim:
raise Exception('Error when checking ' + exception_prefix +
@@ -452,6 +452,7 @@ class Model(Container):
self.optimizer = optimizers.get(optimizer)
self.sample_weight_mode = sample_weight_mode
self.loss = loss
self.loss_weights = loss_weights
# prepare loss weights
if loss_weights is None:
+6 -4
Ver Arquivo
@@ -12,11 +12,13 @@ def get_fans(shape, dim_ordering='th'):
# TH kernel shape: (depth, input_depth, ...)
# TF kernel shape: (..., input_depth, depth)
if dim_ordering == 'th':
fan_in = np.prod(shape[1:])
fan_out = shape[0]
receptive_field_size = np.prod(shape[2:])
fan_in = shape[1] * receptive_field_size
fan_out = shape[0] * receptive_field_size
elif dim_ordering == 'tf':
fan_in = np.prod(shape[:-1])
fan_out = shape[-1]
receptive_field_size = np.prod(shape[:2])
fan_in = shape[-2] * receptive_field_size
fan_out = shape[-1] * receptive_field_size
else:
raise Exception('Invalid dim_ordering: ' + dim_ordering)
else:
+48 -12
Ver Arquivo
@@ -238,6 +238,9 @@ class Convolution2D(Layer):
applied to the bias.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
@@ -255,7 +258,7 @@ class Convolution2D(Layer):
'''
def __init__(self, nb_filter, nb_row, nb_col,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1), dim_ordering='th',
border_mode='valid', subsample=(1, 1), dim_ordering=K.image_dim_ordering(),
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
@@ -421,6 +424,9 @@ class Convolution3D(Layer):
applied to the bias.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
bias: whether to include a bias (i.e. make the layer affine rather than linear).
# Input shape
@@ -439,7 +445,7 @@ class Convolution3D(Layer):
def __init__(self, nb_filter, kernel_dim1, kernel_dim2, kernel_dim3,
init='glorot_uniform', activation='linear', weights=None,
border_mode='valid', subsample=(1, 1, 1), dim_ordering='th',
border_mode='valid', subsample=(1, 1, 1), dim_ordering=K.image_dim_ordering(),
W_regularizer=None, b_regularizer=None, activity_regularizer=None,
W_constraint=None, b_constraint=None,
bias=True, **kwargs):
@@ -686,7 +692,7 @@ class _Pooling2D(Layer):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
super(_Pooling2D, self).__init__(**kwargs)
self.pool_size = tuple(pool_size)
if strides is None:
@@ -752,6 +758,9 @@ class MaxPooling2D(_Pooling2D):
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
4D tensor with shape:
@@ -767,7 +776,7 @@ class MaxPooling2D(_Pooling2D):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
super(MaxPooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -790,6 +799,9 @@ class AveragePooling2D(_Pooling2D):
Note: 'same' will only work with TensorFlow for the time being.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
4D tensor with shape:
@@ -805,7 +817,7 @@ class AveragePooling2D(_Pooling2D):
'''
def __init__(self, pool_size=(2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
super(AveragePooling2D, self).__init__(pool_size, strides, border_mode,
dim_ordering, **kwargs)
@@ -821,7 +833,7 @@ class _Pooling3D(Layer):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
super(_Pooling3D, self).__init__(**kwargs)
self.pool_size = tuple(pool_size)
if strides is None:
@@ -892,6 +904,9 @@ class MaxPooling3D(_Pooling3D):
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
5D tensor with shape:
@@ -907,7 +922,7 @@ class MaxPooling3D(_Pooling3D):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
@@ -934,6 +949,9 @@ class AveragePooling3D(_Pooling3D):
border_mode: 'valid' or 'same'.
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
5D tensor with shape:
@@ -949,7 +967,7 @@ class AveragePooling3D(_Pooling3D):
'''
def __init__(self, pool_size=(2, 2, 2), strides=None, border_mode='valid',
dim_ordering='th', **kwargs):
dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
@@ -1003,6 +1021,9 @@ class UpSampling2D(Layer):
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
4D tensor with shape:
@@ -1017,7 +1038,7 @@ class UpSampling2D(Layer):
`(samples, upsampled_rows, upsampled_cols, channels)` if dim_ordering='tf'.
'''
def __init__(self, size=(2, 2), dim_ordering='th', **kwargs):
def __init__(self, size=(2, 2), dim_ordering=K.image_dim_ordering(), **kwargs):
self.size = tuple(size)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
self.dim_ordering = dim_ordering
@@ -1059,6 +1080,9 @@ class UpSampling3D(Layer):
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
5D tensor with shape:
@@ -1073,7 +1097,7 @@ class UpSampling3D(Layer):
`(samples, upsampled_dim1, upsampled_dim2, upsampled_dim3, channels)` if dim_ordering='tf'.
'''
def __init__(self, size=(2, 2, 2), dim_ordering='th', **kwargs):
def __init__(self, size=(2, 2, 2), dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
@@ -1151,6 +1175,12 @@ class ZeroPadding2D(Layer):
padding: tuple of int (length 2)
How many zeros to add at the beginning and end of
the 2 padding dimensions (axis 3 and 4).
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
4D tensor with shape:
@@ -1161,7 +1191,7 @@ class ZeroPadding2D(Layer):
(samples, depth, first_padded_axis, second_padded_axis)
'''
def __init__(self, padding=(1, 1), dim_ordering='th', **kwargs):
def __init__(self, padding=(1, 1), dim_ordering=K.image_dim_ordering(), **kwargs):
super(ZeroPadding2D, self).__init__(**kwargs)
self.padding = tuple(padding)
assert dim_ordering in {'tf', 'th'}, 'dim_ordering must be in {tf, th}'
@@ -1205,6 +1235,12 @@ class ZeroPadding3D(Layer):
padding: tuple of int (length 3)
How many zeros to add at the beginning and end of
the 3 padding dimensions (axis 3, 4 and 5).
dim_ordering: 'th' or 'tf'.
In 'th' mode, the channels dimension (the depth)
is at index 1, in 'tf' mode is it at index 4.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
# Input shape
5D tensor with shape:
@@ -1215,7 +1251,7 @@ class ZeroPadding3D(Layer):
(samples, depth, first_padded_axis, second_padded_axis, third_axis_to_pad)
'''
def __init__(self, padding=(1, 1, 1), dim_ordering='th', **kwargs):
def __init__(self, padding=(1, 1, 1), dim_ordering=K.image_dim_ordering(), **kwargs):
if K._BACKEND != 'theano':
raise Exception(self.__class__.__name__ +
' is currently only working with Theano backend.')
+3 -6
Ver Arquivo
@@ -669,10 +669,10 @@ class ActivityRegularization(Layer):
self.l1 = l1
self.l2 = l2
super(ActivityRegularization, self).__init__(**kwargs)
activity_regularizer = ActivityRegularizer(l1=l1, l2=l2)
activity_regularizer.set_layer(self)
self.regularizers = [activity_regularizer]
super(ActivityRegularization, self).__init__(**kwargs)
def get_config(self):
config = {'l1': self.l1,
@@ -702,11 +702,6 @@ class MaxoutDense(Layer):
or alternatively, Theano function to use for weights
initialization. This parameter is only relevant
if you don't pass a `weights` argument.
activation: name of activation function to use
(see [activations](../activations.md)),
or alternatively, elementwise Theano function.
If you don't specify anything, no activation is applied
(ie. "linear" activation: a(x) = x).
weights: list of numpy arrays to set as initial weights.
The list should have 2 elements, of shape `(input_dim, output_dim)`
and (output_dim,) for weights and biases respectively.
@@ -972,8 +967,10 @@ class TimeDistributedDense(Layer):
# Input shape
3D tensor with shape `(nb_sample, time_dimension, input_dim)`.
# Output shape
3D tensor with shape `(nb_sample, time_dimension, output_dim)`.
# Arguments
output_dim: int > 0.
init: name of initialization function for the weights of the layer
+39 -12
Ver Arquivo
@@ -19,7 +19,13 @@ class BatchNormalization(Layer):
using Theano conventions (samples, channels, rows, cols)
then you should set `axis` to `1` to normalize along
the channels axis.
During training we use per-batch statistics to normalize
the data, and during testing we use running averages
computed during the training phase.
- 1: sample-wise normalization. This mode assumes a 2D input.
- 2: feature-wise normalization, like mode 0, but
using per-batch statistics to normalize the data during both
testing and training.
axis: integer, axis along which to normalize in mode 0. For instance,
if your input tensor has shape (samples, channels, rows, cols),
set axis to 1 to normalize per feature map (channels axis).
@@ -58,7 +64,8 @@ class BatchNormalization(Layer):
self.axis = axis
self.momentum = momentum
self.initial_weights = weights
self.uses_learning_phase = True
if self.mode == 0:
self.uses_learning_phase = True
super(BatchNormalization, self).__init__(**kwargs)
def build(self, input_shape):
@@ -78,9 +85,12 @@ class BatchNormalization(Layer):
if self.initial_weights is not None:
self.set_weights(self.initial_weights)
del self.initial_weights
self.built = True
self.called_with = None
def call(self, x, mask=None):
if self.mode == 0:
if self.mode == 0 or self.mode == 2:
assert self.built, 'Layer must be built before being called'
input_shape = self.input_spec[0].shape
reduction_axes = list(range(len(input_shape)))
@@ -96,18 +106,35 @@ class BatchNormalization(Layer):
brodcast_std = K.reshape(std, broadcast_shape)
mean_update = self.momentum * self.running_mean + (1 - self.momentum) * mean
std_update = self.momentum * self.running_std + (1 - self.momentum) * std
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
x_normed = (x - brodcast_mean) / (brodcast_std + self.epsilon)
# case: test mode (uses running averages)
brodcast_running_mean = K.reshape(self.running_mean, broadcast_shape)
brodcast_running_std = K.reshape(self.running_std, broadcast_shape)
x_normed_running = ((x - brodcast_running_mean) / (brodcast_running_std + self.epsilon))
if self.mode == 2:
x_normed = (x - brodcast_mean) / (brodcast_std + self.epsilon)
out = K.reshape(self.gamma, broadcast_shape) * x_normed + K.reshape(self.beta, broadcast_shape)
else:
# mode 0
if self.called_with not in {None, x}:
raise Exception('You are attempting to share a '
'same `BatchNormalization` layer across '
'different data flows. '
'This is not possible. '
'You should use `mode=2` in '
'`BatchNormalization`, which has '
'a similar behavior but is shareable '
'(see docs for a description of '
'the behavior).')
self.called_with = x
self.updates = [(self.running_mean, mean_update),
(self.running_std, std_update)]
x_normed = (x - brodcast_mean) / (brodcast_std + self.epsilon)
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
out = K.reshape(self.gamma, broadcast_shape) * x_normed + K.reshape(self.beta, broadcast_shape)
# case: test mode (uses running averages)
brodcast_running_mean = K.reshape(self.running_mean, broadcast_shape)
brodcast_running_std = K.reshape(self.running_std, broadcast_shape)
x_normed_running = ((x - brodcast_running_mean) / (brodcast_running_std + self.epsilon))
# pick the normalized form of x corresponding to the training phase
x_normed = K.in_train_phase(x_normed, x_normed_running)
out = K.reshape(self.gamma, broadcast_shape) * x_normed + K.reshape(self.beta, broadcast_shape)
elif self.mode == 1:
# sample-wise normalization
-2
Ver Arquivo
@@ -85,11 +85,9 @@ class Recurrent(Layer):
If set to "cpu", the RNN will use
an implementation that uses fewer, larger matrix products,
thus running faster on CPU but consuming more memory.
If set to "mem", the RNN will use more matrix products,
but smaller ones, thus running slower (may actually be faster on GPU)
while consuming less memory.
If set to "gpu" (LSTM/GRU only), the RNN will combine the input gate,
the forget gate and the output gate into a single matrix,
enabling more time-efficient parallelization on the GPU. Note: RNN
+24 -7
Ver Arquivo
@@ -11,9 +11,8 @@ from .legacy.models import Graph
def model_from_config(config, custom_objects={}):
from keras.utils.layer_utils import layer_from_config
if isinstance(config, list):
raise Exception('model_fom_config expects a dictionary.'
'To load an old-style config use the appropiate'
'`load_config` method on Sequential or Graph')
raise Exception('`model_fom_config` expects a dictionary, not a list. '
'Maybe you meant to use `Sequential.from_config(config)`?')
return layer_from_config(config, custom_objects=custom_objects)
@@ -462,6 +461,8 @@ class Sequential(Model):
def predict_on_batch(self, x):
'''Returns predictions for a single batch of samples.
'''
if self.model is None:
self.build()
return self.model.predict_on_batch(x)
def train_on_batch(self, x, y, class_weight=None,
@@ -482,6 +483,8 @@ class Sequential(Model):
The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
@@ -512,6 +515,8 @@ class Sequential(Model):
The attribute `model.metrics_names` will give you
the display labels for the scalar outputs.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
if 'accuracy' in kwargs:
kwargs.pop('accuracy')
warnings.warn('The "accuracy" argument is deprecated, '
@@ -697,7 +702,7 @@ class Sequential(Model):
A Numpy array of predictions.
'''
if self.model is None:
raise Exception('The model needs to be compiled before being used.')
self.build()
return self.model.predict_generator(generator, val_samples,
max_q_size=max_q_size)
@@ -725,7 +730,7 @@ class Sequential(Model):
return copy.deepcopy(config)
@classmethod
def from_config(cls, config):
def from_config(cls, config, layer_cache={}):
'''Supports legacy formats
'''
from keras.utils.layer_utils import layer_from_config
@@ -744,8 +749,20 @@ class Sequential(Model):
return new_config
return conf
# the model we will return
model = cls()
def get_or_create_layer(layer_data):
if layer_data['class_name'] == 'Sequential':
return Sequential.from_config(layer_data['config'],
layer_cache=layer_cache)
name = layer_data['config'].get('name')
if name in layer_cache:
return layer_cache[name]
layer = layer_from_config(layer_data)
layer_cache[name] = layer
return layer
first_layer = config[0]
first_layer = normalize_legacy_config(first_layer)
if first_layer['class_name'] == 'Merge':
@@ -758,11 +775,11 @@ class Sequential(Model):
merge = Merge.from_config(first_layer_config)
model.add(merge)
else:
layer = layer_from_config(first_layer)
layer = get_or_create_layer(first_layer)
model.add(layer)
for conf in config[1:]:
conf = normalize_legacy_config(conf)
layer = layer_from_config(conf)
layer = get_or_create_layer(conf)
model.add(layer)
return model
+7
Ver Arquivo
@@ -48,6 +48,12 @@ def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
def kullback_leibler_divergence(y_true, y_pred):
y_true = K.clip(y_true, K.epsilon(), 1)
y_pred = K.clip(y_pred, K.epsilon(), 1)
return K.sum(y_true * K.log(y_true / y_pred), axis=-1)
def poisson(y_true, y_pred):
return K.mean(y_pred - y_true * K.log(y_pred + K.epsilon()), axis=-1)
@@ -63,6 +69,7 @@ mse = MSE = mean_squared_error
mae = MAE = mean_absolute_error
mape = MAPE = mean_absolute_percentage_error
msle = MSLE = mean_squared_logarithmic_error
kld = KLD = kullback_leibler_divergence
cosine = cosine_proximity
from .utils.generic_utils import get_from_module
+245 -86
Ver Arquivo
@@ -1,8 +1,9 @@
'''Fairly basic set of tools for realtime data augmentation on image data.
'''Fairly basic set of tools for real-time data augmentation on image data.
Can easily be extended to include new transformations,
new preprocessing methods, etc...
'''
from __future__ import absolute_import
from __future__ import print_function
import numpy as np
import re
@@ -12,6 +13,8 @@ from six.moves import range
import os
import threading
from .. import backend as K
def random_rotation(x, rg, row_index=1, col_index=2, channel_index=0,
fill_mode='nearest', cval=0.):
@@ -115,7 +118,7 @@ def flip_axis(x, axis):
return x
def array_to_img(x, dim_ordering='th', scale=True):
def array_to_img(x, dim_ordering=K.image_dim_ordering(), scale=True):
from PIL import Image
if dim_ordering == 'th':
x = x.transpose(1, 2, 0)
@@ -133,8 +136,7 @@ def array_to_img(x, dim_ordering='th', scale=True):
raise Exception('Unsupported channel number: ', x.shape[2])
# only used by tests/keras/preprocessing/test_image.py to convert PIL.Image to numpy array
def img_to_array(img, dim_ordering='th'):
def img_to_array(img, dim_ordering=K.image_dim_ordering()):
if dim_ordering not in ['th', 'tf']:
raise Exception('Unknown dim_ordering: ', dim_ordering)
# image has dim_ordering (height, width, channel)
@@ -152,13 +154,15 @@ def img_to_array(img, dim_ordering='th'):
return x
def load_img(path, grayscale=False):
def load_img(path, grayscale=False, target_size=None):
from PIL import Image
img = Image.open(path)
if grayscale:
img = img.convert('L')
else: # Ensure 3 channel even when loaded image is grayscale
img = img.convert('RGB')
if target_size:
img = img.resize(target_size)
return img
@@ -192,8 +196,14 @@ class ImageDataGenerator(object):
'constant'. Default is 0.
horizontal_flip: whether to randomly flip images horizontally.
vertical_flip: whether to randomly flip images vertically.
rescale: rescaling factor. If None or 0, no rescaling is applied,
otherwise we multiply the data by the value provided (before applying
any other transformation).
dim_ordering: 'th' or 'tf'. In 'th' mode, the channels dimension
(the depth) is at index 1, in 'tf' mode it is at index 3.
It defaults to the `image_dim_ordering` value found in your
Keras config file at `~/.keras/keras.json`.
If you never set it, then it will be "th".
'''
def __init__(self,
featurewise_center=False,
@@ -211,23 +221,24 @@ class ImageDataGenerator(object):
cval=0.,
horizontal_flip=False,
vertical_flip=False,
dim_ordering='th'):
rescale=None,
dim_ordering=K.image_dim_ordering()):
self.__dict__.update(locals())
self.mean = None
self.std = None
self.principal_components = None
self.lock = threading.Lock()
self.rescale = rescale
if dim_ordering not in {'tf', 'th'}:
raise Exception('dim_ordering should be "tf" (channel after row and '
'column) or "th" (channel before row and column). '
'Received arg: ', dim_ordering)
self.dim_ordering = dim_ordering
if dim_ordering == "th":
if dim_ordering == 'th':
self.channel_index = 1
self.row_index = 2
self.col_index = 3
if dim_ordering == "tf":
if dim_ordering == 'tf':
self.channel_index = 3
self.row_index = 1
self.col_index = 2
@@ -241,82 +252,30 @@ class ImageDataGenerator(object):
'a tuple or list of two floats. '
'Received arg: ', zoom_range)
self.batch_index = 0
self.total_batches_seen = 0
def reset(self):
self.batch_index = 0
def _flow_index(self, N, batch_size=32, shuffle=False, seed=None):
# ensure self.batch_index is 0
self.reset()
while 1:
if self.batch_index == 0:
index_array = np.arange(N)
if shuffle:
if seed is not None:
np.random.seed(seed + self.total_batches_seen)
index_array = np.random.permutation(N)
current_index = (self.batch_index * batch_size) % N
if N >= current_index + batch_size:
current_batch_size = batch_size
self.batch_index += 1
else:
current_batch_size = N - current_index
self.batch_index = 0
self.total_batches_seen += 1
yield (index_array[current_index: current_index + current_batch_size],
current_index, current_batch_size)
def flow(self, X, y, batch_size=32, shuffle=False, seed=None,
def flow(self, X, y=None, batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
assert len(X) == len(y)
self.X = X
self.y = y
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
self.reset()
self.flow_generator = self._flow_index(X.shape[0], batch_size,
shuffle, seed)
return self
return NumpyArrayIterator(
X, y, self,
batch_size=batch_size, shuffle=shuffle, seed=seed,
dim_ordering=self.dim_ordering,
save_to_dir=save_to_dir, save_prefix=save_prefix, save_format=save_format)
def __iter__(self):
# needed if we want to do something like:
# for x, y in data_gen.flow(...):
return self
def next(self):
# for python 2.x.
# Keeps under lock only the mechanism which advances
# the indexing of each batch
# see # http://anandology.com/blog/using-iterators-and-generators/
with self.lock:
index_array, current_index, current_batch_size = next(self.flow_generator)
# The transformation of images is not under thread lock so it can be done in parallel
bX = np.zeros(tuple([current_batch_size] + list(self.X.shape)[1:]))
for i, j in enumerate(index_array):
x = self.X[j]
x = self.random_transform(x.astype('float32'))
x = self.standardize(x)
bX[i] = x
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(bX[i], self.dim_ordering, scale=True)
fname = '{prefix}_{index}.{format}'.format(prefix=self.save_prefix,
index=current_index + i,
format=self.save_format)
img.save(os.path.join(self.save_to_dir, fname))
bY = self.y[index_array]
return bX, bY
def __next__(self):
# for python 3.x.
return self.next()
def flow_from_directory(self, directory,
target_size=(256, 256), color_mode='rgb',
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
return DirectoryIterator(
directory, self,
target_size=target_size, color_mode=color_mode,
classes=classes, class_mode=class_mode,
dim_ordering=self.dim_ordering,
batch_size=batch_size, shuffle=shuffle, seed=seed,
save_to_dir=save_to_dir, save_prefix=save_prefix, save_format=save_format)
def standardize(self, x):
if self.rescale:
x *= self.rescale
# x is a single image, so it doesn't have image number at index 0
img_channel_index = self.channel_index - 1
if self.samplewise_center:
@@ -438,9 +397,209 @@ class ImageDataGenerator(object):
self.principal_components = np.dot(np.dot(U, np.diag(1. / np.sqrt(S + 10e-7))), U.T)
class GraphImageDataGenerator(ImageDataGenerator):
'''Example of how to build a generator for a Graph model
'''
class Iterator(object):
def __init__(self, N, batch_size, shuffle, seed):
self.N = N
self.batch_size = batch_size
self.shuffle = shuffle
self.batch_index = 0
self.total_batches_seen = 0
self.lock = threading.Lock()
self.index_generator = self._flow_index(N, batch_size, shuffle, seed)
def reset(self):
self.batch_index = 0
def _flow_index(self, N, batch_size=32, shuffle=False, seed=None):
# ensure self.batch_index is 0
self.reset()
while 1:
if self.batch_index == 0:
index_array = np.arange(N)
if shuffle:
if seed is not None:
np.random.seed(seed + self.total_batches_seen)
index_array = np.random.permutation(N)
current_index = (self.batch_index * batch_size) % N
if N >= current_index + batch_size:
current_batch_size = batch_size
self.batch_index += 1
else:
current_batch_size = N - current_index
self.batch_index = 0
self.total_batches_seen += 1
yield (index_array[current_index: current_index + current_batch_size],
current_index, current_batch_size)
def __iter__(self):
# needed if we want to do something like:
# for x, y in data_gen.flow(...):
return self
def __next__(self, *args, **kwargs):
return self.next(*args, **kwargs)
class NumpyArrayIterator(Iterator):
def __init__(self, X, y, image_data_generator,
batch_size=32, shuffle=False, seed=None,
dim_ordering=K.image_dim_ordering(),
save_to_dir=None, save_prefix='', save_format='jpeg'):
if y is not None and len(X) != len(y):
raise Exception('X (images tensor) and y (labels) '
'should have the same length. '
'Found: X.shape = %s, y.shape = %s' % (np.asarray(X).shape, np.asarray(y).shape))
self.X = X
self.y = y
self.image_data_generator = image_data_generator
self.dim_ordering = dim_ordering
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
super(NumpyArrayIterator, self).__init__(X.shape[0], batch_size, shuffle, seed)
def next(self):
bX, bY = super(GraphImageDataGenerator, self).next()
return {'input': bX, 'output': bY}
# for python 2.x.
# Keeps under lock only the mechanism which advances
# the indexing of each batch
# see http://anandology.com/blog/using-iterators-and-generators/
with self.lock:
index_array, current_index, current_batch_size = next(self.index_generator)
# The transformation of images is not under thread lock so it can be done in parallel
batch_x = np.zeros(tuple([current_batch_size] + list(self.X.shape)[1:]))
for i, j in enumerate(index_array):
x = self.X[j]
x = self.image_data_generator.random_transform(x.astype('float32'))
x = self.image_data_generator.standardize(x)
batch_x[i] = x
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(batch_x[i], self.dim_ordering, scale=True)
fname = '{prefix}_{index}_{hash}.{format}'.format(prefix=self.save_prefix,
index=current_index + i,
hash=np.random.randint(1e4),
format=self.save_format)
img.save(os.path.join(self.save_to_dir, fname))
if self.y is None:
return batch_x
batch_y = self.y[index_array]
return batch_x, batch_y
class DirectoryIterator(Iterator):
def __init__(self, directory, image_data_generator,
target_size=(256, 256), color_mode='rgb',
dim_ordering=K.image_dim_ordering,
classes=None, class_mode='categorical',
batch_size=32, shuffle=True, seed=None,
save_to_dir=None, save_prefix='', save_format='jpeg'):
self.directory = directory
self.image_data_generator = image_data_generator
self.target_size = tuple(target_size)
if color_mode not in {'rgb', 'grayscale'}:
raise ValueError('Invalid color mode:', color_mode,
'; expected "rgb" or "grayscale".')
self.color_mode = color_mode
self.dim_ordering = dim_ordering
if self.color_mode == 'rgb':
if self.dim_ordering == 'tf':
self.image_shape = self.target_size + (3,)
else:
self.image_shape = (3,) + self.target_size
else:
if self.dim_ordering == 'tf':
self.image_shape = self.target_size + (1,)
else:
self.image_shape = (1,) + self.target_size
self.classes = classes
if class_mode not in {'categorical', 'binary', 'sparse', None}:
raise ValueError('Invalid class_mode:', class_mode,
'; expected one of "categorical", '
'"binary", "sparse", or None.')
self.class_mode = class_mode
self.save_to_dir = save_to_dir
self.save_prefix = save_prefix
self.save_format = save_format
white_list_formats = {'png', 'jpg', 'jpeg', 'bmp'}
# first, count the number of samples and classes
self.nb_sample = 0
if not classes:
classes = []
for subdir in os.listdir(directory):
if os.path.isdir(os.path.join(directory, subdir)):
classes.append(subdir)
self.nb_class = len(classes)
self.class_indices = dict(zip(classes, range(len(classes))))
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
is_valid = False
for extension in white_list_formats:
if fname.endswith('.' + extension):
is_valid = True
break
if is_valid:
self.nb_sample += 1
print('Found %d images belonging to %d classes.' % (self.nb_sample, self.nb_class))
# second, build an index of the images in the different class subfolders
self.filenames = []
self.classes = np.zeros((self.nb_sample,), dtype='int32')
i = 0
for subdir in classes:
subpath = os.path.join(directory, subdir)
for fname in os.listdir(subpath):
is_valid = False
for extension in white_list_formats:
if fname.endswith('.' + extension):
is_valid = True
break
if is_valid:
self.classes[i] = self.class_indices[subdir]
self.filenames.append(os.path.join(subdir, fname))
i += 1
super(DirectoryIterator, self).__init__(self.nb_sample, batch_size, shuffle, seed)
def next(self):
with self.lock:
index_array, current_index, current_batch_size = next(self.index_generator)
# The transformation of images is not under thread lock so it can be done in parallel
batch_x = np.zeros((current_batch_size,) + self.image_shape)
grayscale = self.color_mode == 'grayscale'
# build batch of image data
for i, j in enumerate(index_array):
fname = self.filenames[j]
img = load_img(os.path.join(self.directory, fname), grayscale=grayscale, target_size=self.target_size)
x = img_to_array(img, dim_ordering=self.dim_ordering)
x = self.image_data_generator.random_transform(x)
x = self.image_data_generator.standardize(x)
batch_x[i] = x
# optionally save augmented images to disk for debugging purposes
if self.save_to_dir:
for i in range(current_batch_size):
img = array_to_img(batch_x[i], self.dim_ordering, scale=True)
fname = '{prefix}_{index}_{hash}.{format}'.format(prefix=self.save_prefix,
index=current_index + i,
hash=np.random.randint(1e4),
format=self.save_format)
img.save(os.path.join(self.save_to_dir, fname))
# build batch of labels
if self.class_mode == 'sparse':
batch_y = self.classes[index_array]
elif self.class_mode == 'binary':
batch_y = self.classes[index_array].astype('float32')
elif self.class_mode == 'categorical':
batch_y = np.zeros((len(batch_x), self.nb_class), dtype='float32')
for i, label in enumerate(self.classes[index_array]):
batch_y[i, label] = 1.
else:
return batch_x
return batch_x, batch_y
+4 -4
Ver Arquivo
@@ -41,8 +41,8 @@ class WeightRegularizer(Regularizer):
def get_config(self):
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
'l1': float(self.l1),
'l2': float(self.l2)}
class ActivityRegularizer(Regularizer):
@@ -68,8 +68,8 @@ class ActivityRegularizer(Regularizer):
def get_config(self):
return {'name': self.__class__.__name__,
'l1': self.l1,
'l2': self.l2}
'l1': float(self.l1),
'l2': float(self.l2)}
def l1(l=0.01):
+11 -2
Ver Arquivo
@@ -34,24 +34,28 @@ def make_tuple(*args):
class Progbar(object):
def __init__(self, target, width=30, verbose=1):
def __init__(self, target, width=30, verbose=1, interval=0.01):
'''
@param target: total number of steps expected
@param interval: minimum visual progress update interval (in seconds)
'''
self.width = width
self.target = target
self.sum_values = {}
self.unique_values = []
self.start = time.time()
self.last_update = 0
self.interval = interval
self.total_width = 0
self.seen_so_far = 0
self.verbose = verbose
def update(self, current, values=[]):
def update(self, current, values=[], force=False):
'''
@param current: index of current step
@param values: list of tuples (name, value_for_last_step).
The progress bar will display averages for these values.
@param force: force visual progress update
'''
for k, v in values:
if k not in self.sum_values:
@@ -64,6 +68,9 @@ class Progbar(object):
now = time.time()
if self.verbose == 1:
if not force and (now - self.last_update) < self.interval:
return
prev_total_width = self.total_width
sys.stdout.write("\b" * prev_total_width)
sys.stdout.write("\r")
@@ -127,6 +134,8 @@ class Progbar(object):
info += ' %.4e' % avg
sys.stdout.write(info + "\n")
self.last_update = now
def add(self, n, values=[]):
self.update(self.seen_so_far + n, values)
+5 -3
Ver Arquivo
@@ -35,9 +35,11 @@ def layer_from_config(config, custom_objects={}):
return layer_class.from_config(config['config'])
def print_summary(layers, relevant_nodes=None):
line_length = 100 # total length of printed lines
positions = [35, 55, 67, 100] # absolute positions of log elements in each line
def print_summary(layers, relevant_nodes=None, line_length=100, positions=[.33, .55, .67, 1.]):
# line_length: total length of printed lines
# positions: relative or absolute positions of log elements in each line
if positions[-1] <= 1:
positions = [int(line_length * p) for p in positions]
# header names for the different log elements
to_display = ['Layer (type)', 'Output Shape', 'Param #', 'Connected to']
+7 -4
Ver Arquivo
@@ -9,7 +9,7 @@ if not pydot.find_graphviz():
' and graphviz for `pydotprint` to work.')
def model_to_dot(model, show_shapes=False):
def model_to_dot(model, show_shapes=False, show_layer_names=True):
dot = pydot.Dot()
dot.set('rankdir', 'TB')
dot.set('concentrate', True)
@@ -24,7 +24,10 @@ def model_to_dot(model, show_shapes=False):
# first, populate the nodes of the graph
for layer in layers:
layer_id = str(id(layer))
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
if show_layer_names:
label = str(layer.name) + ' (' + layer.__class__.__name__ + ')'
else:
label = layer.__class__.__name__
if show_shapes:
# Build the label that will actually contain a table with the
@@ -59,6 +62,6 @@ def model_to_dot(model, show_shapes=False):
return dot
def plot(model, to_file='model.png', show_shapes=False):
dot = model_to_dot(model, show_shapes)
def plot(model, to_file='model.png', show_shapes=False, show_layer_names=True):
dot = model_to_dot(model, show_shapes, show_layer_names)
dot.write_png(to_file)
+2 -2
Ver Arquivo
@@ -3,12 +3,12 @@ from setuptools import find_packages
setup(name='Keras',
version='1.0.3',
version='1.0.4',
description='Deep Learning for Python',
author='Francois Chollet',
author_email='francois.chollet@gmail.com',
url='https://github.com/fchollet/keras',
download_url='https://github.com/fchollet/keras/tarball/1.0.3',
download_url='https://github.com/fchollet/keras/tarball/1.0.4',
license='MIT',
install_requires=['theano', 'pyyaml', 'six'],
extras_require={
-2
Ver Arquivo
@@ -515,8 +515,6 @@ def test_sequential_regression():
name='embed_1'))
branch_1.add(LSTM(32, name='lstm_1'))
branch_1.add(BatchNormalization())
branch_2 = Sequential(name='branch_2')
branch_2.add(Dense(32, input_shape=(8,), name='dense_2'))
+19 -20
Ver Arquivo
@@ -24,22 +24,22 @@ def basic_batchnorm_test():
input_shape=(3, 4, 2))
def test_batchnorm_mode_0():
model = Sequential()
norm_m0 = normalization.BatchNormalization(mode=0, input_shape=(10,))
model.add(norm_m0)
model.compile(loss='mse', optimizer='sgd')
def test_batchnorm_mode_0_or_2():
for mode in [0, 2]:
model = Sequential()
norm_m0 = normalization.BatchNormalization(mode=mode, input_shape=(10,))
model.add(norm_m0)
model.compile(loss='mse', optimizer='sgd')
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 10))
model.fit(X, X, nb_epoch=5, verbose=0)
out = norm_m0.call(K.variable(X))
out -= norm_m0.beta
out /= norm_m0.gamma
np_out = K.function([K.learning_phase()], [out])([1.])[0]
# 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)
out = model.predict(X)
out -= K.eval(norm_m0.beta)
out /= K.eval(norm_m0.gamma)
assert_allclose(np_out.mean(), 0.0, atol=1e-1)
assert_allclose(np_out.std(), 1.0, atol=1e-1)
assert_allclose(out.mean(), 0.0, atol=1e-1)
assert_allclose(out.std(), 1.0, atol=1e-1)
def test_batchnorm_mode_0_convnet():
@@ -51,13 +51,12 @@ def test_batchnorm_mode_0_convnet():
# centered on 5.0, variance 10.0
X = np.random.normal(loc=5.0, scale=10.0, size=(1000, 3, 4, 4))
model.fit(X, X, nb_epoch=5, verbose=0)
out = norm_m0.call(K.variable(X))
out -= K.reshape(norm_m0.beta, (1, 3, 1, 1))
out /= K.reshape(norm_m0.gamma, (1, 3, 1, 1))
np_out = K.function([K.learning_phase()], [out])([1.])[0]
out = model.predict(X)
out -= np.reshape(K.eval(norm_m0.beta), (1, 3, 1, 1))
out /= np.reshape(K.eval(norm_m0.gamma), (1, 3, 1, 1))
assert_allclose(np.mean(np_out, axis=(0, 2, 3)), 0.0, atol=1e-1)
assert_allclose(np.std(np_out, axis=(0, 2, 3)), 1.0, atol=1e-1)
assert_allclose(np.mean(out, axis=(0, 2, 3)), 0.0, atol=1e-1)
assert_allclose(np.std(out, axis=(0, 2, 3)), 1.0, atol=1e-1)
def test_batchnorm_mode_1():
+46 -24
Ver Arquivo
@@ -4,8 +4,14 @@ import numpy as np
from keras import initializations
from keras import backend as K
SHAPE = (100, 100)
# 2D tensor test fixture
FC_SHAPE = (100, 100)
# 4D convolution in th order. This shape has the same effective shape as FC_SHAPE
CONV_SHAPE = (25, 25, 2, 2)
# The equivalent shape of both test fixtures
SHAPE = (100, 100)
def _runner(init, shape, target_mean=None, target_std=None,
target_max=None, target_min=None):
@@ -22,62 +28,78 @@ def _runner(init, shape, target_mean=None, target_std=None,
assert abs(output.min() - target_min) < lim
def test_uniform():
_runner(initializations.uniform, SHAPE, target_mean=0.,
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_uniform(tensor_shape):
_runner(initializations.uniform, tensor_shape, target_mean=0.,
target_max=0.05, target_min=-0.05)
def test_normal():
_runner(initializations.normal, SHAPE, target_mean=0., target_std=0.05)
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_normal(tensor_shape):
_runner(initializations.normal, tensor_shape, target_mean=0., target_std=0.05)
def test_lecun_uniform():
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_lecun_uniform(tensor_shape):
scale = np.sqrt(3. / SHAPE[0])
_runner(initializations.lecun_uniform, SHAPE,
_runner(initializations.lecun_uniform, tensor_shape,
target_mean=0., target_max=scale, target_min=-scale)
def test_glorot_uniform():
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_glorot_uniform(tensor_shape):
scale = np.sqrt(6. / (SHAPE[0] + SHAPE[1]))
_runner(initializations.glorot_uniform, SHAPE, target_mean=0.,
_runner(initializations.glorot_uniform, tensor_shape, target_mean=0.,
target_max=scale, target_min=-scale)
def test_glorot_normal():
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_glorot_normal(tensor_shape):
scale = np.sqrt(2. / (SHAPE[0] + SHAPE[1]))
_runner(initializations.glorot_normal, SHAPE,
_runner(initializations.glorot_normal, tensor_shape,
target_mean=0., target_std=scale)
def test_he_uniform():
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_he_uniform(tensor_shape):
scale = np.sqrt(6. / SHAPE[0])
_runner(initializations.he_uniform, SHAPE, target_mean=0.,
_runner(initializations.he_uniform, tensor_shape, target_mean=0.,
target_max=scale, target_min=-scale)
def test_he_normal():
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_he_normal(tensor_shape):
scale = np.sqrt(2. / SHAPE[0])
_runner(initializations.he_normal, SHAPE,
_runner(initializations.he_normal, tensor_shape,
target_mean=0., target_std=scale)
def test_orthogonal():
_runner(initializations.orthogonal, SHAPE,
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_orthogonal(tensor_shape):
_runner(initializations.orthogonal, tensor_shape,
target_mean=0.)
def test_identity():
_runner(initializations.identity, SHAPE,
target_mean=1./SHAPE[0], target_max=1.)
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_identity(tensor_shape):
if len(tensor_shape) > 2:
with pytest.raises(Exception):
_runner(initializations.identity, tensor_shape,
target_mean=1./SHAPE[0], target_max=1.)
else:
_runner(initializations.identity, tensor_shape,
target_mean=1./SHAPE[0], target_max=1.)
def test_zero():
_runner(initializations.zero, SHAPE,
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_zero(tensor_shape):
_runner(initializations.zero, tensor_shape,
target_mean=0., target_max=0.)
def test_one():
_runner(initializations.one, SHAPE,
@pytest.mark.parametrize('tensor_shape', [FC_SHAPE, CONV_SHAPE], ids=['FC', 'CONV'])
def test_one(tensor_shape):
_runner(initializations.one, tensor_shape,
target_mean=1., target_max=1.)
+1
Ver Arquivo
@@ -12,6 +12,7 @@ allobj = [objectives.mean_squared_error,
objectives.squared_hinge,
objectives.hinge, objectives.categorical_crossentropy,
objectives.binary_crossentropy,
objectives.kullback_leibler_divergence,
objectives.poisson,
objectives.cosine_proximity]