# Developing guides¶

[中文]

## Develop a runnable algorithm component of FATE¶

In this document, it describes how to develop an algorithm component, which can be callable under the architecture of FATE.

To develop a component, the following 6 steps are needed.

1. define the python parameter object which will be used in this component.
2. register meta of the new component.
3. define the transfer_variable object if the component needs federation.
4. define your component which should inherit model_base class.
5. Define the protobuf file required for model saving.
6. (optional) define Pipeline component for your component.

In the following sections we will describe the 6 steps in detail, with hetero_lr.

### Step 1. Define the parameter object this component will use¶

Parameter object is the only way to pass user-define runtime parameters to the developing component, so every component has it's own parameter object. In order to define a usable parameter object, three steps will be needed.

1. Open a new python file, rename it as xxx_param.py where xxx stands for your component'name, putting it in folder python/federatedm/param/. The class object defined in xxx_param.py should inherit the BaseParam class that define in python/federatedml/param/base_param.py
2. __init__ of your parameter class should specify all parameters that the component use.
3. Override the check interface of BaseParam, without which will cause not implemented error. Check method is use to validate the parameter variables.

Take hetero lr's parameter object as example, the python file is here

#### firstly, it inherits BaseParam:¶

class LogisticParam(BaseParam):

#### secondly, define all parameter variable in __init__ method:¶

def __init__(self, penalty='L2',
tol=1e-4, alpha=1.0, optimizer='rmsprop',
batch_size=-1, learning_rate=0.01, init_param=InitParam(),
max_iter=100, early_stop='diff', encrypt_param=EncryptParam(),
predict_param=PredictParam(), cv_param=CrossValidationParam(),
decay=1, decay_sqrt=True,
multi_class='ovr', validation_freqs=None, early_stopping_rounds=None,
stepwise_param=StepwiseParam(), floating_point_precision=23,
metrics=None,
use_first_metric_only=False,
callback_param=CallbackParam()
):
super(LogisticParam, self).__init__()
self.penalty = penalty
self.tol = tol
self.alpha = alpha
self.optimizer = optimizer
self.batch_size = batch_size
self.learning_rate = learning_rate
self.init_param = copy.deepcopy(init_param)
self.max_iter = max_iter
self.early_stop = early_stop
self.encrypt_param = encrypt_param
self.predict_param = copy.deepcopy(predict_param)
self.cv_param = copy.deepcopy(cv_param)
self.decay = decay
self.decay_sqrt = decay_sqrt
self.multi_class = multi_class
self.validation_freqs = validation_freqs
self.stepwise_param = copy.deepcopy(stepwise_param)
self.early_stopping_rounds = early_stopping_rounds
self.metrics = metrics or []
self.use_first_metric_only = use_first_metric_only
self.floating_point_precision = floating_point_precision
self.callback_param = copy.deepcopy(callback_param)

As the example shown above, the parameter can also be a Param class that inherit the BaseParam. The default setting of this kind of parameter is an instance of this class. Then allocated a deepcopy version of this instance to the class attribution. The deepcopy function is used to avoid same pointer risk during the task running.

Once the class defined properly, a provided parameter parser can parse the value of each attribute recursively.

#### thirdly, override the check interface:¶

def check(self):
descr = "logistic_param's"

if type(self.penalty).__name__ != "str":
raise ValueError(
"logistic_param's penalty {} not supported, should be str type".format(self.penalty))
else:
self.penalty = self.penalty.upper()
if self.penalty not in ['L1', 'L2', 'NONE']:
raise ValueError(
"logistic_param's penalty not supported, penalty should be 'L1', 'L2' or 'none'")

if type(self.eps).__name__ != "float":
raise ValueError(
"logistic_param's eps {} not supported, should be float type".format(self.eps))

### Step 2. Register meta of the new component¶

The purpose to register the meta is that FATE Flow uses this file to get the information on how to start program of the component.

1. Define component meta python file under components, name it as xxx.py, where xxx stands for the algorithm component you want to develop.

2. Developing the meta file.

• inherit from ComponentMeta, and name meta with component's name, like xxx_cpn_meta = ComponentMeta("XXX"). XXX is the module to be used in dsl file.

from .components import ComponentMeta
hetero_lr_cpn_meta = ComponentMeta("HeteroLR")

### 3. Check log files¶

Now you can check out the log in the path: $PROJECT_BASE/logs/${your jobid}

For more detailed information about dsl configure file and parameter configure files, please check out examples/dsl/v2

Last update: 2021-12-03