隨著攝像頭和其他設(shè)備產(chǎn)生的數(shù)據(jù)在快速增長(zhǎng),促使人們運(yùn)用機(jī)器學(xué)習(xí)從汽車(chē)、安防和其他應(yīng)用產(chǎn)生的影像中提取更多有用的信息。專(zhuān)用器件有望在嵌入式視覺(jué)應(yīng)用中實(shí)現(xiàn)高性能機(jī)器學(xué)習(xí) (ML) 推理。但是此類(lèi)器件大都處于早期開(kāi)發(fā)階段,因?yàn)樵O(shè)計(jì)人員正在努力尋找最有效的算法,甚至人工智能 (AI) 研究人員也在迅速推演新方法。
目前,開(kāi)發(fā)人員一般使用針對(duì) ML 的可用 FPGA 平臺(tái)來(lái)構(gòu)建嵌入式視覺(jué)系統(tǒng),以期滿足更高的性能要求。與此同時(shí),他們可以保持所需的靈活性,以跟上機(jī)器學(xué)習(xí)發(fā)展的步伐。
本文將介紹 ML 處理的要求,以及為何 FPGA 能解決許多性能問(wèn)題。然后,將介紹一個(gè)合適的基于 FPGA 的 ML 平臺(tái)及其使用方法。
在 ML 算法中,卷積神經(jīng)網(wǎng)絡(luò) (CNN) 已成為圖像分類(lèi)的首選解決方案。其圖像識(shí)別的準(zhǔn)確率非常高,因而得以廣泛應(yīng)用于多種應(yīng)用,跨越不同的平臺(tái),例如智能手機(jī)、安防系統(tǒng)和汽車(chē)駕駛員輔助系統(tǒng)。作為一種深度神經(jīng)網(wǎng)絡(luò) (DNN),CNN 使用的神經(jīng)網(wǎng)絡(luò)架構(gòu)由專(zhuān)用層構(gòu)成。在對(duì)標(biāo)注圖像進(jìn)行訓(xùn)練期間,它會(huì)從圖像中提取特征,并使用這些特征給圖像分類(lèi)(參見(jiàn)“利用現(xiàn)成的軟硬件啟動(dòng)機(jī)器學(xué)習(xí)”)。
CNN 開(kāi)發(fā)人員通常在高性能系統(tǒng)或云平臺(tái)上進(jìn)行訓(xùn)練,使用圖形處理單元 (GPU) 加速在標(biāo)注圖像數(shù)據(jù)集(通常數(shù)以百萬(wàn)計(jì))上訓(xùn)練模型所需的巨量矩陣計(jì)算。訓(xùn)練完成之后,訓(xùn)練好的模型用在推理應(yīng)用中,對(duì)視頻流中的新圖像或幀進(jìn)行分類(lèi)。推理部署完成后,訓(xùn)練好的模型仍然需要執(zhí)行同樣的矩陣計(jì)算,但由于輸入量要少很多,開(kāi)發(fā)人員可以將 CNN 用于在通用硬件上運(yùn)行的普通機(jī)器學(xué)習(xí)應(yīng)用(參見(jiàn)“利用 Raspberry Pi 構(gòu)建機(jī)器學(xué)習(xí)應(yīng)用”)。
然而,對(duì)于許多應(yīng)用而言,通用平臺(tái)缺乏在 CNN 推理中同時(shí)實(shí)現(xiàn)高準(zhǔn)確率和高性能所需的性能。優(yōu)化技術(shù)和替代 CNN 架構(gòu)(如 MobileNet 或 SqueezeNet)有助于降低平臺(tái)要求,但通常會(huì)犧牲準(zhǔn)確率并增加推理延時(shí),而這可能與應(yīng)用要求相沖突。
與此同時(shí),快速發(fā)展的算法使得機(jī)器學(xué)習(xí) IC 的設(shè)計(jì)工作變得復(fù)雜,因?yàn)樾枰獧C(jī)器學(xué)習(xí) IC 既要足夠?qū)iT(mén)化以加速推理,又要足夠通用化以支持新算法。FPGA 多年來(lái)一直扮演著這一特定角色,提供加速關(guān)鍵算法所需的性能和靈活性,解決了通用處理器性能不足或沒(méi)有專(zhuān)用器件可用的問(wèn)題。
對(duì)于機(jī)器學(xué)習(xí)而言,GPU 仍然是標(biāo)桿——這是早期的 FPGA 根本無(wú)法企及的。最近出現(xiàn)的一些器件,如 Intel Arria 10 GX FPGA 和 Lattice Semiconductor ECP5 FPGA,大大縮小了先進(jìn) FPGA 和 GPU 之間的差距。對(duì)于某些使用緊湊的整數(shù)數(shù)據(jù)類(lèi)型的 DNN 架構(gòu)來(lái)說(shuō),此類(lèi) FPGA 的性能/功耗比甚至高于主流 GPU。
高級(jí) FPGA 組合了嵌入式存儲(chǔ)器和數(shù)字信號(hào)處理 (DSP) 資源,對(duì)于一般矩陣乘法 (GEMM) 運(yùn)算能夠?qū)崿F(xiàn)很高的性能。其嵌入式存儲(chǔ)器靠近計(jì)算引擎,從而緩解了 CPU 存儲(chǔ)器瓶頸,而這種瓶頸通常會(huì)限制通用處理器上機(jī)器學(xué)習(xí)算法的性能。反之,相比于典型 DSP 器件(圖 1),F(xiàn)PGA 上的嵌入式 DSP 計(jì)算引擎提供了更多的并行乘法器資源。FPGA 廠商在交付專(zhuān)門(mén)用于機(jī)器學(xué)習(xí)的 FPGA 開(kāi)發(fā)平臺(tái)時(shí)充分利用了這些特性。
圖 1:Lattice Semiconductor ECP5 之類(lèi)的高級(jí) FPGA 提供了實(shí)現(xiàn)高性能推理所需的并行處理資源和嵌入式存儲(chǔ)器。(圖片來(lái)源:Lattice Semiconductor)
例如,Intel 最近推出的支持 FPGA 的 OPENVINO™ 擴(kuò)展了該平臺(tái)將推理模型部署到不同類(lèi)型設(shè)備(包括 GPU、CPU 和 FPGA)的能力。在該平臺(tái)上,開(kāi)發(fā)人員可使用 Intel 的深度學(xué)習(xí)推理引擎工作流程,其中整合了 Intel 深度學(xué)習(xí)部署工具包和在 Intel OPENVINO 工具包中提供的 Intel 計(jì)算機(jī)視覺(jué)軟件開(kāi)發(fā)套件 (SDK)。開(kāi)發(fā)人員使用 SDK 的應(yīng)用編程接口 (API) 構(gòu)建模型,并且可利用 Intel 的運(yùn)行模型優(yōu)化器針對(duì)不同硬件平臺(tái)進(jìn)行優(yōu)化。
深度學(xué)習(xí)部署工具包旨在與 Intel DK-DEV-10AX115S-A Arria 10 GX FPGA 開(kāi)發(fā)套件配合使用,讓開(kāi)發(fā)人員能從領(lǐng)先的 ML 框架(包括 Caffe 和 TensorFlow)導(dǎo)入訓(xùn)練好的模型(圖 2)。在諸如 Arria 10 GX FPGA 開(kāi)發(fā)套件之類(lèi)目標(biāo)平臺(tái)或使用 Arria 10 GX FPGA 器件的定制設(shè)計(jì)上,工具包中的模型優(yōu)化器和推理引擎分別處理模型轉(zhuǎn)換和部署。
圖 2:支持 FPGA 的 Intel OPENVINO 工具包提供了一套必需的完整工具鏈,可將在 Caffe、TensorFlow 和其他框架上訓(xùn)練的模型部署到 Arria 10 GX FPGA 開(kāi)發(fā)套件或圍繞 Arria 10 GX FPGA 構(gòu)建的定制設(shè)計(jì)上。(圖片來(lái)源:Intel)
為了遷移預(yù)訓(xùn)練模型,開(kāi)發(fā)人員使用基于 Python 的模型優(yōu)化器生成了一個(gè)中間表示 (IR),該表示包含在一個(gè)提供網(wǎng)絡(luò)拓?fù)涞?xml 文件和一個(gè)以二進(jìn)制值提供模型參數(shù)的 bin 文件中。除了生成 IR 之外,模型優(yōu)化器還會(huì)執(zhí)行一項(xiàng)關(guān)鍵功能——移除模型中用于訓(xùn)練但對(duì)推理毫無(wú)作用的層。此外,該工具會(huì)在可能的情況下將每個(gè)提供獨(dú)立數(shù)學(xué)運(yùn)算的層合并到一個(gè)組合層中。
通過(guò)這種網(wǎng)絡(luò)修剪和合并,模型變得更緊湊,進(jìn)而加快推理時(shí)間并減少對(duì)目標(biāo)平臺(tái)的存儲(chǔ)器需求。
Intel 推理引擎是一個(gè) C++ 庫(kù),其中包含一組 C++ 類(lèi)。這些類(lèi)對(duì)于受支持的目標(biāo)硬件平臺(tái)來(lái)說(shuō)是通用的,因此可以在各個(gè)平臺(tái)上實(shí)現(xiàn)推理。對(duì)于推理應(yīng)用而言,開(kāi)發(fā)人員使用像 CNNNetReader 這樣的類(lèi)來(lái)讀取 xml 文件 (ReadNetwork) 中包含的 CNN 拓?fù)湟约?bin 文件 (ReadWeights) 中包含的模型參數(shù)。模型加載完成后,調(diào)用類(lèi)方法 Infer() 執(zhí)行阻塞推理,同時(shí)調(diào)用類(lèi)方法 StartAsync() 執(zhí)行異步推理,當(dāng)推理完成時(shí)使用等待或完成例程處理結(jié)果。
Intel 在 OPENVINO 環(huán)境提供的多個(gè)示例應(yīng)用程序中演示了完整的工作流程和詳細(xì)的推理引擎 API 調(diào)用。例如,安全屏障攝像機(jī)示例應(yīng)用程序展示了使用推理模型流水線,以首先確定車(chē)輛邊界框(圖 3)。流水線中的下一個(gè)模型檢查了邊界框中的內(nèi)容,識(shí)別車(chē)輛類(lèi)別、顏色和車(chē)牌位置等車(chē)輛屬性。
圖 3:Intel 安全屏障攝像機(jī)示例應(yīng)用程序演示了使用推理流水線,先識(shí)別車(chē)輛(綠色邊界框),再識(shí)別顏色、類(lèi)型和車(chē)牌位置(紅色框)等車(chē)輛屬性,最后識(shí)別車(chē)牌字符(紅色文本)。(圖片來(lái)源:Intel Corp.)
流水線中的最后一個(gè)模型使用這些車(chē)輛屬性從車(chē)牌中提取字符。為了使用該模型進(jìn)行推理,示例代碼顯示了利用推理模型 C++ 庫(kù)創(chuàng)建對(duì)象 (LPR),而該對(duì)象則是名為 LPRDetection 的結(jié)構(gòu)的一個(gè)實(shí)例。此結(jié)構(gòu)使用推理引擎 API 類(lèi)對(duì)象來(lái)讀取 (CNNNetReader) 并驗(yàn)證模型輸入和輸出(列表 1)。
副本 CNNNetwork read() override { std::cout << "[ INFO ] Loading network files for Licence Plate Recognition (LPR)" << std::endl; CNNNetReader netReader; /** Read network model **/ netReader.ReadNetwork(FLAGS_m_lpr); std::cout << "[ INFO ] Batch size is forced to 1 for LPR Network" << std::endl; netReader.getNetwork().setBatchSize(1); /** Extract model name and load it's weights **/ std::string binFileName = fileNameNoExt(FLAGS_m_lpr) + ".bin"; netReader.ReadWeights(binFileName); /** LPR network should have 2 inputs (and second is just a stub) and one output **/ // ---------------------------Check inputs std::cout << "[ INFO ] Checking LPR Network inputs" << std::endl; InputsDataMap inputInfo(netReader.getNetwork().getInputsInfo()); if (inputInfo.size() != 2) { throw std::logic_error("LPR should have 2 inputs"); } InputInfo::Ptr& inputInfoFirst = inputInfo.begin()->second; inputInfoFirst->setInputPrecision(Precision::U8); inputInfoFirst->getInputData()->setLayout(Layout::NCHW); inputImageName = inputInfo.begin()->first; auto sequenceInput = (++inputInfo.begin()); inputSeqName = sequenceInput->first; if (sequenceInput->second->getTensorDesc().getDims()[0] != maxSequenceSizePerPlate) { throw std::logic_error("LPR post-processing assumes certain maximum sequences"); } // ---------------------------Check outputs std::cout << "[ INFO ] Checking LPR Network outputs" << std::endl; OutputsDataMap outputInfo(netReader.getNetwork().getOutputsInfo()); if (outputInfo.size() != 1) { throw std::logic_error("LPR should have 1 output"); } outputName = outputInfo.begin()->first; std::cout << "[ INFO ] Loading LPR model to the "<< FLAGS_d_lpr << " plugin" << std::endl; _enabled = true; return netReader.getNetwork(); }
列表 1:此代碼片段來(lái)自 Intel OPENVINO 工具包中的安全屏障攝像機(jī)示例應(yīng)用程序,演示了使用 Intel 推理引擎 C++ 庫(kù) API 將模型及其參數(shù)讀入推理引擎的設(shè)計(jì)模式。(代碼來(lái)源:Intel)
為了執(zhí)行推理,該代碼加載數(shù)據(jù)并調(diào)用 submitRequest 方法,該方法啟動(dòng)推理周期并等待結(jié)果,然后顯示識(shí)別的車(chē)牌字符(列表 2)。
副本 if (LPR.enabled()) { // licence plate // expanding a bounding box a bit, better for the license plate recognition result.location.x -= 5; result.location.y -= 5; result.location.width += 10; result.location.height += 10; auto clippedRect = result.location & cv::Rect(0, 0, width, height); cv::Mat Plate = frame(clippedRect); // ----------------------------Run License Plate Recognition LPR.enqueue(Plate); t0 = std::chrono::high_resolution_clock::now(); LPR.submitRequest(); LPR.wait(); t1 = std::chrono::high_resolution_clock::now(); LPRNetworktime += std::chrono::duration_cast(t1 - t0); LPRInferred++; // ----------------------------Process outputs cv::putText(frame, LPR.GetLicencePlateText(), cv::Point2f(result.location.x, result.location.y + result.location.height + 15), cv::FONT_HERSHEY_COMPLEX_SMALL, 0.8, cv::Scalar(0, 0, 255)); if (FLAGS_r) { std::cout << "License Plate Recognition results:" << LPR.GetLicencePlateText() << std::endl; } } cv::rectangle(frame, result.location, cv::Scalar(0, 0, 255), 2); }
列表 2:此代碼片段來(lái)自 Intel OPENVINO 工具包中的安全屏障攝像機(jī)示例應(yīng)用程序,展示了加載模型、執(zhí)行推理和生成結(jié)果的設(shè)計(jì)模式。(代碼來(lái)源:Intel)
Intel 的 OPENVINO 方法強(qiáng)調(diào)平臺(tái)重定向,而 Lattice 的 SensAI 平臺(tái)完全聚焦于 FPGA 推理。SensAI 平臺(tái)的特性之一是為 DNN 架構(gòu)(包括 CNN 和一個(gè)稱(chēng)為二值化神經(jīng)網(wǎng)絡(luò) (BNN) 的緊湊架構(gòu))提供 FPGA IP。針對(duì)嵌入式視覺(jué),SensAI CNN IP 為完整的推理引擎提供框架,將控制子系統(tǒng)、存儲(chǔ)器、輸入和輸出的接口與實(shí)現(xiàn)不同類(lèi)型模型層(包括卷積、BatchNorm 歸一化、ReLu 激活、池化和其他)的資源結(jié)合在一起(圖 4)。
圖 4:Lattice Semiconductor CNN IP 實(shí)現(xiàn)了一個(gè)完整的推理系統(tǒng)框架,將專(zhuān)用引擎和用于控制、存儲(chǔ)器、輸入、輸出的接口結(jié)合在一起。(圖片來(lái)源:Lattice Semiconductor)
為了實(shí)現(xiàn) CNN 模型,開(kāi)發(fā)人員首先要在針對(duì) ECP5 FPGA 的 Lattice Diamond 設(shè)計(jì)環(huán)境中或針對(duì)其他 Lattice FPGA 系列的 Radiant 設(shè)計(jì)環(huán)境中,利用 Lattice Clarity 配置工具配置 CNN。這里,開(kāi)發(fā)人員可以指定模型類(lèi)型(CNN 或 BNN)、卷積引擎數(shù)(最多 8 個(gè))及每層的內(nèi)部存儲(chǔ)大小(最多 16 Kb)或二進(jìn)制大對(duì)象 (blob)。配置 CNN 之后,開(kāi)發(fā)人員使用設(shè)計(jì)環(huán)境生成核心,作為 FPGA 比特流。
開(kāi)發(fā)人員單獨(dú)將通過(guò) Caffe 或 TensorFlow 開(kāi)發(fā)并訓(xùn)練好的模型導(dǎo)入 SensAI 平臺(tái)。這里,Lattice 神經(jīng)網(wǎng)絡(luò)編譯器將訓(xùn)練好的 Caffe 或 TensorFlow 模型轉(zhuǎn)換為一組包含神經(jīng)網(wǎng)絡(luò)模型參數(shù)和執(zhí)行命令序列的文件。SensAI 平臺(tái)將來(lái)自設(shè)計(jì)環(huán)境和編譯器的單獨(dú)輸出一起并入 FPGA,以提供最終的推理模型(圖 5)。
圖 5:Lattice Semiconductor SensAI 平臺(tái)將其 CNN 和 BNN IP 與其神經(jīng)網(wǎng)絡(luò)編譯器結(jié)合在一起,使開(kāi)發(fā)人員能夠轉(zhuǎn)換 Caffe 或 TensorFlow 模型,以在 Lattice FPGA 上作為推理引擎來(lái)運(yùn)行。(圖片來(lái)源:Lattice Semiconductor)
針對(duì)嵌入式視覺(jué)應(yīng)用,Lattice LF-EVDK1-EVN 嵌入式視覺(jué)開(kāi)發(fā)套件 (EVDK) 為運(yùn)行 CNN 模型推理提供了理想的目標(biāo)平臺(tái)。EVDK 提供了一個(gè)完整的 80 x 80 mm 三板堆疊式視頻平臺(tái),包括 Lattice CrossLink 視頻輸入板、帶 ECP5 FPGA 的處理器板和 HDMI 輸出板。開(kāi)發(fā)人員可以將 EVDK 用作 Lattice 提供的多個(gè)示例 CNN 應(yīng)用的目標(biāo)平臺(tái)。例如,Lattice 速度標(biāo)志檢測(cè)參考設(shè)計(jì)運(yùn)用 EVDK 來(lái)展示 SensAI CNN IP 在典型汽車(chē)應(yīng)用中的應(yīng)用(圖 6)。
圖 6:Lattice Semiconductor 速度標(biāo)志檢測(cè)參考設(shè)計(jì)利用 SensAI 平臺(tái)和 Lattice LF_EVDK1-EVN 嵌入式視覺(jué)開(kāi)發(fā)套件提供一個(gè)完整的推理應(yīng)用,開(kāi)發(fā)人員可以對(duì)其立即操作或詳細(xì)探索。(圖片來(lái)源:Lattice Semiconductor)
此示例應(yīng)用程序的項(xiàng)目文件包括全套文件,從 Caffe caffemodel 和 TensorFlow pb 格式的模型開(kāi)始。因此,開(kāi)發(fā)人員可以探索這些模型的細(xì)節(jié)。例如,使用 TensorFlow import_pb_to_tensorboard.py 實(shí)用程序,開(kāi)發(fā)人員可以導(dǎo)入 Lattice 提供的 pb 模型,以查看此示例應(yīng)用程序中使用的 CNN 的細(xì)節(jié)(圖 7)。本例中,所提供的模型是由四個(gè)“Fire”模塊組成的序列,每個(gè)模塊包括:
Conv2D 層,執(zhí)行 3 x 3 卷積以從輸入流中提取特征
激活層,執(zhí)行 BatchNorm 歸一化,然后執(zhí)行修正線性單元 (ReLU) 激活
MaxPool 池化層,用于對(duì)前一層的輸出進(jìn)行采樣
圖 7:Lattice 速度標(biāo)志檢測(cè)示例應(yīng)用程序包括 TensorFlow pb 模型,開(kāi)發(fā)人員可以將其導(dǎo)入 TensorBoard 進(jìn)行詳細(xì)檢查。注意:數(shù)據(jù)向上流過(guò)此圖中的各層。(圖片來(lái)源:Digi-Key Electronics)
開(kāi)發(fā)人員可以使用 SensAI 平臺(tái)生成模型文件,完成前面描述的模型流程。或者,開(kāi)發(fā)人員可以使用所提供的文件直接跳轉(zhuǎn)到部署階段。任一情況下,文件都是通過(guò)接有適配器的 microSD 卡加載到 EVDK 中。
在操作中,EVDK 上的攝像機(jī)向 ECP5 FPGA 提供視頻流,其中配置的 CNN 加速器 IP 執(zhí)行命令序列以執(zhí)行推理。同任何推理引擎一樣,每個(gè)輸出通道都會(huì)產(chǎn)生一個(gè)結(jié)果,指出與該輸出通道相關(guān)聯(lián)的標(biāo)簽即為輸入圖像的校正標(biāo)簽的概率。本例中,模型是用每小時(shí) 25、30、35、40、45、50、55、60 和 65 英里的限速標(biāo)志的標(biāo)注圖像進(jìn)行訓(xùn)練的。因此,當(dāng)模型在其輸入字段中的任何位置檢測(cè)到限速標(biāo)志時(shí),它會(huì)顯示檢測(cè)到的標(biāo)志對(duì)應(yīng)于每小時(shí) 25、30、35、40、45、50、55、60 或 65 英里限速的概率(圖 8)。
圖 8:Lattice 速度標(biāo)志檢測(cè)演示運(yùn)行在 Lattice EVDK 上,對(duì)視頻輸入流執(zhí)行推理,生成輸出值,指示捕獲到的圖像對(duì)應(yīng)于與該特定輸出相關(guān)聯(lián)的標(biāo)簽的可能性。本例中,它顯示限速標(biāo)志最有可能是 25 mph。(圖片來(lái)源:Lattice Semiconductor)
為在嵌入式視覺(jué)應(yīng)用中運(yùn)用機(jī)器學(xué)習(xí),開(kāi)發(fā)人員使用可用硬件平臺(tái)實(shí)現(xiàn)所需性能水平的能力受到了限制。然而,高性能 FPGA 的出現(xiàn)使得開(kāi)發(fā)人員可以構(gòu)建性能接近 GPU 的推理引擎。采用專(zhuān)為嵌入式視覺(jué)設(shè)計(jì)的機(jī)器學(xué)習(xí) FPGA 平臺(tái),開(kāi)發(fā)人員可以專(zhuān)注于特定需求,使用標(biāo)準(zhǔn)機(jī)器學(xué)習(xí)框架訓(xùn)練模型,并依靠 FPGA 平臺(tái)實(shí)現(xiàn)高性能推理。