迁移学习目录 · 定义 · 为什么需要迁移学习 · 迁移学习的研究领域 · 迁移学习的应用 · 基础知识 · 迁移学习的基本方法 · 迁移学习算法-TCA · 迁移学习算法-Deep Adaptation Networks 定义· 迁移学习是一种学习的思想和模式。 · 迁移学习作为机器学习的一个重要分支,侧重于将已经学习过的知识迁移应用于新的问题中。 · 迁移学习的核心问题是,找到新问题和原问题之间的相似性,才可以顺利地实现知识的迁移。 · 迁移学习,是指利用数据、任务、或模型之间的相似性,将在旧领域学习过的模型,应用于新领域的一种学习过程。 迁移学习例子 为什么需要迁移学习原因概括为以下四个方面:
1、大数据与少标注之间的矛盾 我们正处在一个大数据时代,每天每时,社交网络、智能交通、视频监控、行业物流等,都产生着海量的图像、文本、语音等各类数据。数据的增多,使得机器学习和深度学习模型可以依赖于如此海量的数据,持续不断地训练和更新相应的模型,使得模型的性能越来越好,越来越适合特定场景的应用。然而,这些大数据带来了严重的问题:总是缺乏完善的数据标注。 众所周知,机器学习模型的训练和更新,均依赖于数据的标注。然而,尽管我们可以获取到海量的数据,这些数据往往是很初级的原始形态,很少有数据被加以正确的人工标注。数据的标注是一个耗时且昂贵的操作,目前为止,尚未有行之有效的方式来解决这一问题。这给机器学习和深度学习的模型训练和更新带来了挑战。反过来说,特定的领域,因为没有足够的标定数据用来学习,使得这些领域一直不能很好的发展。 2、大数据与弱计算之间的矛盾 大数据,就需要大设备、强计算能力的设备来进行存储和计算。然而,大数据的大计算能力,是' 有钱人' 才能玩得起的游戏。比如 Google,Facebook,Microsoft,这些巨无霸公司有着雄厚的计算能力去利用这些数据训练模型。例如,ResNet 需要很长的时间进行训练。Google TPU 也都是有钱人的才可以用得起的。 绝大多数普通用户是不可能具有这些强计算能力的。这就引发了大数据和弱计算之间的矛盾。在这种情况下,普通人想要利用这些海量的大数据去训练模型完成自己的任务,基本上不太可能。那么如何让普通人也能利用这些数据和模型? 3、普适化模型与个性化需求之间的矛盾 机器学习的目标是构建一个尽可能通用的模型,使得这个模型对于不同用户、不同设备、不同环境、不同需求,都可以很好地进行满足。这是我们的美好愿景。这就是要尽可能地提高机器学习模型的泛化能力,使之适应不同的数据情形。基于这样的愿望,我们构建了多种多样的普适化模型,来服务于现实应用。然而,这只能是我们竭尽全力想要做的,目前却始终无法彻底解决的问题。人们的个性化需求五花八门,短期内根本无法用一个通用的模型去满足。比如导航模型,可以定位及导航所有的路线。但是不同的人有不同的需求。比如有的人喜欢走高速,有的人喜欢走偏僻小路,这就是个性化需求。并且,不同的用户,通常都有不同的隐私需求。这也是构建应用需要着重考虑的。 所以目前的情况是,我们对于每一个通用的任务都构建了一个通用的模型。这个模型可以解决绝大多数的公共问题。但是具体到每个个体、每个需求,都存在其唯一性和特异性,一个普适化的通用模型根本无法满足。那么,能否将这个通用的模型加以改造和适配,使其更好地服务于人们的个性化需求? 4、特定应用的需求 机器学习已经被广泛应用于现实生活中。在这些应用中,也存在着一些特定的应用,它们面临着一些现实存在的问题。比如推荐系统的冷启动问题。一个新的推荐系统,没有足够的用户数据,如何进行精准的推荐? 一个崭新的图片标注系统,没有足够的标签,如何进行精准的服务?现实世界中的应用驱动着我们去开发更加便捷更加高效的机器学习方法来加以解决。 上述存在的几个重要问题,使得传统的机器学习方法疲于应对。迁移学习则可以很好地进行解决。 迁移学习是如何进行解决的呢? 大数据与少标注:迁移数据标注
大数据与弱计算:模型迁移
普适化模型与个性化需求:自适应学习
特定应用的需求:相似领域知识迁移 为了满足特定领域应用的需求,我们可以利用上述介绍过的手段,从数据和模型方法上进行迁移学习。 总结 迁移学习 VS 传统机器学习 迁移学习的研究领域 依据目前较流行的机器学习分类方法,机器学习主要可以分为有监督、半监督和无监督机器学习三大类。同理,迁移学习也可以进行这样的分类。需要注意的是,依据的分类准则不同,分类结果也不同。在这一点上,并没有一个统一的说法。我们在这里仅根据目前较流行的方法,对迁移学习的研究领域进行一个大致的划分。 大体上讲,迁移学习的分类可以按照四个准则进行:按目标域有无标签分、按学习方法分、按特征分、按离线与在线形式分。不同的分类方式对应着不同的专业名词。当然,即使是一个分类下的研究领域,也可能同时处于另一个分类下。下面我们对这些分类方法及相应的领域作简单描述。 按目标域标签分 这种分类方式最为直观。类比机器学习,按照目标领域有无标签,迁移学习可以分为以下三个大类:
显然,少标签或无标签的问题 (半监督和无监督迁移学习),是研究的热点和难点。 按学习方法分类 按学习方法的分类形式,最早在迁移学习领域的权威综述文章 [Pan and Yang, 2010] 给出定义。它将迁移学习方法分为以下四个大类:
这是一个很直观的分类方式,按照数据、特征、模型的机器学习逻辑进行区分,再加上不属于这三者中的关系模式。 · 基于实例的迁移,简单来说就是通过权重重用,对源域和目标域的样例进行迁移。就是说直接对不同的样本赋予不同权重,比如说相似的样本,我就给它高权重,这样我就完成了迁移,非常简单非常非常直接。 · 基于特征的迁移,就是更进一步对特征进行变换。意思是说,假设源域和目标域的特征原来不在一个空间,或者说它们在原来那个空间上不相似,那我们就想办法把它们变换到一个空间里面,那这些特征不就相似了?这个思路也非常直接。这个方法是用得非常多的,一直在研究,目前是感觉是研究最热的。 · 基于模型的迁移,就是说构建参数共享的模型。这个主要就是在神经网络里面用的特别多,因为神经网络的结构可以直接进行迁移。比如说神经网络最经典的 finetune 就是模型参数迁移的很好的体现。 · 基于关系的迁移,这个方法用的比较少,这个主要就是说挖掘和利用关系进行类比迁移。比如老师上课、学生听课就可以类比为公司开会的场景。这个就是一种关系的迁移。 · 目前最热的就是基于特征还有模型的迁移,然后基于实例的迁移方法和他们结合起来使用。 按特征分类 按照特征的属性进行分类,也是一种常用的分类方法。这在最近的迁移学习综述 [Weiss et al., 2016]中给出。按照特征属性,迁移学习可以分为两个大类:
这也是一种很直观的方式:如果特征语义和维度都相同,那么就是同构;反之,如果特征完全不相同,那么就是异构。举个例子来说,不同图片的迁移,就可以认为是同构;而图片到文本的迁移,则是异构的。 按离线与在线形式分 按照离线学习与在线学习的方式,迁移学习还可以被分为:
目前,绝大多数的迁移学习方法,都采用了离线方式。即,源域和目标域均是给定的,迁移一次即可。这种方式的缺点是显而易见的:算法无法对新加入的数据进行学习,模型也无法得到更新。与之相对的,是在线的方式。即随着数据的动态加入,迁移学习算法也可以不断地更新。 迁移学习的应用 迁移学习的应用· 迁移学习是机器学习领域的一个重要分支。因此,其应用并不局限于特定的领域。凡是满足迁移学习问题情景的应用,迁移学习都可以发挥作用。这些领域包括但不限于计算机视觉、文本分类、行为识别、自然语言处理、室内定位、视频监控、舆情分析、人机交互等。 计算机视觉 迁移学习已被广泛地应用于计算机视觉的研究中。特别地,在计算机视觉中,迁移学习方法被称为 Domain Adaptation。Domain adaptation 的应用场景有很多,比如图片分类、图片哈希等。 同一类图片,不同的拍摄角度、不同光照、不同背景,都会造成特征分布发生改变。因此,使用迁移学习构建跨领域的鲁棒分类器是十分重要的。 计算机视觉三大顶会 (CVPR、ICCV、ECCV) 每年都会发表大量的文章对迁移学习在视觉领域的应用进行介绍。 文本分类 由于文本数据有其领域特殊性,因此,在一个领域上训练的分类器,不能直接拿来作用到另一个领域上。这就需要用到迁移学习。例如,在电影评论文本数据集上训练好的分类器,不能直接用于图书评论的预测。这就需要进行迁移学习。下图一个由电子产品评论迁移到 DVD 评论的迁移学习任务。 文本和网络领域顶级会议 WWW 和 CIKM 每年有大量的文章对迁移学习在文本领域的应用作介绍。 时间序列-行为识别 行为识别 (Activity Recognition) 主要通过佩戴在用户身体上的传感器,研究用户的行为。行为数据是一种时间序列数据。不同用户、不同环境、不同位置、不同设备,都会导致时间序列数据的分布发生变化。此时,也需要进行迁移学习。下图展示了同一用户不同位置的信号差异性。在这个领域,华盛顿州立大学的 Diane Cook 等人在 2013 年发表的关于迁移学习在行为识别领域的综述文章 [Cook et al., 2013] 是很好的参考资料。 时间序列-室内定位 室内定位 (Indoor Location) 与传统的室外用 GPS 定位不同,它通过 WiFi、蓝牙等设备研究人在室内的位置。不同用户、不同环境、不同时刻也会使得采集的信号分布发生变化。下图展示了不同时间、不同设备的 WiFi 信号变化。 医疗健康 医疗健康领域的研究正变得越来越重要。不同于其他领域,医疗领域研究的难点问题是,无法获取足够有效的医疗数据。在这一领域,迁移学习同样也变得越来越重要。 基础知识
是进行一切研究的前提。在迁移学习中,有两个基本的概念:领域 (Domain) 和任务 (Task)。它们是最基础的概念。
是进行学习的主体。领域主要由两部分构成:数据和生成这些数据的概率分布。通常我们用 D 来表示一个 domain,用大写 P 来表示一个概率分布。 特别地,因为涉及到迁移,所以对应于两个基本的领域:源领域 (Source Domain) 和目标领域 (Target Domain)。这两个概念很好理解。源领域就是有知识、有大量数据标注的领域,是我们要迁移的对象;目标领域就是我们最终要赋予知识、赋予标注的对象。知识从源领域传递到目标领域,就完成了迁移。 领域上的数据,我们通常用小写粗体 x 来表示,它也是向量的表示形式。例如,xi 就表示第 i 个样本或特征。用大写的黑体 X 表示一个领域的数据,这是一种矩阵形式。我们用大写花体 X 来表示数据的特征空间。 通常我们用小写下标 s 和 t 来分别指代两个领域。结合领域的表示方式,则:Ds 表示源领域,Dt 表示目标领域。 值得注意的是,概率分布 P 通常只是一个逻辑上的概念,即我们认为不同领域有不同的概率分布,却一般不给出(也难以给出)P 的具体形式。
任务 (Task): 是学习的目标。任务主要由两部分组成:标签和标签对应的函数。通常我们用花体 Y 来表示一个标签空间,用 f(·) 来表示一个学习函数。 相应地,源领域和目标领域的类别空间就可以分别表示为 Ys 和 Yt 。我们用小写 ys 和yt 分别表示源领域和目标领域的实际类别。
常用符号总结 迁移学习的核心是,找到源领域和目标领域之间的相似性,并加以合理利用。这种相似性非常普遍。比如,不同人的身体构造是相似的;自行车和摩托车的骑行方式是相似的;国际象棋和中国象棋是相似的;羽毛球和网球的打球方式是相似的。这种相似性也可以理解为不变量。以不变应万变,才能立于不败之地。 找到相似性 (不变量),是进行迁移学习的核心。 有了这种相似性后,下一步工作就是,如何度量和利用这种相似性。度量工作的目标有两点:一是很好地度量两个领域的相似性,不仅定性地告诉我们它们是否相似,更定量地给出相似程度。二是以度量为准则,通过我们所要采用的学习手段,增大两个领域之间的相似性,从而完成迁移学习。
定义在两个向量 (两个点) 上,这两个数据在同一个分布里。点 x 和点 y 的马氏距离为:
最大均值差异是迁移学习中使用频率最高的度量。Maximum mean discrepancy,它度量在再生希尔伯特空间中两个分布的距离,是一种核学习方法。两个随机变量的 MMD 平方距离为 迁移学习的基本方法· 基于样本的迁移 · 基于模型的迁移 · 基于特征的迁移 · 基于关系的迁移
基于样本的迁移学习方法 (Instance based Transfer Learning) 根据一定的权重生成规则,对数据样本进行重用,来进行迁移学习。图片形象地表示了基于样本迁移方法的思想。 源域中存在不同种类的动物,如狗、鸟、猫等,目标域只有狗这一种类别。在迁移时,为了最大限度地和目标域相似,我们可以人为地提高源域中属于狗这个类别的样本权重。 虽然实例权重法具有较好的理论支撑、容易推导泛化误差上界,但这类方法通常只在领域间分布差异较小时有效,因此对自然语言处理、计算机视觉等任务效果并不理想。
基于特征的迁移方法 (Feature based Transfer Learning) 是指将通过特征变换的方式互相迁移 [Liu et al., 2011, Zheng et al., 2008, Hu and Yang, 2011],来减少源域和目标域之间的差距;或者将源域和目标域的数据特征变换到统一特征空间中 [Pan et al., 2011,Long et al., 2014b, Duan et al., 2012],然后利用传统的机器学习方法进行分类识别。根据特征的同构和异构性,又可以分为同构和异构迁移学习。图片很形象地表示了两种基于特征的迁移学习方法。 基于特征的迁移学习方法是迁移学习领域中最热门的研究方法,这类方法通常假设源域和目标域间有一些交叉的特征。
基于模型的迁移方法 (Parameter/Model based Transfer Learning) 是指从源域和目标域中找到他们之间共享的参数信息,以实现迁移的方法。这种迁移方式要求的假设条件是:源域中的数据与目标域中的数据可以共享一些模型的参数。
基于关系的迁移学习方法 (Relation Based Transfer Learning) 与上述三种方法具有截然不同的思路。这种方法比较关注源域和目标域的样本之间的关系。图片形象地表示了不同领域之间相似的关系。 就目前来说,基于关系的迁移学习方法的相关研究工作非常少,大部分都借助于马尔科夫逻辑网络 (Markov Logic Net) 来挖掘不同领域之间的关系相似性。 基于关系的迁移学习方法示意图
迁移学习算法-TCA
数据分布自适应 (Distribution Adaptation) 是一类最常用的迁移学习方法。这种方法的基本思想是,由于源域和目标域的数据概率分布不同,那么最直接的方式就是通过一些变换,将不同的数据分布的距离拉近。 根据数据分布的性质,这类方法又可以分为边缘分布自适应、条件分布自适应、以及联合分布自适应。 图片形象地表示了几种数据分布的情况。简单来说,数据的边缘分布不同,就是数据整体不相似。数据的条件分布不同,就是数据整体相似,但是具体到每个类里,都不太相似。
迁移成分分析 (Transfer Component Analysis)是一种边缘分布自适应方法 (Marginal Distribution Adaptation) 其目标是减小源域和目标域的边缘概率分布的距离,从而完成迁移学习 从形式上来说,边缘分布自适应方法是用 P(xs )和 P(xt ) 之间的距离来近似两个领域之间的差异。即: 边缘分布自适应的方法最早由香港科技大学杨强教授团队提出 [Pan et al., 2011] 问题:但是世界上有无穷个这样的 ϕ,我们肯定不能通过穷举的方法来找 ϕ 的。那么怎么办呢? 迁移学习的本质:最小化源域和目标域的距离。 能否先假设这个ϕ 是已知的,然后去求距离,看看能推出什么? 以上式子下面的条件是什么意思呢?那个 min 的目标就是要最小化源域和目标域的距离,加上 W 的约束让它不能太复杂。下面的条件是是要实现第二个目标:维持各自的数据特征。 TCA 要维持的特征是scatter matrix,就是数据的散度。就是说,一个矩阵散度怎么计算?对于一个矩阵 A,它的 scatter matrix 就是AHA⊤ 。这个 H 就是上面的中心矩阵。 TCA 和 PCA 的效果对比 可以很明显地看出,对于概率分布不同的两部分数据,在经过 TCA处理后,概率分布更加接近。这说明了 TCA 在拉近数据分布距离上的优势。 迁移学习算法-Deep Adaptation Networks from __future__ import print_function import argparse import torch import torch.nn.functional as F import torch.optim as optim from torch.autograd import Variable import os import math import data_loader import ResNet as models from torch.utils import model_zoo os.environ['CUDA_VISIBLE_DEVICES'] = '1' # Training settings batch_size = 32 epochs = 200 lr = 0.01 momentum = 0.9 no_cuda =False seed = 8 log_interval = 10 l2_decay = 5e-4 root_path = './dataset/' source_name = 'amazon' target_name = 'webcam' cuda = not no_cuda and torch.cuda.is_available() torch.manual_seed(seed) if cuda: torch.cuda.manual_seed(seed) kwargs = {'num_workers': 1, 'pin_memory': True} if cuda else {} source_loader = data_loader.load_training(root_path, source_name, batch_size, kwargs) target_train_loader = data_loader.load_training(root_path, target_name, batch_size, kwargs) target_test_loader = data_loader.load_testing(root_path, target_name, batch_size, kwargs) len_source_dataset = len(source_loader.dataset) len_target_dataset = len(target_test_loader.dataset) len_source_loader = len(source_loader) len_target_loader = len(target_train_loader) def load_pretrain(model): url = 'https://download.pytorch.org/models/resnet50-19c8e357.pth' pretrained_dict = model_zoo.load_url(url) model_dict = model.state_dict() for k, v in model_dict.items(): if not 'cls_fc' in k: model_dict[k] = pretrained_dict[k[k.find('.') + 1:]] model.load_state_dict(model_dict) return model def train(epoch, model): LEARNING_RATE = lr / math.pow((1 + 10 * (epoch - 1) / epochs), 0.75) print('learning rate{: .4f}'.format(LEARNING_RATE) ) optimizer = torch.optim.SGD([ {'params': model.sharedNet.parameters()}, {'params': model.cls_fc.parameters(), 'lr': LEARNING_RATE}, ], lr=LEARNING_RATE / 10, momentum=momentum, weight_decay=l2_decay) model.train() iter_source = iter(source_loader) iter_target = iter(target_train_loader) num_iter = len_source_loader for i in range(1, num_iter): data_source, label_source = iter_source.next() data_target, _ = iter_target.next() if i % len_target_loader == 0: iter_target = iter(target_train_loader) if cuda: data_source, label_source = data_source.cuda(), label_source.cuda() data_target = data_target.cuda() data_source, label_source = Variable(data_source), Variable(label_source) data_target = Variable(data_target) optimizer.zero_grad() label_source_pred, loss_mmd = model(data_source, data_target) loss_cls = F.nll_loss(F.log_softmax(label_source_pred, dim=1), label_source) gamma = 2 / (1 + math.exp(-10 * (epoch) / epochs)) - 1 loss = loss_cls + gamma * loss_mmd loss.backward() optimizer.step() if i % log_interval == 0: print('Train Epoch: {} [{}/{} ({:.0f}%)]\tLoss: {:.6f}\tsoft_Loss: {:.6f}\tmmd_Loss: {:.6f}'.format( epoch, i * len(data_source), len_source_dataset, 100. * i / len_source_loader, loss.data[0], loss_cls.data[0], loss_mmd.data[0])) def test(model): model.eval() test_loss = 0 correct = 0 for data, target in target_test_loader: if cuda: data, target = data.cuda(), target.cuda() data, target = Variable(data, volatile=True), Variable(target) s_output, t_output = model(data, data) test_loss += F.nll_loss(F.log_softmax(s_output, dim = 1), target, size_average=False).data[0] # sum up batch loss pred = s_output.data.max(1)[1] # get the index of the max log-probability correct += pred.eq(target.data.view_as(pred)).cpu().sum() test_loss /= len_target_dataset print('\n{} set: Average loss: {:.4f}, Accuracy: {}/{} ({:.2f}%)\n'.format( target_name, test_loss, correct, len_target_dataset, 100. * correct / len_target_dataset)) return correct if __name__ == '__main__': model = models.DANNet(num_classes=31) correct = 0 print(model) if cuda: model.cuda() model = load_pretrain(model) for epoch in range(1, epochs + 1): train(epoch, model) t_correct = test(model) if t_correct > correct: correct = t_correct print('source: {} to target: {} max correct: {} max accuracy{: .2f}%\n'.format( source_name, target_name, correct, 100. * correct / len_target_dataset )) |
|
来自: taotao_2016 > 《AI》