当您希望开发自定义模型时,需要继承模型的模板基类,并实现三个必要的方法init_hyper_parameter
,intput_data
,net
并按照以下规范添加代码。
继承paddlerec.core.model
的ModelBase,命名为Class Model
from paddlerec.core.model import ModelBase
class Model(ModelBase):
# 构造函数无需显式指定
# 若继承,务必调用基类的__init__方法
def __init__(self, config):
ModelBase.__init__(self, config)
# ModelBase的__init__方法会调用_init_hyper_parameter()
继承并实现_init_hyper_parameter
方法(必要),可以在该方法中,从yaml
文件获取超参或进行自定义操作。如下面的示例:
所有的envs调用接口在_init_hyper_parameters()方法中实现,同时类成员也推荐在此做声明及初始化。
def _init_hyper_parameters(self):
self.feature_size = envs.get_global_env(
"hyper_parameters.feature_size")
self.expert_num = envs.get_global_env("hyper_parameters.expert_num")
self.gate_num = envs.get_global_env("hyper_parameters.gate_num")
self.expert_size = envs.get_global_env("hyper_parameters.expert_size")
self.tower_size = envs.get_global_env("hyper_parameters.tower_size")
继承并实现input_data
方法(非必要)
ModelBase
中的input_data默认实现为slot_reader,在config.yaml
中分别配置reader.sparse_slot
及reader.dense_slot
选项实现slog:feasign
模式的数据读取。
Slot : Feasign 是什么?
Slot直译是槽位,在Rec工程中,是指某一个宽泛的特征类别,比如用户ID、性别、年龄就是Slot,Feasign则是具体值,比如:12345,男,20岁。
在实践过程中,很多特征槽位不是单一属性,或无法量化并且离散稀疏的,比如某用户兴趣爱好有三个:游戏/足球/数码,且每个具体兴趣又有多个特征维度,则在兴趣爱好这个Slot兴趣槽位中,就会有多个Feasign值。
PaddleRec在读取数据时,每个Slot ID对应的特征,支持稀疏,且支持变长,可以非常灵活的支持各种场景的推荐模型训练。
使用示例请参考rank.dnn
模型。
如果您不想使用slot:feasign
模式,则需继承并实现input_data
接口,接口定义:def input_data(self, is_infer=False, **kwargs)
使用示例如下:
def input_data(self, is_infer=False, **kwargs):
ser_slot_names = fluid.data(
name='user_slot_names',
shape=[None, 1],
dtype='int64',
lod_level=1)
item_slot_names = fluid.data(
name='item_slot_names',
shape=[None, self.item_len],
dtype='int64',
lod_level=1)
lens = fluid.data(name='lens', shape=[None], dtype='int64')
labels = fluid.data(
name='labels',
shape=[None, self.item_len],
dtype='int64',
lod_level=1)
train_inputs = [user_slot_names] + [item_slot_names] + [lens] + [labels]
infer_inputs = [user_slot_names] + [item_slot_names] + [lens]
if is_infer:
return infer_inputs
else:
return train_inputs
更多数据读取教程,请参考自定义数据集及Reader
继承并实现net
方法(必要)
-
接口定义
def net(self, inputs, is_infer=False)
-
自定义网络需在该函数中使用paddle组网,实现前向逻辑,定义网络的Loss及Metrics,通过
is_infer
判断是否为infer网络。 -
我们强烈建议
train
及infer
尽量复用相同代码, -
net
中调用的其他函数以下划线为头进行命名,封装网络中的结构模块,如_sparse_embedding_layer(self)
。 -
inputs
为def input_data()
的输出,若使用slot_reader
方式,inputs为占位符,无实际意义,通过以下方法拿到dense及sparse的输入self.sparse_inputs = self._sparse_data_var[1:] self.dense_input = self._dense_data_var[0] self.label_input = self._sparse_data_var[0]
可以参考官方模型的示例学习net的构造方法。
记录model.py
,config.yaml
及数据读取reader.py
的文件路径,建议置于同一文件夹下,如/home/custom_model
下,更改config.yaml
中的配置选项
- 更改 workerspace为模型文件所在文件夹
workspace: "/home/custom_model"
- 更改数据地址及读取reader地址
dataset:
- name: custom_model_train
- data_path: "{workspace}/data/train" # or "/home/custom_model/data/train"
- data_converter: "{workspace}/reader.py" # or "/home/custom_model/reader.py"
- 更改执行器的路径配置
mode: train_runner
runner:
- name: train_runner
class: single_train
device: cpu
epochs: 10
save_checkpoint_interval: 2
save_inference_interval: 5
save_checkpoint_path: "{workspace}/increment" # or "/home/custom_model/increment"
save_inference_path: "{workspace}/inference" # or "/home/custom_model/inference"
print_interval: 10
phase:
- name: train
model: "{workspace}/model.py" # or "/home/custom_model/model"
dataset_name: custom_model_train
thread_num: 1
- 使用paddlerec.run方法运行自定义模型
python -m paddlerec.run -m /home/custom_model/config.yaml
以上~请开始享受你的推荐算法高效开发流程。如有任何问题,欢迎在issue提出,我们会第一时间跟进解决。