Skip to content

Contribution Guideline

namizzz edited this page Jul 9, 2018 · 3 revisions

Contribution Guideline

Author: namizzz


How To Add Customized Operator

Two steps are listed below:

  • Implement original framework to IR part: get the attribute from the source_node and also add IR properties to IR node in the original framework parser file. more detail
  • Implement IR to destination framework part: get IR properties and generate the target code. more detail

How To Edit Parsers

When you make some changes:

  • Start with 'rename_' to add the new funtion to convert the new type source node to IR node
def rename_Dense(self, source_node):
    IR_node = self.IR_graph.node.add()
    _copy_and_reop(source_node, IR_node, new_op = None)
    convert_inedge(self, source_node, IR_node, start_idx = 0, end_idx = None)
    # pseudo code
  • Use 'assign_IRnode_values' to save the necessary parameters of the operation (eg. kernel_shape, strides, pads)
def rename_Conv2D(self, source_node):
    ......
    kwargs = {}
    kwargs['strides'] = source_node.get_attr('strides')
    W = self.tf_graph.get_node(source_node.layer.input[1])
    W = self.tf_graph.get_node(W.layer.input[0]).layer
    kwargs['kernel_shape'] = self.tensor_shape_to_list(W.attr['shape'])
    ......
    assign_IRnode_values(IR_node, kwargs)
  • Use 'set_weight' to save the pretrained parameters of the layer (eg. kernel matrix, mean matrix, bias matrix)
def __init__(self, meta_file, checkpoint_file, frozen_file, dest_nodes = None):
    ......
    if checkpoint_file:
        self.ckpt_data = TensorflowParser._load_weights(checkpoint_file)
        self.weight_loaded = True

......

def rename_Conv2D(self, source_node):
    ......
    if self.weight_loaded:
        self.set_weight(source_node.name, 'weights', self.ckpt_data[W.name])

After you make some changes:

  • Run the related test functions to ensure correctness after your changes using
$ python -m pytest -v -s ./test/test_conversion_imagenet.py

How To Edit Emitters

When you make some changes:

  • Start with 'emit_' to add the new funtion to convert the new type IR node to model code(eg. else) or model components(eg. CoreML)
def emit_Dropout(self, IR_node):
    parent = self.IR_graph.get_parent(IR_node.name, [0])
    self.add_body(...)
  • Follow the order in 'gen_code' function of every emitter file to use 'add_body' to generate the code of the operations or add some model layers to the 'base builder'(eg. self.builder in coreml_emitter)
def add_body(self, indent, codes):
    if isinstance(codes, _string_types):
        codes = [codes]
    for code in codes:
        self.body_code += ("    " * indent) + code + '\n'

'add_body(1, codes)' means 1 Tab at the start of the line. 'add_body(0, codes)' means 0 Tab at the start of the line.For example, 'self.add_body(0, self.header_code)' in the 'gen_code()' function.

def emit_Dropout(self, IR_node):
    parent = self.IR_graph.get_parent(IR_node.name, [0])
    self.add_body(1, "{:<15} = Dropout(name = '{}', dropout_rate = {})({})".format(
        IR_node.variable_name,
        IR_node.name,
        1 - IR_node.IR_layer.attr["keep_prob"].f,
        parent.real_variable_name))
  • [Only Model Code]Use self.used_layers to save some operation types for adding the modified functions to the target model code file.
def emit_BatchNorm(self, IR_node):
    self.used_layers.add(IR_node.type)
    self.add_body(1, "{:<15} = batch_normalization(...)".format(...)) 

......

def _layer_BatchNorm(self):
    self.add_body(0, """
def batch_normalization(input, name, **kwargs):
    mean = tf.Variable(__weights_dict[name]['mean'], name = name + "_mean", trainable = is_train)
    variance = tf.Variable(__weights_dict[name]['var'], name = name + "_var", trainable = is_train)
    offset = tf.Variable(__weights_dict[name]['bias'], name = name + "_bias", trainable = is_train) if 'bias' in __weights_dict[name] else None
    scale = tf.Variable(__weights_dict[name]['scale'], name = name + "_scale", trainable = is_train) if 'scale' in __weights_dict[name] else None
    return tf.nn.batch_normalization(input, mean, variance, offset, scale, name = name, **kwargs)
""")

[Note!] You can create and test the layer of new type and the modified function in the code file of target framework. Then put them to the 'target_framework'_emitter

After you make some changes:

$ python -m pytest -v -s ./test/test_conversion_imagenet.py

Pull Request

Before you make a PR:

  • Explain your idea by making an issue on GitHub issues of each projects, especially when introducing new features.

When you make a PR:

  • Reference the issue you made for explaining your idea.

Commit Message

When you leave commit message: The most important thing is simple but needs to contain primary summary what you did. And It is also recommended to start with capitalized verb the subject line. For example:

  • Remove deprecated methods Instead of:
  • methods are removed

Coding Style

Several major rules are listed below:

  • Requires 4 spaces for indentation.
  • No trailing whitespace, blank lines should have no whitespace.
  • End of Line Sequence is 'LF' instand of 'CRLF'
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.