??導(dǎo)語:PaddlePaddle是由百度研發(fā)蛮放,國內(nèi)首個(gè)開源的深度學(xué)習(xí)框架渺绒。你在學(xué)了N多機(jī)器學(xué)習(xí)課程后签餐,發(fā)現(xiàn)要手寫一個(gè)深度學(xué)習(xí)程序的時(shí)候仍會(huì)無從下手。本文目的是解決這種入門問題愚战,適合有深度學(xué)習(xí)基礎(chǔ)但不會(huì)寫程序娇唯,或者會(huì)使用其他深度學(xué)習(xí)框架但想學(xué)習(xí)PaddlePaddle使用方式的人群。本文將帶領(lǐng)大家將大腦中的想法及模型用PaddlePaddle框架實(shí)現(xiàn)出來寂玲。
設(shè)想一下塔插,如果要實(shí)現(xiàn)一個(gè)圖像分類的深度學(xué)習(xí)程序,有哪些必要的模塊拓哟?首先想到的是他一定要有一個(gè)描述想许、定義網(wǎng)絡(luò)結(jié)構(gòu)的模塊。在本文中我們就用VGG來描述網(wǎng)絡(luò)結(jié)構(gòu)断序,那第一個(gè)模塊就是Vgg_bn_drop流纹。有了這個(gè)網(wǎng)絡(luò)模塊我們可以推想出一定需要一個(gè)推理程序,這個(gè)程序會(huì)驅(qū)動(dòng)網(wǎng)絡(luò)模塊產(chǎn)生一個(gè)輸出逢倍,我們就叫這個(gè)輸出為Predict捧颅。那第二個(gè)模塊就是推理程序(Inference_Program)。我們有了Predict之后较雕,在訓(xùn)練過程中自然需要將Predict與數(shù)據(jù)集中的Label進(jìn)行比較,并通過損失函數(shù)來計(jì)算比較的差值挚币。那第三個(gè)模塊就是將Predict實(shí)例亮蒋、Label定義、cost函數(shù)計(jì)算整合在一起的程序妆毕,它在PaddlePaddle里我們將它成為train_func慎玖,那在這里我們將第三個(gè)模塊起名為train_program。在第三個(gè)模塊里我們定義了cost笛粘,cost存在的意義是計(jì)算當(dāng)前參數(shù)的推理與label的差值趁怔,從而調(diào)整網(wǎng)絡(luò)中的參數(shù)湿硝,那我們就需要定義一個(gè)優(yōu)化器來調(diào)整網(wǎng)絡(luò)中的參數(shù)。所以第四個(gè)模塊就是Optimizer润努。有了以上的四個(gè)模塊关斜,就將整個(gè)網(wǎng)絡(luò)運(yùn)轉(zhuǎn)的流程(從推理到反向調(diào)整)都定義好了。
我們將框架定義好之后铺浇,需要一個(gè)程序?qū)⑦@個(gè)框架給驅(qū)動(dòng)起來痢畜。這個(gè)驅(qū)動(dòng)程序還有一個(gè)作用是數(shù)據(jù)灌入框架中,讓數(shù)據(jù)再里面流動(dòng)起來(這也是Fluid這個(gè)詞的由來)鳍侣。在PaddlePaddle中丁稀,可以使用Trainer這個(gè)方法來實(shí)現(xiàn)這個(gè)功能。之后我們只需要將數(shù)據(jù)準(zhǔn)備好倚聚,做成reader的格式线衫,就可以使用Trainer中的train函數(shù)來執(zhí)行訓(xùn)練啦。
千里之行惑折,至于足下桶雀。我們來看一下第一步代碼該怎么寫。
一唬复、第一步除了導(dǎo)入各種庫之外矗积,
import paddle
import paddle.fluid as fluid
import numpy
import sys
from __future__ import print_function #用于提供Python3標(biāo)準(zhǔn)的print特性
自然是要將我們的第一個(gè)模塊——網(wǎng)絡(luò)結(jié)構(gòu)定義給實(shí)現(xiàn)出來。所以我們定義一個(gè)vgg_bn_drop的函數(shù):
def vgg_bn_drop(input):
??我們觀察一下VGG的網(wǎng)絡(luò)結(jié)構(gòu)
??可以發(fā)現(xiàn)VGG網(wǎng)絡(luò)中有很多重復(fù)的部分敞咧,如果我們把這些重復(fù)的卷積操作化為一組棘捣,那么VGG中卷積的部分可以分為五組。在PaddlePaddle中對于這種連續(xù)的卷積操作可以用img_conv_group函數(shù)來實(shí)現(xiàn)休建。
····def conv_block(參數(shù)先空著):
········return fluid.nets.img_conv_group()
??img_conv_group是整合了卷積層乍恐、池化層、BatchNorm和DropOut的復(fù)合函數(shù)测砂,并且可以很方便的支持連續(xù)卷及操作茵烈。我們想一下,對于每組連續(xù)卷積砌些,我們需要定義哪些內(nèi)容呢呜投?首先它必須接受一個(gè)數(shù)據(jù)輸入input。在卷積層方面存璃,我們可以想到的是要定義卷積核大小仑荐、卷積核數(shù)量、卷積層激活函數(shù)纵东;在池化層方面我們可以想到要定義池化區(qū)域的大小粘招、池化窗口的步長以及池化的方法。那關(guān)于DropOut的功能我們需要提供一個(gè)DropOut的概率偎球,在img_conv_group的參數(shù)中還有一個(gè)是否打開batchnorm的開關(guān)洒扎,需要指定一下辑甜。那么我們關(guān)img_conv_group的參數(shù)定義如下:
········return fluid.nets.img_conv_group(
input=ipt,
conv_filter_size=3,
conv_num_filter=[num_filter] * groups,
conv_act='relu',
pool_size=2,
pool_stride=2,
pool_type='max'
conv_with_batchnorm=True,
conv_batchnorm_drop_rate=dropouts)
根據(jù)VGG的網(wǎng)絡(luò)圖我們發(fā)現(xiàn)所有卷積層的卷積核都為3*3,那么我們在參數(shù)中就直接指定一個(gè)參數(shù)3袍冷,如果在此處給定兩個(gè)參數(shù)磷醋,PaddlePaddle會(huì)認(rèn)為這是個(gè)WH格式的矩形卷積核。conv_num_filte參數(shù)需要給定這組連續(xù)卷積操作中所有的卷積核數(shù)量难裆,以用來統(tǒng)一初始化子檀,所以這里需要在num_filter后乘上group的數(shù)量。根據(jù)論文我們可以知道激活函數(shù)為'relu'乃戈。根據(jù)VGG的網(wǎng)絡(luò)圖我們看到是二分之一池化褂痰,所以pool_size和pool_stride都定義為2。之后使用最大池化方法症虑、打開batchnorm選項(xiàng)缩歪、指定dropout的概率。需要注意的是這里給到的dropout需要以Python中List數(shù)據(jù)結(jié)構(gòu)給出谍憔,這個(gè)list存放的是連續(xù)卷積中每一層卷積的dropout概率匪蝙。到這里img_conv_group的定義就完成。根據(jù)這些參數(shù)习贫,去除硬編碼的參數(shù)我們發(fā)現(xiàn)input逛球、num_filter、groups苫昌、dropouts需要在上層函數(shù)中傳遞颤绕。所以conv_block參數(shù)如下:
····def conv_block(ipt, num_filter, groups, dropouts):
所以在這一步我們的連續(xù)卷積定義就完成啦。但是我們的conv_block不能只有連續(xù)卷積的定義祟身,還需要將他按照VGG模型的樣子給組裝起來奥务。那么卷積層的組裝代碼為:
····conv1 = conv_block(input, 64, 2, [0.3, 0])
conv2 = conv_block(conv1, 128, 2, [0.4, 0])
conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
從第二層開始,每一層接受上一層的輸出袜硫,第二個(gè)參數(shù)根據(jù)VGG結(jié)構(gòu)定義每一層輸出的維度氯葬,第三個(gè)參數(shù)定義連續(xù)卷積的次數(shù),第四個(gè)參數(shù)定義dropout的概率婉陷,最后一層不進(jìn)行dropout操作帚称。根據(jù)網(wǎng)絡(luò)結(jié)構(gòu),后面需要做三層全連接操作憨攒,定義如下:
····drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
fc1 = fluid.layers.fc(input=drop, size=512, act=None)
bn = fluid.layers.batch_norm(input=fc1, act='relu')
drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
predict = fluid.layers.fc(input=fc2, size=10, act='softmax')
這里用到了PaddlePaddle內(nèi)置的算子世杀,有全連接layers.fc,batch_norm和dropout肝集。所以整個(gè)vgg_bn_drop代碼如下:
def vgg_bn_drop(input):
def conv_block(ipt, num_filter, groups, dropouts):
return fluid.nets.img_conv_group(
input=ipt,
pool_size=2,
pool_stride=2,
conv_num_filter=[num_filter] * groups,
conv_filter_size=3,
conv_act='relu',
conv_with_batchnorm=True,
conv_batchnorm_drop_rate=dropouts,
pool_type='max')
conv1 = conv_block(input, 64, 2, [0.3, 0])
conv2 = conv_block(conv1, 128, 2, [0.4, 0])
conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
fc1 = fluid.layers.fc(input=drop, size=512, act=None)
bn = fluid.layers.batch_norm(input=fc1, act='relu')
drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
predict = fluid.layers.fc(input=fc2, size=10, act='softmax')
return predict
二、定義好網(wǎng)絡(luò)結(jié)構(gòu)以后蛛壳,我們需要將網(wǎng)絡(luò)的輸出Predict給接住杏瞻,并且將它的奶嘴(輸入格式)給備好所刀,所以我們定義
def inference_program():
方法時(shí)要先接住輸出:
predict = vgg_bn_drop(images)
再喂上奶嘴:
data_shape = [3, 32, 32]
images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
predict = vgg_bn_drop(images) # un-comment to use vgg net
在PaddlePaddle中,無論是圖像數(shù)據(jù)捞挥,張量數(shù)據(jù)還是標(biāo)簽數(shù)據(jù)浮创,都可以用layers.data容器來存放。在data函數(shù)中砌函,'name'參數(shù)是可以自定義指定的斩披。因?yàn)楸緦?shí)驗(yàn)是使用cifar10的數(shù)據(jù),是3通道32x32的圖片讹俊。所以inference_program的代碼如下:
def inference_program():
# The image is 32 * 32 with RGB representation.
data_shape = [3, 32, 32]
images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
#predict = resnet_cifar10(images, 32)
predict = vgg_bn_drop(images) # un-comment to use vgg net
return predict
三垦沉、根據(jù)開頭講的思路,我們有了推理模塊后仍劈,需要將Predict和label進(jìn)行交叉對比計(jì)算厕倍,所以我們需要一個(gè)train_program。train_program起到的作用是定義label贩疙、計(jì)算損失函數(shù)讹弯、計(jì)算準(zhǔn)確率。他需要將每一批的平均cost和準(zhǔn)確率轉(zhuǎn)給下一步的優(yōu)化器这溅。所以train_program的定義如下:
def train_program():
predict = inference_program()
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
cost = fluid.layers.cross_entropy(input=predict, label=label)
avg_cost = fluid.layers.mean(cost)
accuracy = fluid.layers.accuracy(input=predict, label=label)
return [avg_cost, accuracy]
我們得到cost之后组民,在訓(xùn)練過程需要根據(jù)cost返回的數(shù)據(jù)來反向調(diào)整神經(jīng)網(wǎng)絡(luò)中的參數(shù),那反向調(diào)整參數(shù)的模塊就叫optimizer_program悲靴,我們對optimizer_program的定義只需要返回指定的optimizer即可(在這里指定學(xué)習(xí)率超參數(shù)):
def optimizer_program():
return fluid.optimizer.Adam(learning_rate=0.001)
四臭胜、有了以上三個(gè)模塊,訓(xùn)練-推理-調(diào)整這一個(gè)有向循環(huán)圖就構(gòu)成了《钥ⅲ現(xiàn)在我們就像已經(jīng)將自來水管道修好庇楞,需要往里通水的狀態(tài)。那我們整個(gè)循環(huán)系統(tǒng)的中控程序是什么呢否纬?是fluid.Trainer吕晌。在PaddlePaddle中fluid.Trainer是一個(gè)較高層的API,使用時(shí)只需將fluid.Trainer這個(gè)類實(shí)例化即可临燃,啟動(dòng)實(shí)例化對象中的.train()方法即可啟動(dòng)網(wǎng)絡(luò)訓(xùn)練睛驳。那這就涉及到了兩個(gè)步驟:實(shí)例化對象和啟動(dòng)訓(xùn)練。
五膜廊、在實(shí)例化對象時(shí)需要指定3個(gè)參數(shù):train_func乏沸、optimizer和place。train_func就是我們剛才定義的train_program爪瓜,它包含了網(wǎng)絡(luò)正向推理及cost的所有信息蹬跃,只需將train_program傳遞給train_func參數(shù)就好。optimizer如同一轍铆铆。place的含義是整個(gè)訓(xùn)練程序在哪個(gè)設(shè)備上運(yùn)行蝶缀,不用多說丹喻,計(jì)算機(jī)中進(jìn)行大規(guī)模計(jì)算的硬件只有CPU和GPU。為了程序設(shè)計(jì)規(guī)范翁都,我們設(shè)置一個(gè)指定設(shè)備的開關(guān):
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
這樣我們就可以將Trainer實(shí)例化部分給寫出來了:
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
trainer = fluid.Trainer(
train_func=train_program,
optimizer_func=optimizer_program,
place=place)
六碍论、讀到這里是不是想趕緊運(yùn)行一下trainer.train()趕緊讓他先跑起來?且慢柄慰,我們發(fā)現(xiàn)鳍悠,我們只定義了數(shù)據(jù)的容器(杯子),且從沒有處理讓真正數(shù)據(jù)讀進(jìn)網(wǎng)絡(luò)的代碼(水)坐搔。所以我們還需要寫一個(gè)數(shù)據(jù)讀取藏研、預(yù)處理的模塊。因?yàn)閳D像識別的網(wǎng)絡(luò)都是將圖片一批一批訓(xùn)練的薯蝎,所以顯而易見我們需要數(shù)據(jù)讀入和分批這兩個(gè)操作遥倦。PaddlePaddle在daraset包里存放個(gè)各種各樣公開數(shù)據(jù)庫的API,一句話就可以調(diào)用這些數(shù)據(jù)包占锯,并返回Python reader格式的數(shù)據(jù)袒哥。所以我們的流程是先將數(shù)據(jù)從API中讀出來,然后做亂序處理消略,之后用batch函數(shù)進(jìn)行分批操作(在這里指定BATCH_SIZE超參數(shù)):
# Each batch will yield 128 images
BATCH_SIZE = 128
# Reader for training
train_reader = paddle.batch(
paddle.reader.shuffle(paddle.dataset.cifar.train10(), buf_size=50000),
batch_size=BATCH_SIZE)
# Reader for testing. A separated data set for testing.
test_reader = paddle.batch(
paddle.dataset.cifar.test10(), batch_size=BATCH_SIZE)
七堡称、是不是覺得有了數(shù)據(jù)就可以跑起來了?Naive~ 在trainer中艺演,必須指定一個(gè)事件處理函數(shù)才可以運(yùn)行却紧。這個(gè)函數(shù)的作用是觀察、調(diào)試參數(shù)胎撤,保存參數(shù)模型晓殊。這里我們用畫圖的方式來觀察網(wǎng)絡(luò)中cost參數(shù)的變化過程:
params_dirname = "image_classification_resnet.inference.model"
from paddle.v2.plot import Ploter
train_title = "Train cost"
test_title = "Test cost"
cost_ploter = Ploter(train_title, test_title)
step = 0
def event_handler_plot(event):
global step
if isinstance(event, fluid.EndStepEvent):
cost_ploter.append(train_title, step, event.metrics[0])
cost_ploter.plot()
step += 1
if isinstance(event, fluid.EndEpochEvent):
avg_cost, accuracy = trainer.test(
reader=test_reader,
feed_order=['pixel', 'label'])
cost_ploter.append(test_title, step, avg_cost)
# save parameters
if params_dirname is not None:
trainer.save_params(params_dirname)
使用paddle.v2.plot可以輕松在ipython notebook中將參數(shù)點(diǎn)在圖像中畫出來,核心代碼只有一個(gè) cost_ploter.append()
伤提。本塊代碼的核心是定義一個(gè)事件處理函數(shù)event_handler_plot巫俺。在這個(gè)函數(shù)中,對每批次訓(xùn)練和每一輪訓(xùn)練進(jìn)行不同的操作肿男。在每輪結(jié)束后介汹,event接口會(huì)收到fluid.EndStepEvent類的對象。在批次訓(xùn)練完成后event會(huì)收到fluid.EndEpochEvent類的對象舶沛,通過isinstance方法可以判斷event是哪個(gè)事件對象的實(shí)例嘹承。最后在完成每一輪數(shù)據(jù)的訓(xùn)練時(shí),我們將模型保存在第一行指定的地址如庭。
八叹卷、現(xiàn)在可以執(zhí)行訓(xùn)練了,啟動(dòng)trainer.train方法需要指定4個(gè)必要參數(shù):reader(Python reader格式的數(shù)據(jù)流)、num_epochs(對數(shù)據(jù)集訓(xùn)練輪次的超參數(shù))豪娜、event_handler(事件處理函數(shù))餐胀、feed_order(存放訓(xùn)練數(shù)據(jù)和標(biāo)簽的容器)哟楷。所以代碼如下:
trainer.train(
reader=train_reader,
num_epochs=2,
event_handler=event_handler_plot,
feed_order=['pixel', 'label'])
等待一會(huì)就可以看到輸出不斷變化的cost值了:
九、在訓(xùn)練一輪數(shù)據(jù)集之后卖擅,模型便保存在我們制定的路徑中了鸣奔。那如何使用這個(gè)模型來進(jìn)行預(yù)測呢?PaddlePaddle的預(yù)測代碼很簡單惩阶,先實(shí)例化一個(gè)預(yù)測引擎inferencer = fluid.Inferencer()
挎狸,然后使用inferencer.infer()啟動(dòng)引擎就可以了。所以我們想一下断楷,預(yù)測引擎啟動(dòng)前需要哪些參數(shù)呢锨匆?首先,推理程序是必不可少的冬筒,我們就使用之前寫的inference_program就可以恐锣,其次還要指定剛剛保存的模型存放路徑params_dirname。最后和trainer一樣舞痰,要指定一下計(jì)算運(yùn)行的設(shè)備place土榴。所以代碼如下:
inferencer = fluid.Inferencer(infer_func=inference_program, param_path=params_dirname, place=place)
results = inferencer.infer({'pixel': img})
我們從results中取到的是由每一分類的似然值構(gòu)成的List。ifar.train10是10分類數(shù)據(jù)响牛,所以我們將這個(gè)分類的名稱用人類的語言來描述一下:
label_list = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
然后result這個(gè)List中用np.argmax取最大概率的位置值玷禽,將其對應(yīng)的label輸出就得到了我們想要的分類了:
print("infer results: %s" % label_list[np.argmax(results[0])])
你以為大功告成了嗎?仔細(xì)看一下results = inferencer.infer({'pixel': img})
發(fā)現(xiàn)我們還沒有對要預(yù)測的圖像進(jìn)行處理呀打、定義矢赁。要符合PaddlePaddle的格式圖像應(yīng)為CHW格式(通道、高度贬丛、寬度)撩银,每個(gè)像素的顏色表示應(yīng)在[-1,1]的閉區(qū)間內(nèi)。所以我們使用Python內(nèi)置的PIL包來處理讀入的圖像:
# Prepare testing data.
from PIL import Image
import numpy as np
import os
def load_image(file):
im = Image.open(file)
im = im.resize((32, 32), Image.ANTIALIAS)
im = np.array(im).astype(np.float32)#浮點(diǎn)精度轉(zhuǎn)換
im = im.transpose((2, 0, 1)) # 轉(zhuǎn)為CHW順序
im = im / 255.0 #歸一化在[-1,1]的區(qū)間內(nèi)
# Add one dimension to mimic the list format.
im = numpy.expand_dims(im, axis=0)
return im
cur_dir = os.getcwd()#拼接為絕對地址
img = load_image( './image/dog.png')#要預(yù)測圖像的地址
所以我們的整段預(yù)測代碼為:
# Prepare testing data.
from PIL import Image
import numpy as np
import os
def load_image(file):
im = Image.open(file)
im = im.resize((32, 32), Image.ANTIALIAS)
im = np.array(im).astype(np.float32)
# The storage order of the loaded image is W(width),
# H(height), C(channel). PaddlePaddle requires
# the CHW order, so transpose them.
im = im.transpose((2, 0, 1)) # CHW
im = im / 255.0 #-1 - 1
# Add one dimension to mimic the list format.
im = numpy.expand_dims(im, axis=0)
return im
cur_dir = os.getcwd()
img = load_image(cur_dir + '/03.image_classification/image/dog.png')
#img = load_image( './image/dog.png')
inferencer = fluid.Inferencer(infer_func=inference_program, param_path=params_dirname, place=place)
label_list = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
# inference
results = inferencer.infer({'pixel': img})
#print(results[0])
print("infer results: %s" % label_list[np.argmax(results[0])+1])
十瘫寝、附整個(gè)過程的完整代碼:
import paddle
import paddle.fluid as fluid
import numpy
import sys
from __future__ import print_function
def vgg_bn_drop(input):
def conv_block(ipt, num_filter, groups, dropouts):
return fluid.nets.img_conv_group(
input=ipt,
pool_size=2,
pool_stride=2,
conv_num_filter=[num_filter] * groups,
conv_filter_size=3,
conv_act='relu',
conv_with_batchnorm=True,
conv_batchnorm_drop_rate=dropouts,
pool_type='max')
conv1 = conv_block(input, 64, 2, [0.3, 0])
conv2 = conv_block(conv1, 128, 2, [0.4, 0])
conv3 = conv_block(conv2, 256, 3, [0.4, 0.4, 0])
conv4 = conv_block(conv3, 512, 3, [0.4, 0.4, 0])
conv5 = conv_block(conv4, 512, 3, [0.4, 0.4, 0])
drop = fluid.layers.dropout(x=conv5, dropout_prob=0.5)
fc1 = fluid.layers.fc(input=drop, size=512, act=None)
bn = fluid.layers.batch_norm(input=fc1, act='relu')
drop2 = fluid.layers.dropout(x=bn, dropout_prob=0.5)
fc2 = fluid.layers.fc(input=drop2, size=512, act=None)
predict = fluid.layers.fc(input=fc2, size=10, act='softmax')
return predict
def inference_program():
# The image is 32 * 32 with RGB representation.
data_shape = [3, 32, 32]
images = fluid.layers.data(name='pixel', shape=data_shape, dtype='float32')
#predict = resnet_cifar10(images, 32)
predict = vgg_bn_drop(images) # un-comment to use vgg net
return predict
def train_program():
predict = inference_program()
label = fluid.layers.data(name='label', shape=[1], dtype='int64')
cost = fluid.layers.cross_entropy(input=predict, label=label)
avg_cost = fluid.layers.mean(cost)
accuracy = fluid.layers.accuracy(input=predict, label=label)
return [avg_cost, accuracy]
def optimizer_program():
return fluid.optimizer.Adam(learning_rate=0.001)
use_cuda = False
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
trainer = fluid.Trainer(
train_func=train_program,
optimizer_func=optimizer_program,
place=place)
# Each batch will yield 128 images
BATCH_SIZE = 128
# Reader for training
train_reader = paddle.batch(
paddle.reader.shuffle(paddle.dataset.cifar.train10(), buf_size=50000),
batch_size=BATCH_SIZE)
# Reader for testing. A separated data set for testing.
test_reader = paddle.batch(
paddle.dataset.cifar.test10(), batch_size=BATCH_SIZE)
params_dirname = "image_classification_resnet.inference.model"
from paddle.v2.plot import Ploter
train_title = "Train cost"
test_title = "Test cost"
cost_ploter = Ploter(train_title, test_title)
step = 0
def event_handler_plot(event):
global step
if isinstance(event, fluid.EndStepEvent):
cost_ploter.append(train_title, step, event.metrics[0])
cost_ploter.plot()
step += 1
if isinstance(event, fluid.EndEpochEvent):
avg_cost, accuracy = trainer.test(
reader=test_reader,
feed_order=['pixel', 'label'])
cost_ploter.append(test_title, step, avg_cost)
# save parameters
if params_dirname is not None:
trainer.save_params(params_dirname)
trainer.train(
reader=train_reader,
num_epochs=2,
event_handler=event_handler_plot,
feed_order=['pixel', 'label'])
# Prepare testing data.
from PIL import Image
import numpy as np
import os
def load_image(file):
im = Image.open(file)
im = im.resize((32, 32), Image.ANTIALIAS)
im = np.array(im).astype(np.float32)
# The storage order of the loaded image is W(width),
# H(height), C(channel). PaddlePaddle requires
# the CHW order, so transpose them.
im = im.transpose((2, 0, 1)) # CHW
im = im / 255.0 #-1 - 1
# Add one dimension to mimic the list format.
im = numpy.expand_dims(im, axis=0)
return im
cur_dir = os.getcwd()
img = load_image(cur_dir + '/03.image_classification/image/dog.png')
#img = load_image( './image/dog.png')
inferencer = fluid.Inferencer(infer_func=inference_program, param_path=params_dirname, place=place)
label_list = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
# inference
results = inferencer.infer({'pixel': img})
#print(results[0])
print("infer results: %s" % label_list[np.argmax(results[0])+1])