Comparar commits

...

3 Commits

Autor SHA1 Mensagem Data
Francois Chollet d135eda40e Update backend docs. 2017-06-30 16:38:16 -07:00
Francois Chollet 49f7649036 Fix backend tests 2017-06-30 15:40:14 -07:00
Francois Chollet 6b16f3c135 Style cleanup, in particular crossentropy backend API 2017-06-30 15:07:09 -07:00
5 arquivos alterados com 79 adições e 60 exclusões
+60 -37
Ver Arquivo
@@ -1,7 +1,7 @@
from __future__ import print_function
import cntk as C
import numpy as np
from .common import _FLOATX, _EPSILON, image_dim_ordering, image_data_format
from .common import floatx, epsilon, image_dim_ordering, image_data_format
from collections import defaultdict
from contextlib import contextmanager
import warnings
@@ -130,7 +130,10 @@ def _convert_dtype_string(dtype):
'float64.' % dtype)
def variable(value, dtype=_FLOATX, name=None):
def variable(value, dtype=None, name=None):
if dtype is None:
dtype = floatx()
if name is None:
name = ''
@@ -227,10 +230,12 @@ def eval(x):
def placeholder(
shape=None,
ndim=None,
dtype=_FLOATX,
dtype=None,
sparse=False,
name=None,
dynamic_axis_num=1):
if dtype is None:
dtype = floatx()
if not shape:
if ndim:
shape = tuple([None for _ in range(ndim)])
@@ -304,7 +309,7 @@ def _prepare_name(name, default):
def constant(value, dtype=None, shape=None, name=None):
if dtype is None:
dtype = _FLOATX
dtype = floatx()
if shape is None:
shape = ()
np_value = value * np.ones(shape)
@@ -351,8 +356,10 @@ def random_uniform(shape, minval=0.0, maxval=1.0, dtype=None, seed=None):
return random_uniform_variable(shape, minval, maxval, dtype, seed)
def random_uniform_variable(shape, low, high, dtype=_FLOATX,
name=None, seed=None):
def random_uniform_variable(shape, low, high,
dtype=None, name=None, seed=None):
if dtype is None:
dtype = floatx()
if seed is None:
# ensure that randomness is conditioned by the Numpy RNG
seed = np.random.randint(10e3)
@@ -380,9 +387,11 @@ def random_normal_variable(
shape,
mean,
scale,
dtype=_FLOATX,
dtype=None,
name=None,
seed=None):
if dtype is None:
dtype = floatx()
if seed is None:
# ensure that randomness is conditioned by the Numpy RNG
seed = np.random.randint(10e7)
@@ -403,7 +412,9 @@ def random_normal_variable(
name=name)
def random_normal(shape, mean=0.0, stddev=1.0, dtype=_FLOATX, seed=None):
def random_normal(shape, mean=0.0, stddev=1.0, dtype=None, seed=None):
if dtype is None:
dtype = floatx()
for _ in shape:
if _ is None:
raise ValueError('CNTK Backend: randomness op with '
@@ -435,17 +446,23 @@ def dtype(x):
return _convert_dtype_string(x.dtype)
def zeros(shape, dtype=_FLOATX, name=None):
def zeros(shape, dtype=None, name=None):
if dtype is None:
dtype = floatx()
ctype = _convert_string_dtype(dtype)
return variable(value=np.zeros(shape, ctype), dtype=dtype, name=name)
def ones(shape, dtype=_FLOATX, name=None):
def ones(shape, dtype=None, name=None):
if dtype is None:
dtype = floatx()
ctype = _convert_string_dtype(dtype)
return variable(value=np.ones(shape, ctype), dtype=dtype, name=name)
def eye(size, dtype=_FLOATX, name=None):
def eye(size, dtype=None, name=None):
if dtype is None:
dtype = floatx()
return variable(np.eye(size), dtype, name)
@@ -729,7 +746,7 @@ def all(x, axis=None, keepdims=False):
return all_matrix
def classification_error(output, target, axis=-1):
def classification_error(target, output, axis=-1):
return C.ops.reduce_mean(
C.equal(
argmax(
@@ -801,10 +818,10 @@ def clip(x, min_value, max_value):
return C.clip(x, min_value, max_value)
def binary_crossentropy(output, target, from_logits=False):
def binary_crossentropy(target, output, from_logits=False):
if from_logits:
output = C.sigmoid(output)
output = C.clip(output, _EPSILON, 1.0 - _EPSILON)
output = C.clip(output, epsilon(), 1.0 - epsilon())
output = -target * C.log(output) - (1.0 - target) * C.log(1.0 - output)
return output
@@ -1522,7 +1539,7 @@ def softsign(x):
return x / (1 + C.abs(x))
def categorical_crossentropy(output, target, from_logits=False):
def categorical_crossentropy(target, output, from_logits=False):
if from_logits:
result = C.cross_entropy_with_softmax(output, target)
# cntk's result shape is (batch, 1), while keras expect (batch, )
@@ -1530,18 +1547,19 @@ def categorical_crossentropy(output, target, from_logits=False):
else:
# scale preds so that the class probas of each sample sum to 1
output /= C.reduce_sum(output, axis=-1)
# avoid numerical instability with _EPSILON clipping
output = C.clip(output, _EPSILON, 1.0 - _EPSILON)
# avoid numerical instability with epsilon clipping
output = C.clip(output, epsilon(), 1.0 - epsilon())
return -sum(target * C.log(output), axis=-1)
def sparse_categorical_crossentropy(output, target, from_logits=False):
def sparse_categorical_crossentropy(target, output, from_logits=False):
target = C.one_hot(target, output.shape[-1])
target = C.reshape(target, output.shape)
return categorical_crossentropy(output, target, from_logits)
class Function(object):
def __init__(self, inputs, outputs, updates=[], **kwargs):
self.placeholders = inputs
self.trainer = None
@@ -1578,11 +1596,12 @@ class Function(object):
p_list.append(grad_parameter_dict[g])
u_list.append(g)
else:
raise ValueError('CNTK backend: when constructing trainer, '
'found gradient node `%s` which is not '
'related to any parameters in the model. '
'Please double check how the gradient node '
'is constructed.' % g)
raise ValueError(
'CNTK backend: when constructing trainer, '
'found gradient node `%s` which is not '
'related to any parameters in the model. '
'Please double check how the gradient node '
'is constructed.' % g)
if len(u_list) > 0:
learner = C.cntk_py.universal_learner(p_list, u_list, update_func)
@@ -1635,11 +1654,12 @@ class Function(object):
# in current version cntk can't support input with variable
# length. Will support it in next release.
if not self._is_input_shape_compatible(value, tensor):
raise ValueError('CNTK backend: The placeholder has been resolved '
'to shape `%s`, but input shape is `%s`. Currently '
'CNTK can not take variable length inputs. Please '
'pass inputs that have a static shape.'
% (tensor.shape, value.shape))
raise ValueError(
'CNTK backend: The placeholder has been resolved '
'to shape `%s`, but input shape is `%s`. Currently '
'CNTK can not take variable length inputs. Please '
'pass inputs that have a static shape.'
% (tensor.shape, value.shape))
feed_dict[tensor] = value
updated = []
@@ -1649,9 +1669,10 @@ class Function(object):
if argument in feed_dict:
input_dict[argument] = feed_dict[argument]
else:
raise ValueError('CNTK backend: argument %s is not found in inputs. '
'Please double check the model and inputs in '
'`train_function`.' % argument.name)
raise ValueError(
'CNTK backend: argument %s is not found in inputs. '
'Please double check the model and inputs in '
'`train_function`.' % argument.name)
result = self.trainer.train_minibatch(
input_dict, self.trainer_output)
@@ -1667,9 +1688,10 @@ class Function(object):
if argument in feed_dict:
input_dict[argument] = feed_dict[argument]
else:
raise ValueError('CNTK backend: metrics argument %s '
'is not found in inputs. Please double '
'check the model and inputs.' % argument.name)
raise ValueError(
'CNTK backend: metrics argument %s '
'is not found in inputs. Please double '
'check the model and inputs.' % argument.name)
output_values = self.metrics_func.eval(input_dict, as_numpy=False)
if isinstance(output_values, dict):
for o in self.metrics_outputs:
@@ -1687,9 +1709,10 @@ class Function(object):
if argument in feed_dict:
input_dict[argument] = feed_dict[argument]
else:
raise ValueError('CNTK backend: assign ops argument %s '
'is not found in inputs. Please double '
'check the model and inputs.' % argument.name)
raise ValueError(
'CNTK backend: assign ops argument %s '
'is not found in inputs. Please double '
'check the model and inputs.' % argument.name)
self.unrelated_updates.eval(input_dict, as_numpy=False)
return updated
+6 -6
Ver Arquivo
@@ -2722,14 +2722,14 @@ def softsign(x):
return tf.nn.softsign(x)
def categorical_crossentropy(output, target, from_logits=False):
def categorical_crossentropy(target, output, from_logits=False):
"""Categorical crossentropy between an output tensor and a target tensor.
# Arguments
target: A tensor of the same shape as `output`.
output: A tensor resulting from a softmax
(unless `from_logits` is True, in which
case `output` is expected to be the logits).
target: A tensor of the same shape as `output`.
from_logits: Boolean, whether `output` is the
result of a softmax, or is a tensor of logits.
@@ -2753,14 +2753,14 @@ def categorical_crossentropy(output, target, from_logits=False):
logits=output)
def sparse_categorical_crossentropy(output, target, from_logits=False):
def sparse_categorical_crossentropy(target, output, from_logits=False):
"""Categorical crossentropy with integer targets.
# Arguments
target: An integer tensor.
output: A tensor resulting from a softmax
(unless `from_logits` is True, in which
case `output` is expected to be the logits).
target: An integer tensor.
from_logits: Boolean, whether `output` is the
result of a softmax, or is a tensor of logits.
@@ -2787,12 +2787,12 @@ def sparse_categorical_crossentropy(output, target, from_logits=False):
return res
def binary_crossentropy(output, target, from_logits=False):
def binary_crossentropy(target, output, from_logits=False):
"""Binary crossentropy between an output tensor and a target tensor.
# Arguments
output: A tensor.
target: A tensor with the same shape as `output`.
output: A tensor.
from_logits: Whether `output` is expected to be a logits tensor.
By default, we consider that `output`
encodes a probability distribution.
+7 -11
Ver Arquivo
@@ -1,7 +1,6 @@
from collections import defaultdict
from contextlib import contextmanager
import theano
from theano import ifelse
from theano import tensor as T
from theano.sandbox.rng_mrg import MRG_RandomStreams as RandomStreams
from theano.tensor.signal import pool
@@ -1502,7 +1501,7 @@ def softsign(x):
return T_softsign(x)
def categorical_crossentropy(output, target, from_logits=False):
def categorical_crossentropy(target, output, from_logits=False):
if from_logits:
output = T.nnet.softmax(output)
else:
@@ -1513,14 +1512,14 @@ def categorical_crossentropy(output, target, from_logits=False):
return T.nnet.categorical_crossentropy(output, target)
def sparse_categorical_crossentropy(output, target, from_logits=False):
def sparse_categorical_crossentropy(target, output, from_logits=False):
target = T.cast(T.flatten(target), 'int32')
target = T.extra_ops.to_one_hot(target, nb_class=output.shape[-1])
target = reshape(target, shape(output))
return categorical_crossentropy(output, target, from_logits)
def binary_crossentropy(output, target, from_logits=False):
def binary_crossentropy(target, output, from_logits=False):
if from_logits:
output = T.nnet.sigmoid(output)
# avoid numerical instability with _EPSILON clipping
@@ -2355,9 +2354,8 @@ def foldl(fn, elems, initializer=None, name=None):
# We need to change the order of the arguments because theano accepts x as
# first parameter and accumulator as second
fn2 = lambda x, acc: fn(acc, x)
return theano.foldl(fn2, elems, initializer, name=name)[0]
return theano.foldl(lambda x, acc: fn(acc, x),
elems, initializer, name=name)[0]
def foldr(fn, elems, initializer=None, name=None):
@@ -2379,9 +2377,8 @@ def foldr(fn, elems, initializer=None, name=None):
# We need to change the order of the arguments because theano accepts x as
# first parameter and accumulator as second
fn2 = lambda x, acc: fn(acc, x)
return theano.foldr(fn2, elems, initializer, name=name)[0]
return theano.foldr(lambda x, acc: fn(acc, x),
elems, initializer, name=name)[0]
def local_conv1d(inputs, kernel, kernel_size, strides, data_format=None):
@@ -2449,5 +2446,4 @@ def local_conv2d(inputs, kernel, kernel_size, strides, output_shape, data_format
output = reshape(output,
(output_row, output_col, -1, filters))
output = permute_dimensions(output, (2, 0, 1, 3))
return output
+3 -3
Ver Arquivo
@@ -46,15 +46,15 @@ def logcosh(y_true, y_pred):
def categorical_crossentropy(y_true, y_pred):
return K.categorical_crossentropy(y_pred, y_true)
return K.categorical_crossentropy(y_true, y_pred)
def sparse_categorical_crossentropy(y_true, y_pred):
return K.sparse_categorical_crossentropy(y_pred, y_true)
return K.sparse_categorical_crossentropy(y_true, y_pred)
def binary_crossentropy(y_true, y_pred):
return K.mean(K.binary_crossentropy(y_pred, y_true), axis=-1)
return K.mean(K.binary_crossentropy(y_true, y_pred), axis=-1)
def kullback_leibler_divergence(y_true, y_pred):
+3 -3
Ver Arquivo
@@ -131,11 +131,11 @@ def check_cross_entropy_with_valid_probability_distribution():
yth = KTH.variable(yval)
yc = KC.placeholder((4, 2))
ztf = KTF.eval(KTF.categorical_crossentropy(xtf, ytf, from_logits=True))
zth = KTH.eval(KTH.categorical_crossentropy(xth, yth, from_logits=True))
ztf = KTF.eval(KTF.categorical_crossentropy(ytf, xtf, from_logits=True))
zth = KTH.eval(KTH.categorical_crossentropy(yth, xth, from_logits=True))
func_cntk = KC.function([xc, yc],
[KC.categorical_crossentropy(xc, yc, from_logits=True), ])
[KC.categorical_crossentropy(yc, xc, from_logits=True)])
zc = func_cntk([xval, yval])
# Keras function return a list, take the first output
assert len(zc) == 1