-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
caffe2fluid:upgrade argmax implementtion (#866)
- Loading branch information
1 parent
237fe2f
commit e7684f0
Showing
15 changed files
with
507 additions
and
52 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
104 changes: 104 additions & 0 deletions
104
fluid/image_classification/caffe2fluid/kaffe/custom_layers/__init__.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
""" | ||
""" | ||
|
||
from .register import get_registered_layers | ||
#custom layer import begins | ||
|
||
import axpy | ||
import flatten | ||
import argmax | ||
|
||
#custom layer import ends | ||
|
||
custom_layers = get_registered_layers() | ||
|
||
|
||
def set_args(f, params): | ||
""" set args for function 'f' using the parameters in node.layer.parameters | ||
Args: | ||
f (function): a python function object | ||
params (object): a object contains attributes needed by f's arguments | ||
Returns: | ||
arg_names (list): a list of argument names | ||
kwargs (dict): a dict contains needed arguments | ||
""" | ||
argc = f.__code__.co_argcount | ||
arg_list = f.__code__.co_varnames[0:argc] | ||
|
||
kwargs = {} | ||
for arg_name in arg_list: | ||
try: | ||
v = getattr(node.layer.parameters, arg_name, None) | ||
except Exception as e: | ||
v = None | ||
|
||
if v is not None: | ||
kwargs[arg_name] = v | ||
|
||
return arg_list, kwargs | ||
|
||
|
||
def has_layer(kind): | ||
""" test whether this layer exists in custom layer | ||
""" | ||
return kind in custom_layers | ||
|
||
|
||
def compute_output_shape(kind, node): | ||
assert kind in custom_layers, "layer[%s] not exist in custom layers" % ( | ||
kind) | ||
shape_func = custom_layers[kind]['shape'] | ||
|
||
parents = node.parents | ||
inputs = [list(p.output_shape) for p in parents] | ||
arg_names, kwargs = set_args(shape_func, node.layer.parameters) | ||
|
||
if len(inputs) == 1: | ||
inputs = inputs[0] | ||
|
||
return shape_func(inputs, **kwargs) | ||
|
||
|
||
def make_node(template, kind, node): | ||
""" make a TensorFlowNode for custom layer which means construct | ||
a piece of code to define a layer implemented in 'custom_layers' | ||
Args: | ||
@template (TensorFlowNode): a factory to new a instance of TensorFLowNode | ||
@kind (str): type of custom layer | ||
@node (graph.Node): a layer in the net | ||
Returns: | ||
instance of TensorFlowNode | ||
""" | ||
assert kind in custom_layers, "layer[%s] not exist in custom layers" % ( | ||
kind) | ||
|
||
layer_func = custom_layers[kind]['layer'] | ||
|
||
#construct arguments needed by custom layer function from node's parameters | ||
arg_names, kwargs = set_args(layer_func, node.layer.parameters) | ||
|
||
return template('custom_layer', kind, **kwargs) | ||
|
||
|
||
def make_custom_layer(kind, inputs, name, *args, **kwargs): | ||
""" execute a custom layer which is implemented by users | ||
Args: | ||
@kind (str): type name of this layer | ||
@inputs (vars): variable list created by fluid | ||
@namme (str): name for this layer | ||
@args (tuple): other positional arguments | ||
@kwargs (dict): other kv arguments | ||
Returns: | ||
output (var): output variable for this layer | ||
""" | ||
assert kind in custom_layers, "layer[%s] not exist in custom layers" % ( | ||
kind) | ||
|
||
layer_func = custom_layers[kind]['layer'] | ||
return layer_func(inputs, name, *args, **kwargs) |
70 changes: 70 additions & 0 deletions
70
fluid/image_classification/caffe2fluid/kaffe/custom_layers/argmax.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
""" a custom layer for 'argmax', maybe we should implement this in standard way. | ||
more info can be found here: http://caffe.berkeleyvision.org/tutorial/layers/argmax.html | ||
""" | ||
from .register import register | ||
|
||
|
||
def import_fluid(): | ||
import paddle.fluid as fluid | ||
return fluid | ||
|
||
|
||
def argmax_shape(input_shape, out_max_val=False, top_k=1, axis=-1): | ||
""" calculate the output shape of this layer using input shape | ||
Args: | ||
@input_shape (list of num): a list of number which represents the input shape | ||
@out_max_val (bool): parameter from caffe's ArgMax layer | ||
@top_k (int): parameter from caffe's ArgMax layer | ||
@axis (int): parameter from caffe's ArgMax layer | ||
Returns: | ||
@output_shape (list of num): a list of numbers represent the output shape | ||
""" | ||
input_shape = list(input_shape) | ||
|
||
if axis < 0: | ||
axis += len(input_shape) | ||
|
||
assert (axis + 1 == len(input_shape) | ||
), 'only can be applied on the last dimension now' | ||
|
||
output_shape = input_shape | ||
output_shape[-1] = top_k | ||
if out_max_val is True: | ||
output_shape[-1] *= 2 | ||
|
||
return output_shape | ||
|
||
|
||
def argmax_layer(input, name, out_max_val=False, top_k=1, axis=-1): | ||
""" build a layer of type 'ArgMax' using fluid | ||
Args: | ||
@input (variable): input fluid variable for this layer | ||
@name (str): name for this layer | ||
@out_max_val (bool): parameter from caffe's ArgMax layer | ||
@top_k (int): parameter from caffe's ArgMax layer | ||
@axis (int): parameter from caffe's ArgMax layer | ||
Returns: | ||
output (variable): output variable for this layer | ||
""" | ||
|
||
fluid = import_fluid() | ||
|
||
if axis < 0: | ||
axis += len(input.shape) | ||
|
||
assert (axis + 1 == len(input_shape) | ||
), 'only can be applied on the last dimension now' | ||
|
||
topk_var, index_var = fluid.layers.topk(input=input, k=top_k) | ||
if out_max_val is True: | ||
output = fluid.layers.concate([topk_var, index_var], axis=axis) | ||
else: | ||
output = topk_var | ||
return output | ||
|
||
|
||
register(kind='ArgMax', shape=argmax_shape, layer=argmax_layer) |
51 changes: 51 additions & 0 deletions
51
fluid/image_classification/caffe2fluid/kaffe/custom_layers/axpy.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
""" A custom layer for 'axpy' which receives 3 tensors and output 1 tensor. | ||
the function performed is:(the mupltiplication and add are elementewise) | ||
output = inputs[0] * inputs[1] + inputs[2] | ||
""" | ||
|
||
from .register import register | ||
|
||
|
||
def axpy_shape(input_shapes): | ||
""" calculate the output shape of this layer using input shapes | ||
Args: | ||
@input_shapes (list of tuples): a list of input shapes | ||
Returns: | ||
@output_shape (list of num): a list of numbers represent the output shape | ||
""" | ||
assert len(input_shapes) == 3, "not valid input shape for axpy layer" | ||
assert len(input_shapes[0]) == len(input_shapes[1]), 'should have same dims' | ||
|
||
output_shape = input_shapes[1] | ||
assert (input_shapes[2] == output_shape),\ | ||
"shape not consistent for axpy[%s <--> %s]" \ | ||
% (str(output_shape), str(input_shapes[2])) | ||
|
||
return output_shape | ||
|
||
|
||
def axpy_layer(inputs, name): | ||
""" build a layer of type 'Axpy' using fluid | ||
Args: | ||
@inputs (list of variables): input fluid variables for this layer | ||
@name (str): name for this layer | ||
Returns: | ||
output (variable): output variable for this layer | ||
""" | ||
import paddle.fluid as fluid | ||
|
||
assert len(inputs) == 3, "invalid inputs for axpy[%s]" % (name) | ||
alpha = inputs[0] | ||
x = inputs[1] | ||
y = inputs[2] | ||
output = fluid.layers.elementwise_mul(x, alpha, axis=0) | ||
output = fluid.layers.elementwise_add(output, y) | ||
|
||
return output | ||
|
||
|
||
register(kind='Axpy', shape=axpy_shape, layer=axpy_layer) |
Oops, something went wrong.