端对端学习与多任务学习整理

端对端学习

基础概念

相对于深度学习,传统机器学习的流程往往由多个独立的模块组成,比如在一个典型的自然语言处理(Natural Language Processing)问题中,包括分词、词性标注、句法分析、语义分析等多个独立步骤,每个步骤是一个独立的任务,其结果的好坏会影响到下一步骤,从而影响整个训练的结果,这是非端到端的。

而深度学习模型在训练过程中,从输入端(输入数据)到输出端会得到一个预测结果,与真实结果相比较会得到一个误差,这个误差会在模型中的每一层传递(反向传播),每一层的表示都会根据这个误差来做调整,直到模型收敛或达到预期的效果才结束,这是端到端的。

两者相比,端到端的学习省去了在每一个独立学习任务执行之前所做的数据标注,为样本做标注的代价是昂贵的、易出错的。

相关应用举例

语音识别

在语音识别中,目标是输入x,一段音频,把它映射到一个输出y,就是这段音频的听写文本。所以传统上,语音识别需要很多阶段的处理:首先会提取一些特征,比如MFCC,这种算法是用来从音频中提取一组特定的人工设计的特征。在提取出一些低层次特征之后,可以应用机器学习算法在音频片段中找到音位。音位是声音的基本单位,比如说“Cat”这个词是三个音节构成的,Cu-、Ah-和Tu-。算法就把这三个音位提取出来,然后将音位串在一起构成独立的词,再将词串起来构成音频片段的听写文本
所以,和这种有很多阶段的流水线相比,端到端深度学习做的是训练一个巨大的神经网络,输入就是一段音频,输出直接是听写文本。

事实证明,端到端深度学习的挑战之一是,可能需要大量数据才能让系统表现良好。比如,只有3k小时数据去训练语音识别系统,那么传统的流水线效果就比较好。但当拥有非常大的数据集时,比如10k小时数据或者100k小时数据,这样端到端方法突然开始很厉害了。

人脸识别

在人脸识别中,如果数据集很大的话,可以使用端到端的方法很快地直接识别出人脸。但是如果数据集很小的话,就可以通过分成两步的方法来完成。首先要做的是找到人脸,然后放大图像的那部分,并裁剪图像,使人脸居中显示,然后再喂到神经网络里,让网络去学习,估计身份。总的来说就是,是弄清楚脸在哪里,再弄清楚这是谁。

机器翻译

传统上,机器翻译系统也有一个很复杂的流水线:比如英语机翻得到法文,需要先将英语文本拆分,然后做文本分析,基本上要从文本中提取一些特征之类的,经过很多步骤,最后会将英文文本翻译成法文。
端到端深度学习在机器翻译领域非常好用,那是因为现在可以收集x-y对的大数据集,也就是英文句子和对应的法语翻译。所以在大量数据的情况下就很有优势。

端到端优缺点

应用端到端学习的一些好处:
第一个好处是端到端学习真的是只让数据说话
第二个好处是简化设计工作流程,无需花太多时间去手工设计功能和中间表示方式。
缺点是它可能需要大量的数据,另一方面也排除了可能有用的手工设计组件。

多任务学习

基础概念

在机器学习(ML)中,通常的关注点是对特定度量进行优化,度量有很多种,例如特定基准或商业 KPI 的分数。为了做到这一点,我们通常训练一个模型或模型组合来执行目标任务。然后,我们微调这些模型,直到模型的结果不能继续优化。虽然通常可以通过这种方式使模型达到可接受的性能,但是由于我们的关注点集中在单个任务上,所以忽略了可能帮助优化度量指标的其它信息。具体来说,这些信息来自相关任务的训练信号。通过共享相关任务之间的表征,可以使我们的模型更好地概括原始任务。这种方法被称为多任务学习(MTL)。

MTL 有很多形式:联合学习(joint learning)、自主学习(learning to learn)和带有辅助任务的学习(learning with auxiliary task)等都可以指 MTL。一般来说,优化多个损失函数就等同于进行多任务学习(与单任务学习相反)。这些情况有助于明确地思考如何在 MTL 方面做尝试并从中获得启发。

即使只优化一个损失函数(如在典型情况下),也有可能借助辅助任务来改善原任务模型。Rich Caruana简要总结了 MTL 的目标:「MTL 通过利用包含在相关任务训练信号中的特定领域的信息来改进泛化能力」。
多任务学习的动机有不同的方式:从生物学的角度,多任务学习可以看作是受到人类学习的启发。对于学习新任务,我们经常应用通过学习相关任务获得的知识。例如,宝宝首先学会识别面部,然后可以应用这些知识来识别其它对象。
从教学的角度,我们经常通过学习任务来获得必要的技能,以便掌握更复杂的技术。学习武术(比如柔道)的恰当方式也适用于学习编程。
最后,从机器学习的角度:我们可以将多任务学习看作归纳转移的一种形式。归纳传递可以通过引入归纳偏置(inductive bias)来帮助改进模型,这导致模型比其它模型更喜欢某些假设。例如,一种常见形式的归纳偏置是 L1 正则化,这导致偏好稀疏解。在 MTL 模型下,归纳偏置由辅助任务提供,这导致模型更喜欢假设而不是解释多个任务。

两种MTL方法

Hard 参数共享

共享 Hard 参数是神经网络 MTL 最常用的方法。在实际应用中,通常通过在所有任务之间共享隐藏层,同时保留几个特定任务的输出层来实现。
在这里插入图片描述
共享 Hard 参数大大降低了过拟合的风险。实际上, 表明过拟合共享参数的风险为 O(N)——其中 N 是任务数——小于过拟合特定任务参数,即输出层。这很直观:我们同时学习的工作越多,我们的模型找到一个含有所有任务的表征就越困难,而过拟合我们原始任务的可能性就越小。

Soft 参数共享

另一方面,在共享 Soft 参数时,每个任务都有自己的参数和模型。模型参数之间的距离是正则化的,以便鼓励参数相似化。
在这里插入图片描述
约束深度神经网络 Soft 参数共享的思想受到了 MTL 正则化技术的极大启发,这种思想已经用于其它模型开发。

多任务学习实践

本次实践目的是用多任务学习实现验证码识别。
验证码生成使用captcha包提供的ImageCaptcha方法。
再使用TFRecords将数据转换为TensorFlow所支持的格式。
将谷歌的alexnet_v2网络改写后进行训练:

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import tensorflow as tf
from tensorflow.contrib import slim as contrib_slim

slim = contrib_slim

# pylint: disable=g-long-lambda
trunc_normal = lambda stddev: tf.compat.v1.truncated_normal_initializer(
    0.0, stddev)


def alexnet_v2_arg_scope(weight_decay=0.0005):
  with slim.arg_scope([slim.conv2d, slim.fully_connected],
                      activation_fn=tf.nn.relu,
                      biases_initializer=tf.compat.v1.constant_initializer(0.1),
                      weights_regularizer=slim.l2_regularizer(weight_decay)):
    with slim.arg_scope([slim.conv2d], padding='SAME'):
      with slim.arg_scope([slim.max_pool2d], padding='VALID') as arg_sc:
        return arg_sc


def alexnet_v2(inputs,
               num_classes=1000,
               is_training=True,
               dropout_keep_prob=0.5,
               spatial_squeeze=True,
               scope='alexnet_v2',
               global_pool=False):
 
  with tf.compat.v1.variable_scope(scope, 'alexnet_v2', [inputs]) as sc:
    end_points_collection = sc.original_name_scope + '_end_points'
    # Collect outputs for conv2d, fully_connected and max_pool2d.
    with slim.arg_scope([slim.conv2d, slim.fully_connected, slim.max_pool2d],
                        outputs_collections=[end_points_collection]):
      net = slim.conv2d(inputs, 64, [11, 11], 4, padding='VALID',
                        scope='conv1')
      net = slim.max_pool2d(net, [3, 3], 2, scope='pool1')
      net = slim.conv2d(net, 192, [5, 5], scope='conv2')
      net = slim.max_pool2d(net, [3, 3], 2, scope='pool2')
      net = slim.conv2d(net, 384, [3, 3], scope='conv3')
      net = slim.conv2d(net, 384, [3, 3], scope='conv4')
      net = slim.conv2d(net, 256, [3, 3], scope='conv5')
      net = slim.max_pool2d(net, [3, 3], 2, scope='pool5')

      # Use conv2d instead of fully_connected layers.
      with slim.arg_scope(
          [slim.conv2d],
          weights_initializer=trunc_normal(0.005),
          biases_initializer=tf.compat.v1.constant_initializer(0.1)):
        net = slim.conv2d
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值