百度 PaddlePaddle作者

十余行代码完成迁移学习,百度PaddleHub实战解读

迁移学习 (Transfer Learning) 是属于深度学习的一个子研究领域,该研究领域的目标在于利用数据、任务、或模型之间的相似性,将在旧领域学习过的知识,迁移应用于新领域中。迁移学习吸引了很多研究者投身其中,因为它能够很好的解决深度学习中的以下几个问题:
  • 一些研究领域只有少量标注数据,且数据标注成本较高,不足以训练一个足够鲁棒的神经网络

  • 大规模神经网络的训练依赖于大量的计算资源,这对于一般用户而言难以实现

  • 应对于普适化需求的模型,在特定应用上表现不尽如人意

为了让开发者更便捷地应用迁移学习百度 PaddlePaddle 开源了预训练模型管理工具 PaddleHub。开发者用使用仅仅十余行的代码,就能完成迁移学习。本文将为读者全面介绍 PaddleHub 并其应用方法。

项目地址:https://github.com/PaddlePaddle/PaddleHub

PaddleHub 介绍

PaddleHub 是基于 PaddlePaddle 开发的预训练模型管理工具,可以借助预训练模型更便捷地开展迁移学习工作,旨在让 PaddlePaddle 生态下的开发者更便捷体验到大规模预训练模型的价值。

PaddleHub 目前的预训练模型覆盖了图像分类目标检测词法分析、Transformer、情感分析五大类别。未来会持续开放更多类型的深度学习模型,如语言模型、视频分类、图像生成等预训练模型。PaddleHub 的功能全景如图 1 所示。

图 1 PaddleHub 功能全景

PaddleHub 主要包括两个功能:命令行工具和 Fine-tune API。

命令行工具

PaddleHub 借鉴了 Anaconda 和 PIP 等软件包管理的理念,开发了命令行工具,可以方便快捷的完成模型的搜索、下载、安装、预测等功能,对应的关键的命令分别是 search,download,install,run 等。我们以 run 命令为例,介绍如何通过命令行工具进行预测。

Run 命令用于执行 Module 的预测,这里分别举一个 NLP 和 CV 的例子。

对于 NLP 任务:输入数据通过--input_text 指定。以百度 LAC 模型(中文词法分析)为例,可以通过以下命令实现单行文本分析

# 单文本预测
$ hub run lac --input_text "今天是个好日子"

对于 CV 任务:输入数据通过--input_path 指定。以 SSD 模型(单阶段目标检测)为例子,可以通过以下命令实现单张图片的预测

# 使用SSD检测模型对图片进行目标检测,第一条命令是下载图片,第二条命令是执行预测,用户也可以自
# 己准备图片
$ wget --no-check-certificate https://paddlehub.bj.bcebos.com/resources/test_img_bird.jpg
$ hub run ssd_mobilenet_v1_pascal --input_path test_img_bird.jpg

更多的命令用法,请读者参考文首的 Github 项目链接。

Fine-tune API

PaddleHub 提供了基于 PaddlePaddle 实现的 Fine-tune API, 重点针对大规模预训练模型的 Fine-tune 任务做了高阶的抽象,让预训练模型能更好服务于用户特定场景的应用。通过大规模预训练模型结合 Fine-tune,可以在更短的时间完成模型的收敛,同时具备更好的泛化能力。PaddleHub API 的全景如图 2 所示。

图 2 PaddleHub Fine-tune API 全景

  • Fine-tune :对一个 Task 进行 Fine-tune,并且定期进行验证集评估。在 Fine-tune 的过程中,接口会定期的保存 checkpoint(模型和运行数据),当运行被中断时,通过 RunConfig 指定上一次运行的 checkpoint 目录,可以直接从上一次运行的最后一次评估中恢复状态继续运行。

  • 迁移任务 Task:在 PaddleHub 中,Task 代表了一个 Fine-tune 的任务。任务中包含了执行该任务相关的 program 以及和任务相关的一些度量指标(如分类准确率 accuracy、precision、 recall、 F1-score 等)、模型损失等。

  • 运行配置 RunConfig:在 PaddleHub 中,RunConfig 代表了在对 Task 进行 Fine-tune 时的运行配置。包括运行的 epoch 次数、batch 的大小、是否使用 GPU 训练等。

  • 优化策略 Strategy:在 PaddleHub 中,Strategy 类封装了一系列适用于迁移学习的 Fine-tune 策略。Strategy 包含了对预训练参数使用什么学习率变化策略,使用哪种类型的优化器,使用什么类型的正则化等。

  • 预训练模型 Module :Module 代表了一个可执行的模型。这里的可执行指的是,Module 可以直接通过命令行 hub run ${MODULE_NAME} 执行预测,或者通过 context 接口获取上下文后进行 Fine-tune。在生成一个 Module 时,支持通过名称、url 或者路径创建 Module。

  • 数据预处理 Reader :PaddleHub 的数据预处理模块 Reader 对常见的 NLP 和 CV 任务进行了抽象。

  • 数据集 Dataset:PaddleHub 提供多种 NLP 任务和 CV 任务的数据集,可供用户载,用户也可以在自定义数据集上完成 Fine-tune。

基于以上介绍的 PaddleHub 两大功能,用户可以实现:

  • 无需编写代码,一键使用预训练模型进行预测;

  • 通过 hub download 命令,快速地获取 PaddlePaddle 生态下的所有预训练模型;

  • 借助 PaddleHub Fine-tune API,使用少量代码完成迁移学习

以下将从实战角度,教你如何使用 PaddleHub 进行图像分类迁移。

PaddleHub 实战

1. 安装

PaddleHub 是基于 PaddlePaddle 的预训练模型管理框架,使用 PaddleHub 前需要先安装 PaddlePaddle,如果你本地已经安装了 CPU 或者 GPU 版本的 PaddlePaddle,那么可以跳过以下安装步骤。

$ pip install paddlepaddle #CPU 安装命令
或者
$ pip install paddlepaddle-gpu # GPU 安装

推荐使用大于 1.4.0 版本的 PaddlePaddle。

通过以下命令来安装 PaddleHub

$ pip install paddlehub

2. 选择合适的模型

首先导入必要的 python 包

# -*- coding: utf8 -*-
import paddlehub as hub
import paddle.fluid as fluid

接下来我们要在 PaddleHub 中选择合适的预训练模型来 Fine-tune,由于猫狗分类是一个图像分类任务,因此我们使用经典的 ResNet-50 作为预训练模型。PaddleHub 提供了丰富的图像分类预训练模型,包括了最新的神经网络架构搜索类的 PNASNet,我们推荐你尝试不同的预训练模型来获得更好的性能。

module_map = {
    "resnet50": "resnet_v2_50_imagenet",
    "resnet101": "resnet_v2_101_imagenet",
    "resnet152": "resnet_v2_152_imagenet",
    "mobilenet": "mobilenet_v2_imagenet",
    "nasnet": "nasnet_imagenet",
    "pnasnet": "pnasnet_imagenet"
}

module_name = module_map["resnet50"]
module = hub.Module(name = module_name)

3. 数据准备

接着需要加载图片数据集。为了快速体验,我们直接加载 PaddleHub 提供的猫狗分类数据集,如果想要使用自定义的数据进行体验,请查看自定义数据。

# 直接用PaddleHub提供的数据集
dataset = hub.dataset.DogCat()

4. 自定义数据

本节说明如何组装自定义的数据,如果想使用猫狗数据集进行体验,可以直接跳过本节。

使用自定义数据时,我们需要自己切分数据集,将数据集且分为训练集、验证集和测试集。

同时使用三个文本文件来记录对应的图片路径和标签,此外还需要一个标签文件用于记录标签的名称。

├─data: 数据目录
  ├─train_list.txt:训练集数据列表
  ├─test_list.txt:测试集数据列表
  ├─validate_list.txt:验证集数据列表
 ├─label_list.txt:标签列表
  └─……

训练/验证/测试集的数据列表文件的格式如下

图片 1 路径 图片 1 标签
图片 2 路径 图片 2 标签
...

标签列表文件的格式如下

分类 1 名称
分类 2 名称
...

使用如下的方式进行加载数据,生成数据集对象

注意事项:

  1. num_labels 要填写实际的分类数量,如猫狗分类该字段值为 2,food101 该字段值为 101,下文以 2 为例子

  2. base_path 为数据集实际路径,需要填写全路径,下文以/test/data 为例子

  3. 训练/验证/测试集的数据列表文件中的图片路径需要相对于 base_path 的相对路径,例如图片的实际位置为/test/data/dog/dog1.jpg,base_path 为/test/data,则文件中填写的路径应该为 dog/dog1.jpg

# 使用本地数据集
class MyDataSet(hub.dataset.base_cv_dataset.ImageClassificationDataset):
 def __init__(self):
 self.base_path = "/test/data"
 self.train_list_file = "train_list.txt"
 self.test_list_file = "test_list.txt"
 self.validate_list_file = "validate_list.txt"
 self.label_list_file = "label_list.txt"
 self.label_list = None
 self.num_labels = 2

5. 生成 Reader

接着生成一个图像分类的 reader,reader 负责将 dataset 的数据进行预处理,接着以特定格式组织并输入给模型进行训练。

当我们生成一个图像分类的 reader 时,需要指定输入图片的大小

data_reader = hub.reader.ImageClassificationReader(
    image_width=module.get_expected_image_width(),
    image_height=module.get_expected_image_height(),
    images_mean=module.get_pretrained_images_mean(),
    images_std=module.get_pretrained_images_std(),
    dataset=dataset)

6. 组建 Fine-tune Task

有了合适的预训练模型和准备要迁移的数据集后,我们开始组建一个 Task。

由于猫狗分类是一个二分类的任务,而我们下载的 cv_classifer_module 是在 ImageNet 数据集上训练的千分类模型,所以我们需要对模型进行简单的微调,把模型改造为一个二分类模型:

  1. 获取 cv_classifer_module 的上下文环境,包括输入和输出的变量,以及 Paddle Program;

  2. 从输出变量中找到特征图提取层 feature_map;

  3. 在 feature_map 后面接入一个全连接层,生成 Task;

input_dict, output_dict, program = module.context(trainable=True)

img = input_dict["image"]
feature_map = output_dict["feature_map"]

task = hub.create_img_cls_task(
    feature=feature_map, num_classes=dataset.num_labels)

feed_list = [img.name, task.variable("label").name]

7. 选择运行时配置

在进行 Fine-tune 前,我们可以设置一些运行时的配置,例如如下代码中的配置,表示:

  • use_cuda:设置为 False 表示使用 CPU 进行训练。如果本机支持 GPU,且安装的是 GPU 版本的 PaddlePaddle,我们建议你将这个选项设置为 True;

  • epoch:要求 Fine-tune 的任务只遍历 1 次训练集;

  • batch_size:每次训练的时候,给模型输入的每批数据大小为 32,模型训练时能够并行处理批数据,因此 batch_size 越大,训练的效率越高,但是同时带来了内存的负荷,过大的 batch_size 可能导致内存不足而无法训练,因此选择一个合适的 batch_size 是很重要的一步;

  • log_interval:每隔 10 step 打印一次训练日志;

  • eval_interval:每隔 50 step 在验证集上进行一次性能评估;

  • checkpoint_dir:将训练的参数和数据保存到 cv_Fine-tune_turtorial_demo 目录中;

  • strategy:使用 DefaultFine-tuneStrategy 策略进行 Fine-tune;

更多运行配置,请查看文首的 Github 项目链接。

config = hub.RunConfig(
    use_cuda=False,
    num_epoch=1,
    checkpoint_dir="cv_finetune_turtorial_demo",
    batch_size=32,
    log_interval=10,
    eval_interval=50,
    strategy=hub.finetune.strategy.DefaultFinetuneStrategy())

8. 开始 Fine-tune

我们选择 Fine-tune_and_eval 接口来进行模型训练,这个接口在 Fine-tune 的过程中,会周期性的进行模型效果的评估,以便我们了解整个训练过程的性能变化。

hub.finetune_and_eval(
    task, feed_list=feed_list, data_reader=data_reader, config=config)

9. 查看训练过程的效果

训练过程中的性能数据会被记录到本地,我们可以通过 visualdl 来可视化这些数据。

我们在 shell 中输入以下命令来启动 visualdl,其中${HOST_IP} 为本机 IP,需要用户自行指定

$ visualdl --logdir ./ cv_finetune_turtorial_demo/vdllog --host ${HOST_IP} --port 8989

启动服务后,我们使用浏览器访问${HOST_IP}:8989,可以看到训练以及预测的 loss 曲线和 accuracy 曲线,如下图所示。

10. 使用模型进行预测

当 Fine-tune 完成后,我们使用模型来进行预测,整个预测流程大致可以分为以下几步:

  1. 构建网络

  2. 生成预测数据的 Reader

  3. 切换到预测的 Program

  4. 加载预训练好的参数

  5. 运行 Program 进行预测

通过以下命令来获取测试的图片(适用于猫狗分类的数据集)

$ wget --no-check-certificate https://PaddleHub.bj.bcebos.com/resources/test_img_cat.jpg
$ wget --no-check-certificate https://PaddleHub.bj.bcebos.com/resources/test_img_dog.jpg

注意:其他数据集所用的测试图片请自行准备。

完整预测代码如下:

import os
import numpy as np
import paddle.fluid as fluid
import paddlehub as hub

# Step 1: build Program
module_map = {
    "resnet50": "resnet_v2_50_imagenet",
    "resnet101": "resnet_v2_101_imagenet",
    "resnet152": "resnet_v2_152_imagenet",
    "mobilenet": "mobilenet_v2_imagenet",
    "nasnet": "nasnet_imagenet",
    "pnasnet": "pnasnet_imagenet"
}

module_name = module_map["resnet50"]
module = hub.Module(name = module_name)
input_dict, output_dict, program = module.context(trainable=False)
img = input_dict["image"]
feature_map = output_dict["feature_map"]

dataset = hub.dataset.DogCat()
task = hub.create_img_cls_task(
    feature=feature_map, num_classes=dataset.num_labels)
feed_list = [img.name]

# Step 2: create data reader
data = [
    "test_img_dog.jpg",
    "test_img_cat.jpg"
]

data_reader = hub.reader.ImageClassificationReader(
    image_width=module.get_expected_image_width(),
    image_height=module.get_expected_image_height(),
    images_mean=module.get_pretrained_images_mean(),
    images_std=module.get_pretrained_images_std(),
    dataset=None)

predict_reader = data_reader.data_generator(
    phase="predict", batch_size=1, data=data)

label_dict = dataset.label_dict()

# Step 3: switch to inference program
with fluid.program_guard(task.inference_program()):
    # Step 4: load pretrained parameters
    place = fluid.CPUPlace()
    exe = fluid.Executor(place)
    pretrained_model_dir = os.path.join("cv_finetune_turtorial_demo", "best_model")
    fluid.io.load_persistables(exe, pretrained_model_dir)
    feeder = fluid.DataFeeder(feed_list=feed_list, place=place)
    # Step 5: predict
    for index, batch in enumerate(predict_reader()):
        result, = exe.run(
            feed=feeder.feed(batch), fetch_list=[task.variable('probs')])
        predict_result = np.argsort(result[0])[::-1][0]
        print("input %i is %s, and the predict result is %s" %
              (index+1, data[index], label_dict[predict_result]))
工程百度PaddlePaddle迁移学习
相关数据
深度学习技术

深度学习(deep learning)是机器学习的分支,是一种试图使用包含复杂结构或由多重非线性变换构成的多个处理层对数据进行高层抽象的算法。 深度学习是机器学习中一种基于对数据进行表征学习的算法,至今已有数种深度学习框架,如卷积神经网络和深度置信网络和递归神经网络等已被应用在计算机视觉、语音识别、自然语言处理、音频识别与生物信息学等领域并获取了极好的效果。

参数技术

在数学和统计学裡,参数(英语:parameter)是使用通用变量来建立函数和变量之间关系(当这种关系很难用方程来阐述时)的一个数量。

分类数据技术

一种特征,拥有一组离散的可能值。以某个名为 house style 的分类特征为例,该特征拥有一组离散的可能值(共三个),即 Tudor, ranch, colonial。通过将 house style 表示成分类数据,相应模型可以学习 Tudor、ranch 和 colonial 分别对房价的影响。 有时,离散集中的值是互斥的,只能将其中一个值应用于指定样本。例如,car maker 分类特征可能只允许一个样本有一个值 (Toyota)。在其他情况下,则可以应用多个值。一辆车可能会被喷涂多种不同的颜色,因此,car color 分类特征可能会允许单个样本具有多个值(例如 red 和 white)。

收敛技术

在数学,计算机科学和逻辑学中,收敛指的是不同的变换序列在有限的时间内达到一个结论(变换终止),并且得出的结论是独立于达到它的路径(他们是融合的)。 通俗来说,收敛通常是指在训练期间达到的一种状态,即经过一定次数的迭代之后,训练损失和验证损失在每次迭代中的变化都非常小或根本没有变化。也就是说,如果采用当前数据进行额外的训练将无法改进模型,模型即达到收敛状态。在深度学习中,损失值有时会在最终下降之前的多次迭代中保持不变或几乎保持不变,暂时形成收敛的假象。

SSD技术

一种计算机视觉模型。论文发表于 2015 年(Wei Liu et al.)

学习率技术

在使用不同优化器(例如随机梯度下降,Adam)神经网络相关训练中,学习速率作为一个超参数控制了权重更新的幅度,以及训练的速度和精度。学习速率太大容易导致目标(代价)函数波动较大从而难以找到最优,而弱学习速率设置太小,则会导致收敛过慢耗时太长

验证集技术

验证数据集是用于调整分类器超参数(即模型结构)的一组数据集,它有时也被称为开发集(dev set)。

神经网络技术

(人工)神经网络是一种起源于 20 世纪 50 年代的监督式机器学习模型,那时候研究者构想了「感知器(perceptron)」的想法。这一领域的研究者通常被称为「联结主义者(Connectionist)」,因为这种模型模拟了人脑的功能。神经网络模型通常是通过反向传播算法应用梯度下降训练的。目前神经网络有两大主要类型,它们都是前馈神经网络:卷积神经网络(CNN)和循环神经网络(RNN),其中 RNN 又包含长短期记忆(LSTM)、门控循环单元(GRU)等等。深度学习是一种主要应用于神经网络帮助其取得更好结果的技术。尽管神经网络主要用于监督学习,但也有一些为无监督学习设计的变体,比如自动编码器和生成对抗网络(GAN)。

词法分析技术

词法分析是计算机科学中将字符序列转换为标记序列的过程。进行词法分析的程序或者函数叫作词法分析器,也叫扫描器。词法分析器一般以函数的形式存在,供语法分析器调用

准确率技术

分类模型的正确预测所占的比例。在多类别分类中,准确率的定义为:正确的预测数/样本总数。 在二元分类中,准确率的定义为:(真正例数+真负例数)/样本总数

文本分析技术

文本分析是指对文本的表示及其特征项的选取;文本分析是文本挖掘、信息检索的一个基本问题,它把从文本中抽取出的特征词进行量化来表示文本信息。

迁移学习技术

迁移学习是一种机器学习方法,就是把为任务 A 开发的模型作为初始点,重新使用在为任务 B 开发模型的过程中。迁移学习是通过从已学习的相关任务中转移知识来改进学习的新任务,虽然大多数机器学习算法都是为了解决单个任务而设计的,但是促进迁移学习的算法的开发是机器学习社区持续关注的话题。 迁移学习对人类来说很常见,例如,我们可能会发现学习识别苹果可能有助于识别梨,或者学习弹奏电子琴可能有助于学习钢琴。

图像生成技术

正则化技术

当模型的复杂度增大时,训练误差会逐渐减小并趋向于0;而测试误差会先减小,达到最小值后又增大。当选择的模型复杂度过大时,过拟合现象就会发生。这样,在学习时就要防止过拟合。进行最优模型的选择,即选择复杂度适当的模型,以达到使测试误差最小的学习目的。

图像分类技术

图像分类,根据各自在图像信息中所反映的不同特征,把不同类别的目标区分开来的图像处理方法。它利用计算机对图像进行定量分析,把图像或图像中的每个像元或区域划归为若干个类别中的某一种,以代替人的视觉判读。

优化器技术

优化器基类提供了计算梯度loss的方法,并可以将梯度应用于变量。优化器里包含了实现了经典的优化算法,如梯度下降和Adagrad。 优化器是提供了一个可以使用各种优化算法的接口,可以让用户直接调用一些经典的优化算法,如梯度下降法等等。优化器(optimizers)类的基类。这个类定义了在训练模型的时候添加一个操作的API。用户基本上不会直接使用这个类,但是你会用到他的子类比如GradientDescentOptimizer, AdagradOptimizer, MomentumOptimizer(tensorflow下的优化器包)等等这些算法。

语言模型技术

语言模型经常使用在许多自然语言处理方面的应用,如语音识别,机器翻译,词性标注,句法分析和资讯检索。由于字词与句子都是任意组合的长度,因此在训练过的语言模型中会出现未曾出现的字串(资料稀疏的问题),也使得在语料库中估算字串的机率变得很困难,这也是要使用近似的平滑n元语法(N-gram)模型之原因。

百度机构

百度(纳斯达克:BIDU),全球最大的中文搜索引擎、最大的中文网站。1999年底,身在美国硅谷的李彦宏看到了中国互联网及中文搜索引擎服务的巨大发展潜力,抱着技术改变世界的梦想,他毅然辞掉硅谷的高薪工作,携搜索引擎专利技术,于 2000年1月1日在中关村创建了百度公司。 “百度”二字,来自于八百年前南宋词人辛弃疾的一句词:众里寻他千百度。这句话描述了词人对理想的执着追求。 百度拥有数万名研发工程师,这是中国乃至全球最为优秀的技术团队。这支队伍掌握着世界上最为先进的搜索引擎技术,使百度成为中国掌握世界尖端科学核心技术的中国高科技企业,也使中国成为美国、俄罗斯、和韩国之外,全球仅有的4个拥有搜索引擎核心技术的国家之一。

目标检测技术

一般目标检测(generic object detection)的目标是根据大量预定义的类别在自然图像中确定目标实例的位置,这是计算机视觉领域最基本和最有挑战性的问题之一。近些年兴起的深度学习技术是一种可从数据中直接学习特征表示的强大方法,并已经为一般目标检测领域带来了显著的突破性进展。

推荐文章
暂无评论
暂无评论~