Comparar commits
46 Commits
| Autor | SHA1 | Data | |
|---|---|---|---|
| 4fa7e5d454 | |||
| 14f35ab055 | |||
| 9777b51ee2 | |||
| 434545a11f | |||
| e58f0be8f0 | |||
| f85695cb7b | |||
| 66f2613416 | |||
| 793232fe76 | |||
| 3ad7463b60 | |||
| 5ea9f5bdd1 | |||
| 757b3ed1b0 | |||
| c13f890972 | |||
| 99ee2fb09a | |||
| d009ac8fba | |||
| 5c384a1bca | |||
| 0f450fe265 | |||
| c2a7c69f9d | |||
| 676e227b47 | |||
| 1de4bf1b59 | |||
| 7016e8f1d9 | |||
| 0f4fec30f0 | |||
| ff1f796032 | |||
| f1a95869eb | |||
| 4cd3d284e9 | |||
| 0f4be6d17b | |||
| ab3b93e8dd | |||
| 3d400116b9 | |||
| f41d5f021a | |||
| 7174a09d3c | |||
| 180fa47123 | |||
| 1585b8dd4e | |||
| c07d0e6448 | |||
| aabda13a10 | |||
| dcb9fac577 | |||
| 2b674827c3 | |||
| a5a775b79f | |||
| 9736056a60 | |||
| d739b3c2cd | |||
| c751f81d0d | |||
| d675907654 | |||
| 72f1ce4ed4 | |||
| 5d38b04415 | |||
| d7e0621ed3 | |||
| c57d1a3219 | |||
| d87148c56b | |||
| 15338cc3da |
+6
-8
@@ -9,11 +9,11 @@ matrix:
|
||||
env: KERAS_BACKEND=theano TEST_MODE=INTEGRATION_TESTS
|
||||
- python: 2.7
|
||||
env: KERAS_BACKEND=tensorflow
|
||||
- python: 3.4
|
||||
- python: 3.5
|
||||
env: KERAS_BACKEND=tensorflow
|
||||
- python: 2.7
|
||||
env: KERAS_BACKEND=theano
|
||||
- python: 3.4
|
||||
- python: 3.5
|
||||
env: KERAS_BACKEND=theano
|
||||
install:
|
||||
# code below is taken from http://conda.pydata.org/docs/travis.html
|
||||
@@ -34,24 +34,22 @@ install:
|
||||
|
||||
- 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 pytest-xdist coverage==3.7.1 #we need this version of coverage for coveralls.io to work
|
||||
- pip install pep8 pytest-pep8
|
||||
- pip install git+git://github.com/Theano/Theano.git
|
||||
|
||||
# install PIL for preprocessing tests
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||
conda install pil;
|
||||
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
|
||||
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.5" ]]; then
|
||||
conda install Pillow;
|
||||
fi
|
||||
|
||||
- python setup.py install
|
||||
- pip install -e .[tests]
|
||||
|
||||
# install TensorFlow
|
||||
- if [[ "$TRAVIS_PYTHON_VERSION" == "2.7" ]]; then
|
||||
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.1-cp27-none-linux_x86_64.whl;
|
||||
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.4" ]]; then
|
||||
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.1-cp34-cp34m-linux_x86_64.whl;
|
||||
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.5" ]]; then
|
||||
pip install https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.1-cp35-cp35m-linux_x86_64.whl;
|
||||
fi
|
||||
# command to run tests
|
||||
script:
|
||||
|
||||
+1
-1
@@ -43,7 +43,7 @@ We love pull requests. Here's a quick guide:
|
||||
4. Write tests. Your code should have full unit test coverage. If you want to see your PR merged promptly, this is crucial.
|
||||
|
||||
5. Run our test suite locally. It's easy: from the Keras folder, simply run: `py.test tests/`.
|
||||
- You will need to install `pytest`, `coveralls`, `pytest-cov`, `pytest-xdist`: `pip install pytest pytest-cov python-coveralls pytest-xdist pep8 pytest-pep8`
|
||||
- You will need to install the test requirements as well: `pip install -e .[tests]`.
|
||||
|
||||
6. Make sure all tests are passing:
|
||||
- with the Theano backend, on Python 2.7 and Python 3.5
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ Keras uses the following dependencies:
|
||||
*When using the TensorFlow backend:*
|
||||
|
||||
- TensorFlow
|
||||
- [See installation instructions](https://github.com/tensorflow/tensorflow#download-and-setup).
|
||||
- [See installation instructions](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md)
|
||||
|
||||
*When using the Theano backend:*
|
||||
|
||||
|
||||
@@ -89,6 +89,7 @@ from keras.utils import data_utils
|
||||
from keras.utils import io_utils
|
||||
from keras.utils import layer_utils
|
||||
from keras.utils import np_utils
|
||||
from keras.utils import generic_utils
|
||||
|
||||
|
||||
EXCLUDE = {
|
||||
@@ -265,6 +266,11 @@ PAGES = [
|
||||
'page': 'utils/np_utils.md',
|
||||
'all_module_functions': [np_utils]
|
||||
},
|
||||
{
|
||||
'page': 'utils/generic_utils.md',
|
||||
'all_module_functions': [generic_utils],
|
||||
'classes': [generic_utils.CustomObjectScope]
|
||||
},
|
||||
]
|
||||
|
||||
ROOT = 'http://keras.io/'
|
||||
|
||||
@@ -55,6 +55,7 @@ pages:
|
||||
- I/O Utils: utils/io_utils.md
|
||||
- Layer Utils: utils/layer_utils.md
|
||||
- Numpy Utils: utils/np_utils.md
|
||||
- Generic Utils: utils/generic_utils.md
|
||||
|
||||
|
||||
|
||||
|
||||
+18
@@ -2,6 +2,7 @@
|
||||
|
||||
- [How should I cite Keras?](#how-should-i-cite-keras)
|
||||
- [How can I run Keras on GPU?](#how-can-i-run-keras-on-gpu)
|
||||
- [What does \["sample", "batch", "epoch"\] mean?](#what-does-sample-batch-epoch-mean)
|
||||
- [How can I save a Keras model?](#how-can-i-save-a-keras-model)
|
||||
- [Why is the training loss much higher than the testing loss?](#why-is-the-training-loss-much-higher-than-the-testing-loss)
|
||||
- [How can I obtain the output of an intermediate layer?](#how-can-i-obtain-the-output-of-an-intermediate-layer)
|
||||
@@ -31,6 +32,8 @@ Please cite Keras in your publications if it helps your research. Here is an exa
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### How can I run Keras on GPU?
|
||||
|
||||
If you are running on the TensorFlow backend, your code will automatically run on GPU if any available GPU is detected.
|
||||
@@ -54,6 +57,21 @@ theano.config.floatX = 'float32'
|
||||
|
||||
---
|
||||
|
||||
### What does \["sample", "batch", "epoch"\] mean?
|
||||
|
||||
Below are some common definitions that are necessary to know and understand to correctly utilize Keras:
|
||||
|
||||
- **Sample**: one element of a dataset.
|
||||
- *Example:* one image is a **sample** in a convolutional network
|
||||
- *Example:* one audio file is a **sample** for a speech recognition model
|
||||
- **Batch**: a set of *N* samples. The samples in a **batch** are processed independently, in parallel. If training, a batch results in only one update to the model.
|
||||
- A **batch** generally approximates the distribution of the input data better than a single input. The larger the batch, the better the approximation; however, it is also true that the batch will take longer to processes and will still result in only one update. For inference (evaluate/predict), it is recommended to pick a batch size that is as large as you can afford without going out of memory (since larger batches will usually result in faster evaluating/prediction).
|
||||
- **Epoch**: an arbitrary cutoff, generally defined as "one pass over the entire dataset", used to separate training into distinct phases, which is useful for logging and periodic evaluation.
|
||||
- When using `evaluation_data` or `evaluation_split` with the `fit` method of Keras models, evaluation will be run at the end of every **epoch**.
|
||||
- Within Keras, there is the ability to add [callbacks](https://keras.io/callbacks/) specifically designed to be run at the end of an **epoch**. Examples of these are learning rate changes and model checkpointing (saving).
|
||||
|
||||
---
|
||||
|
||||
### How can I save a Keras model?
|
||||
|
||||
*It is not recommended to use pickle or cPickle to save a Keras model.*
|
||||
|
||||
+11
-1
@@ -5,11 +5,21 @@ All Keras layers have a number of methods in common:
|
||||
- `layer.get_weights()`: returns the weights of the layer as a list of Numpy arrays.
|
||||
- `layer.set_weights(weights)`: sets the weights of the layer from a list of Numpy arrays (with the same shapes as the output of `get_weights`).
|
||||
- `layer.get_config()`: returns a dictionary containing the configuration of the layer. The layer can be reinstantiated from its config via:
|
||||
|
||||
```python
|
||||
layer = Dense(32)
|
||||
config = layer.get_config()
|
||||
reconstructed_layer = Dense.from_config(config)
|
||||
```
|
||||
|
||||
Or:
|
||||
|
||||
```python
|
||||
from keras.utils.layer_utils import layer_from_config
|
||||
|
||||
config = layer.get_config()
|
||||
layer = layer_from_config(config)
|
||||
layer = layer_from_config({'class_name': layer.__class__.__name__,
|
||||
'config': config})
|
||||
```
|
||||
|
||||
If a layer has a single node (i.e. if it isn't a shared layer), you can get its input tensor, output tensor, input shape and output shape via:
|
||||
|
||||
+1
-1
@@ -78,7 +78,7 @@ Generate batches of tensor image data with real-time data augmentation. The data
|
||||
- __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.
|
||||
Any PNG, JPG or BNP images inside each of the subdirectories directory tree will be included in the generator.
|
||||
Any PNG, JPG or BMP images inside each of the subdirectories directory tree will be included in the generator.
|
||||
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.
|
||||
|
||||
+66
-33
@@ -35,22 +35,29 @@ from six.moves import range
|
||||
|
||||
|
||||
class CharacterTable(object):
|
||||
'''
|
||||
Given a set of characters:
|
||||
"""Given a set of characters:
|
||||
+ Encode them to a one hot integer representation
|
||||
+ Decode the one hot integer representation to their character output
|
||||
+ Decode a vector of probabilities to their character output
|
||||
'''
|
||||
"""
|
||||
def __init__(self, chars):
|
||||
"""Initialize character table.
|
||||
|
||||
def __init__(self, chars, maxlen):
|
||||
# Arguments
|
||||
chars: Characters that can appear in the input.
|
||||
"""
|
||||
self.chars = sorted(set(chars))
|
||||
self.char_indices = dict((c, i) for i, c in enumerate(self.chars))
|
||||
self.indices_char = dict((i, c) for i, c in enumerate(self.chars))
|
||||
self.maxlen = maxlen
|
||||
|
||||
def encode(self, C, maxlen=None):
|
||||
maxlen = maxlen if maxlen else self.maxlen
|
||||
X = np.zeros((maxlen, len(self.chars)))
|
||||
def encode(self, C, num_rows):
|
||||
"""One hot encode given string C.
|
||||
|
||||
# Arguments
|
||||
num_rows: Number of rows in the returned one hot encoding. This is
|
||||
used to keep the # of rows for each data the same.
|
||||
"""
|
||||
X = np.zeros((num_rows, len(self.chars)))
|
||||
for i, c in enumerate(C):
|
||||
X[i, self.char_indices[c]] = 1
|
||||
return X
|
||||
@@ -66,40 +73,42 @@ class colors:
|
||||
fail = '\033[91m'
|
||||
close = '\033[0m'
|
||||
|
||||
# Parameters for the model and dataset
|
||||
# Parameters for the model and dataset.
|
||||
TRAINING_SIZE = 50000
|
||||
DIGITS = 3
|
||||
INVERT = True
|
||||
# Try replacing GRU, or SimpleRNN
|
||||
RNN = recurrent.LSTM
|
||||
HIDDEN_SIZE = 128
|
||||
BATCH_SIZE = 128
|
||||
LAYERS = 1
|
||||
|
||||
# Maximum length of input is 'int + int' (e.g., '345+678'). Maximum length of
|
||||
# int is DIGITS.
|
||||
MAXLEN = DIGITS + 1 + DIGITS
|
||||
|
||||
# All the numbers, plus sign and space for padding.
|
||||
chars = '0123456789+ '
|
||||
ctable = CharacterTable(chars, MAXLEN)
|
||||
ctable = CharacterTable(chars)
|
||||
|
||||
questions = []
|
||||
expected = []
|
||||
seen = set()
|
||||
print('Generating data...')
|
||||
while len(questions) < TRAINING_SIZE:
|
||||
f = lambda: int(''.join(np.random.choice(list('0123456789')) for i in range(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)
|
||||
# Also skip any such that X+Y == Y+X (hence the sorting).
|
||||
key = tuple(sorted((a, b)))
|
||||
if key in seen:
|
||||
continue
|
||||
seen.add(key)
|
||||
# Pad the data with spaces such that it is always MAXLEN
|
||||
# Pad the data with spaces such that it is always MAXLEN.
|
||||
q = '{}+{}'.format(a, b)
|
||||
query = q + ' ' * (MAXLEN - len(q))
|
||||
ans = str(a + b)
|
||||
# Answers can be of maximum size DIGITS + 1
|
||||
# Answers can be of maximum size DIGITS + 1.
|
||||
ans += ' ' * (DIGITS + 1 - len(ans))
|
||||
if INVERT:
|
||||
# Reverse the query, e.g., '12+345 ' becomes ' 543+21'. (Note the
|
||||
# space used for padding.)
|
||||
query = query[::-1]
|
||||
questions.append(query)
|
||||
expected.append(ans)
|
||||
@@ -109,53 +118,73 @@ print('Vectorization...')
|
||||
X = np.zeros((len(questions), MAXLEN, len(chars)), dtype=np.bool)
|
||||
y = np.zeros((len(questions), DIGITS + 1, len(chars)), dtype=np.bool)
|
||||
for i, sentence in enumerate(questions):
|
||||
X[i] = ctable.encode(sentence, maxlen=MAXLEN)
|
||||
X[i] = ctable.encode(sentence, MAXLEN)
|
||||
for i, sentence in enumerate(expected):
|
||||
y[i] = ctable.encode(sentence, maxlen=DIGITS + 1)
|
||||
y[i] = ctable.encode(sentence, DIGITS + 1)
|
||||
|
||||
# Shuffle (X, y) in unison as the later parts of X will almost all be larger digits
|
||||
# Shuffle (X, y) in unison as the later parts of X will almost all be larger
|
||||
# digits.
|
||||
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
|
||||
# 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))
|
||||
(y_train, y_val) = (y[:split_at], y[split_at:])
|
||||
|
||||
print('Training Data:')
|
||||
print(X_train.shape)
|
||||
print(y_train.shape)
|
||||
|
||||
print('Validation Data:')
|
||||
print(X_val.shape)
|
||||
print(y_val.shape)
|
||||
|
||||
# Try replacing GRU, or SimpleRNN.
|
||||
RNN = recurrent.LSTM
|
||||
HIDDEN_SIZE = 128
|
||||
BATCH_SIZE = 128
|
||||
LAYERS = 1
|
||||
|
||||
print('Build model...')
|
||||
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,
|
||||
# "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=(MAXLEN, len(chars))))
|
||||
# For the decoder's input, we repeat the encoded input for each time step
|
||||
# As the decoder RNN's input, repeatedly provide with the last hidden state of
|
||||
# RNN for each time step. Repeat 'DIGITS + 1' times as that's the maximum
|
||||
# length of output, e.g., when DIGITS=3, max output is 999+999=1998.
|
||||
model.add(RepeatVector(DIGITS + 1))
|
||||
# The decoder RNN could be multiple layers stacked or a single layer
|
||||
# The decoder RNN could be multiple layers stacked or a single layer.
|
||||
for _ in range(LAYERS):
|
||||
# By setting return_sequences to True, return not only the last output but
|
||||
# all the outputs so far in the form of (nb_samples, timesteps,
|
||||
# output_dim). This is necessary as TimeDistributed in the below expects
|
||||
# the first dimension to be the timesteps.
|
||||
model.add(RNN(HIDDEN_SIZE, return_sequences=True))
|
||||
|
||||
# For each of step of the output sequence, decide which character should be chosen
|
||||
# Apply a dense layer to the every temporal slice of an input. For each of step
|
||||
# of the output sequence, decide which character should be chosen.
|
||||
model.add(TimeDistributed(Dense(len(chars))))
|
||||
model.add(Activation('softmax'))
|
||||
|
||||
model.compile(loss='categorical_crossentropy',
|
||||
optimizer='adam',
|
||||
metrics=['accuracy'])
|
||||
model.summary()
|
||||
|
||||
# Train the model each generation and show predictions against the validation dataset
|
||||
# Train the model each generation and show predictions against the validation
|
||||
# dataset.
|
||||
for iteration in range(1, 200):
|
||||
print()
|
||||
print('-' * 50)
|
||||
print('Iteration', iteration)
|
||||
model.fit(X_train, y_train, batch_size=BATCH_SIZE, nb_epoch=1,
|
||||
validation_data=(X_val, y_val))
|
||||
###
|
||||
# Select 10 samples from the validation set at random so we can visualize errors
|
||||
# Select 10 samples from the validation set at random so we can visualize
|
||||
# errors.
|
||||
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])]
|
||||
@@ -165,5 +194,9 @@ for iteration in range(1, 200):
|
||||
guess = ctable.decode(preds[0], calc_argmax=False)
|
||||
print('Q', q[::-1] if INVERT else q)
|
||||
print('T', correct)
|
||||
print(colors.ok + '☑' + colors.close if correct == guess else colors.fail + '☒' + colors.close, guess)
|
||||
if correct == guess:
|
||||
print(colors.ok + '☑' + colors.close, end=" ")
|
||||
else:
|
||||
print(colors.fail + '☒' + colors.close, end=" ")
|
||||
print(guess)
|
||||
print('---')
|
||||
|
||||
+14
-14
@@ -37,8 +37,8 @@ base_image_path = args.base_image_path
|
||||
result_prefix = args.result_prefix
|
||||
|
||||
# dimensions of the generated picture.
|
||||
img_width = 600
|
||||
img_height = 600
|
||||
img_width = 600
|
||||
|
||||
# path to the model weights file.
|
||||
weights_path = 'vgg16_weights.h5'
|
||||
@@ -64,7 +64,7 @@ settings = saved_settings['dreamy']
|
||||
|
||||
|
||||
def preprocess_image(image_path):
|
||||
img = load_img(image_path, target_size=(img_width, img_height))
|
||||
img = load_img(image_path, target_size=(img_height, img_width))
|
||||
img = img_to_array(img)
|
||||
img = np.expand_dims(img, axis=0)
|
||||
img = vgg16.preprocess_input(img)
|
||||
@@ -75,10 +75,10 @@ def preprocess_image(image_path):
|
||||
|
||||
def deprocess_image(x):
|
||||
if K.image_dim_ordering() == 'th':
|
||||
x = x.reshape((3, img_width, img_height))
|
||||
x = x.reshape((3, img_height, img_width))
|
||||
x = x.transpose((1, 2, 0))
|
||||
else:
|
||||
x = x.reshape((img_width, img_height, 3))
|
||||
x = x.reshape((img_height, img_width, 3))
|
||||
# Remove zero-center by mean pixel
|
||||
x[:, :, 0] += 103.939
|
||||
x[:, :, 1] += 116.779
|
||||
@@ -89,9 +89,9 @@ def deprocess_image(x):
|
||||
return x
|
||||
|
||||
if K.image_dim_ordering() == 'th':
|
||||
img_size = (3, img_width, img_height)
|
||||
img_size = (3, img_height, img_width)
|
||||
else:
|
||||
img_size = (img_width, img_height, 3)
|
||||
img_size = (img_height, img_width, 3)
|
||||
# this will contain our generated image
|
||||
dream = Input(batch_shape=(1,) + img_size)
|
||||
|
||||
@@ -110,15 +110,15 @@ layer_dict = dict([(layer.name, layer) for layer in model.layers])
|
||||
def continuity_loss(x):
|
||||
assert K.ndim(x) == 4
|
||||
if K.image_dim_ordering() == 'th':
|
||||
a = K.square(x[:, :, :img_width - 1, :img_height - 1] -
|
||||
x[:, :, 1:, :img_height - 1])
|
||||
b = K.square(x[:, :, :img_width - 1, :img_height - 1] -
|
||||
x[:, :, :img_width - 1, 1:])
|
||||
a = K.square(x[:, :, :img_height - 1, :img_width - 1] -
|
||||
x[:, :, 1:, :img_width - 1])
|
||||
b = K.square(x[:, :, :img_height - 1, :img_width - 1] -
|
||||
x[:, :, :img_height - 1, 1:])
|
||||
else:
|
||||
a = K.square(x[:, :img_width - 1, :img_height - 1, :] -
|
||||
x[:, 1:, :img_height - 1, :])
|
||||
b = K.square(x[:, :img_width - 1, :img_height - 1, :] -
|
||||
x[:, :img_width - 1, 1:, :])
|
||||
a = K.square(x[:, :img_height - 1, :img_width - 1, :] -
|
||||
x[:, 1:, :img_width - 1, :])
|
||||
b = K.square(x[:, :img_height - 1, :img_width - 1, :] -
|
||||
x[:, :img_height - 1, 1:, :])
|
||||
return K.sum(K.pow(a + b, 1.25))
|
||||
|
||||
# define the loss
|
||||
|
||||
@@ -75,7 +75,7 @@ def create_base_network(input_dim):
|
||||
def compute_accuracy(predictions, labels):
|
||||
'''Compute classification accuracy with a fixed threshold on distances.
|
||||
'''
|
||||
return np.mean(labels == (predictions.ravel() > 0.5))
|
||||
return labels[predictions.ravel() < 0.5].mean()
|
||||
|
||||
|
||||
# the data, shuffled and split between train and test sets
|
||||
|
||||
@@ -13,6 +13,7 @@ from keras.layers import Dense, Dropout, Activation, Flatten
|
||||
from keras.layers import Convolution2D, MaxPooling2D
|
||||
from keras.utils import np_utils
|
||||
from keras.wrappers.scikit_learn import KerasClassifier
|
||||
from keras import backend as K
|
||||
from sklearn.grid_search import GridSearchCV
|
||||
|
||||
|
||||
@@ -23,8 +24,16 @@ img_rows, img_cols = 28, 28
|
||||
|
||||
# load training data and do basic data normalization
|
||||
(X_train, y_train), (X_test, y_test) = mnist.load_data()
|
||||
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
|
||||
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
|
||||
|
||||
if K.image_dim_ordering() == 'th':
|
||||
X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols)
|
||||
X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols)
|
||||
input_shape = (1, img_rows, img_cols)
|
||||
else:
|
||||
X_train = X_train.reshape(X_train.shape[0], img_rows, img_cols, 1)
|
||||
X_test = X_test.reshape(X_test.shape[0], img_rows, img_cols, 1)
|
||||
input_shape = (img_rows, img_cols, 1)
|
||||
|
||||
X_train = X_train.astype('float32')
|
||||
X_test = X_test.astype('float32')
|
||||
X_train /= 255
|
||||
@@ -48,7 +57,7 @@ def make_model(dense_layer_sizes, nb_filters, nb_conv, nb_pool):
|
||||
|
||||
model.add(Convolution2D(nb_filters, nb_conv, nb_conv,
|
||||
border_mode='valid',
|
||||
input_shape=(1, img_rows, img_cols)))
|
||||
input_shape=input_shape))
|
||||
model.add(Activation('relu'))
|
||||
model.add(Convolution2D(nb_filters, nb_conv, nb_conv))
|
||||
model.add(Activation('relu'))
|
||||
|
||||
@@ -102,9 +102,9 @@ print('Preparing embedding matrix.')
|
||||
|
||||
# prepare embedding matrix
|
||||
nb_words = min(MAX_NB_WORDS, len(word_index))
|
||||
embedding_matrix = np.zeros((nb_words + 1, EMBEDDING_DIM))
|
||||
embedding_matrix = np.zeros((nb_words, EMBEDDING_DIM))
|
||||
for word, i in word_index.items():
|
||||
if i > MAX_NB_WORDS:
|
||||
if i >= MAX_NB_WORDS:
|
||||
continue
|
||||
embedding_vector = embeddings_index.get(word)
|
||||
if embedding_vector is not None:
|
||||
@@ -113,7 +113,7 @@ for word, i in word_index.items():
|
||||
|
||||
# load pre-trained word embeddings into an Embedding layer
|
||||
# note that we set trainable = False so as to keep the embeddings fixed
|
||||
embedding_layer = Embedding(nb_words + 1,
|
||||
embedding_layer = Embedding(nb_words,
|
||||
EMBEDDING_DIM,
|
||||
weights=[embedding_matrix],
|
||||
input_length=MAX_SEQUENCE_LENGTH,
|
||||
|
||||
+1
-1
@@ -15,4 +15,4 @@ from . import objectives
|
||||
from . import optimizers
|
||||
from . import regularizers
|
||||
|
||||
__version__ = '1.2.1'
|
||||
__version__ = '1.2.2'
|
||||
|
||||
@@ -57,12 +57,12 @@ def preprocess_input(audio_path, dim_ordering='default'):
|
||||
if n_sample < n_sample_wanted: # if too short
|
||||
src = np.hstack((src, np.zeros((int(duration * sr) - n_sample,))))
|
||||
elif n_sample > n_sample_wanted: # if too long
|
||||
src = src[(n_sample - n_sample_wanted) / 2:
|
||||
(n_sample + n_sample_wanted) / 2]
|
||||
src = src[(n_sample - n_sample_wanted) // 2:
|
||||
(n_sample + n_sample_wanted) // 2]
|
||||
|
||||
logam = librosa.logamplitude
|
||||
melgram = librosa.feature.melspectrogram
|
||||
x = logam(melgram(y=src, sr=sr, hop_lengthgth=hop_length,
|
||||
x = logam(melgram(y=src, sr=sr, hop_length=hop_length,
|
||||
n_fft=n_fft, n_mels=n_mels) ** 2,
|
||||
ref_power=1.0)
|
||||
|
||||
|
||||
@@ -28,6 +28,10 @@ _GRAPH_LEARNING_PHASES = {}
|
||||
# Change its value via `manual_variable_initialization(value)`.
|
||||
_MANUAL_VAR_INIT = False
|
||||
|
||||
# These two integers contain the tensorflow version for coping with API breaks.
|
||||
tf_major_version = int(tf.__version__.split('.')[0])
|
||||
tf_minor_version = int(tf.__version__.split('.')[1])
|
||||
|
||||
|
||||
def clear_session():
|
||||
"""Destroys the current TF graph and creates a new one.
|
||||
@@ -77,6 +81,9 @@ def learning_phase():
|
||||
def set_learning_phase(value):
|
||||
"""Sets the learning phase to a fixed value,
|
||||
either 0 or 1 (integers).
|
||||
|
||||
# Raises
|
||||
ValueError: if `value` is neither `0` nor `1`.
|
||||
"""
|
||||
global _GRAPH_LEARNING_PHASES
|
||||
if value not in {0, 1}:
|
||||
@@ -237,9 +244,14 @@ def variable(value, dtype=None, name=None):
|
||||
sparse_coo = value.tocoo()
|
||||
indices = np.concatenate((np.expand_dims(sparse_coo.row, 1),
|
||||
np.expand_dims(sparse_coo.col, 1)), 1)
|
||||
v = tf.SparseTensor(indices=indices,
|
||||
values=sparse_coo.data,
|
||||
shape=sparse_coo.shape)
|
||||
if tf_major_version >= 1:
|
||||
v = tf.SparseTensor(indices=indices,
|
||||
values=sparse_coo.data,
|
||||
dense_shape=sparse_coo.shape)
|
||||
else:
|
||||
v = tf.SparseTensor(indices=indices,
|
||||
values=sparse_coo.data,
|
||||
shape=sparse_coo.shape)
|
||||
v._dims = len(sparse_coo.shape)
|
||||
v._keras_shape = sparse_coo.shape
|
||||
v._uses_learning_phase = False
|
||||
@@ -711,7 +723,8 @@ def cast(x, dtype):
|
||||
# you need to assign it.
|
||||
>>> input = K.cast(input, dtype='float16')
|
||||
>>> input
|
||||
<tf.Tensor 'Cast_2:0' shape=(2, 3) dtype=float16> ```
|
||||
<tf.Tensor 'Cast_2:0' shape=(2, 3) dtype=float16>
|
||||
```
|
||||
"""
|
||||
return tf.cast(x, dtype)
|
||||
|
||||
@@ -827,7 +840,6 @@ def batch_dot(x, y, axes=None):
|
||||
|
||||
# Arguments
|
||||
x, y: Keras tensors or variables with `ndim >= 2`
|
||||
(With TensorFlow backend, `batch_dot()` only supports `ndim >= 3`)
|
||||
axes: list of (or single) int with target dimensions.
|
||||
The lengths of `axes[0]` and `axes[1]` should be the same.
|
||||
|
||||
@@ -868,20 +880,32 @@ def batch_dot(x, y, axes=None):
|
||||
"""
|
||||
if isinstance(axes, int):
|
||||
axes = (axes, axes)
|
||||
if axes is not None:
|
||||
adj_x = None if axes[0] == ndim(x) - 1 else True
|
||||
adj_y = True if axes[1] == ndim(y) - 1 else None
|
||||
if ndim(x) == 2 and ndim(y) == 2:
|
||||
if tf_major_version >= 1:
|
||||
if axes[0] == axes[1]:
|
||||
out = tf.reduce_sum(tf.multiply(x, y), axes[0])
|
||||
else:
|
||||
out = tf.reduce_sum(tf.multiply(tf.transpose(x, [1, 0]), y), axes[1])
|
||||
else:
|
||||
if axes[0] == axes[1]:
|
||||
out = tf.reduce_sum(tf.mul(x, y), axes[0])
|
||||
else:
|
||||
out = tf.reduce_sum(tf.mul(tf.transpose(x, [1, 0]), y), axes[1])
|
||||
else:
|
||||
adj_x = None
|
||||
adj_y = None
|
||||
# TODO: remove later.
|
||||
if hasattr(tf, 'batch_matmul'):
|
||||
try:
|
||||
out = tf.batch_matmul(x, y, adj_a=adj_x, adj_b=adj_y)
|
||||
except TypeError:
|
||||
out = tf.batch_matmul(x, y, adj_x=adj_x, adj_y=adj_y)
|
||||
else:
|
||||
out = tf.matmul(x, y, adjoint_a=adj_x, adjoint_b=adj_y)
|
||||
if axes is not None:
|
||||
adj_x = None if axes[0] == ndim(x) - 1 else True
|
||||
adj_y = True if axes[1] == ndim(y) - 1 else None
|
||||
else:
|
||||
adj_x = None
|
||||
adj_y = None
|
||||
# TODO: remove later.
|
||||
if hasattr(tf, 'batch_matmul'):
|
||||
try:
|
||||
out = tf.batch_matmul(x, y, adj_a=adj_x, adj_b=adj_y)
|
||||
except TypeError:
|
||||
out = tf.batch_matmul(x, y, adj_x=adj_x, adj_y=adj_y)
|
||||
else:
|
||||
out = tf.matmul(x, y, adjoint_a=adj_x, adjoint_b=adj_y)
|
||||
if ndim(out) == 1:
|
||||
out = expand_dims(out, 1)
|
||||
return out
|
||||
@@ -1421,10 +1445,13 @@ def concatenate(tensors, axis=-1):
|
||||
if py_all([is_sparse(x) for x in tensors]):
|
||||
return tf.sparse_concat(axis, tensors)
|
||||
else:
|
||||
try:
|
||||
return tf.concat_v2([to_dense(x) for x in tensors], axis)
|
||||
except AttributeError:
|
||||
return tf.concat(axis, [to_dense(x) for x in tensors])
|
||||
if tf_major_version >= 1:
|
||||
return tf.concat([to_dense(x) for x in tensors], axis)
|
||||
else:
|
||||
try:
|
||||
return tf.concat_v2([to_dense(x) for x in tensors], axis)
|
||||
except AttributeError:
|
||||
return tf.concat(axis, [to_dense(x) for x in tensors])
|
||||
|
||||
|
||||
def reshape(x, shape):
|
||||
@@ -1458,6 +1485,9 @@ def resize_images(X, height_factor, width_factor, dim_ordering):
|
||||
|
||||
# Returns
|
||||
A tensor.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'th':
|
||||
original_shape = int_shape(X)
|
||||
@@ -1490,6 +1520,9 @@ def resize_volumes(X, depth_factor, height_factor, width_factor, dim_ordering):
|
||||
|
||||
# Returns
|
||||
A tensor.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'th':
|
||||
output = repeat_elements(X, depth_factor, axis=2)
|
||||
@@ -1643,6 +1676,9 @@ def spatial_2d_padding(x, padding=(1, 1), dim_ordering='default'):
|
||||
|
||||
# Returns
|
||||
A padded 4D tensor.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -1668,6 +1704,9 @@ def asymmetric_spatial_2d_padding(x, top_pad=1, bottom_pad=1,
|
||||
|
||||
# Returns
|
||||
A padded 4D tensor.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -1696,6 +1735,10 @@ def spatial_3d_padding(x, padding=(1, 1, 1), dim_ordering='default'):
|
||||
|
||||
# Returns
|
||||
A padded 5D tensor.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -1963,8 +2006,7 @@ def rnn(step_function, inputs, initial_states,
|
||||
mask: binary tensor with shape `(samples, time, 1)`,
|
||||
with a zero for every element that is masked.
|
||||
constants: a list of constant values passed at each step.
|
||||
unroll: with TensorFlow the RNN is always unrolled, but with Theano you
|
||||
can use this boolean flag to unroll the RNN.
|
||||
unroll: whether to unroll the RNN or to use a symbolic loop (`while_loop` or `scan` depending on backend).
|
||||
input_length: not relevant in the TensorFlow implementation.
|
||||
Must be specified if using unrolling with Theano.
|
||||
|
||||
@@ -1977,6 +2019,12 @@ def rnn(step_function, inputs, initial_states,
|
||||
at time `t` for sample `s`.
|
||||
new_states: list of tensors, latest states returned by
|
||||
the step function, of shape `(samples, ...)`.
|
||||
|
||||
# Raises
|
||||
ValueError: if input dimension is less than 3.
|
||||
ValueError: if `unroll` is `True` but input timestep is not a fixed number.
|
||||
ValueError: if `mask` is provided (not `None`) but states is not provided
|
||||
(`len(states)` == 0).
|
||||
"""
|
||||
ndim = len(inputs.get_shape())
|
||||
if ndim < 3:
|
||||
@@ -2205,9 +2253,15 @@ def in_train_phase(x, alt):
|
||||
Either `x` or `alt` based on `K.learning_phase`.
|
||||
"""
|
||||
if learning_phase() is 1:
|
||||
return x
|
||||
if callable(x):
|
||||
return x()
|
||||
else:
|
||||
return x
|
||||
elif learning_phase() is 0:
|
||||
return alt
|
||||
if callable(alt):
|
||||
return alt()
|
||||
else:
|
||||
return alt
|
||||
# else: assume learning phase is a placeholder tensor.
|
||||
x = switch(learning_phase(), x, alt)
|
||||
x._uses_learning_phase = True
|
||||
@@ -2222,9 +2276,15 @@ def in_test_phase(x, alt):
|
||||
Either `x` or `alt` based on `K.learning_phase`.
|
||||
"""
|
||||
if learning_phase() is 1:
|
||||
return alt
|
||||
if callable(alt):
|
||||
return alt()
|
||||
else:
|
||||
return alt
|
||||
elif learning_phase() is 0:
|
||||
return x
|
||||
if callable(x):
|
||||
return x()
|
||||
else:
|
||||
return x
|
||||
# else: assume learning phase is a placeholder tensor.
|
||||
x = switch(learning_phase(), alt, x)
|
||||
x._uses_learning_phase = True
|
||||
@@ -2494,6 +2554,7 @@ def _preprocess_deconv_output_shape(x, shape, dim_ordering):
|
||||
|
||||
if shape[0] is None:
|
||||
shape = (tf.shape(x)[0], ) + tuple(shape[1:])
|
||||
shape = tf.stack(list(shape))
|
||||
return shape
|
||||
|
||||
|
||||
@@ -2613,6 +2674,9 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
|
||||
|
||||
# Returns
|
||||
A tensor, result of 2D convolution.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2650,6 +2714,9 @@ def deconv2d(x, kernel, output_shape, strides=(1, 1),
|
||||
|
||||
# Returns
|
||||
A tensor, result of transposed 2D convolution.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2687,6 +2754,9 @@ def atrous_conv2d(x, kernel, rate=1,
|
||||
|
||||
# Returns
|
||||
A tensor, result of atrous transposed 2D convolution.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2707,6 +2777,9 @@ def atrous_conv2d(x, kernel, rate=1,
|
||||
def separable_conv2d(x, depthwise_kernel, pointwise_kernel, strides=(1, 1),
|
||||
border_mode='valid', dim_ordering='default'):
|
||||
"""2-D convolution with separable filters.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2741,6 +2814,9 @@ def conv3d(x, kernel, strides=(1, 1, 1),
|
||||
|
||||
# Returns
|
||||
A tensor, result of 3D convolution.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2770,6 +2846,10 @@ def pool2d(x, pool_size, strides=(1, 1),
|
||||
|
||||
# Returns
|
||||
A tensor, result of 2D pooling.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
ValueError: if `pool_mode` is neither `max` or `avg`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2805,6 +2885,10 @@ def pool3d(x, pool_size, strides=(1, 1, 1), border_mode='valid',
|
||||
|
||||
# Returns
|
||||
A tensor, result of 3D pooling.
|
||||
|
||||
# Raises
|
||||
ValueError: if `dim_ordering` is neither `tf` or `th`.
|
||||
ValueError: if `pool_mode` is neither `max` or `avg`.
|
||||
"""
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = image_dim_ordering()
|
||||
@@ -2995,8 +3079,12 @@ def ctc_decode(y_pred, input_length, greedy=True, beam_width=100,
|
||||
sequence_length=input_length, beam_width=beam_width,
|
||||
top_paths=top_paths)
|
||||
|
||||
decoded_dense = [tf.sparse_to_dense(st.indices, st.shape, st.values, default_value=-1)
|
||||
for st in decoded]
|
||||
if tf_major_version >= 1:
|
||||
decoded_dense = [tf.sparse_to_dense(st.indices, st.dense_shape, st.values, default_value=-1)
|
||||
for st in decoded]
|
||||
else:
|
||||
decoded_dense = [tf.sparse_to_dense(st.indices, st.shape, st.values, default_value=-1)
|
||||
for st in decoded]
|
||||
|
||||
return (decoded_dense, log_prob)
|
||||
|
||||
|
||||
@@ -1008,7 +1008,7 @@ def rnn(step_function, inputs, initial_states,
|
||||
mask: binary tensor with shape (samples, time),
|
||||
with a zero for every element that is masked.
|
||||
constants: a list of constant values passed at each step.
|
||||
unroll: whether to unroll the RNN or to use a symbolic loop (`scan`).
|
||||
unroll: whether to unroll the RNN or to use a symbolic loop (`while_loop` or `scan` depending on backend).
|
||||
input_length: must be specified if using `unroll`.
|
||||
|
||||
# Returns
|
||||
@@ -1075,6 +1075,8 @@ def rnn(step_function, inputs, initial_states,
|
||||
initial_output = step_function(inputs[0], initial_states + constants)[0] * 0
|
||||
# Theano gets confused by broadcasting patterns in the scan op
|
||||
initial_output = T.unbroadcast(initial_output, 0, 1)
|
||||
if len(initial_states) > 0:
|
||||
initial_states[0] = T.unbroadcast(initial_states[0], 0, 1)
|
||||
|
||||
def _step(input, mask, output_tm1, *states):
|
||||
output, new_states = step_function(input, states)
|
||||
@@ -1122,6 +1124,10 @@ def rnn(step_function, inputs, initial_states,
|
||||
output, new_states = step_function(input, states)
|
||||
return [output] + new_states
|
||||
|
||||
# Theano likes to make shape==1 dimensions in the initial states (outputs_info) broadcastable
|
||||
if len(initial_states) > 0:
|
||||
initial_states[0] = T.unbroadcast(initial_states[0], 1)
|
||||
|
||||
results, _ = theano.scan(
|
||||
_step,
|
||||
sequences=inputs,
|
||||
@@ -1157,28 +1163,28 @@ def switch(condition, then_expression, else_expression):
|
||||
|
||||
|
||||
def in_train_phase(x, alt):
|
||||
if _LEARNING_PHASE is 1:
|
||||
return x
|
||||
elif _LEARNING_PHASE is 0:
|
||||
return alt
|
||||
if callable(x):
|
||||
x = x()
|
||||
if callable(alt):
|
||||
alt = alt()
|
||||
if _LEARNING_PHASE is 1:
|
||||
return x
|
||||
elif _LEARNING_PHASE is 0:
|
||||
return alt
|
||||
x = theano.ifelse.ifelse(_LEARNING_PHASE, x, alt)
|
||||
x._uses_learning_phase = True
|
||||
return x
|
||||
|
||||
|
||||
def in_test_phase(x, alt):
|
||||
if _LEARNING_PHASE is 1:
|
||||
return alt
|
||||
elif _LEARNING_PHASE is 0:
|
||||
return x
|
||||
if callable(x):
|
||||
x = x()
|
||||
if callable(alt):
|
||||
alt = alt()
|
||||
if _LEARNING_PHASE is 1:
|
||||
return alt
|
||||
elif _LEARNING_PHASE is 0:
|
||||
return x
|
||||
x = theano.ifelse.ifelse(_LEARNING_PHASE, alt, x)
|
||||
x._uses_learning_phase = True
|
||||
return x
|
||||
@@ -1438,24 +1444,24 @@ def _preprocess_conv3d_filter_shape(dim_ordering, filter_shape):
|
||||
return filter_shape
|
||||
|
||||
|
||||
def _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel, strides, dim_ordering):
|
||||
def _postprocess_conv2d_output(conv_out, x, border_mode, kernel_shape, strides, dim_ordering):
|
||||
if border_mode == 'same':
|
||||
if np_kernel.shape[2] % 2 == 0:
|
||||
if kernel_shape[2] % 2 == 0:
|
||||
conv_out = conv_out[:, :, :(x.shape[2] + strides[0] - 1) // strides[0], :]
|
||||
if np_kernel.shape[3] % 2 == 0:
|
||||
if kernel_shape[3] % 2 == 0:
|
||||
conv_out = conv_out[:, :, :, :(x.shape[3] + strides[1] - 1) // strides[1]]
|
||||
if dim_ordering == 'tf':
|
||||
conv_out = conv_out.dimshuffle((0, 2, 3, 1))
|
||||
return conv_out
|
||||
|
||||
|
||||
def _postprocess_conv3d_output(conv_out, x, border_mode, np_kernel, strides, dim_ordering):
|
||||
def _postprocess_conv3d_output(conv_out, x, border_mode, kernel_shape, strides, dim_ordering):
|
||||
if border_mode == 'same':
|
||||
if np_kernel.shape[2] % 2 == 0:
|
||||
if kernel_shape[2] % 2 == 0:
|
||||
conv_out = conv_out[:, :, :(x.shape[2] + strides[0] - 1) // strides[0], :, :]
|
||||
if np_kernel.shape[3] % 2 == 0:
|
||||
if kernel_shape[3] % 2 == 0:
|
||||
conv_out = conv_out[:, :, :, :(x.shape[3] + strides[1] - 1) // strides[1], :]
|
||||
if np_kernel.shape[4] % 2 == 0:
|
||||
if kernel_shape[4] % 2 == 0:
|
||||
conv_out = conv_out[:, :, :, :, :(x.shape[4] + strides[2] - 1) // strides[2]]
|
||||
if dim_ordering == 'tf':
|
||||
conv_out = conv_out.dimshuffle((0, 2, 3, 4, 1))
|
||||
@@ -1495,7 +1501,13 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
|
||||
x = _preprocess_conv2d_input(x, dim_ordering)
|
||||
kernel = _preprocess_conv2d_kernel(kernel, dim_ordering)
|
||||
th_border_mode = _preprocess_border_mode(border_mode)
|
||||
np_kernel = kernel.eval()
|
||||
|
||||
if hasattr(kernel, '_keras_shape'):
|
||||
kernel_shape = kernel._keras_shape
|
||||
else:
|
||||
# Will only work if `kernel` is a shared variable.
|
||||
kernel_shape = kernel.eval().shape
|
||||
|
||||
image_shape = _preprocess_conv2d_image_shape(dim_ordering, image_shape)
|
||||
filter_shape = _preprocess_conv2d_filter_shape(dim_ordering, filter_shape)
|
||||
|
||||
@@ -1519,8 +1531,8 @@ def conv2d(x, kernel, strides=(1, 1), border_mode='valid',
|
||||
filter_shape=filter_shape,
|
||||
filter_dilation=filter_dilation)
|
||||
|
||||
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel,
|
||||
strides, dim_ordering)
|
||||
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode,
|
||||
kernel_shape, strides, dim_ordering)
|
||||
return conv_out
|
||||
|
||||
|
||||
@@ -1552,7 +1564,13 @@ def deconv2d(x, kernel, output_shape, strides=(1, 1),
|
||||
kernel = _preprocess_conv2d_kernel(kernel, dim_ordering)
|
||||
kernel = kernel.dimshuffle((1, 0, 2, 3))
|
||||
th_border_mode = _preprocess_border_mode(border_mode)
|
||||
np_kernel = kernel.eval()
|
||||
|
||||
if hasattr(kernel, '_keras_shape'):
|
||||
kernel_shape = kernel._keras_shape
|
||||
else:
|
||||
# Will only work if `kernel` is a shared variable.
|
||||
kernel_shape = kernel.eval().shape
|
||||
|
||||
filter_shape = _preprocess_conv2d_filter_shape(dim_ordering, filter_shape)
|
||||
filter_shape = tuple(filter_shape[i] for i in (1, 0, 2, 3))
|
||||
|
||||
@@ -1563,8 +1581,8 @@ def deconv2d(x, kernel, output_shape, strides=(1, 1),
|
||||
filter_flip=not flip_filters)
|
||||
conv_out = op(kernel, x, output_shape[2:])
|
||||
|
||||
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode, np_kernel,
|
||||
strides, dim_ordering)
|
||||
conv_out = _postprocess_conv2d_output(conv_out, x, border_mode,
|
||||
kernel_shape, strides, dim_ordering)
|
||||
return conv_out
|
||||
|
||||
|
||||
@@ -1611,7 +1629,13 @@ def conv3d(x, kernel, strides=(1, 1, 1),
|
||||
x = _preprocess_conv3d_input(x, dim_ordering)
|
||||
kernel = _preprocess_conv3d_kernel(kernel, dim_ordering)
|
||||
th_border_mode = _preprocess_border_mode(border_mode)
|
||||
np_kernel = kernel.eval()
|
||||
|
||||
if hasattr(kernel, '_keras_shape'):
|
||||
kernel_shape = kernel._keras_shape
|
||||
else:
|
||||
# Will only work if `kernel` is a shared variable.
|
||||
kernel_shape = kernel.eval().shape
|
||||
|
||||
volume_shape = _preprocess_conv3d_volume_shape(dim_ordering, volume_shape)
|
||||
filter_shape = _preprocess_conv3d_filter_shape(dim_ordering, filter_shape)
|
||||
|
||||
@@ -1622,8 +1646,8 @@ def conv3d(x, kernel, strides=(1, 1, 1),
|
||||
filter_shape=filter_shape,
|
||||
filter_dilation=filter_dilation)
|
||||
|
||||
conv_out = _postprocess_conv3d_output(conv_out, x, border_mode, np_kernel,
|
||||
strides, dim_ordering)
|
||||
conv_out = _postprocess_conv3d_output(conv_out, x, border_mode,
|
||||
kernel_shape, strides, dim_ordering)
|
||||
return conv_out
|
||||
|
||||
|
||||
|
||||
@@ -811,7 +811,7 @@ class CSVLogger(Callback):
|
||||
if self.append:
|
||||
if os.path.exists(self.filename):
|
||||
with open(self.filename) as f:
|
||||
self.append_header = bool(len(f.readline()))
|
||||
self.append_header = not bool(len(f.readline()))
|
||||
self.csv_file = open(self.filename, 'a')
|
||||
else:
|
||||
self.csv_file = open(self.filename, 'w')
|
||||
@@ -828,8 +828,12 @@ class CSVLogger(Callback):
|
||||
|
||||
if not self.writer:
|
||||
self.keys = sorted(logs.keys())
|
||||
|
||||
class CustomDialect(csv.excel):
|
||||
delimiter = self.sep
|
||||
|
||||
self.writer = csv.DictWriter(self.csv_file,
|
||||
fieldnames=['epoch'] + self.keys)
|
||||
fieldnames=['epoch'] + self.keys, dialect=CustomDialect)
|
||||
if self.append_header:
|
||||
self.writer.writeheader()
|
||||
|
||||
@@ -840,6 +844,7 @@ class CSVLogger(Callback):
|
||||
|
||||
def on_train_end(self, logs=None):
|
||||
self.csv_file.close()
|
||||
self.writer = None
|
||||
|
||||
|
||||
class LambdaCallback(Callback):
|
||||
|
||||
@@ -91,6 +91,53 @@ class UnitNorm(Constraint):
|
||||
'axis': self.axis}
|
||||
|
||||
|
||||
class MinMaxNorm(Constraint):
|
||||
"""MinMaxNorm weight constraint.
|
||||
|
||||
Constrains the weights incident to each hidden unit
|
||||
to have the norm between a lower bound and an upper bound.
|
||||
|
||||
# Arguments
|
||||
low: the minimum norm for the incoming weights.
|
||||
high: the maximum norm for the incoming weights.
|
||||
rate: rate for enforcing the constraint: weights will be
|
||||
rescaled to yield (1 - rate) * norm + rate * norm.clip(low, high).
|
||||
Effectively, this means that rate=1.0 stands for strict
|
||||
enforcement of the constraint, while rate<1.0 means that
|
||||
weights will be rescaled at each step to slowly move
|
||||
towards a value inside the desired interval.
|
||||
axis: integer, axis along which to calculate weight norms.
|
||||
For instance, in a `Dense` layer the weight matrix
|
||||
has shape `(input_dim, output_dim)`,
|
||||
set `axis` to `0` to constrain each weight vector
|
||||
of length `(input_dim,)`.
|
||||
In a `Convolution2D` layer with `dim_ordering="tf"`,
|
||||
the weight tensor has shape
|
||||
`(rows, cols, input_depth, output_depth)`,
|
||||
set `axis` to `[0, 1, 2]`
|
||||
to constrain the weights of each filter tensor of size
|
||||
`(rows, cols, input_depth)`.
|
||||
"""
|
||||
def __init__(self, low=0.0, high=1.0, rate=1.0, axis=0):
|
||||
self.low = low
|
||||
self.high = high
|
||||
self.rate = rate
|
||||
self.axis = axis
|
||||
|
||||
def __call__(self, p):
|
||||
norms = K.sqrt(K.sum(K.square(p), axis=self.axis, keepdims=True))
|
||||
desired = self.rate * K.clip(norms, self.low, self.high) + (1 - self.rate) * norms
|
||||
p *= (desired / (K.epsilon() + norms))
|
||||
return p
|
||||
|
||||
def get_config(self):
|
||||
return {'name': self.__class__.__name__,
|
||||
'low': self.low,
|
||||
'high': self.high,
|
||||
'rate': self.rate,
|
||||
'axis': self.axis}
|
||||
|
||||
|
||||
# Aliases.
|
||||
|
||||
maxnorm = MaxNorm
|
||||
|
||||
@@ -49,7 +49,7 @@ def standardize_input_data(data, names, shapes=None,
|
||||
if name not in data:
|
||||
raise ValueError('No data provided for "' +
|
||||
name + '". Need data for each key in: ' +
|
||||
str(data.keys()))
|
||||
str(names))
|
||||
arrays.append(data[name])
|
||||
elif isinstance(data, list):
|
||||
if len(data) != len(names):
|
||||
@@ -724,7 +724,6 @@ class Model(Container):
|
||||
append_metric(i, name, tensor)
|
||||
|
||||
# prepare gradient updates and state updates
|
||||
self.optimizer = optimizers.get(optimizer)
|
||||
self.total_loss = total_loss
|
||||
self.sample_weights = sample_weights
|
||||
|
||||
@@ -1124,7 +1123,12 @@ class Model(Container):
|
||||
elif len(validation_data) == 3:
|
||||
val_x, val_y, val_sample_weight = validation_data
|
||||
else:
|
||||
raise
|
||||
raise ValueError('When passing validation_data, '
|
||||
'it must contain 2 (x_val, y_val) '
|
||||
'or 3 (x_val, y_val, val_sample_weights) '
|
||||
'items, however it contains %d items' %
|
||||
len(validation_data))
|
||||
|
||||
val_x, val_y, val_sample_weights = self._standardize_user_data(
|
||||
val_x, val_y,
|
||||
sample_weight=val_sample_weight,
|
||||
|
||||
@@ -102,9 +102,9 @@ class PReLU(Layer):
|
||||
pos = K.relu(x)
|
||||
if K.backend() == 'theano':
|
||||
neg = (K.pattern_broadcast(self.alphas, self.param_broadcast) *
|
||||
(x - abs(x)) * 0.5)
|
||||
(x - K.abs(x)) * 0.5)
|
||||
else:
|
||||
neg = self.alphas * (x - abs(x)) * 0.5
|
||||
neg = self.alphas * (x - K.abs(x)) * 0.5
|
||||
return pos + neg
|
||||
|
||||
def get_config(self):
|
||||
@@ -331,7 +331,7 @@ class SReLU(Layer):
|
||||
self.a_right = a_right_init(param_shape,
|
||||
name='{}_a_right'.format(self.name))
|
||||
# ensure the the right part is always to the right of the left
|
||||
self.t_right_actual = self.t_left + abs(self.t_right)
|
||||
self.t_right_actual = self.t_left + K.abs(self.t_right)
|
||||
self.trainable_weights = [self.t_left, self.a_left,
|
||||
self.t_right, self.a_right]
|
||||
|
||||
|
||||
@@ -1169,7 +1169,6 @@ class Convolution3D(Layer):
|
||||
|
||||
def build(self, input_shape):
|
||||
assert len(input_shape) == 5
|
||||
self.input_spec = [InputSpec(shape=input_shape)]
|
||||
|
||||
if self.dim_ordering == 'th':
|
||||
stack_size = input_shape[1]
|
||||
@@ -1229,11 +1228,9 @@ class Convolution3D(Layer):
|
||||
raise ValueError('Invalid dim_ordering:', self.dim_ordering)
|
||||
|
||||
def call(self, x, mask=None):
|
||||
input_shape = self.input_spec[0].shape
|
||||
output = K.conv3d(x, self.W, strides=self.subsample,
|
||||
border_mode=self.border_mode,
|
||||
dim_ordering=self.dim_ordering,
|
||||
volume_shape=input_shape,
|
||||
filter_shape=self.W_shape)
|
||||
if self.bias:
|
||||
if self.dim_ordering == 'th':
|
||||
|
||||
@@ -19,6 +19,7 @@ from ..engine import Layer
|
||||
from ..engine import Merge
|
||||
from ..utils.generic_utils import func_dump
|
||||
from ..utils.generic_utils import func_load
|
||||
from ..utils.generic_utils import get_from_module
|
||||
|
||||
|
||||
class Masking(Layer):
|
||||
@@ -676,7 +677,7 @@ class Lambda(Layer):
|
||||
|
||||
function_type = config.pop('function_type')
|
||||
if function_type == 'function':
|
||||
function = globs[config['function']]
|
||||
function = get_from_module(config['function'], globs, 'core')
|
||||
elif function_type == 'lambda':
|
||||
function = func_load(config['function'], globs=globs)
|
||||
else:
|
||||
@@ -684,7 +685,7 @@ class Lambda(Layer):
|
||||
|
||||
output_shape_type = config.pop('output_shape_type')
|
||||
if output_shape_type == 'function':
|
||||
output_shape = globs[config['output_shape']]
|
||||
output_shape = get_from_module(config['output_shape'], globs, 'core')
|
||||
elif output_shape_type == 'lambda':
|
||||
output_shape = func_load(config['output_shape'], globs=globs)
|
||||
else:
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import absolute_import
|
||||
|
||||
from keras import backend as K
|
||||
from keras.layers import activations
|
||||
from keras.layers import initializations
|
||||
from keras.layers import regularizers
|
||||
from keras.layers import constraints
|
||||
from keras.engine import Layer
|
||||
from keras.engine import InputSpec
|
||||
from .. import backend as K
|
||||
from .. import activations
|
||||
from .. import initializations
|
||||
from .. import regularizers
|
||||
from .. import constraints
|
||||
from ..engine import Layer
|
||||
from ..engine import InputSpec
|
||||
from ..utils.np_utils import conv_output_length
|
||||
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import copy
|
||||
from ..engine import Layer
|
||||
from ..engine import InputSpec
|
||||
from .. import backend as K
|
||||
@@ -68,10 +69,7 @@ class TimeDistributed(Wrapper):
|
||||
|
||||
The output will then have shape `(32, 10, 8)`.
|
||||
|
||||
Note this is strictly equivalent to
|
||||
using `layers.core.TimeDistributedDense`.
|
||||
However what is different about `TimeDistributed`
|
||||
is that it can be used with arbitrary layers, not just `Dense`,
|
||||
`TimeDistributed` can be used with arbitrary layers, not just `Dense`,
|
||||
for instance with a `Convolution2D` layer:
|
||||
|
||||
```python
|
||||
@@ -166,7 +164,7 @@ class Bidirectional(Wrapper):
|
||||
raise ValueError('Invalid merge mode. '
|
||||
'Merge mode should be one of '
|
||||
'{"sum", "mul", "ave", "concat", None}')
|
||||
self.forward_layer = layer
|
||||
self.forward_layer = copy.copy(layer)
|
||||
config = layer.get_config()
|
||||
config['go_backwards'] = not config['go_backwards']
|
||||
self.backward_layer = layer.__class__.from_config(config)
|
||||
|
||||
@@ -3,7 +3,7 @@ from __future__ import absolute_import
|
||||
from six.moves import zip
|
||||
|
||||
from . import backend as K
|
||||
from .utils.generic_utils import get_from_module
|
||||
from .utils.generic_utils import get_from_module, get_custom_objects
|
||||
|
||||
if K.backend() == 'tensorflow':
|
||||
import tensorflow as tf
|
||||
@@ -42,6 +42,8 @@ def optimizer_from_config(config, custom_objects=None):
|
||||
class_name = config['class_name']
|
||||
if custom_objects and class_name in custom_objects:
|
||||
cls = custom_objects[class_name]
|
||||
elif class_name in get_custom_objects():
|
||||
cls = get_custom_objects()[class_name]
|
||||
else:
|
||||
if class_name.lower() not in all_classes:
|
||||
raise ValueError('Optimizer class not found:', class_name)
|
||||
@@ -211,6 +213,9 @@ class RMSprop(Optimizer):
|
||||
rho: float >= 0.
|
||||
epsilon: float >= 0. Fuzz factor.
|
||||
decay: float >= 0. Learning rate decay over each update.
|
||||
|
||||
# References
|
||||
- [rmsprop: Divide the gradient by a running average of its recent magnitude](http://www.cs.toronto.edu/~tijmen/csc321/slides/lecture_slides_lec6.pdf)
|
||||
"""
|
||||
|
||||
def __init__(self, lr=0.001, rho=0.9, epsilon=1e-8, decay=0.,
|
||||
|
||||
@@ -210,7 +210,7 @@ def array_to_img(x, dim_ordering='default', scale=True):
|
||||
if pil_image is None:
|
||||
raise ImportError('Could not import PIL.Image. '
|
||||
'The use of `array_to_img` requires PIL.')
|
||||
x = np.asarray(x)
|
||||
x = np.asarray(x, dtype=K.floatx())
|
||||
if x.ndim != 3:
|
||||
raise ValueError('Expected image array to have rank 3 (single image). '
|
||||
'Got array with shape:', x.shape)
|
||||
@@ -249,7 +249,7 @@ def img_to_array(img, dim_ordering='default'):
|
||||
dim_ordering: Image data format.
|
||||
|
||||
# Returns
|
||||
A 3D Numpy array (float32).
|
||||
A 3D Numpy array.
|
||||
|
||||
# Raises
|
||||
ValueError: if invalid `img` or `dim_ordering` is passed.
|
||||
@@ -261,7 +261,7 @@ def img_to_array(img, dim_ordering='default'):
|
||||
# Numpy array x has format (height, width, channel)
|
||||
# or (channel, height, width)
|
||||
# but original PIL image has format (width, height, channel)
|
||||
x = np.asarray(img, dtype='float32')
|
||||
x = np.asarray(img, dtype=K.floatx())
|
||||
if len(x.shape) == 3:
|
||||
if dim_ordering == 'th':
|
||||
x = x.transpose(2, 0, 1)
|
||||
@@ -572,7 +572,7 @@ class ImageDataGenerator(object):
|
||||
# Raises
|
||||
ValueError: in case of invalid input `x`.
|
||||
"""
|
||||
x = np.asarray(x)
|
||||
x = np.asarray(x, dtype=K.floatx())
|
||||
if x.ndim != 4:
|
||||
raise ValueError('Input to `.fit()` should have rank 4. '
|
||||
'Got array with shape: ' + str(x.shape))
|
||||
@@ -590,7 +590,7 @@ class ImageDataGenerator(object):
|
||||
|
||||
x = np.copy(x)
|
||||
if augment:
|
||||
ax = np.zeros(tuple([rounds * x.shape[0]] + list(x.shape)[1:]))
|
||||
ax = np.zeros(tuple([rounds * x.shape[0]] + list(x.shape)[1:]), dtype=K.floatx())
|
||||
for r in range(rounds):
|
||||
for i in range(x.shape[0]):
|
||||
ax[i + r * x.shape[0]] = self.random_transform(x[i])
|
||||
@@ -675,7 +675,7 @@ class NumpyArrayIterator(Iterator):
|
||||
(np.asarray(x).shape, np.asarray(y).shape))
|
||||
if dim_ordering == 'default':
|
||||
dim_ordering = K.image_dim_ordering()
|
||||
self.x = np.asarray(x)
|
||||
self.x = np.asarray(x, dtype=K.floatx())
|
||||
if self.x.ndim != 4:
|
||||
raise ValueError('Input data in `NumpyArrayIterator` '
|
||||
'should have rank 4. You passed an array '
|
||||
@@ -708,10 +708,10 @@ class NumpyArrayIterator(Iterator):
|
||||
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:]))
|
||||
batch_x = np.zeros(tuple([current_batch_size] + list(self.x.shape)[1:]), dtype=K.floatx())
|
||||
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.random_transform(x.astype(K.floatx()))
|
||||
x = self.image_data_generator.standardize(x)
|
||||
batch_x[i] = x
|
||||
if self.save_to_dir:
|
||||
@@ -822,7 +822,7 @@ class DirectoryIterator(Iterator):
|
||||
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)
|
||||
batch_x = np.zeros((current_batch_size,) + self.image_shape, dtype=K.floatx())
|
||||
grayscale = self.color_mode == 'grayscale'
|
||||
# build batch of image data
|
||||
for i, j in enumerate(index_array):
|
||||
@@ -847,9 +847,9 @@ class DirectoryIterator(Iterator):
|
||||
if self.class_mode == 'sparse':
|
||||
batch_y = self.classes[index_array]
|
||||
elif self.class_mode == 'binary':
|
||||
batch_y = self.classes[index_array].astype('float32')
|
||||
batch_y = self.classes[index_array].astype(K.floatx())
|
||||
elif self.class_mode == 'categorical':
|
||||
batch_y = np.zeros((len(batch_x), self.nb_class), dtype='float32')
|
||||
batch_y = np.zeros((len(batch_x), self.nb_class), dtype=K.floatx())
|
||||
for i, label in enumerate(self.classes[index_array]):
|
||||
batch_y[i, label] = 1.
|
||||
else:
|
||||
|
||||
@@ -9,10 +9,91 @@ import six
|
||||
import marshal
|
||||
import types as python_types
|
||||
|
||||
_GLOBAL_CUSTOM_OBJECTS = {}
|
||||
|
||||
|
||||
class CustomObjectScope(object):
|
||||
"""Provides a scope that changes to `_GLOBAL_CUSTOM_OBJECTS` cannot escape.
|
||||
|
||||
Code within a `with` statement will be able to access custom objects
|
||||
by name. Changes to global custom objects persist within the enclosing `with` statement. At end of the `with`
|
||||
statement, global custom objects are reverted to state at beginning of the `with` statement.
|
||||
|
||||
# Example
|
||||
|
||||
Consider a custom object `MyObject`
|
||||
|
||||
```python
|
||||
with CustomObjectScope({"MyObject":MyObject}):
|
||||
layer = Dense(..., W_regularizer="MyObject")
|
||||
# save, load, etc. will recognize custom object by name
|
||||
```
|
||||
"""
|
||||
def __init__(self, *args):
|
||||
self.custom_objects = args
|
||||
self.backup = None
|
||||
|
||||
def __enter__(self):
|
||||
self.backup = _GLOBAL_CUSTOM_OBJECTS.copy()
|
||||
for objects in self.custom_objects:
|
||||
_GLOBAL_CUSTOM_OBJECTS.update(objects)
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, traceback):
|
||||
_GLOBAL_CUSTOM_OBJECTS.clear()
|
||||
_GLOBAL_CUSTOM_OBJECTS.update(self.backup)
|
||||
|
||||
|
||||
def custom_object_scope(*args):
|
||||
"""Provides a scope that changes to `_GLOBAL_CUSTOM_OBJECTS` cannot escape.
|
||||
|
||||
Convenience wrapper for `CustomObjectScope`. Code within a `with` statement will be able to access custom objects
|
||||
by name. Changes to global custom objects persist within the enclosing `with` statement. At end of the `with`
|
||||
statement, global custom objects are reverted to state at beginning of the `with` statement.
|
||||
|
||||
# Example
|
||||
|
||||
Consider a custom object `MyObject`
|
||||
|
||||
```python
|
||||
with custom_object_scope({"MyObject":MyObject}):
|
||||
layer = Dense(..., W_regularizer="MyObject")
|
||||
# save, load, etc. will recognize custom object by name
|
||||
```
|
||||
|
||||
# Arguments
|
||||
*args: Variable length list of dictionaries of name, class pairs to add to custom objects.
|
||||
|
||||
# Returns
|
||||
Object of type `CustomObjectScope`.
|
||||
"""
|
||||
return CustomObjectScope(*args)
|
||||
|
||||
|
||||
def get_custom_objects():
|
||||
"""Retrieves a live reference to the global dictionary of custom objects (`_GLOBAL_CUSTOM_OBJECTS`).
|
||||
|
||||
Updating and clearing custom objects using `custom_object_scope` is preferred, but `get_custom_objects` can
|
||||
be used to directly access `_GLOBAL_CUSTOM_OBJECTS`.
|
||||
|
||||
# Example
|
||||
|
||||
```python
|
||||
get_custom_objects().clear()
|
||||
get_custom_objects()["MyObject"] = MyObject
|
||||
```
|
||||
|
||||
# Returns
|
||||
Global dictionary of names to classes (`_GLOBAL_CUSTOM_OBJECTS`).
|
||||
"""
|
||||
return _GLOBAL_CUSTOM_OBJECTS
|
||||
|
||||
|
||||
def get_from_module(identifier, module_params, module_name,
|
||||
instantiate=False, kwargs=None):
|
||||
"""Retrieves a class of function member of a module.
|
||||
"""Retrieves a class or function member of a module.
|
||||
|
||||
First checks `_GLOBAL_CUSTOM_OBJECTS` for `module_name`, then checks `module_params`.
|
||||
|
||||
# Arguments
|
||||
identifier: the object to retrieve. It could be specified
|
||||
@@ -34,7 +115,11 @@ def get_from_module(identifier, module_params, module_name,
|
||||
ValueError: if the identifier cannot be found.
|
||||
"""
|
||||
if isinstance(identifier, six.string_types):
|
||||
res = module_params.get(identifier)
|
||||
res = None
|
||||
if identifier in _GLOBAL_CUSTOM_OBJECTS:
|
||||
res = _GLOBAL_CUSTOM_OBJECTS[identifier]
|
||||
if not res:
|
||||
res = module_params.get(identifier)
|
||||
if not res:
|
||||
raise ValueError('Invalid ' + str(module_name) + ': ' +
|
||||
str(identifier))
|
||||
@@ -46,7 +131,11 @@ def get_from_module(identifier, module_params, module_name,
|
||||
return res
|
||||
elif isinstance(identifier, dict):
|
||||
name = identifier.pop('name')
|
||||
res = module_params.get(name)
|
||||
res = None
|
||||
if name in _GLOBAL_CUSTOM_OBJECTS:
|
||||
res = _GLOBAL_CUSTOM_OBJECTS[name]
|
||||
if not res:
|
||||
res = module_params.get(name)
|
||||
if res:
|
||||
return res(**identifier)
|
||||
else:
|
||||
@@ -108,7 +197,7 @@ class Progbar(object):
|
||||
interval: Minimum visual progress update interval (in seconds).
|
||||
"""
|
||||
|
||||
def __init__(self, target, width=30, verbose=1, interval=0.01):
|
||||
def __init__(self, target, width=30, verbose=1, interval=0.05):
|
||||
self.width = width
|
||||
self.target = target
|
||||
self.sum_values = {}
|
||||
|
||||
@@ -110,7 +110,7 @@ def save_array(array, name):
|
||||
|
||||
def load_array(name):
|
||||
if tables is None:
|
||||
raise ImportError('The use of `save_array` requires '
|
||||
raise ImportError('The use of `load_array` requires '
|
||||
'the tables module.')
|
||||
f = tables.open_file(name)
|
||||
array = f.root.data
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from __future__ import print_function
|
||||
import inspect
|
||||
|
||||
from .generic_utils import get_from_module
|
||||
from .generic_utils import get_from_module, get_custom_objects
|
||||
from .np_utils import convert_kernel
|
||||
from ..layers import *
|
||||
from ..models import Model, Sequential
|
||||
@@ -22,8 +22,7 @@ def layer_from_config(config, custom_objects=None):
|
||||
# Insert custom layers into globals so they can
|
||||
# be accessed by `get_from_module`.
|
||||
if custom_objects:
|
||||
for cls_key in custom_objects:
|
||||
globals()[cls_key] = custom_objects[cls_key]
|
||||
get_custom_objects().update(custom_objects)
|
||||
|
||||
class_name = config['class_name']
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class BaseWrapper(object):
|
||||
if params_name not in legal_params:
|
||||
raise ValueError('{} is not a legal parameter'.format(params_name))
|
||||
|
||||
def get_params(self, _):
|
||||
def get_params(self, **params):
|
||||
"""Gets parameters for this estimator.
|
||||
|
||||
# Returns
|
||||
|
||||
+8
-2
@@ -3,16 +3,22 @@ from setuptools import find_packages
|
||||
|
||||
|
||||
setup(name='Keras',
|
||||
version='1.2.1',
|
||||
version='1.2.2',
|
||||
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.2.1',
|
||||
download_url='https://github.com/fchollet/keras/tarball/1.2.2',
|
||||
license='MIT',
|
||||
install_requires=['theano', 'pyyaml', 'six'],
|
||||
extras_require={
|
||||
'h5py': ['h5py'],
|
||||
'visualize': ['pydot-ng'],
|
||||
'tests': ['pytest',
|
||||
'pytest-cov',
|
||||
'pytest-pep8',
|
||||
'pytest-xdist',
|
||||
'python-coveralls',
|
||||
'coverage==3.7.1'],
|
||||
},
|
||||
packages=find_packages())
|
||||
|
||||
@@ -77,10 +77,27 @@ class TestBackend(object):
|
||||
|
||||
check_two_tensor_operation('batch_dot', (4, 2, 3), (4, 5, 3),
|
||||
axes=(2, 2))
|
||||
check_two_tensor_operation('batch_dot', (32, 20), (32, 20), axes=1)
|
||||
check_two_tensor_operation('batch_dot', (32, 20), (32, 20), axes=(1, 1))
|
||||
check_single_tensor_operation('transpose', (4, 2))
|
||||
check_single_tensor_operation('reverse', (4, 3, 2), axes=1)
|
||||
check_single_tensor_operation('reverse', (4, 3, 2), axes=(1, 2))
|
||||
|
||||
def test_batch_dot_shape(self):
|
||||
x_batch = KTF.ones(shape=(32, 20))
|
||||
y_batch = KTF.ones(shape=(32, 20))
|
||||
xy_batch_dot = KTF.batch_dot(x_batch, y_batch, axes=1)
|
||||
assert_allclose(KTF.eval(xy_batch_dot), np.ones((32, 1)) * 20, atol=1e-05)
|
||||
xy_batch_dot = KTF.batch_dot(x_batch, y_batch, axes=0)
|
||||
assert_allclose(KTF.eval(xy_batch_dot), np.ones((20, 1)) * 32, atol=1e-05)
|
||||
# making sure swapping axes when ndim == 2 works
|
||||
x_batch = KTF.ones(shape=(32, 20))
|
||||
y_batch = KTF.ones(shape=(20, 32))
|
||||
xy_batch_dot = KTF.batch_dot(x_batch, y_batch, axes=(0, 1))
|
||||
assert_allclose(KTF.eval(xy_batch_dot), np.ones((20, 1)) * 32, atol=1e-05)
|
||||
xy_batch_dot = KTF.batch_dot(x_batch, y_batch, axes=(1, 0))
|
||||
assert_allclose(KTF.eval(xy_batch_dot), np.ones((32, 1)) * 20, atol=1e-05)
|
||||
|
||||
def test_shape_operations(self):
|
||||
# concatenate
|
||||
xval = np.random.random((4, 3))
|
||||
|
||||
@@ -4,6 +4,7 @@ import multiprocessing
|
||||
|
||||
import numpy as np
|
||||
import pytest
|
||||
from csv import Sniffer
|
||||
from keras import optimizers
|
||||
|
||||
np.random.seed(1337)
|
||||
@@ -203,6 +204,59 @@ def test_ReduceLROnPlateau():
|
||||
assert np.allclose(float(K.get_value(model.optimizer.lr)), 0.1, atol=K.epsilon())
|
||||
|
||||
|
||||
def test_CSVLogger():
|
||||
filepath = 'log.tsv'
|
||||
sep = '\t'
|
||||
(X_train, y_train), (X_test, y_test) = get_test_data(nb_train=train_samples,
|
||||
nb_test=test_samples,
|
||||
input_shape=(input_dim,),
|
||||
classification=True,
|
||||
nb_class=nb_class)
|
||||
y_test = np_utils.to_categorical(y_test)
|
||||
y_train = np_utils.to_categorical(y_train)
|
||||
|
||||
def make_model():
|
||||
np.random.seed(1337)
|
||||
model = Sequential()
|
||||
model.add(Dense(nb_hidden, input_dim=input_dim, activation='relu'))
|
||||
model.add(Dense(nb_class, activation='softmax'))
|
||||
|
||||
model.compile(loss='categorical_crossentropy',
|
||||
optimizer=optimizers.SGD(lr=0.1),
|
||||
metrics=['accuracy'])
|
||||
return model
|
||||
|
||||
# case 1, create new file with defined separator
|
||||
model = make_model()
|
||||
cbks = [callbacks.CSVLogger(filepath, separator=sep)]
|
||||
model.fit(X_train, y_train, batch_size=batch_size,
|
||||
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
|
||||
|
||||
assert os.path.exists(filepath)
|
||||
with open(filepath) as csvfile:
|
||||
dialect = Sniffer().sniff(csvfile.read())
|
||||
assert dialect.delimiter == sep
|
||||
del model
|
||||
del cbks
|
||||
|
||||
# case 2, append data to existing file, skip header
|
||||
model = make_model()
|
||||
cbks = [callbacks.CSVLogger(filepath, separator=sep, append=True)]
|
||||
model.fit(X_train, y_train, batch_size=batch_size,
|
||||
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
|
||||
|
||||
# case 3, reuse of CSVLogger object
|
||||
model.fit(X_train, y_train, batch_size=batch_size,
|
||||
validation_data=(X_test, y_test), callbacks=cbks, nb_epoch=1)
|
||||
|
||||
import re
|
||||
with open(filepath) as csvfile:
|
||||
output = " ".join(csvfile.readlines())
|
||||
assert len(re.findall('epoch', output)) == 1
|
||||
|
||||
os.remove(filepath)
|
||||
|
||||
|
||||
@pytest.mark.skipif((K.backend() != 'tensorflow'),
|
||||
reason="Requires tensorflow backend")
|
||||
def test_TensorBoard():
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
import pytest
|
||||
import keras
|
||||
from keras import backend as K
|
||||
from keras.utils.generic_utils import custom_object_scope, get_custom_objects, get_from_module
|
||||
|
||||
|
||||
def test_custom_object_scope_adds_objects():
|
||||
get_custom_objects().clear()
|
||||
assert (len(get_custom_objects()) == 0)
|
||||
with custom_object_scope({"Test1": object, "Test2": object}, {"Test3": object}):
|
||||
assert (len(get_custom_objects()) == 3)
|
||||
assert (len(get_custom_objects()) == 0)
|
||||
|
||||
|
||||
class CustomObject(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
||||
def test_get_from_module_uses_custom_object():
|
||||
get_custom_objects().clear()
|
||||
assert (get_from_module("CustomObject", globals(), "test_generic_utils") == CustomObject)
|
||||
with pytest.raises(ValueError):
|
||||
get_from_module("TestObject", globals(), "test_generic_utils")
|
||||
with custom_object_scope({"TestObject": CustomObject}):
|
||||
assert (get_from_module("TestObject", globals(), "test_generic_utils") == CustomObject)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
pytest.main([__file__])
|
||||
Referência em uma Nova Issue
Bloquear um usuário