keras Layer
2016-05-15 15:38
309 查看
keras Layer
Simple Introduction
Keras实现了很多层,包括核心层、卷基层、RNN网络层等诸多常用的网络结构。Core 核心层
Source
class Layer(object): '''Abstract base layer class. All Keras layers accept certain keyword arguments: trainable: boolean. Set to "False" before model compilation to freeze layer weights (they won't be updated further during training). input_shape: a tuple of integers specifying the expected shape of the input samples. Does not includes the batch size. (e.g. `(100,)` for 100-dimensional inputs). batch_input_shape: a tuple of integers specifying the expected shape of a batch of input samples. Includes the batch size (e.g. `(32, 100)` for a batch of 32 100-dimensional inputs). ''' def __init__(self, **kwargs): allowed_kwargs = {'input_shape', 'trainable', 'batch_input_shape', 'cache_enabled'} for kwarg in kwargs: assert kwarg in allowed_kwargs, 'Keyword argument not understood: ' + kwarg if 'input_shape' in kwargs: self.set_input_shape((None,) + tuple(kwargs['input_shape'])) if 'batch_input_shape' in kwargs: self.set_input_shape(tuple(kwargs['batch_input_shape'])) if 'trainable' in kwargs: self._trainable = kwargs['trainable'] if not hasattr(self, 'params'): self.params = [] self._cache_enabled = True if 'cache_enabled' in kwargs: self._cache_enabled = kwargs['cache_enabled'] @property def cache_enabled(self): return self._cache_enabled @cache_enabled.setter def cache_enabled(self, value): self._cache_enabled = value def __call__(self, X, mask=None, train=False): # set temporary input tmp_input = self.get_input tmp_mask = None if hasattr(self, 'get_input_mask'): tmp_mask = self.get_input_mask self.get_input_mask = lambda _: mask self.get_input = lambda _: X Y = self.get_output(train=train) # return input to what it was if hasattr(self, 'get_input_mask'): self.get_input_mask = tmp_mask self.get_input = tmp_input return Y def set_previous(self, layer, connection_map={}): '''Connect a layer to its parent in the computational graph. ''' assert self.nb_input == layer.nb_output == 1, 'Cannot connect layers: input count and output count should be 1.' if hasattr(self, 'input_ndim'): assert self.input_ndim == len(layer.output_shape), ('Incompatible shapes: layer expected input with ndim=' + str(self.input_ndim) + ' but previous layer has output_shape ' + str(layer.output_shape)) if layer.get_output_mask() is not None: assert self.supports_masked_input(), 'Cannot connect non-masking layer to layer with masked output.' self.previous = layer self.build() def build(self): '''Instantiation of layer weights. Called after `set_previous`, or after `set_input_shape`, once the layer has a defined input shape. Must be implemented on all layers that have weights. ''' pass @property def trainable(self): if hasattr(self, '_trainable'): return self._trainable else: return True @trainable.setter def trainable(self, value): self._trainable = value @property def nb_input(self): return 1 @property def nb_output(self): return 1 @property def input_shape(self): # if layer is not connected (e.g. input layer), # input shape can be set manually via _input_shape attribute. if hasattr(self, 'previous'): return self.previous.output_shape elif hasattr(self, '_input_shape'): return self._input_shape else: raise Exception('Layer is not connected. Did you forget to set "input_shape"?') def set_input_shape(self, input_shape): if type(input_shape) not in [tuple, list]: raise Exception('Invalid input shape - input_shape should be a tuple of int.') input_shape = tuple(input_shape) if hasattr(self, 'input_ndim') and self.input_ndim: if self.input_ndim != len(input_shape): raise Exception('Invalid input shape - Layer expects input ndim=' + str(self.input_ndim) + ', was provided with input shape ' + str(input_shape)) self._input_shape = input_shape self.input = K.placeholder(shape=self._input_shape) self.build() @property def output_shape(self): # default assumption: tensor shape unchanged. return self.input_shape def get_output(self, train=False): return self.get_input(train) def get_input(self, train=False): if hasattr(self, 'previous'): # to avoid redundant computations, # layer outputs are cached when possible. if hasattr(self, 'layer_cache') and self.cache_enabled: previous_layer_id = '%s_%s' % (id(self.previous), train) if previous_layer_id in self.layer_cache: return self.layer_cache[previous_layer_id] previous_output = self.previous.get_output(train=train) if hasattr(self, 'layer_cache') and self.cache_enabled: previous_layer_id = '%s_%s' % (id(self.previous), train) self.layer_cache[previous_layer_id] = previous_output return previous_output elif hasattr(self, 'input'): return self.input else: raise Exception('Layer is not connected' + 'and is not an input layer.') def supports_masked_input(self): '''Whether or not this layer respects the output mask of its previous layer in its calculations. If you try to attach a layer that does *not* support masked_input to a layer that gives a non-None output_mask(), an error will be raised. ''' return False def get_output_mask(self, train=None): '''For some models (such as RNNs) you want a way of being able to mark some output data-points as "masked", so they are not used in future calculations. In such a model, get_output_mask() should return a mask of one less dimension than get_output() (so if get_output is (nb_samples, nb_timesteps, nb_dimensions), then the mask is (nb_samples, nb_timesteps), with a one for every unmasked datapoint, and a zero for every masked one. If there is *no* masking then it shall return None. For instance if you attach an Activation layer (they support masking) to a layer with an output_mask, then that Activation shall also have an output_mask. If you attach it to a layer with no such mask, then the Activation's get_output_mask shall return None. Some layers have an output_mask even if their input is unmasked, notably Embedding which can turn the entry "0" into a mask. ''' return None def set_weights(self, weights): '''Set the weights of the layer. weights: a list of numpy arrays. The number of arrays and their shape must match number of the dimensions of the weights of the layer (i.e. it should match the output of `get_weights`). ''' assert len(self.params) == len(weights), ('Provided weight array does not match layer weights (' + str(len(self.params)) + ' layer params vs. ' + str(len(weights)) + ' provided weights)') for p, w in zip(self.params, weights): if K.get_value(p).shape != w.shape: raise Exception('Layer shape %s not compatible with weight shape %s.' % (K.get_value(p).shape, w.shape)) K.set_value(p, w) def get_weights(self): '''Return the weights of the layer, as a list of numpy arrays. ''' weights = [] for p in self.params: weights.append(K.get_value(p)) return weights def get_config(self): '''Return the parameters of the layer, as a dictionary. ''' config = {'name': self.__class__.__name__} if hasattr(self, '_input_shape'): config['input_shape'] = self._input_shape[1:] if hasattr(self, '_trainable'): config['trainable'] = self._trainable config['cache_enabled'] = self.cache_enabled return config def get_params(self): consts = [] updates = [] if hasattr(self, 'regularizers'): regularizers = self.regularizers else: regularizers = [] if hasattr(self, 'constraints') and len(self.constraints) == len(self.params): for c in self.constraints: if c: consts.append(c) else: consts.append(constraints.identity()) elif hasattr(self, 'constraint') and self.constraint: consts += [self.constraint for _ in range(len(self.params))] else: consts += [constraints.identity() for _ in range(len(self.params))] if hasattr(self, 'updates') and self.updates: updates += self.updates return self.params, regularizers, consts, updates def count_params(self): '''Return the total number of floats (or ints) composing the weights of the layer. ''' return sum([K.count_params(p) for p in self.params])
set_previous
设置previous layer, 使previous layer连接到当前的layer,同时会调用build方法初始化regularizers,weights等参数.build
被set_previous调用,初始化regularizers,weights等参数.input_shape
python property. 如果该layer是输入层,返回自身的input shape, 否则返回previous layer的input shape.set_input_shape
设置input shape(tuple, list), 并调用build方法初始化regularizers,weights等参数.get_input
返回previous layer的output,如果当前层是输入层,则返回当前的输入.Activation Layer
主要是计算经过激活函数后输出值,激活函数有softmax, softplus, relu, tanh, sigmoid, hard_sigmoid, linear.source
class Activation(MaskedLayer): '''Apply an activation function to an output. # Input shape Arbitrary. Use the keyword argument `input_shape` (tuple of integers, does not include the samples axis) when using this layer as the first layer in a model. # Output shape Same shape as input. # Arguments: activation: name of activation function to use (see: [activations](../activations.md)), or alternatively, a Theano or TensorFlow operation. ''' def __init__(self, activation, **kwargs): super(Activation, self).__init__(**kwargs) self.activation = activations.get(activation) def get_output(self, train=False): X = self.get_input(train) return self.activation(X) def get_config(self): config = {'name': self.__class__.__name__, 'activation': self.activation.__name__} base_config = super(Activation, self).get_config() return dict(list(base_config.items()) + list(config.items()))
Lambda Layer
该layer的output是经过lambda计算,如果该layer是input layer,则lambda的input是当前layer 的input,否则是previous layer的inputexample
kerasmodel.add_node(Lambda(lambda x:x.sum(2)), name='merge',inputs=['embedding','embedpoint'], merge_mode='mul')
source
class Lambda(Layer): '''Used for evaluating an arbitrary Theano / TensorFlow expression on the output of the previous layer. # Input shape Arbitrary. Use the keyword argument input_shape (tuple of integers, does not include the samples axis) when using this layer as the first layer in a model. # Output shape Specified by `output_shape` argument. # Arguments function: The function to be evaluated. Takes one argument: the output of previous layer output_shape: Expected output shape from function. Could be a tuple or a function of the shape of the input ''' def __init__(self, function, output_shape=None, **kwargs): super(Lambda, self).__init__(**kwargs) py3 = sys.version_info[0] == 3 if py3: self.function = marshal.dumps(function.__code__) else: assert hasattr(function, 'func_code'), ('The Lambda layer "function"' ' argument must be a Python function.') self.function = marshal.dumps(function.func_code) if output_shape is None: self._output_shape = None elif type(output_shape) in {tuple, list}: self._output_shape = tuple(output_shape) else: if py3: self._output_shape = marshal.dumps(output_shape.__code__) else: self._output_shape = marshal.dumps(output_shape.func_code) super(Lambda, self).__init__() @property def output_shape(self): if self._output_shape is None: return self.input_shape elif type(self._output_shape) == tuple: return (self.input_shape[0], ) + self._output_shape else: output_shape_func = marshal.loads(self._output_shape) output_shape_func = types.FunctionType(output_shape_func, globals()) shape = output_shape_func(self.previous.output_shape) if type(shape) not in {list, tuple}: raise Exception('output_shape function must return a tuple') return tuple(shape) def get_output(self, train=False): func = marshal.loads(self.function) func = types.FunctionType(func, globals()) if hasattr(self, 'previous'): return func(self.previous.get_output(train)) else: return func(self.input)
Embedding Layer
使用keras实现word2Vector时,需要用到Embedding Layer相关文章推荐
- 前端性能优化
- spark countByKey用法详解
- 自定义View遇到的小坑
- centos7的一些改变
- 2016.5.14——leetcode-HappyNumber,House Robber
- LayoutInflater
- 【github】github 使用教程初级版【wins】
- HDU1671 ①string char一维/二维数组 的比较 ②字典树
- SpringMvc 拦截器 Interceptor的基础知识
- 电子海图7Csahara.000解析结果
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位
- CSS中关于定位的问题, 相对,绝对定位