2021SC@SDUSC
lingvo.core.multitask_model.py
多任务模型
多任务学习(Multi-task learning)是和单任务学习(single-task learning)相对的一种机器学习方法。在机器学习领域,标准的算法理论是一次学习一个任务,也就是系统的输出为实数的情况。复杂的学习问题先被分解成理论上独立的子问题,然后分别对每个子问题进行学习,最后通过对子问题学习结果的组合建立复杂问题的数学模型。多任务学习是一种联合学习,多个任务并行学习,结果相互影响。
在机器学习中,我们通常关心优化某一特定指标,不管这个指标是一个标准值,还是企业KPI。为了达到这个目标,我们训练单一模型或多个模型集合来完成指定得任务。然后,我们通过精细调参,来改进模型直至性能不再提升。尽管这样做可以针对一个任务得到一个可接受得性能,但是我们可能忽略了一些信息,这些信息有助于在我们关心的指标上做得更好。具体来说,这些信息就是相关任务的监督数据。通过在相关任务间共享表示信息,我们的模型在原始任务上泛化性能更好。这种方法称为多任务学习(Multi-Task Learning),是本博文的关注点。
典型方法
目前多任务学习方法大致可以总结为两类,一是不同任务之间共享相同的参数(common parameter),二是挖掘不同任务之间隐藏的共有数据特征(latent feature)。
lingvo中的multitask模型主要是共享参数。
类 class SharedEncoderModel(base_model.MultiTaskModel)
在任务之间共享 encoder 的多任务模型。
类初始化
源码
def __init__(self, params):
super().__init__(params)
p = self.params
assert p.encoder_to_share in self.task_names
将 p.encoder_to_share 任务中的 encoder 分配给所有其他任务。
encoder = self.GetTask(p.encoder_to_share).encoder
for name in self.task_names:
if name != p.encoder_to_share:
task = self.GetTask(name)
assert 'encoder' not in task.children
task.AddChild('encoder', encoder)
类方法def _CreateChildrenVariables(self)
方法作用:确保p.encoder_to_share已经被创建。
源码:
def _CreateChildrenVariables(self):
task_name = self.params.encoder_to_share
with tf.name_scope(self.params.name):
if self.params.task_name_var_scope:
with tf.variable_scope(task_name):
self.GetTask(task_name).InstantiateVariables()
else:
self.GetTask(task_name).InstantiateVariables()
super()._CreateChildrenVariables()
类class SharedEncoderDecoderModel(base_model.MultiTaskModel)
在任务之间共享编码器和解码器的多任务模型。
类初始化
def __init__(self, params):
super().__init__(params)
p = self.params
assert p.encoder_to_share in self.task_names
assert p.decoder_to_share in self.task_names
将p.encoder_to_share任务中的编码器分配给所有其他任务,并将p.decoder_to_share任务中的解码器分配给所有其他任务。
encoder = self.GetTask(p.encoder_to_share).encoder
decoder = self.GetTask(p.decoder_to_share).decoder
for name in self.task_names:
if name != p.encoder_to_share:
task = self.GetTask(name)
assert 'encoder' not in task.children
task.AddChild('encoder', encoder)
if name != p.decoder_to_share:
task = self.GetTask(name)
assert 'decoder' not in task.children
task.AddChild('decoder', decoder)
类class RegExSharedVariableModel(base_model.MultiTaskModel)
在不同任务之间共享变量的多任务模型。
这个模型是个大boss,好用的时候非常好用,不好用的时候很拉跨。除非确切地知道想要做什么,并且已经验证过它确实达到了期望的效果,否则不要轻易的使用这个模型。
类初始化
启用变量共享
def __init__(self, params):
with py_utils.OpportunisticVariableReuseScope():
with py_utils.VariableRenameScope(params.variable_renaming_rules):
super().__init__(params)
类方法def InstantiateVariables(self)
实例化变量,使变量共享
def InstantiateVariables(self):
with py_utils.OpportunisticVariableReuseScope():
with py_utils.VariableRenameScope(self.params.variable_renaming_rules):
super().InstantiateVariables()
类方法ConstructFPropBPropGraph(self)
我们需要 override,因为构造BPropGraph会创建槽变量。
def ConstructFPropBPropGraph(self):
with py_utils.OpportunisticVariableReuseScope():
with py_utils.VariableRenameScope(self.params.variable_renaming_rules):
super().ConstructFPropBPropGraph()