自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

用PaddlePaddle 實(shí)現(xiàn)目標(biāo)檢測(cè)任務(wù)——Paddle Fluid v1.1深度測(cè)評(píng)

原創(chuàng)
新聞 人工智能 開(kāi)發(fā)工具
為了一探Paddle Fluid 1.1版本究竟做了哪些方面的更新,筆者第一時(shí)間安裝了新發(fā)布的版本,用一個(gè)基于SSD的目標(biāo)檢測(cè)任務(wù)來(lái)測(cè)試一下新版PaddlePaddle的表現(xiàn)。

【51CTO.com原創(chuàng)稿件】 

1.前言

11月1日,百度發(fā)布了Paddle Fluid的1.1版本,作為國(guó)內(nèi)***深度學(xué)習(xí)框架,PaddlePaddle對(duì)中文社區(qū)非常友好,有完善的中文社區(qū)、項(xiàng)目為導(dǎo)向的中文教程,可以讓更多中文使用者更方便地進(jìn)行深度學(xué)習(xí)、機(jī)器學(xué)習(xí)相關(guān)的研究和實(shí)踐。我本人也非常希望PaddlePaddle能夠不斷發(fā)展壯大,畢竟這是國(guó)內(nèi)公司為開(kāi)源社區(qū)做出的一項(xiàng)非常有意義的貢獻(xiàn)。為了一探Paddle Fluid 1.1版本究竟做了哪些方面的更新,筆者***時(shí)間安裝了新發(fā)布的版本,用一個(gè)基于SSD的目標(biāo)檢測(cè)任務(wù)來(lái)測(cè)試一下新版PaddlePaddle的表現(xiàn)。

2.什么是目標(biāo)檢測(cè)

圖像識(shí)別對(duì)于做視覺(jué)的同學(xué)來(lái)說(shuō)應(yīng)該是一個(gè)非常熟悉的任務(wù)了,最初深度學(xué)習(xí)就是是應(yīng)用于圖像識(shí)別任務(wù)的,舉例來(lái)說(shuō),給計(jì)算機(jī)一張汽車圖片,讓它判斷這圖片里有沒(méi)有汽車。

[[252202]]

對(duì)于背景干凈的圖片來(lái)說(shuō),這樣做很有意義也比較容易。但是如果是一張包含豐富元素的圖片,不僅識(shí)別難度大大提高,僅僅判斷出里面有沒(méi)有圖片的意義也不大了,我們需要找到到底在讀片的什么位置出現(xiàn)了一輛汽車,這就提出了一個(gè)新的任務(wù)和需求——目標(biāo)檢測(cè)。

[[252203]]

我們的任務(wù)就是給定一張圖像或是一個(gè)視頻幀,讓計(jì)算機(jī)找出其中所有目標(biāo)的位置,并給出每個(gè)目標(biāo)的具體類別。對(duì)于人類來(lái)說(shuō),目標(biāo)檢測(cè)是一個(gè)非常簡(jiǎn)單的任務(wù)。然而,計(jì)算機(jī)能夠“看到”的是圖像被編碼之后的數(shù)字,很難解圖像或是視頻幀中出現(xiàn)了人或是物體這樣的高層語(yǔ)義概念,也就更加難以定位目標(biāo)出現(xiàn)在圖像中哪個(gè)區(qū)域。

與此同時(shí),由于目標(biāo)會(huì)出現(xiàn)在圖像或是視頻幀中的任何位置,目標(biāo)的形態(tài)千變?nèi)f化,圖像或是視頻幀的背景千差萬(wàn)別,諸多因素都使得目標(biāo)檢測(cè)對(duì)計(jì)算機(jī)來(lái)說(shuō)是一個(gè)具有挑戰(zhàn)性的問(wèn)題。目前主流的方法是FasterRCNN、YOLO和SSD,本文使用SSD進(jìn)行實(shí)驗(yàn)。

3.PaddlePaddle簡(jiǎn)介

***次聽(tīng)到PaddlePaddle是在CCF前線研討會(huì)上,當(dāng)時(shí)幾個(gè)人聊起來(lái)關(guān)于機(jī)器學(xué)習(xí)算法平臺(tái)的事情,有一位小伙伴提起了這個(gè)名字,所以一段時(shí)間以來(lái)我一直認(rèn)為這是一個(gè)機(jī)器學(xué)習(xí)算法平臺(tái)。直到16年百度開(kāi)源了PaddlePaddle我才知道,原來(lái)這是一個(gè)可以跟TensorFlow媲美的深度學(xué)習(xí)框架,主打“易用、高效、靈活、可擴(kuò)展”。所以,簡(jiǎn)單來(lái)說(shuō),PaddlePaddle就是百度自研的一套深度學(xué)習(xí)框架(看過(guò)發(fā)布會(huì)后了解到,百度為此建立了一套覆蓋面非常廣的生態(tài),包括金融、推薦、決策等,但筆者主要是對(duì)PaddlePaddle的核心框架進(jìn)行測(cè)評(píng),不在此浪費(fèi)過(guò)多筆墨了)。

3.1如何安裝

筆者的工作站是Ubuntu 16.04系統(tǒng),PaddlePaddle在CentOS和Ubuntu都支持pip安裝和docker安裝,GPU版本在Linux下也可以***適配。下面來(lái)看一下具體的安裝步驟。

首先我們使用cat /proc/cpuinfo | grep avx2來(lái)查看我們的Ubuntu系統(tǒng)是否支持avx2指令集,如果發(fā)現(xiàn)系統(tǒng)返回了如下一系列信息,就說(shuō)明系統(tǒng)是支持avx2指令集的,可以放心進(jìn)行后續(xù)安裝。如果不支持也沒(méi)關(guān)系,在官網(wǎng)上可以直接下載no_avx的whl包進(jìn)行安裝。

接下來(lái)使用pip安裝***的Fluid v1.1版本的PaddlePaddle(GPU),在安裝前注意,需要在機(jī)器上安裝python3.5-dev才可以用pip安裝PaddlePaddle。下載速度會(huì)比較慢,需要20分鐘左右的下載時(shí)間。

安裝完成后,在python里import paddle測(cè)試一下,如果成功導(dǎo)入則說(shuō)明安裝成功!

在更新的Paddle Fluid v1.1版本中還特意優(yōu)化了對(duì)MacOS的支持,可以直接通過(guò)pip安裝,也可以用源碼編譯安裝。具體細(xì)節(jié)可參考:http://www.paddlepaddle.org/documentation/docs/zh/1.1/beginners_guide/install/Start.html

3.2PaddlePaddle的計(jì)算描述方式

框架的計(jì)算描述方式是深度學(xué)習(xí)項(xiàng)目開(kāi)發(fā)者非常關(guān)注的一個(gè)問(wèn)題。計(jì)算的描述方式經(jīng)歷了從Caffe1.0時(shí)代的一組連續(xù)執(zhí)行的layers到TensorFlow的變量和操作構(gòu)成的計(jì)算圖再到PaddlePaddle Fluid[1]提出不再有模型的概念一系列的演變。那么PaddlePaddle現(xiàn)在是怎么描述計(jì)算的呢?

PaddlePaddle使用Program來(lái)描述模型和優(yōu)化過(guò)程,可以把它簡(jiǎn)單理解為數(shù)據(jù)流的控制過(guò)程。Program由Block、Operator和Variable構(gòu)成,variable和operator被組織成為多個(gè)可以嵌套的block。具體的,如果要實(shí)現(xiàn)一個(gè)神經(jīng)網(wǎng)絡(luò),我們只需要通過(guò)添加必要的variable、operator來(lái)定義網(wǎng)絡(luò)的前向計(jì)算,而反向計(jì)算、內(nèi)存管理、block創(chuàng)建都由框架來(lái)完成。下面展示一下如何在PaddlePaddle中定義program:

以一個(gè)簡(jiǎn)單的線性回歸為例,我們這樣定義前向計(jì)算邏輯:

#定義輸入數(shù)據(jù)類型

x = fluid.layers.data(name="x",shape=[1],dtype='float32')

#搭建全連接網(wǎng)絡(luò)

y_predict = fluid.layers.fc(input=x,size=1,act=None)

定義好計(jì)算邏輯后,與TensorFlow一樣,下一步就需要定義損失函數(shù),feed數(shù)據(jù),開(kāi)始訓(xùn)練,feed數(shù)據(jù)也是在執(zhí)行運(yùn)算的時(shí)候進(jìn)行,我們先定義一下數(shù)據(jù),這里train_data 就是我們的輸入數(shù)據(jù),y_true是label:

train_data=numpy.array([[1.0],[2.0],[3.0],[4.0]]).astype('float32')

y_true = numpy.array([[2.0],[4.0],[6.0],[8.0]]).astype('float32')

添加均方誤差損失函數(shù)(MSE),框架會(huì)自動(dòng)完成反向計(jì)算:

cost = fluid.layers.square_error_cost(input=y_predict,label=y)

avg_cost = fluid.layers.mean(cost)

執(zhí)行我們定義的上述Program:

cpu = fluid.core.CPUPlace()

exe = fluid.Executor(cpu)

exe.run(fluid.default_startup_program())

#開(kāi)始訓(xùn)練

outs = exe.run(

feed={'x':train_data,'y':y_true},

fetch_list=[y_predict.name,avg_cost.name])

#觀察結(jié)果

print outs

輸出結(jié)果:

[array([[0.9010564],

[1.8021128],

[2.7031693],

[3.6042256]], dtype=float32), array([9.057577], dtype=float32)]

這樣就用PaddlePaddle實(shí)現(xiàn)了簡(jiǎn)單的計(jì)算流程,個(gè)人感覺(jué)使用起來(lái)跟TensorFlow的相似度較高,習(xí)慣在TensorFlow上跑模型的小伙伴應(yīng)該很容易適應(yīng)PaddlePaddle的這一套生態(tài)。

關(guān)于PaddlePaddle計(jì)算描述的詳情可以參考Fluid編程指南:http://www.paddlepaddle.org/documentation/docs/zh/1.1/beginners_guide/programming_guide/programming_guide.html

3.3PaddlePaddle的模型庫(kù)簡(jiǎn)介

PaddlePaddle的核心框架內(nèi)置了非常多的經(jīng)典模型和網(wǎng)絡(luò),涵蓋了幾乎所有主流的機(jī)器學(xué)習(xí)/深度學(xué)習(xí)任務(wù),包括圖像、語(yǔ)音、自然語(yǔ)言處理、推薦等諸多方面。因?yàn)楸疚氖亲瞿繕?biāo)檢測(cè),所以主要調(diào)研了一下圖像方面的模型庫(kù),在此大致介紹一下。

3.3.1分類

分類任務(wù)中的模型庫(kù)是最全面的,AlexNet、VGG、GoogleNet、ResNet、Inception、MobileNet、Dual Path Network以及SE-ResNeXt,2012年以來(lái)的經(jīng)典圖像識(shí)別網(wǎng)絡(luò)都包含其中,每個(gè)網(wǎng)絡(luò)模型是一個(gè)獨(dú)立的py文件,里面是這個(gè)網(wǎng)絡(luò)模型的類,類里面公用的方法是net(),在調(diào)用時(shí)初始化對(duì)應(yīng)的類之后調(diào)用.net()方法,就可以得到對(duì)應(yīng)網(wǎng)絡(luò)的Program描述,之后只需要給網(wǎng)絡(luò)feed數(shù)據(jù)、定義損失函數(shù)、優(yōu)化方法等就可以輕松使用了。分類模型作為圖像任務(wù)的基礎(chǔ)任務(wù),在目標(biāo)檢測(cè)、語(yǔ)義分割等任務(wù)中都會(huì)重復(fù)利用這些模型,所以這樣一個(gè)模型庫(kù)可以為大大簡(jiǎn)化后續(xù)任務(wù)的開(kāi)發(fā)工作。這部分的模型庫(kù)里的寫法比較統(tǒng)一,只要了解網(wǎng)絡(luò)結(jié)構(gòu),用.net()方法調(diào)用就可以,這里就不一一介紹了,具體可以參考:https://github.com/PaddlePaddle/models/tree/develop/fluid/PaddleCV/image_classification/models。

3.3.2目標(biāo)檢測(cè)

SSD

Single Shot MultiBox Detector (SSD) 是一種單階段的目標(biāo)檢測(cè)器。與兩階段的檢測(cè)方法不同,單階段目標(biāo)檢測(cè)并不進(jìn)行區(qū)域推薦,而是直接從特征圖回歸出目標(biāo)的邊界框和分類概率。SSD 運(yùn)用了這種單階段檢測(cè)的思想,并且對(duì)其進(jìn)行改進(jìn):在不同尺度的特征圖上檢測(cè)對(duì)應(yīng)尺度的目標(biāo)。如下圖所示,SSD 在六個(gè)尺度的特征圖上進(jìn)行了不同層級(jí)的預(yù)測(cè)。每個(gè)層級(jí)由兩個(gè)3x3卷積分別對(duì)目標(biāo)類別和邊界框偏移進(jìn)行回歸。因此對(duì)于每個(gè)類別,SSD 的六個(gè)層級(jí)一共會(huì)產(chǎn)生 38x38x4 + 19x19x6 + 10x10x6 + 5x5x6 + 3x3x4 + 1x1x4 = 8732 個(gè)檢測(cè)結(jié)果。

SSD 目標(biāo)檢測(cè)模型

SSD 可以方便地插入到任何一種標(biāo)準(zhǔn)卷積網(wǎng)絡(luò)中,比如 VGG、ResNet 或者 MobileNet,這些網(wǎng)絡(luò)被稱作檢測(cè)器的基網(wǎng)絡(luò)。PaddlePaddle里的SSD使用Google的MobileNet作為基網(wǎng)絡(luò)。

目標(biāo)檢測(cè)模型庫(kù)不同于分類模型庫(kù),PaddlePaddle是以一個(gè)工程的形式提供SSD的模型庫(kù)。工程里面包含如下文件:

其中,train.py、reader.py、mobilenet_ssd.py是與網(wǎng)絡(luò)訓(xùn)練相關(guān)的文件,包括數(shù)據(jù)讀取、網(wǎng)絡(luò)結(jié)構(gòu)、訓(xùn)練參數(shù)等過(guò)程的定義都在這3個(gè)文件中;eval.py、eval_coco_map.py是網(wǎng)絡(luò)預(yù)測(cè)評(píng)估相關(guān)文件;infer.py是可視化預(yù)測(cè)結(jié)果相關(guān)文件。Data文件夾用于存儲(chǔ)數(shù)據(jù)集,使用時(shí)可以把訓(xùn)練集、測(cè)試集、驗(yàn)證集放在data目錄下,reader會(huì)在data目錄下尋找圖片數(shù)據(jù)加載;pretrained目錄存放預(yù)訓(xùn)練模型,如果不想從頭訓(xùn)練一個(gè)SSD,可以把預(yù)訓(xùn)練好的模型放在這個(gè)目錄下,方便進(jìn)行遷移學(xué)習(xí)。

4.PaddlePaddle實(shí)現(xiàn)SSD的目標(biāo)檢測(cè)

有了上述的一些基礎(chǔ),我們就可以輕松使用PaddlePaddle上手一些項(xiàng)目了。現(xiàn)在我們就來(lái)實(shí)現(xiàn)一個(gè)基于SSD的目標(biāo)檢測(cè)任務(wù)。

4.1服務(wù)器配置

系統(tǒng):Ubuntu 16.04

GPU:NVIDIA GTX 1080*4 顯存:8GB

環(huán)境:python 3.5

4.2框架配置

Paddle Fluid v1.1 GPU版本

4.3數(shù)據(jù)準(zhǔn)備

我們使用微軟的COCO2017數(shù)據(jù)集來(lái)預(yù)訓(xùn)練模型(PaddlePaddle提供了一個(gè)基于COCO的預(yù)訓(xùn)練模型,可以直接使用),COCO數(shù)據(jù)集是微軟團(tuán)隊(duì)獲取的一個(gè)可以用來(lái)圖像recognition+segmentation+captioning 數(shù)據(jù)集,其官方說(shuō)明網(wǎng)址:http://mscoco.org/。微軟在ECCV Workshops里發(fā)表文章《Microsoft COCO: Common Objects in Context》更充分地介紹了該數(shù)據(jù)集。COCO以場(chǎng)景理解為目標(biāo),從復(fù)雜場(chǎng)景中截取了328,000張影像,包括了91類目標(biāo)和2,500,000個(gè)label。整個(gè)COCO2017數(shù)據(jù)集20G,官網(wǎng)下載非常慢,可以在國(guó)內(nèi)找一些鏡像站下載,數(shù)據(jù)集里分好了訓(xùn)練集、測(cè)試集和驗(yàn)證集,標(biāo)注和file_list用json文件保存。

拿到預(yù)訓(xùn)練數(shù)據(jù)集后,我們?cè)赑ascal VOC數(shù)據(jù)集上對(duì)模型進(jìn)行進(jìn)一步訓(xùn)練,做一下微調(diào)。Pascal VOC數(shù)據(jù)集相較COCO數(shù)據(jù)集來(lái)說(shuō)圖片數(shù)量和種類小很多,共計(jì)20類,11540張訓(xùn)練圖片,標(biāo)注采用xml格式文件保存。

4.4數(shù)據(jù)讀取

圖片格式為jpg,需要對(duì)圖像進(jìn)行轉(zhuǎn)碼讀取,SSD中的reader.py文件幫助我們實(shí)現(xiàn)了這個(gè)功能,內(nèi)置的數(shù)據(jù)讀取使用了一個(gè)生成器來(lái)逐個(gè)batch讀取圖片并轉(zhuǎn)碼,這樣內(nèi)存占用率非常低。由于我們機(jī)器內(nèi)存不大,設(shè)置的batch為32,在此情況下load十萬(wàn)張圖片的annotation只需要17秒左右,每一個(gè)batch的load+train時(shí)間只需要0.3秒左右。

可以看一下這個(gè)reader的核心代碼:

def reader():

if mode == 'train' and shuffle:

np.random.shuffle(images)

batch_out = []

for image in images:

image_name = image['file_name']

image_path = os.path.join(settings.data_dir, image_name)

im = Image.open(image_path)

if im.mode == 'L':

im = im.convert('RGB')

im_width, im_height = im.size

im_id = image['id']

# layout: category_id | xmin | ymin | xmax | ymax | iscrowd

bbox_labels = []

annIds = coco.getAnnIds(imgIds=image['id'])

anns = coco.loadAnns(annIds)

for ann in anns:

bbox_sample = []

# start from 1, leave 0 to background

bbox_sample.append(float(ann['category_id']))

bbox = ann['bbox']

xmin, ymin, w, h = bbox

xmax = xmin + w

ymax = ymin + h

bbox_sample.append(float(xmin) / im_width)

bbox_sample.append(float(ymin) / im_height)

bbox_sample.append(float(xmax) / im_width)

bbox_sample.append(float(ymax) / im_height)

bbox_sample.append(float(ann['iscrowd']))

bbox_labels.append(bbox_sample)

im, sample_labels = preprocess(im, bbox_labels, mode, settings)

sample_labels = np.array(sample_labels)

if len(sample_labels) == 0: continue

im = im.astype('float32')

boxes = sample_labels[:, 1:5]

lbls = sample_labels[:, 0].astype('int32')

iscrowd = sample_labels[:, -1].astype('int32')

if 'cocoMAP' in settings.ap_version:

batch_out.append((im, boxes, lbls, iscrowd,

[im_id, im_width, im_height]))

else:

batch_out.append((im, boxes, lbls, iscrowd))

if len(batch_out) == batch_size:

yield batch_out

batch_out = []

可以看到,這里的reader是一個(gè)生成器,逐個(gè)batch把數(shù)據(jù)load進(jìn)內(nèi)存。在數(shù)據(jù)讀取過(guò)程中,需要注意一下幾點(diǎn):

1. 數(shù)據(jù)集需要放在項(xiàng)目的data目錄下,reader通過(guò)annotations下的instances_train2017.json文件區(qū)分訓(xùn)練集和驗(yàn)證集,不需要在data目錄下用文件夾區(qū)分訓(xùn)練集和驗(yàn)證集。

2. 如果數(shù)據(jù)沒(méi)有按要求保存,則需要在reader.py修改數(shù)據(jù)路徑:

class Settings(object):

def __init__(self,

dataset=None,

data_dir=None,

label_file=None,

resize_h=300,

resize_w=300,

mean_value=[127.5, 127.5, 127.5],

apply_distort=True,

apply_expand=True,

ap_version='11point'):

self._dataset = dataset

self._ap_version = ap_version

# 把data_dir替換為數(shù)據(jù)所在路徑

self._data_dir = data_dir

if 'pascalvoc' in dataset:

self._label_list = []

label_fpath = os.path.join(data_dir, label_file)

for line in open(label_fpath):

self._label_list.append(line.strip())

1. 如果遇到NoneType is not iterable的錯(cuò)誤,一般是由于數(shù)據(jù)讀取錯(cuò)誤導(dǎo)致的,仔細(xì)檢查文件路徑應(yīng)該可以解決。

2. 讀取PascalVOC數(shù)據(jù)集用reader.py文件中的pascalvoc()函數(shù),兩個(gè)數(shù)據(jù)集的文件結(jié)構(gòu)和標(biāo)注不太一樣,Paddle為我們寫好了兩個(gè)版本數(shù)據(jù)集的讀取方法,可以直接調(diào)用。

4.5模型訓(xùn)練

數(shù)據(jù)讀取完成后,就可以著手開(kāi)始模型的訓(xùn)練了,這里直接使用PaddlePaddle SSD model里面的train.py進(jìn)行訓(xùn)練:

python -u train.py

train.py里為所有的超參數(shù)都設(shè)置了缺省值,不熟悉PaddlePaddle參數(shù)調(diào)整的工程師可以直接用缺省參數(shù)進(jìn)行訓(xùn)練,非常方便。如果需要,可以根據(jù)下表進(jìn)行對(duì)應(yīng)超參數(shù)的修改:

參數(shù)名

類型

意義

learning_rate

Float

學(xué)習(xí)率

batch_size

Int

Batch大小

epoc_num

Int

迭代次數(shù)

use_gpu

Bool

是否使用GPU訓(xùn)練

parallel

Bool

是否使用多卡訓(xùn)練

dataset

Str

數(shù)據(jù)集名稱

model_save_dir

Str

模型保存路徑

pretrained_model

Str

預(yù)訓(xùn)練模型路徑(如果使用)

image_shape

Str

輸入圖片尺寸

data_dir

Str

數(shù)據(jù)集路徑

在執(zhí)行腳本時(shí),傳入相應(yīng)的參數(shù)值即可,例如:

python -u train.py --batch_size=16 --epoc_num=1 --dataset='pascalvoc' --pretrained_model='pretrain/ssd_mobilenet_v1_coco/'

4.5.1單機(jī)多卡配置

單機(jī)多卡的配置相較于多機(jī)多卡配置較為簡(jiǎn)單,參數(shù)需要先在GPU0上初始化,再經(jīng)由fluid.ParallelExecutor() 分發(fā)到多張顯卡上。這里可以使用fluid.core.get_cuda_device_count()得到可用顯卡數(shù)量,也可以自己定義用幾張顯卡。

train_exe = fluid.ParallelExecutor(use_cuda=True, loss_name=loss.name,

main_program=fluid.default_main_program())

train_exe.run(fetch_list=[loss.name], feed={...})

4.5.2參數(shù)調(diào)整

PaddlePaddle這一套SSD模型給了使用者非常大的自由度,可以對(duì)網(wǎng)絡(luò)結(jié)構(gòu)、損失函數(shù)、優(yōu)化方法等多個(gè)角度對(duì)模型進(jìn)行調(diào)整。本文采用的是基于MobileNet的SSD,如果想使用基于VGG的SSD,可以自己修改工程中的mobilenet_ssd.py文件,把里面定義的MobileNet Program更改為VGG的Program描述就可以了;如果需要修改損失函數(shù)或優(yōu)化方法,則在train.py中找到build_program()函數(shù),在

with fluid.unique_name.guard("train"):

loss = fluid.layers.ssd_loss(locs, confs, gt_box, gt_label, box,

box_var)

loss = fluid.layers.reduce_sum(loss)

optimizer = optimizer_setting(train_params)

optimizer.minimize(loss)

里修改損失函數(shù)或優(yōu)化器即可;修改batch_num、epoch_num、learning rate等參數(shù)可以直接在train.py傳入?yún)?shù)中進(jìn)行。

4.5.3模型保存

模型在COCO數(shù)據(jù)集上訓(xùn)練完后,可以用fluid.io.save_persistables()方法將模型保存下來(lái),我們實(shí)現(xiàn)了如下save_model()函數(shù)來(lái)將模型保存到指定路徑。

def save_model(postfix, main_prog, model_path):

model_path = os.path.join(model_save_dir, postfix)

if os.path.isdir(model_path):

shutil.rmtree(model_path)

print('save models to %s' % (model_path))

fluid.io.save_persistables(exe, model_path, main_program=main_prog)

4.5.4繼續(xù)訓(xùn)練

訓(xùn)練過(guò)程有時(shí)候會(huì)被打斷,只要每個(gè)過(guò)幾個(gè)batch保存一下模型,我們就可以通過(guò)load_vars()方法來(lái)恢復(fù)已經(jīng)保存的模型來(lái)繼續(xù)訓(xùn)練或者用于預(yù)測(cè)。文中提到的這些API,大家可以去PaddlePaddle的官網(wǎng)教程上進(jìn)行更系統(tǒng)的學(xué)習(xí)和查看,PaddlePaddle提供了大量的中文文檔和使用教程,對(duì)中文使用者可以說(shuō)是非常友好的了。

fluid.io.load_vars(exe, pretrained_model, main_program=train_prog, predicate=if_exist)

4.5.5性能參數(shù)

訓(xùn)練速度:在COCO2017數(shù)據(jù)集上單卡訓(xùn)練,迭代1個(gè)epoch耗時(shí)3 min33s;單機(jī)4卡訓(xùn)練,迭代1個(gè)epoch耗時(shí)1min02s。

CPU/GPU占用率:正常訓(xùn)練情況下CPU占用率在40%-60%之間,GPU占用率穩(wěn)定在50%左右。

CPU/GPU使用情況

4.6模型評(píng)估

在PaddlePaddle的SSD模型中,可以使用eval.py腳本進(jìn)行模型評(píng)估,可以選擇11point、integral等方法來(lái)計(jì)算模型在驗(yàn)證集上的mAP。

python eval.py --dataset='pascalvoc' --model_dir='train_pascal_model/best_model' --data_dir='data/pascalvoc' --test_list='test.txt' --ap_version='11point' --nms_threshold=0.45

其中,model_dir是我們訓(xùn)練好的模型的保存目錄,data_dir是數(shù)據(jù)集目錄,test_list是作為驗(yàn)證集的文件列表(txt文件),前提是這些文件必須要有對(duì)應(yīng)的標(biāo)簽文件,ap_version是計(jì)算mAP的方法,nms_threshold是分類閾值。***我們得到PaddlePaddle SSD模型在Pascal VOC數(shù)據(jù)集上的mAP為73.32%[2]

模型

預(yù)訓(xùn)練模型

訓(xùn)練數(shù)據(jù)

測(cè)試數(shù)據(jù)

mAP

MobileNet-v1-SSD 300x300

COCO MobileNet SSD

VOC07+12 trainval

VOC07 test

73.32%

4.7模型預(yù)測(cè)及可視化

4.7.1模型預(yù)測(cè)

模型訓(xùn)練完成后,用test_program = fluid.default_main_program().clone(for_test=True)將Program轉(zhuǎn)換到test模式,然后把要預(yù)測(cè)的數(shù)據(jù)feed進(jìn)Executor執(zhí)行Program就可以計(jì)算得到圖像的分類標(biāo)簽、目標(biāo)框的得分、xmin、ymin、xmax、ymax。具體過(guò)程如下:

test_program = fluid.default_main_program().clone(for_test=True)

image = fluid.layers.data(name='image', shape=image_shape, dtype='float32')

locs, confs, box, box_var = mobile_net(num_classes, image, image_shape)

nmsed_out = fluid.layers.detection_output(

locs, confs, box, box_var, nms_threshold=args.nms_threshold)

place = fluid.CUDAPlace(0) if args.use_gpu else fluid.CPUPlace()

exe = fluid.Executor(place)

nmsed_out_v, = exe.run(test_program,

feed=feeder.feed([[data]]),

fetch_list=[nmsed_out],

return_numpy=False)

nmsed_out_v = np.array(nmsed_out_v)

4.7.2預(yù)測(cè)結(jié)果可視化

對(duì)于目標(biāo)檢測(cè)任務(wù),我們通常需要對(duì)預(yù)測(cè)結(jié)果進(jìn)行可視化進(jìn)而獲得對(duì)結(jié)果的感性認(rèn)識(shí)。我們可以編寫一個(gè)程序,讓它在原圖像上畫出預(yù)測(cè)框,核心代碼如下:

def draw_bounding_box_on_image(image_path, nms_out, confs_threshold,

label_list):

image = Image.open(image_path)

draw = ImageDraw.Draw(image)

im_width, im_height = image.size

for dt in nms_out:

if dt[1] < confs_threshold:

continue

category_id = dt[0]

bbox = dt[2:]

xmin, ymin, xmax, ymax = clip_bbox(dt[2:])

(left, right, top, bottom) = (xmin * im_width, xmax * im_width,

ymin * im_height, ymax * im_height)

draw.line(

[(left, top), (left, bottom), (right, bottom), (right, top),

(left, top)],

width=4,

fill='red')

if image.mode == 'RGB':

draw.text((left, top), label_list[int(category_id)], (255, 255, 0))

image_name = image_path.split('/')[-1]

print("image with bbox drawed saved as {}".format(image_name))

image.save(image_name)

這樣,我們可以很直觀的看到預(yù)測(cè)結(jié)果:

令人欣喜的是,PaddlePaddle的SSD模型中幫我們實(shí)現(xiàn)了完整的一套預(yù)測(cè)流程,我們可以直接運(yùn)行SSD model下的infer.py腳本使用訓(xùn)練好的模型對(duì)圖片進(jìn)行預(yù)測(cè):

python infer.py --dataset='coco' --nms_threshold=0.45 --model_dir='pretrained/ssd_mobilenet_v1_coco' --image_path='./data/ pascalvoc/VOCdevkit/VOC2012/JPEGImages/2007_002216.jpg'

4.8模型部署

PaddlePaddle的模型部署需要先安裝編譯C++預(yù)測(cè)庫(kù),可以在http://www.paddlepaddle.org/documentation/docs/zh/1.1/user_guides/howto/inference/build_and_install_lib_cn.html下載安裝。預(yù)測(cè)庫(kù)中提供了Paddle的預(yù)測(cè)API,預(yù)測(cè)部署過(guò)程大致分為三個(gè)步驟:1.創(chuàng)建PaddlePredictor;2.創(chuàng)建PaddleTensor傳入PaddlePredictor中;3.獲取輸出 PaddleTensor,輸出結(jié)果。這部分操作也并不復(fù)雜,而且Paddle的教程中也提供了一份部署詳細(xì)代碼參考,大家可以很快地利用這個(gè)模板完成模型部署(https://github.com/PaddlePaddle/Paddle/tree/develop/paddle/fluid/inference/api/demo_ci)

5.使用感受

  • 中文社區(qū)支持好

在搭建SSD過(guò)程中,遇到了一些問(wèn)題,例如segmentation fault、NoneType等,筆者直接在paddle的GitHub上提了相關(guān)issue,很快就得到了contributor的回復(fù),問(wèn)題很快得到了解決。

  • 教程完善

PaddlePaddle的官網(wǎng)上提供了非常詳盡的中英文教程,相較于之前學(xué)TensorFlow的時(shí)候經(jīng)??次臋n看半天才能理解其中的意思,PaddlePaddle對(duì)于中文使用者真是一大福音。

  • 相比較TensorFlow,整體架構(gòu)簡(jiǎn)明清晰,沒(méi)有太多難以理解的概念。
  • 模型庫(kù)豐富

內(nèi)置了CV、NLP、Recommendation等多種任務(wù)常用經(jīng)典的模型,可以快速開(kāi)發(fā)迭代AI產(chǎn)品。

  • 性能優(yōu)越,生態(tài)完整

從這次實(shí)驗(yàn)的結(jié)果來(lái)看,PaddlePaddle在性能上與TensorFlow等主流框架的性能差別不大,訓(xùn)練速度、CPU/GPU占用率等方面均表現(xiàn)優(yōu)異,而且PaddlePaddle已經(jīng)布局了一套完整的生態(tài),前景非常好。

6.總結(jié)

整體來(lái)說(shuō),PaddlePaddle是一個(gè)不錯(cuò)的框架。由于設(shè)計(jì)簡(jiǎn)潔加之文檔、社區(qū)做的很好,非常容易上手,在使用過(guò)程中也沒(méi)有非常難理解的概念,用fluid Program定義網(wǎng)絡(luò)結(jié)構(gòu)很方便,對(duì)于之前使用過(guò)TensorFlow的工程師來(lái)說(shuō)可以比較快速的遷移到PaddlePaddle上。這次實(shí)驗(yàn)過(guò)程中,還是發(fā)現(xiàn)了一些PaddlePaddle的問(wèn)題,訓(xùn)練過(guò)程如果意外終止,Paddle的訓(xùn)練任務(wù)并沒(méi)有被完全kill掉,依然會(huì)占用CPU和GPU大量資源,內(nèi)存和顯存的管理還需要進(jìn)一步的提高。不過(guò),實(shí)驗(yàn)也證實(shí)了,正常情況下PaddlePaddle在SSD模型上的精度、速度等性能與TensorFlow差不多,在數(shù)據(jù)讀取操作上比TensorFlow要更加簡(jiǎn)潔明了。

  1. PaddlePaddle Fluid是2016年百度對(duì)原有PaddlePaddle的重構(gòu)版本,如無(wú)特殊說(shuō)明,本文中所述PaddlePaddle均指PaddlePaddle Fluid。

  2. 此處引用了官方的評(píng)估結(jié)果,數(shù)據(jù)來(lái)源:https://github.com/PaddlePaddle/models/blob/develop/fluid/PaddleCV/object_detection/README_cn.md#%E6%A8%A1%E5%9E%8B%E8%AF%84%E4%BC%B0 

 

【51CTO原創(chuàng)稿件,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文作者和出處為51CTO.com】

責(zé)任編輯:張燕妮 來(lái)源: 51CTO
相關(guān)推薦

2020-07-25 19:40:33

Java開(kāi)發(fā)代碼

2014-09-19 15:37:11

WVS掃描工具安全掃描

2018-03-27 23:25:40

Paddle

2024-05-17 09:44:49

Kubernetes均衡器Envoy

2012-02-24 11:11:43

Platform

2018-04-18 09:39:07

深度學(xué)習(xí)

2017-09-22 11:45:10

深度學(xué)習(xí)OpenCVPython

2018-04-11 09:30:41

深度學(xué)習(xí)

2018-04-16 11:30:32

深度學(xué)習(xí)

2018-04-17 09:40:22

深度學(xué)習(xí)

2021-10-08 09:46:42

深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)人工智能

2018-04-09 10:20:32

深度學(xué)習(xí)

2018-03-26 21:26:50

深度學(xué)習(xí)

2018-03-26 21:31:30

深度學(xué)習(xí)

2018-03-26 20:14:32

深度學(xué)習(xí)

2017-10-02 16:13:47

深度學(xué)習(xí)目標(biāo)檢測(cè)計(jì)算機(jī)視覺(jué)

2020-03-09 14:08:25

Python目標(biāo)檢測(cè)視覺(jué)識(shí)別

2017-09-20 16:25:00

深度學(xué)習(xí)視覺(jué)領(lǐng)域計(jì)算機(jī)

2023-12-19 16:01:40

深度學(xué)習(xí)人工智能目標(biāo)檢測(cè)

2010-08-25 10:18:27

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)