0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

在FPGA上實現(xiàn)深度學(xué)習(xí)

OpenFPGA ? 來源:OpenFPGA ? 2023-02-15 09:41 ? 次閱讀

在上一篇文章中,談到了深度學(xué)習(xí)是什么以及在 FPGA 上進行深度學(xué)習(xí)的好處。在本課程的后續(xù)文章中,我們將開始開發(fā)針對 FPGA 的深度學(xué)習(xí)設(shè)計。特別是,在本文中,我們將首先在 Python 上運行訓(xùn)練代碼,并創(chuàng)建一個網(wǎng)絡(luò)模型方便在后續(xù) FPGA 上運行。

在后續(xù)文章中,我們將根據(jù)實際源碼進行講解。稍后將提供包括 FPGA 設(shè)計在內(nèi)的所有代碼。

要使用的數(shù)據(jù)集工具

MNIST 數(shù)據(jù)庫

本課程針對的問題是通常稱為圖像分類的任務(wù)。在這個任務(wù)中,我們輸出一個代表輸入圖像的標(biāo)簽。這里的標(biāo)簽例如是圖像中物體的通用名稱。

MNIST 數(shù)據(jù)庫是一個包含 0 到 9 的手寫數(shù)字的數(shù)據(jù)集,并為每個手寫數(shù)字定義了正確的標(biāo)簽 (0-9)。由于輸入是一張28x28的灰度圖,輸出最多10個類,在圖像分類任務(wù)中屬于非常初級的任務(wù)。除了 MNIST 之外,主要的圖像分類數(shù)據(jù)集包括CIFAR10和ImageNet,并且往往會按上訴列出的順序成為更難的問題。

MNIST 在許多深度學(xué)習(xí)教程中都有使用,因為它是一個非常簡單的數(shù)據(jù)集。由于本課程的主要目的是在 FPGA 上實現(xiàn)深度學(xué)習(xí),因此我們將創(chuàng)建一個針對 MNIST 的學(xué)習(xí)模型。

fe7783d0-a86b-11ed-bfe3-dac502259ad0.png

MNIST 數(shù)據(jù)庫——維基百科

PyTorch

PyTorch是來自 Facebook 的開源深度學(xué)習(xí)框架,也是與來自 Google 的TensorFlow一起使用最頻繁的框架之一。在本文中,我們將在 PyTorch 上學(xué)習(xí)和創(chuàng)建網(wǎng)絡(luò)模型。

PyTorch安裝參考官網(wǎng)步驟。我使用的 Ubuntu 16.04 LTS 上安裝的 Python 3.5 不支持最新的 PyTorch,所以我使用以下命令安裝了舊版本。

pipinstalltorch==1.4.0torchvision==0.5.0

由于本文的重點不在于如何使用PyTorch,所以我將省略代碼的解釋,尤其是學(xué)習(xí)部分。如果有興趣,建議嘗試下面的官方教程,盡管它是英文的。

卷積神經(jīng)網(wǎng)絡(luò)

卷積神經(jīng)網(wǎng)絡(luò) (CNN) 是一種旨在在圖像任務(wù)中表現(xiàn)出色的神經(jīng)網(wǎng)絡(luò)。本文創(chuàng)建的網(wǎng)絡(luò)模型是一個卷積神經(jīng)網(wǎng)絡(luò),該網(wǎng)絡(luò)由以下三層和激活函數(shù)的組合組成。

全連接層

卷積層

池化層

激活函數(shù)

下面概述了每一層的處理和作用。

全連接層

全連接層是通過將輸入向量乘以內(nèi)部參數(shù)矩陣來輸出向量的過程。如果只說神經(jīng)網(wǎng)絡(luò)沒有前言比如卷積,往往指的就是這個全連接層。

fe8aa62c-a86b-11ed-bfe3-dac502259ad0.png

由于全連接層的輸入是向量,所以無法得到圖像中應(yīng)該注意的與周圍像素點的關(guān)系。在卷積神經(jīng)網(wǎng)絡(luò)中,全連接層主要用于將卷積層和池化層創(chuàng)建的壓縮圖像信息(特征)轉(zhuǎn)換為標(biāo)簽數(shù)據(jù)(0-9)。

卷積層

卷積層是對圖像進行卷積處理的層。如果熟悉圖像處理,可能會稱其為濾鏡處理。

在卷積層中,對于輸入圖像中的每個像素,獲取周圍像素的像素值,每個像素值乘以一個數(shù)組(kernel),它是一個內(nèi)參,求和就是像素值輸出圖像。這以圖形方式表示,如下所示。

fea10322-a86b-11ed-bfe3-dac502259ad0.png

卷積神經(jīng)網(wǎng)絡(luò)的許多層都是由這個卷積層組成的,因為它以這種方式針對圖像處理。

池化層

池化層是用于壓縮由卷積層獲得的信息的層。使用本次使用的參數(shù),通過取圖像中2x2塊的最大值將圖像大小減半。下圖顯示了最大值的減少處理。

fec523e2-a86b-11ed-bfe3-dac502259ad0.png

通過應(yīng)用多個池化層,聚合圖像每個部分的信息,并接近表示最終圖像整體的標(biāo)簽信息。

激活函數(shù)

激活函數(shù)是一個非線性函數(shù),插入在卷積層和全連接層之后。這是為了避免將實際上是線性函數(shù)的兩層合并為一層。已經(jīng)提出了各種類型的激活函數(shù),但近年來 ReLU 是主要使用的激活函數(shù)。

ReLU 是 Rectified Linear Unit 的縮寫。該函數(shù)會將小于0的輸入值置為0,大于0的值原樣輸出。

創(chuàng)建網(wǎng)絡(luò)模型

使用的網(wǎng)絡(luò)模型是著名網(wǎng)絡(luò)模型LeNet的簡化版。LeNet 是早期的卷積神經(jīng)網(wǎng)絡(luò)之一,和這個一樣,都是針對手寫識別的。

本文使用的模型定義如下。與原來的LeNet相比,有一些不同之處,例如卷積層的核大小減小,激活函數(shù)為ReLU。

classNet(nn.Module):
def__init__(self,num_output_classes=10):
super(Net,self).__init__()


self.conv1=nn.Conv2d(in_channels=1,out_channels=4,kernel_size=3,padding=1)

#激活函數(shù)ReLU
self.relu1=nn.ReLU(inplace=True)

#
self.pool1=nn.MaxPool2d(kernel_size=2,stride=2)

#4ch->8ch,14x14->7x7
self.conv2=nn.Conv2d(in_channels=4,out_channels=8,kernel_size=3,padding=1)
self.relu2=nn.ReLU(inplace=True)
self.pool2=nn.MaxPool2d(kernel_size=2,stride=2)

#全連接層
self.fc1=nn.Linear(8*7*7,32)
self.relu3=nn.ReLU(inplace=True)

#全連接層
self.fc2=nn.Linear(32,num_output_classes)

defforward(self,x):

#激活函數(shù)ReLU
x=self.conv1(x)
x=self.relu1(x)

#縮小
x=self.pool1(x)

#2層+縮小
x=self.conv2(x)
x=self.relu2(x)
x=self.pool2(x)

#(Batch,Ch,Height,Width)->(Batch,Ch)
x=x.view(x.shape[0],-1)

#全連接層
x=self.fc1(x)
x=self.relu3(x)
x=self.fc2(x)

returnx

使用netron可視化此模型的數(shù)據(jù)流如下所示:

fed9a06a-a86b-11ed-bfe3-dac502259ad0.png

按照數(shù)據(jù)的順序流動,首先輸入一張手寫圖像(28×28, 1ch),在第一個Conv2d層轉(zhuǎn)換為(28×28, 4ch)的圖像,通過ReLU變成非負(fù)的。

然后通過 Maxpool2d 層將該圖像縮小為 (14×14, 4ch) 圖像。隨后的 Conv2d、ReLU、MaxPool2d 遵循幾乎相同的程序,生成 (7×7, 8ch) 圖像。將此圖像視為7x7x8 = 392度的向量,應(yīng)用兩次全連接層最終將輸出10度的向量。此 10 階向量中具有最大值的元素的索引 (argmax) 是推斷字符 (0-9)。

學(xué)習(xí)/推理

使用上述模型訓(xùn)練 MNIST。這里需要執(zhí)行三個步驟:

加載訓(xùn)練/測試數(shù)據(jù)

循環(huán)學(xué)習(xí)

測試(推理)

首先,讀取數(shù)據(jù)。PyTorch 帶有一個預(yù)定義的 MNIST 加載器,我們用它來加載數(shù)據(jù)(訓(xùn)練集/測試集)。trainloader/testloader 是定義如何讀取每個數(shù)據(jù)集中數(shù)據(jù)的對象。

importtorch
importtorchvision
importtorchvision.transformsastransforms

#2.定義數(shù)據(jù)集讀取方法
#獲取MNIST的學(xué)習(xí)測試數(shù)據(jù)
trainset=torchvision.datasets.MNIST(root='./data',train=True,download=True,transform=transforms.ToTensor())
testset=torchvision.datasets.MNIST(root='./data',train=False,download=True,transform=transforms.ToTensor())

#數(shù)據(jù)讀取方法的定義
#1步驟的每個學(xué)習(xí)測試讀取16張圖像
trainloader=torch.utils.data.DataLoader(trainset,batch_size=16,shuffle=True)
testloader=torch.utils.data.DataLoader(testset,batch_size=16,shuffle=False)

現(xiàn)在數(shù)據(jù)讀取已經(jīng)完成,是時候開始學(xué)習(xí)了。首先,我們定義損失函數(shù)(誤差函數(shù))和優(yōu)化器。在后續(xù)的學(xué)習(xí)中,我們會朝著損失值減小的方向?qū)W習(xí)。

#損失函數(shù),最優(yōu)化器的定義
loss_func=nn.CrossEntropyLoss()
optimizer=torch.optim.Adam(net.parameters(),lr=0.0001)

學(xué)習(xí)循環(huán)像這樣:從trainloader讀取輸入數(shù)據(jù)(inputs),糾正標(biāo)簽(labels),通過網(wǎng)絡(luò)得到輸出(outputs),得到帶有正確標(biāo)簽的error(loss)。

然后我們使用一種稱為誤差反向傳播 (loss.backward()) 的技術(shù)來計算每一層的學(xué)習(xí)方向(梯度)。優(yōu)化器使用獲得的梯度來優(yōu)化模型(optimizer.step())。這是一步學(xué)習(xí)流程,在此代碼中,重復(fù)學(xué)習(xí)直到夠 10 個數(shù)據(jù)集。

由于我們將使用 FPGA 進行推理處理,因此即使不了解此處描述的學(xué)習(xí)過程也沒有問題。如果你對我們?yōu)槭裁催@樣學(xué)習(xí)感興趣,請參考上一篇文章中一些通俗易懂的文獻。

#循環(huán)直到使用數(shù)據(jù)集中的所有圖像10次
forepochinrange(10):
running_loss=0

#在數(shù)據(jù)集中循環(huán)
fori,datainenumerate(trainloader,0):
#導(dǎo)入輸入批(圖像,正確標(biāo)簽)
inputs,labels=data

#零初始化優(yōu)化程序
optimizer.zero_grad()

#通過模型獲取輸入圖像的輸出標(biāo)簽
outputs=net(inputs)

#與正確答案的誤差計算+誤差反向傳播
loss=loss_func(outputs,labels)
loss.backward()

#使用誤差優(yōu)化模型
optimizer.step()
running_loss+=loss.item()
ifi%1000==999:
print('[%d,%5d]loss:%.3f'%
(epoch+1,i+1,running_loss/1000))
running_loss=0.0

測試代碼如下所示:該測試與學(xué)習(xí)循環(huán)幾乎相同,但省略了學(xué)習(xí)的損失計算。scikit-learn我們還使用這里的函數(shù)來accuracy_score, confusion_matrix輸出準(zhǔn)確度和混淆矩陣。

fromsklearn.metricsimportaccuracy_score,confusion_matrix

#4.測試
ans=[]
pred=[]
fori,datainenumerate(testloader,0):
inputs,labels=data
outputs=net(inputs)

ans+=labels.tolist()
pred+=torch.argmax(outputs,1).tolist()

print('accuracy:',accuracy_score(ans,pred))
print('confusionmatrix:')
print(confusion_matrix(ans,pred))

通過到目前為止的實施,可以在 PyTorch 上訓(xùn)練和推斷 MNIST。當(dāng)我在 i7 CPU 上實際運行上述代碼時,該過程在大約 3 分鐘內(nèi)完成。日志在下面。

[n, m] loss: X這條線表示第n個epoch(使用數(shù)據(jù)集的次數(shù))和學(xué)習(xí)數(shù)據(jù)集中第m個數(shù)據(jù)時的損失(錯誤)??梢钥闯?,隨著學(xué)習(xí)的進行,損失幾乎接近于 0。即使是這種非常小的網(wǎng)絡(luò)模型也可以成功學(xué)習(xí)。

測試準(zhǔn)確率最終顯示出足夠高的準(zhǔn)確率,達到 97.26%。接下來的矩陣是混淆矩陣(confusion_matrix),其中第i行第j列的值代表正確答案i和推理結(jié)果j。這次數(shù)據(jù)的準(zhǔn)確性足夠了,結(jié)果似乎沒有什么明顯的偏差。這一次,我們一次性得到了足夠的準(zhǔn)確率,但是我們在原來的開發(fā)中并沒有得到我們想要的準(zhǔn)確率,所以我們在這里回顧一下模型和學(xué)習(xí)方法。

[1,1000]loss:1.765
[1,2000]loss:0.655
[1,3000]loss:0.475
...
[10,1000]loss:0.106
[10,2000]loss:0.101
[10,3000]loss:0.104
accuracy:0.9726
confusionmatrix:
[[973010020220]
[0112821002020]
[3399780127101]
[10696801205108]
[1030960012213]
[310508702074]
[1021178927020]
[1390100100617]
[51112433892710]
[56031010104970]]

最后,使用以下代碼保存模型。前者是從 PyTorch 重新評估的模型文件,后者用于在 PyTorch 的 C++ API(libtorch)上讀取網(wǎng)絡(luò)模型。

#5.保存模型
#用于從PyTorch正常讀取的模型文件
torch.save(net.state_dict(),'model.pt')

#保存用于從libtorch(C++API)讀取的TorchScriptModule
example=torch.rand(1,1,28,28)
traced_script_module=torch.jit.trace(net,example)
traced_script_module.save('traced_model.pt')

總結(jié)

在本文中,我們使用 MNIST 數(shù)據(jù)集作為學(xué)習(xí)目標(biāo)來創(chuàng)建、訓(xùn)練和推斷網(wǎng)絡(luò)模型。

使用基于 LeNet 的輕量級網(wǎng)絡(luò)模型,我們能夠在 MNIST 數(shù)據(jù)集上實現(xiàn)良好的準(zhǔn)確性。在下一篇和后續(xù)文章中,我們的目標(biāo)是在 FPGA 上運行該模型,并在考慮高級綜合(HLS)的情況下開始 C++ 實現(xiàn)。






審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1629

    文章

    21750

    瀏覽量

    604058
  • 數(shù)據(jù)庫
    +關(guān)注

    關(guān)注

    7

    文章

    3817

    瀏覽量

    64485
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84787
  • Ubuntu系統(tǒng)
    +關(guān)注

    關(guān)注

    0

    文章

    91

    瀏覽量

    3986
  • MNIST
    +關(guān)注

    關(guān)注

    0

    文章

    10

    瀏覽量

    3386

原文標(biāo)題:從FPGA說起的深度學(xué)習(xí)(二)

文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    相比GPU和GPP,FPGA深度學(xué)習(xí)的未來?

    相比GPU和GPP,FPGA滿足深度學(xué)習(xí)的硬件需求提供了具有吸引力的替代方案。憑借流水線并行計算的能力和高效的能耗,
    發(fā)表于 07-28 12:16 ?7482次閱讀

    FPGA深度學(xué)習(xí)應(yīng)用中或?qū)⑷〈鶪PU

    上漲,因為事實表明,它們的 GPU 訓(xùn)練和運行 深度學(xué)習(xí)模型 方面效果明顯。實際,英偉達也已經(jīng)對自己的業(yè)務(wù)進行了轉(zhuǎn)型,之前它是一家純粹做 GPU 和游戲的公司,現(xiàn)在除了作為一家云
    發(fā)表于 03-21 15:19

    FPGA深度學(xué)習(xí)能走多遠?

    。FPGA的優(yōu)勢就是可編程可配置,邏輯資源多,功耗低,而且賽靈思等都在極力推廣。不知道用FPGA深度學(xué)習(xí)未來會怎樣發(fā)展,能走多遠,你怎么看。 A:
    發(fā)表于 09-27 20:53

    【詳解】FPGA深度學(xué)習(xí)的未來?

    。此外,FPGA正迅速取代ASIC和應(yīng)用專用標(biāo)準(zhǔn)產(chǎn)品(ASSP)來實現(xiàn)固定功能邏輯。 FPGA市場規(guī)模預(yù)計2016年將達到100億美元。對于深度
    發(fā)表于 08-13 09:33

    深度學(xué)習(xí)汽車中的應(yīng)用

    嵌入式開發(fā)和平臺抽象;TI硬件實現(xiàn)用于加速CNN的高度優(yōu)化的內(nèi)核,以及支持從開放框架(如Caffe和TensorFlow)到使用TIDL應(yīng)用程序編程界面的嵌入式框架進行網(wǎng)絡(luò)轉(zhuǎn)換的轉(zhuǎn)換器。有關(guān)此解決方案的更多詳細信息,請閱讀白
    發(fā)表于 03-13 06:45

    什么是深度學(xué)習(xí)?使用FPGA進行深度學(xué)習(xí)的好處?

    FPGA實現(xiàn)。易于適應(yīng)新的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)深度學(xué)習(xí)是一個非?;钴S的研究領(lǐng)域,每天都在設(shè)計新的 DNN。其中許多結(jié)合了現(xiàn)有的標(biāo)準(zhǔn)計算,但有些需要全新的計算方法。特別是
    發(fā)表于 02-17 16:56

    FPGA深度學(xué)習(xí)的未來

    FPGA深度學(xué)習(xí)的未來,學(xué)習(xí)資料,感興趣的可以看看。
    發(fā)表于 10-26 15:29 ?0次下載

    云中的機器學(xué)習(xí)FPGA深度神經(jīng)網(wǎng)絡(luò)

    憑借出色的性能和功耗指標(biāo),賽靈思 FPGA 成為設(shè)計人員構(gòu)建卷積神經(jīng)網(wǎng)絡(luò)的首選。新的軟件工具可簡化實現(xiàn)工作。人工智能正在經(jīng)歷一場變革,這要得益于機器學(xué)習(xí)的快速進步。機器
    發(fā)表于 11-17 11:47 ?1383次閱讀

    FPGA深度學(xué)習(xí)領(lǐng)域的應(yīng)用

    本文從硬件加速的視角考察深度學(xué)習(xí)FPGA,指出有哪些趨勢和創(chuàng)新使得這些技術(shù)相互匹配,并激發(fā)對FPGA如何幫助深度
    的頭像 發(fā)表于 06-28 17:31 ?6940次閱讀

    FPGA深度學(xué)習(xí)領(lǐng)域的未來會有怎樣的發(fā)展

    近十年來,人工智能又到了一個快速發(fā)展的階段。深度學(xué)習(xí)在其發(fā)展中起到了中流砥柱的作用,盡管擁有強大的模擬預(yù)測能力,深度學(xué)習(xí)還面臨著超大計算量的問題。
    發(fā)表于 10-22 15:26 ?1080次閱讀

    FPGA說起的深度學(xué)習(xí)

    這是新的系列教程,本教程中,我們將介紹使用 FPGA 實現(xiàn)深度學(xué)習(xí)的技術(shù),深度
    的頭像 發(fā)表于 03-03 09:52 ?1532次閱讀

    FPGA深度學(xué)習(xí)領(lǐng)域有哪些優(yōu)勢?

    FPGA(Field-Programmable Gate Array)是一種靈活的可編程硬件設(shè)備,它在深度學(xué)習(xí)應(yīng)用領(lǐng)域中具有許多優(yōu)勢。
    的頭像 發(fā)表于 03-09 09:41 ?1797次閱讀

    FPGA說起的深度學(xué)習(xí):任務(wù)并行性

    這是新的系列教程,本教程中,我們將介紹使用 FPGA 實現(xiàn)深度學(xué)習(xí)的技術(shù),深度
    的頭像 發(fā)表于 04-12 10:19 ?996次閱讀

    FPGA說起的深度學(xué)習(xí):數(shù)據(jù)并行性

    這是新的系列教程,本教程中,我們將介紹使用 FPGA 實現(xiàn)深度學(xué)習(xí)的技術(shù),深度
    的頭像 發(fā)表于 05-04 11:22 ?1327次閱讀
    從<b class='flag-5'>FPGA</b>說起的<b class='flag-5'>深度</b><b class='flag-5'>學(xué)習(xí)</b>:數(shù)據(jù)并行性

    FPGA加速深度學(xué)習(xí)模型的案例

    FPGA(現(xiàn)場可編程門陣列)加速深度學(xué)習(xí)模型是當(dāng)前硬件加速領(lǐng)域的一個熱門研究方向。以下是一些FPGA加速深度
    的頭像 發(fā)表于 10-25 09:22 ?254次閱讀