PaddlePaddle升級解讀 | PaddleHub輕松完成遷移學習
引言
遷移學習(Transfer Learning)是屬于深度學習的一個子研究領域,該研究領域的目標在于利用數(shù)據(jù)、任務、或模型之間的相似性,將在舊領域學習過的知識,遷移應用于新領域中。遷移學習吸引了很多研究者投身其中,因為它能夠很好的解決深度學習中的以下幾個問題:
一些研究領域只有少量標注數(shù)據(jù),且數(shù)據(jù)標注成本較高,不足以訓練一個足夠魯棒的神經網絡
大規(guī)模神經網絡的訓練依賴于大量的計算資源,這對于一般用戶而言難以實現(xiàn)
應對于普適化需求的模型,在特定應用上表現(xiàn)不盡如人意
為了讓開發(fā)者更便捷地應用遷移學習,百度PaddlePaddle開源了預訓練模型管理工具PaddleHub。開發(fā)者用使用僅僅十余行的代碼,就能完成遷移學習。本文將為讀者全面介紹PaddleHub并介紹其應用方法。
項目地址:
https://github.com/PaddlePaddle/PaddleHub
PaddleHub介紹
PaddleHub是基于PaddlePaddle開發(fā)的預訓練模型管理工具,可以借助預訓練模型更便捷地開展遷移學習工作,旨在讓PaddlePaddle生態(tài)下的開發(fā)者更便捷體驗到大規(guī)模預訓練模型的價值。
PaddleHub目前的預訓練模型覆蓋了圖像分類、目標檢測、詞法分析、Transformer、情感分析五大類別。 未來會持續(xù)開放更多類型的深度學習模型,如語言模型、視頻分類、圖像生成等預訓練模型。PaddleHub的功能全景如圖1所示。
圖1 PaddleHub功能全景
PaddleHub主要包括兩個功能:命令行工具和Fine-tune API。
命令行工具
PaddleHub借鑒了Anaconda和PIP等軟件包管理的理念,開發(fā)了命令行工具,可以方便快捷的完成模型的搜索、下載、安裝、預測等功能,對應的關鍵的命令分別是search,download,install,run等。我們以run命令為例,介紹如何通過命令行工具進行預測。
Run命令用于執(zhí)行Module的預測,這里分別舉一個NLP和CV的例子。
對于NLP任務:輸入數(shù)據(jù)通過—input_text指定。以百度LAC模型(中文詞法分析)為例,可以通過以下命令實現(xiàn)單行文本分析。
# 單文本預測
$ hub run lac –input_text “今天是個好日子”
對于CV任務:
輸入數(shù)據(jù)通過—input_path指定。以SSD模型(單階段目標檢測)為例子,可以通過以下命令實現(xiàn)單張圖片的預測
# 使用SSD檢測模型對圖片進行目標檢測,第一條命令是下載圖片,第二條命令是執(zhí)行預測,用戶也可以自
# 己準備圖片
$ 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實現(xiàn)的Fine-tune API, 重點針對大規(guī)模預訓練模型的Fine-tune任務做了高階的抽象,讓預訓練模型能更好服務于用戶特定場景的應用。通過大規(guī)模預訓練模型結合Fine-tune,可以在更短的時間完成模型的收斂,同時具備更好的泛化能力。PaddleHub API的全景如圖2所示。
圖2 PaddleHub Fine-tune API全景
Fine-tune?:對一個Task進行Fine-tune,并且定期進行驗證集評估。在Fine-tune的過程中,接口會定期的保存checkpoint(模型和運行數(shù)據(jù)),當運行被中斷時,通過RunConfig指定上一次運行的checkpoint目錄,可以直接從上一次運行的最后一次評估中恢復狀態(tài)繼續(xù)運行。
遷移任務Task:在PaddleHub中,Task代表了一個Fine-tune的任務。任務中包含了執(zhí)行該任務相關的program以及和任務相關的一些度量指標(如分類準確率accuracy、precision、 recall、 F1-score等)、模型損失等。
運行配置 RunConfig:在PaddleHub中,RunConfig代表了在對Task進行Fine-tune時的運行配置。包括運行的epoch次數(shù)、batch的大小、是否使用GPU訓練等。
優(yōu)化策略Strategy:在PaddleHub中,Strategy類封裝了一系列適用于遷移學習的Fine-tune策略。Strategy包含了對預訓練參數(shù)使用什么學習率變化策略,使用哪種類型的優(yōu)化器,使用什么類型的正則化等。
預訓練模型Module?:Module代表了一個可執(zhí)行的模型。這里的可執(zhí)行指的是,Module可以直接通過命令行hub run ${MODULE_NAME}執(zhí)行預測,或者通過context接口獲取上下文后進行Fine-tune。在生成一個Module時,支持通過名稱、url或者路徑創(chuàng)建Module。
數(shù)據(jù)預處理Reader?:PaddleHub的數(shù)據(jù)預處理模塊Reader對常見的NLP和CV任務進行了抽象。
數(shù)據(jù)集Dataset:PaddleHub提供多種NLP任務和CV任務的數(shù)據(jù)集,可供用戶載,用戶也可以在自定義數(shù)據(jù)集上完成Fine-tune。
基于以上介紹的PaddleHub兩大功能,用戶可以實現(xiàn):
無需編寫代碼,一鍵使用預訓練模型進行預測;
通過hub download命令,快速地獲取PaddlePaddle生態(tài)下的所有預訓練模型;
借助PaddleHub Fine-tune API,使用少量代碼完成遷移學習。
以下將從實戰(zhàn)角度,教你如何使用PaddleHub進行圖像分類遷移。
PaddleHub實戰(zhàn)
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 hubimport 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. 數(shù)據(jù)準備
接著需要加載圖片數(shù)據(jù)集。為了快速體驗,我們直接加載PaddleHub提供的貓狗分類數(shù)據(jù)集,如果想要使用自定義的數(shù)據(jù)進行體驗,請查看自定義數(shù)據(jù)。
# 直接用PaddleHub提供的數(shù)據(jù)集
dataset = hub.dataset.DogCat()
4.自定義數(shù)據(jù)
本節(jié)說明如何組裝自定義的數(shù)據(jù),如果想使用貓狗數(shù)據(jù)集進行體驗,可以直接跳過本節(jié)。
使用自定義數(shù)據(jù)時,我們需要自己切分數(shù)據(jù)集,將數(shù)據(jù)集且分為訓練集、驗證集和測試集。
同時使用三個文本文件來記錄對應的圖片路徑和標簽,此外還需要一個標簽文件用于記錄標簽的名稱。
├─data: 數(shù)據(jù)目錄
├─train_list.txt:訓練集數(shù)據(jù)列表
├─test_list.txt:測試集數(shù)據(jù)列表
├─validate_list.txt:驗證集數(shù)據(jù)列表
├─label_list.txt:標簽列表
└─……
訓練/驗證/測試集的數(shù)據(jù)列表文件的格式如下
圖片1路徑 圖片1標簽
圖片2路徑 圖片2標簽
…
標簽列表文件的格式如下
分類1名稱
分類2名稱
…
使用如下的方式進行加載數(shù)據(jù),生成數(shù)據(jù)集對象
注意事項:
- num_labels要填寫實際的分類數(shù)量,如貓狗分類該字段值為2,food101該字段值為101,下文以2為例子
- base_path為數(shù)據(jù)集實際路徑,需要填寫全路徑,下文以/test/data為例子
- 訓練/驗證/測試集的數(shù)據(jù)列表文件中的圖片路徑需要相對于base_path的相對路徑,例如圖片的實際位置為/test/data/dog/dog1.jpg,base_path為/test/data,則文件中填寫的路徑應該為dog/dog1.jpg
# 使用本地數(shù)據(jù)集
dataset = MyDataSet()
class MyDataSet(hub.dataset.basecvdataset.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 = “l(fā)abel_list.txt”
self.label_list = None
self.num_labels = 2
5.生成Reader
接著生成一個圖像分類的reader,reader負責將dataset的數(shù)據(jù)進行預處理,接著以特定格式組織并輸入給模型進行訓練。
當我們生成一個圖像分類的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
有了合適的預訓練模型和準備要遷移的數(shù)據(jù)集后,我們開始組建一個Task。
由于貓狗分類是一個二分類的任務,而我們下載的cv_classifer_module是在ImageNet數(shù)據(jù)集上訓練的千分類模型,所以我們需要對模型進行簡單的微調,把模型改造為一個二分類模型:
- 獲取cv_classifer_module的上下文環(huán)境,包括輸入和輸出的變量,以及Paddle Program;
- 從輸出變量中找到特征圖提取層feature_map;
- 在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(“l(fā)abel”).name]
7.選擇運行時配置
在進行Fine-tune前,我們可以設置一些運行時的配置,例如如下代碼中的配置,表示:
use_cuda:設置為False表示使用CPU進行訓練。如果本機支持GPU,且安裝的是GPU版本的PaddlePaddle,我們建議你將這個選項設置為True;
epoch:要求Fine-tune的任務只遍歷1次訓練集;
batch_size:每次訓練的時候,給模型輸入的每批數(shù)據(jù)大小為32,模型訓練時能夠并行處理批數(shù)據(jù),因此batch_size越大,訓練的效率越高,但是同時帶來了內存的負荷,過大的batch_size可能導致內存不足而無法訓練,因此選擇一個合適的batch_size是很重要的一步;
log_interval:每隔10 step打印一次訓練日志;
eval_interval:每隔50 step在驗證集上進行一次性能評估;
checkpoint_dir:將訓練的參數(shù)和數(shù)據(jù)保存到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.查看訓練過程的效果
訓練過程中的性能數(shù)據(jù)會被記錄到本地,我們可以通過visualdl來可視化這些數(shù)據(jù)。
我們在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完成后,我們使用模型來進行預測,整個預測流程大致可以分為以下幾步:
- 構建網絡
- 生成預測數(shù)據(jù)的Reader
- 切換到預測的Program
- 加載預訓練好的參數(shù)
- 運行Program進行預測
通過以下命令來獲取測試的圖片(適用于貓狗分類的數(shù)據(jù)集)
$ 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
注意:其他數(shù)據(jù)集所用的測試圖片請自行準備
完整預測代碼如下:
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]))
- 長城汽車自研芯片點亮!提前布局下一代架構RISC-V,魏建軍:不能再受制于人2024-09-27
- 騰訊云發(fā)布自研大數(shù)據(jù)高性能計算引擎Meson,性能最高提升6倍2024-07-04
- Intel2024-03-18
- 數(shù)字員工全新發(fā)布 加速企業(yè)轉型2024-01-15