粟 煒,宗 容,張 強,奎皓然,楊宏波,王威廉+
(1.云南大學(xué) 信息學(xué)院,云南 昆明 650500;2.云南省阜外心血管病醫(yī)院 心血管內(nèi)科,云南 昆明 650102)
如今,先心病已經(jīng)成為嚴(yán)重危害青少年健康成長的疾病,早預(yù)防、早發(fā)現(xiàn)、早診斷、早治療是減少先心病危害的4種重要途徑[1],早發(fā)現(xiàn)、早診斷是4個途徑中難以實現(xiàn)的。對先心病的早發(fā)現(xiàn)、早診段,僅能通過醫(yī)務(wù)人員的下鄉(xiāng)篩查、定點檢查等方式,帶來難度大、成本高等缺陷。隨著信息時代的發(fā)展,可以利用深度學(xué)習(xí)對心音進行分類,然后將網(wǎng)絡(luò)模型移植進低成本、高實時性的嵌入式端,進行離線的輔助診斷,以此來緩解先心病篩查的壓力。
卷積神經(jīng)網(wǎng)絡(luò)(convolutional neural network,CNN)是目前在圖像處理領(lǐng)域應(yīng)用成熟,同時也被廣泛應(yīng)用在語音語義識別、生物醫(yī)學(xué)信號分類等方面的深度學(xué)習(xí)模型中[2-4]。CNN也被應(yīng)用在心音分類[5],有些研究者將心音數(shù)據(jù)變換得到聲譜圖、頻譜圖的形式,再利用卷積結(jié)構(gòu)提取圖像特征,這類方法的平均準(zhǔn)確率也達到0.8[6-8]。但此類研究也有局限:隱層中參數(shù)過多造成計算量大、實時性不高;該研究的架構(gòu)需依賴高功耗、高成本的硬件環(huán)境,難以移植進低功耗、低成本嵌入式平臺。因此,針對這些問題,本文對先心病心音CNN分類算法和其并行執(zhí)行能力進行了研究:首先,對心音信號進行預(yù)處理;其次,設(shè)計CNN的網(wǎng)絡(luò)結(jié)構(gòu);最后,通過對卷積層中的循環(huán)進行流水線的設(shè)計,實現(xiàn)了先心病心音分類算法的硬件加速。本文在硬件加速的過程中,保證算法達到平均準(zhǔn)確率的前提下,損失部分計算精度以換取算法在硬件中執(zhí)行效率的提升。本文在多種嵌入式平臺上選用了ZYNQ系列片上系統(tǒng),本文采用的了Zynq-7020芯片(Zedboard)并在VIVADO HLS進行綜合仿真。
CNN是一種深度前饋神經(jīng)網(wǎng)絡(luò),由輸入層、隱層、全連接層和輸出層組成??紤]到卷積神經(jīng)網(wǎng)絡(luò)具有高度并行性的特點,十分契合FPGA的運行機制,CNN也被證實了在心音分類上具有一定的優(yōu)勢。本文設(shè)計了一種適于先心病心音分類的CNN結(jié)構(gòu),該結(jié)構(gòu)由兩個卷積層、兩個池化層和一個全連接層所組成,如圖1所示。
圖1 先心病分類算法的CNN網(wǎng)絡(luò)結(jié)構(gòu)
其中模型的隱層由卷積層和池化層交替連接組成,通過卷積操作提取局部特征,通過池化操作對卷積層產(chǎn)生的特征向量進行降維,并將其輸入到一個或多個全連接層。全連接層在整個CNN中起到分類器的作用,其將隱層中學(xué)習(xí)到的分布式特征映射到樣本標(biāo)記空間,最終經(jīng)過Softmax獲得輸出結(jié)果。Softmax函數(shù)公式如式(1)所示
(1)
卷積層與池化層之間都需要通過激活函數(shù)實現(xiàn)非線性變化,激活函數(shù)負責(zé)將上一層的輸出結(jié)果映射成非線性函數(shù),作為下一層網(wǎng)絡(luò)的輸入向量。相比于Sigmoid/tanH函數(shù),ReLU只需要一個門限值,即可得到激活值,計算速度更快。本文采用的ReLU做層間的激活函數(shù), ReLU函數(shù)可以很好地克服梯度的消失,ReLU函數(shù)公式如式(2)所示,式(2)中x為卷積后輸出的參數(shù)
(2)
從圖1中,可看出本文所用CNN網(wǎng)絡(luò)結(jié)構(gòu)簡單和隱層的參數(shù)不多。因為預(yù)處理已經(jīng)顯化了數(shù)據(jù)的特征,因此不需要復(fù)雜的網(wǎng)絡(luò)結(jié)構(gòu)來處理數(shù)據(jù)。在對算法進行硬件移植的過程中,隱層的參數(shù)帶來的計算量決定了算法在硬件上的執(zhí)行效率和硬件資源的使用率。因此,在保證分類準(zhǔn)確率的前提下,減少隱層的參數(shù),可以留有大量的硬件資源方便后期的在硬件上的優(yōu)化操作。在上述模型中,各層的權(quán)重值、偏置值、特征圖的個數(shù)及變量見表1。實驗采用基于快速特征嵌入的卷積結(jié)構(gòu)(convolutional architecture for fast feature embedding,CAFFE)框架的CNN模型作為先心病分類算法的分類器。在圖1中,在卷積層、池化層、全連接層下面留有結(jié)構(gòu)體名稱,會在2.2節(jié)對其做解釋。
表1 各層權(quán)重值、偏置值、特征圖個數(shù)及變量
1.2.1 數(shù)據(jù)說明
本文中1020例心音數(shù)據(jù)樣本,用于訓(xùn)練和測試CNN模型,均為課題組從臨床(1歲到20歲)先心病患者,以及在先心病篩查中6歲到20歲志愿者實際采集所得。數(shù)據(jù)采樣率為5000 Hz,每個樣本長度為20 s,病例樣本均為超聲心動圖確診,即采用“金標(biāo)準(zhǔn)”[10]確認過的數(shù)據(jù)。此數(shù)據(jù)集中包括:訓(xùn)練集900例,其中正常心音樣本450例,異常心音樣本450例;測試集為120例,其中正常心音樣本60例,異常心音樣本60例。研究樣本標(biāo)注為:正常心音標(biāo)簽為0,異常心音標(biāo)簽為1。
1.2.2 數(shù)據(jù)預(yù)處理
借鑒CNN在語音信號處理的研究,本文將一維心音信號[11]進行短時傅里葉變換(short-time Fourier transform,STFT)[12],采用時頻分析的方法對心音信號進行分析。在此研究中,將每例樣本平均截斷成10個片段,每段時長為2 s,含2-3個完整心動周期,如圖2所示。隨機對每例心音數(shù)據(jù)選出1個片段,在MATLAB上使用SPECGRAM函數(shù)對單個片段進行短時傅里葉變換,用于顯化心動周期的特征??紤]到心音信號的病理雜音通常發(fā)生在心臟的收縮期,時長約為0.20 s-0.25 s,實施短時傅里葉變換的參數(shù)如下選擇,窗長0.256 s(1280樣點)可以包含一個S1至S2的時間片段;步進128點(0.025 s),可最大限度捕獲病理特征,得到如圖3所示的時頻圖,該時頻圖像素大小為560*420,其反映了心音信號經(jīng)時域、頻域變換后,在相位、頻率和能量方面的特征。通過Linux下的BASH腳本中RESIZE函數(shù)對其進行歸一化,歸一化后的特征圖像像素大小為64*64。心音數(shù)據(jù)采用上述方法預(yù)處理后,作為后期分類器的輸入樣本。
圖2 一個心音片段的心音原信號
圖3 一個心音片段的時頻圖
1.2.3 數(shù)據(jù)集制作
為對應(yīng)本文所設(shè)計的CNN模型結(jié)構(gòu),心音數(shù)據(jù)需做預(yù)處理才能放入CNN模型中進行訓(xùn)練。原始的心音數(shù)據(jù)是一維信號,而CAFFE框架中使用的數(shù)據(jù)類型為內(nèi)存映射數(shù)據(jù)庫(lightning memory-mapped database,LMDB),LMDB并不支持音頻信號數(shù)據(jù),因此需要將心音數(shù)據(jù)經(jīng)過預(yù)處理成圖像形式,再進行歸一化,并生成數(shù)據(jù)集和均值文件,如圖4所示。
圖4 數(shù)據(jù)集制作流程
經(jīng)上述的方法,將時頻圖制作成訓(xùn)練集、測試集后,放入設(shè)計好的CNN模型,在PC上進行訓(xùn)練和測試。數(shù)據(jù)樣本共有1020張時頻圖,其中訓(xùn)練集900張,正常和異常樣本各450張;測試集為120張,正常樣本有60張,異常樣本有60張;實驗中在PC上訓(xùn)練900張時頻圖獲得了0.8222的準(zhǔn)確度,對120張時頻圖的分類獲得了0.8667的準(zhǔn)確度。PC端訓(xùn)練集結(jié)果見表2,其中訓(xùn)練集的準(zhǔn)確度、損失函數(shù)直接從終端顯示得知,測試集準(zhǔn)確度需要根據(jù)式(2)計算得出,PC上對測試集的結(jié)果見表3。
表2 PC訓(xùn)練和測試結(jié)果
表3 PC測試結(jié)果
其中損失函數(shù)采用的二分類中常見的對數(shù)損失,也稱為交叉熵損失,如式(3)所示
(3)
準(zhǔn)確度定義為式(4)所示
(4)
式中:TP為正確識別的正常心音,F(xiàn)P為錯誤識別的正常心音,TN表示為正確識別的異常心音,F(xiàn)N表示為錯誤識別的異常心音。
高層次綜合將硬件領(lǐng)域和軟件領(lǐng)域相結(jié)合,為軟件設(shè)計人員提供了高效的系統(tǒng)設(shè)計,使得軟件開發(fā)者可以在FPGA上加速算法的密集型計算部分。本文通過以下3個步驟來保證算法在硬件上的適用性、高效性。首先是對模型進行量化,降低計算精度,以應(yīng)對無浮點硬核的FPGA。然后,利用VIVAOD HLS中提供的編譯指令來提高算法在硬件上的工作效率。最后,在FPGA上,通過流水線約束的方法,去控制數(shù)據(jù)流在硬件中的運行效率,來獲得更低的計算延時。
在對算法進行硬件移植的過程中,研究發(fā)現(xiàn)大多數(shù)的FPGA上并沒有浮點硬核[13],因此保持如此高的計算精度并不明智。同時也考慮到今后的算法需要對不同版本的FPGA進行移植,本文采用RISTRETTO固定點浮點數(shù)量化工具,對CNN模型的參數(shù)進行量化,犧牲了算法部分精度。模型量化的目的是將32位浮點運算轉(zhuǎn)換為16位定點運算,用于適配大多數(shù)的FPGA,方便之后的移植。本文在Ubuntu OS下,完成對CNN模型的量化后,編寫python腳本用于提取模型參數(shù)的權(quán)重值和偏置值,并與卷積核數(shù)、輸入通道和卷積核尺寸保持對應(yīng)一致;然后將模型提取得到的參數(shù)保存為文本格式,使用CC++語言讀取文本格式中的內(nèi)容,用于算法在對數(shù)據(jù)集進行處理、分類過程中的調(diào)用。
需要注意的是,在VIVADO HLS編程中,HLS提供了一種定點數(shù)據(jù)類型用于將數(shù)據(jù)建模為整數(shù)和小數(shù)位。在使用這種類型前,需要先導(dǎo)入AP_FIXED.H頭文件,才能使用ap_fixed.h
在VIVAOD HLS編程中,編譯指令(pragma)也是非常重要的一項,因為使用CC++高級綜合轉(zhuǎn)換到硬件電路是需要通過添加編譯指令來告訴編譯器一些額外的操作,這些操作將作為實現(xiàn)各種優(yōu)化設(shè)計的前提。
本文中使用了如下3類pragma編譯指令:
(1)接口類指令
代碼示例:#pragma HLS INTERFACE
其中
代碼示例:#pragma HLS INTERFACE register register_mode =
其中register_mode=
(2)數(shù)組類指令
代碼示例:#pragma HLS array_partition variable =
其中variable=
(3)數(shù)據(jù)流類指令
代碼示例:#pragma HLS stream variable =
其中variable=
本文在VIVADO HLS下采用CC++語言對已經(jīng)訓(xùn)練好的CNN前向過程進行編程,使用CC++語言中的STRCUT類型(其中包含可以調(diào)用模型參數(shù)的函數(shù))存儲隱層參數(shù),通過求地址運算符的方式調(diào)用參數(shù)。在圖1下方展示了模型各層結(jié)構(gòu)對應(yīng)的結(jié)構(gòu)體名稱。其中Strcut C1中存儲了卷積一層中的參數(shù),包含權(quán)重值的個數(shù)為600個(8*5*5*3),其中8為卷積核個數(shù),5*5為卷積核尺寸,3為輸入數(shù)據(jù)的通道數(shù),偏置值的個數(shù)為8個。Strcut P1用于存儲從經(jīng)池化一層池化后的結(jié)果,Strcut C2中存儲了卷積二層中的參數(shù),其包含的權(quán)重值的個數(shù)為2400個(8*12*5*5),其中12為卷積核個數(shù),5*5為卷積核尺寸,8為輸入數(shù)據(jù)的通道數(shù),偏置值的個數(shù)為12個。Strcut P2用于存儲經(jīng)池化二層池化后的結(jié)果;Strcut output中存儲了全連接層的參數(shù),Strcut Rst用于輸出分類結(jié)果。預(yù)處理后的數(shù)據(jù)導(dǎo)入進HLS中,需要經(jīng)過以下的操作來獲取結(jié)果。
首先將64*64*3的時頻圖通過調(diào)用結(jié)構(gòu)體C1進行卷積,經(jīng)過ReLU函數(shù)處理,得到大于0的數(shù)據(jù),再通過第一層的池化處理,將結(jié)果保存到結(jié)構(gòu)體P1中。同理,再次調(diào)用P1的地址,將參數(shù)輸入至卷積二層中進行卷積,再進行激活函數(shù)ReLU處理及第二層的池化處理,得到的結(jié)果數(shù)據(jù)存到結(jié)構(gòu)體P2中;通過調(diào)用P2的地址,將P2中保存的參數(shù)輸入到全連接層結(jié)構(gòu)體output進行全局變量提取,再經(jīng)過結(jié)構(gòu)體Rst即可得到對心音數(shù)據(jù)的識別效果。在VIVADO高層次綜合中, FPGA加速CNN的測試文件遵從VIVADO高層次綜合的格式規(guī)范編寫[14],具體測試程序如圖5所示,運行完成后在VIVADO HLS的仿真串口中查看運行結(jié)果。
圖5 高層次綜合的TESTBENCH編寫流程
本文使用的CNN模型在1.1節(jié)中已經(jīng)介紹,在每一個卷積層內(nèi)采用6個for循環(huán)進行相互嵌套循環(huán)。按照順序依次遍歷卷積核數(shù)量、通道數(shù)量、卷積圖像高度、卷積圖像寬度、卷積核行數(shù)、卷積核列數(shù)。為了便于討論,本文將卷積一層C1中部分代碼列出,其中for循環(huán)代碼如圖6所示,代碼對應(yīng)的約束方法如圖7所示。本文設(shè)定最內(nèi)層,即卷積核寬度作為第一層,自內(nèi)向外的層數(shù)依次遞增,用于說明在不同循環(huán)層進行約束后與其所生成IP核的性能的關(guān)系。
圖6 卷積層for循環(huán)代碼示例
圖7 HLS中Directive配置
在FPGA上實現(xiàn)硬件加速算法,通常對卷積中的for循環(huán)層采用流水線(Pipeline)約束或者展開(Unroll)約束這類方法來提升算法的執(zhí)行能力[15]。相對于不采用任何約束的執(zhí)行方式,Pipeline約束可以減少整個數(shù)據(jù)的操作時間,且只增加少量的邏輯資源。Unroll約束是將循環(huán)完全展開,讓多個計算單元同時運行,因此硬件資源消耗比Pipeline約束帶來的硬件資源消耗更大,效率也要比Pipeline約束更高。
在目前的研究中,平衡CNN_IP核的資源消耗和計算性能最優(yōu)的方法是對最內(nèi)層的循環(huán)采用Pipeline約束,使用Pipeline約束的特點是當(dāng)前層循環(huán)下的子循環(huán)都會執(zhí)行Unroll約束[16]。而只對最內(nèi)層的循環(huán)采用Pipeline約束時,由于沒有子循環(huán),便不會執(zhí)行Unroll約束。在這種情況下,CNN_IP核的資源消耗將會是最小的,同時,也可以為大多數(shù)應(yīng)用程序提供可接受的吞吐量。Pipeline約束的層數(shù)循環(huán)越高,其子循環(huán)執(zhí)行Unroll約束越多,消耗的計算和存儲資源將會越多,帶來吞吐量的增加和計算延時上的縮減。這就使得IP核的性能得到提高。首先,將卷積一層中的for循環(huán)從最內(nèi)層逐步向外層依次展開,通過HLS生成的綜合報告可以看到IP核的各方面的資源消耗;其次,確定好卷積一層的優(yōu)化后,再開始進行對卷積二層的優(yōu)化;最后,根據(jù)資源消耗報告確定最終優(yōu)化方案。
在本文研究中,研發(fā)環(huán)境為Xilinx公司的VIVADO HLS v2019.1開發(fā)工具以及Zedboard開發(fā)板(主芯片是XCZ7020),芯片的PS部分的時鐘頻率為33.333 MHz,芯片的PL部分的時鐘頻率為100 MHz。PC端的操作系統(tǒng)為Ubnutu16.04 OS,其使用的中央處理器型號為Intel core i5-8300H CPU 2.30 GHz,分別對進行預(yù)處理后的單張和多張心音數(shù)據(jù)樣本進行測試,對獲得的結(jié)果進行了分析。
本實驗在VIVADO HLS中編程實現(xiàn)IP核。在卷積一層中,對不同的for循環(huán)層采用流水線約束綜合后對應(yīng)的計算延時和硬件資源消耗,見表4。在對卷積一層優(yōu)化的基礎(chǔ)上,對卷積二層優(yōu)化后IP核的計算延時和硬件資源消耗見表5。最終優(yōu)化目標(biāo)的時鐘頻率、時鐘不確定性、估計可達到的最快時鐘頻率的報告見表6。
表4 C1優(yōu)化后IP核的延時和資源消耗
表5 C2優(yōu)化后IP核的延時和資源消耗
表6 IP核的時鐘頻率報告
表4、表5中的DSP48E表示PL中的數(shù)字信號處理邏輯單元,共計220個;LUT表示PL中的一種用于實現(xiàn)組合邏輯和時序邏輯的存儲資源,共計53 200個;隨著并行度的增加,對數(shù)字信號處理器模塊(DSP)和LUT的資源消耗的使用會大大增加;從表5中可以看出,在卷積二層中,流水線處理第三層循環(huán)時,綜合的IP具有最低的計算延時,但是LUT消耗資源已經(jīng)達到飽和狀態(tài)。因此最終確定的優(yōu)化方法是同時對卷積一層中的第三層for循環(huán)和卷積二層中的第三層for循環(huán)采用流水線約束,計算延時周期數(shù)為3 168 322個(每個周期10 ns),單個周期計算延時預(yù)計可達8.621 ns,總體計算延時通過計算延時的周期數(shù)與單個周期計算延時相乘獲得,約為0.03 s。
在卷積一層和卷積二層中,約束不同的for循環(huán)層,對單張時頻圖進行識別所消耗的時間見表7。結(jié)合表4,當(dāng)對卷積一層中的第一層for循環(huán)(最內(nèi)層循環(huán))做流水線約束后,DSP48E的資源消耗量增加約0.5%和LUT的資源消耗量增加約1%,將IP核的計算延時縮短了1.3倍;越往外層約束,資源利用率越高,得到效率也越高,在第三層時IP核的計算延時縮短了1.7倍;再結(jié)合表5,對第二層卷積中的第一層for循環(huán)進行流水線約束后,DSP48E和LUT的資源消耗量增加約0.5%。在對卷積一層優(yōu)化后的時間基礎(chǔ)上,將IP核的計算延時縮短了1.73倍;對卷積二層中的第三層for循環(huán)優(yōu)化后,LUT的資源消耗達到飽和。對比于表4中,未對IP核作優(yōu)化產(chǎn)生計算延時,優(yōu)化后的計算延時縮短了約7.4倍。
表7 PC與嵌入式設(shè)備實現(xiàn)算法對數(shù)據(jù)集測試的效率對比
在上述的基礎(chǔ)上,對模型實現(xiàn)流水線約束前后運行效率對比PC上運行效率進行分析,見表7,其Zynq-7020(*)表示未采用任何約束,Zynq-7020表示采用流水線的約束。本文對兩個卷積層中的第三層for循環(huán)同時采用流水線約束,相比于PC提升了約2.38倍的識別速度。雖然識別率降低了,但是可以增加算法在FPGA中的普適性。
本文在已有研究的基礎(chǔ)上進行了新的探索,對心音信號進了預(yù)處理,設(shè)計了一種結(jié)構(gòu)簡單、隱層參數(shù)少的先心病心音CNN分類算法。結(jié)合CNN內(nèi)部運算特點,在VIVADO HLS上將算法映射到FPGA中的并行硬件,仿真實現(xiàn)了對算法的硬件加速。解決了先心病心音分類算法需要依賴高成本、高功耗的硬件設(shè)備,實時性不高等問題,雖然過程中損失部分精度,但準(zhǔn)確率也達到這類方法的平均準(zhǔn)確度。本文適用于先心病下鄉(xiāng)篩查、定點篩查等場合,這類先心病篩查需要設(shè)備具有高效率、低成本等特點。此外,在硬件綜合的測試完成之后,可以把硬件加速先心病的分類識別的CC++程序,封裝為可供片上系統(tǒng)使用的IP核,這便于今后將先心病心音CNN分類算法向ZYNQ片上系統(tǒng)的移植。