機器學(xué)習(xí)已從一個有趣的研究課題迅速發(fā)展成為廣泛應(yīng)用的有效解決方案。它顯而易見的有效性迅速吸引了人工智能理論學(xué)者群體之外的開發(fā)者社區(qū)的興趣。在某些方面,機器學(xué)習(xí)開發(fā)能力已經(jīng)擴展到其它基于強大理論基礎(chǔ)的技術(shù)應(yīng)用層面。
要開發(fā)有價值、高精度的機器學(xué)習(xí)應(yīng)用絕非易事。盡管如此,不斷增長的機器學(xué)習(xí)生態(tài)系統(tǒng)已經(jīng)大大減少了對底層算法深入理解的要求,并使機器學(xué)習(xí)開發(fā)越來越容易被嵌入式系統(tǒng)開發(fā)人員使用,而不僅僅是理論上的研究。本文著重介紹一些神經(jīng)網(wǎng)絡(luò)模型開發(fā)中使用的主要概念和方法,機器學(xué)習(xí)本身是一個非常多樣化的領(lǐng)域,目前只有一種實用的機器學(xué)習(xí)方法可供嵌入式開發(fā)人員使用。
任何基于高深理論的方法都遵循從研究到工程的發(fā)展模式,機器學(xué)習(xí)也是一樣。就在不久前,希望實現(xiàn)三相交流感應(yīng)電機精確控制的開發(fā)人員需要自己找出解決方案來處理相關(guān)的微分方程組。如今,開發(fā)人員可以使用庫來快速實現(xiàn)先進(jìn)的運動控制系統(tǒng),這些庫使用非常先進(jìn)的技術(shù)(如磁場定向控制、空間矢量調(diào)制和梯形控制等)集成完整的電機控制解決方案。除非遇到特殊要求,開發(fā)人員通常無需深入了解底層算法或其特定的數(shù)學(xué)方法,即可部署復(fù)雜的電機控制解決方案。運動控制研究人員繼續(xù)用新的理論技術(shù)發(fā)展這門學(xué)科,但開發(fā)人員可以開發(fā)有用的應(yīng)用,依靠庫來抽象底層方法。
在某些方面,機器學(xué)習(xí)已達(dá)到類似的階段。機器學(xué)習(xí)算法研究及專用硬件的發(fā)展在持續(xù)進(jìn)步當(dāng)中,如果工程師在理解其相關(guān)要求和當(dāng)前局限的情況下進(jìn)行處理,這些算法的應(yīng)用便可成為一種實用的工程方法。在這種情況下,機器學(xué)習(xí)可以提供有用的結(jié)果,不需要高級線性代數(shù)專業(yè)知識,只要對目標(biāo)應(yīng)用數(shù)據(jù)有正確的理解,并且愿意接受比傳統(tǒng)軟件開發(fā)經(jīng)驗更具實驗性的開發(fā)方法。對機器學(xué)習(xí)基礎(chǔ)感興趣的工程師會發(fā)現(xiàn)他們對細(xì)節(jié)的偏愛可以得到滿足。然而,那些沒有時間或興趣探索理論的人會發(fā)現(xiàn)有一個不斷擴大的機器學(xué)習(xí)生態(tài)系統(tǒng),可以幫助他們簡化有用的機器學(xué)習(xí)應(yīng)用開發(fā)。
機器學(xué)習(xí)方法
工程師可以找到能夠支持廣泛類型機器學(xué)習(xí)的優(yōu)化庫,包括無監(jiān)督學(xué)習(xí)、強化學(xué)習(xí)和監(jiān)督學(xué)習(xí)。無監(jiān)督學(xué)習(xí)可以揭示出大量數(shù)據(jù)中的模式,但是這種方法不能將這些模式明確地標(biāo)記為屬于特定類別的數(shù)據(jù)。盡管本文未涉及無監(jiān)督學(xué)習(xí),但這些技術(shù)在物聯(lián)網(wǎng)應(yīng)用中可能非常重要,可以揭示數(shù)據(jù)集中的異常值或表明存在偏離數(shù)據(jù)趨勢的情況。例如,在工業(yè)應(yīng)用中,從一組機器的傳感器讀數(shù)中可以看出,統(tǒng)計上顯著偏離正常的現(xiàn)象可以作為該組機器出現(xiàn)潛在故障的指示。類似地,在一個大規(guī)模分布式IoT應(yīng)用中,顯著偏離多個性能參數(shù)正常值的現(xiàn)象可能揭示出,在數(shù)百或數(shù)千個設(shè)備組成的網(wǎng)絡(luò)中可能有遭受黑客攻擊的設(shè)備。
強化學(xué)習(xí)是一種通過實驗進(jìn)行有效學(xué)習(xí)的應(yīng)用方法,利用正反饋(激勵)來學(xué)習(xí)對事件的成功響應(yīng)。例如,當(dāng)一個強化學(xué)習(xí)系統(tǒng)檢測到來自一組機器的異常傳感器讀數(shù)時,可能試圖通過采取不同的動作(例如增加冷卻劑流量、降低室溫、減少機器負(fù)載等)來校正,以便將這些讀數(shù)恢復(fù)到正常。在了解到哪個動作達(dá)到期望的結(jié)果后,強化學(xué)習(xí)系統(tǒng)在下次遇到相同的異常讀數(shù)時就可以更快地執(zhí)行相同的操作。雖然本文不探討這種方法,但強化學(xué)習(xí)可能會在大規(guī)模復(fù)雜應(yīng)用(如物聯(lián)網(wǎng))中得到越來越廣泛的應(yīng)用,因為在這些應(yīng)用中所實現(xiàn)的運行狀態(tài)都不能有效地預(yù)測。
監(jiān)督學(xué)習(xí)
監(jiān)督學(xué)習(xí)方法消除了在識別哪組輸入數(shù)據(jù)對應(yīng)于哪個特定狀態(tài)(或?qū)ο螅r進(jìn)行的猜測。 利用這種方法,開發(fā)人員明確識別出與特定對象、狀態(tài)或條件相對應(yīng)的輸入值或特征組合。 在一個假設(shè)的機器示例中,工程師通過一組由n和x組成的函數(shù)來表征要解決的問題,其中x是函數(shù)表達(dá)式(如x2),而n代表不同的特征參數(shù),比如傳感器輸入、機器運行時間、最后服務(wù)日期、機器年齡和其他可測量參數(shù)。然后工程師根據(jù)他們的專業(yè)知識創(chuàng)建一個訓(xùn)練數(shù)據(jù)集,即這些特征向量的多個實例(x1 x2 ... xn),每個特征向量都有n個觀察值與已知輸出狀態(tài)相關(guān)聯(lián),標(biāo)記為y:
(x11, x12, … x1n) ? y1
(x21, x22, … x2n) ? y2
(x31, x32, … x3n) ? y3
…
給定所測量特征值與相應(yīng)標(biāo)簽之間的已知關(guān)系,開發(fā)人員就可以為訓(xùn)練集中的每個特征向量(x1k x2k ... xnk)生成預(yù)期標(biāo)簽yk的模型(方程組)。在這一訓(xùn)練過程期間,訓(xùn)練算法使用迭代方法,通過調(diào)整構(gòu)成該模型的方程組的參數(shù)來最小化預(yù)測標(biāo)簽與其實際標(biāo)簽之間的差異。將訓(xùn)練集中的所有樣本都訓(xùn)練一次,稱為“一次迭代(epoch)”,而每一次epoch都會產(chǎn)生一組新的參數(shù)、一組與這些參數(shù)相關(guān)的新預(yù)測標(biāo)簽,以及相關(guān)的差異或損失。
針對損失進(jìn)行繪圖,在每次迭代時產(chǎn)生的參數(shù)值集合是具有一些最小值的多維表面。該最小值對應(yīng)于訓(xùn)練集中提供的實際標(biāo)簽與模型推斷的預(yù)測標(biāo)簽之間的最接近的一致性。因此,訓(xùn)練的目標(biāo)是調(diào)整模型的內(nèi)部參數(shù)以達(dá)到最小損失值,使用方法來尋求最小的“下坡”路徑。在多維表面上,通過計算每個參數(shù)相對于其他參數(shù)的斜率 - 即每個參數(shù)的偏導(dǎo)數(shù),可以確定導(dǎo)致最佳下坡路徑的方向。訓(xùn)練算法通常使用矩陣方法,稱為梯度下降,以便在每個epoch通過模型運行訓(xùn)練數(shù)據(jù)的全部或子集之后來調(diào)整模型參數(shù)值。為了最小化這種調(diào)整的幅度,訓(xùn)練算法將每個步長調(diào)整一些值,稱為學(xué)習(xí)速率,這有助于訓(xùn)練過程收斂。在沒有受控學(xué)習(xí)速率的情況下,由于模型參數(shù)的過大調(diào)整,梯度下降可能超過最小值。在模型達(dá)到(或可接受地收斂)最小損失之后,工程師就可以測試模型的標(biāo)簽預(yù)測能力。
一旦經(jīng)過訓(xùn)練和評估,就可以在生產(chǎn)環(huán)境中部署合適的模型,作為推理模型來預(yù)測實際應(yīng)用數(shù)據(jù)的標(biāo)簽。請注意,推理會為訓(xùn)練中使用的每個標(biāo)簽生成一組概率值。因此,用標(biāo)記為“y1”,“y2”或“y3”的特征向量訓(xùn)練的模型可能在呈現(xiàn)與y1相關(guān)的特征向量時產(chǎn)生這樣的推斷結(jié)果,比如“y1:0.8; y2:0.19; y3:0.01”。額外的軟件邏輯將監(jiān)視輸出層以選擇具有最佳似然值的標(biāo)簽,并將所選標(biāo)簽傳遞給應(yīng)用。通過這種方式,一個應(yīng)用就可以使用機器學(xué)習(xí)模型來識別一個或其他數(shù)據(jù)模式,并采取適當(dāng)?shù)男袆印?/p>
神經(jīng)網(wǎng)絡(luò)的發(fā)展
創(chuàng)建精確的推理模型當(dāng)然是對監(jiān)督學(xué)習(xí)過程的回報,該過程能夠利用各種基礎(chǔ)模型的類型和體系結(jié)構(gòu)。在這些模型類型中,神經(jīng)網(wǎng)絡(luò)因其在圖像識別、自然語言處理和其他應(yīng)用領(lǐng)域的成功而迅速普及。實際上,當(dāng)先進(jìn)的神經(jīng)網(wǎng)絡(luò)在圖像識別中顯著優(yōu)于早期算法之后,神經(jīng)網(wǎng)絡(luò)架構(gòu)已經(jīng)成為這類問題事實上的解決方案。隨著GPU等能夠快速執(zhí)行基礎(chǔ)計算的硬件的出現(xiàn),算法開發(fā)者和用戶可以快速獲得這些技術(shù)。反過來,有效的硬件平臺和神經(jīng)網(wǎng)絡(luò)的廣泛接受又推動了各種方便開發(fā)人員使用的框架,包括Facebook的Caffe2、H2O、英特爾的neon、MATLAB、微軟認(rèn)知工具包、Apache MXNet、三星Veles、TensorFlow、Theano和PyTorch等。結(jié)果,開發(fā)人員可以輕松地找到合適的環(huán)境來評估機器學(xué)習(xí),特別是神經(jīng)網(wǎng)絡(luò)。
神經(jīng)網(wǎng)絡(luò)的開發(fā)始于使用任意數(shù)量的可用安裝選項來部署框架。盡管依賴性通常很小,但所有流行的框架都能夠利用GPU加速庫。因此,開發(fā)人員可以通過安裝NVIDA CUDA工具包和NVIDIA深度學(xué)習(xí)SDK中的一個或多個庫[比如用于多節(jié)點/多GPU平臺的NCCL(NVIDIA集體通信庫)或NVIDIA cuDNN(CUDA深度神經(jīng)網(wǎng)絡(luò))庫]來大幅提高計算速度。機器學(xué)習(xí)框架在GPU加速模式下運行,可充分利用cuDNN針對標(biāo)準(zhǔn)神經(jīng)網(wǎng)絡(luò)例程的優(yōu)化實現(xiàn),包括卷積、池化、規(guī)范化和激活層。
無論是否使用GPU,框架的安裝都很簡單,通常需要為這些基于Python的軟件包安裝pip。例如,要安裝TensorFlow,可以使用與任何Python模塊相同的Python安裝方法:
pip3 install --upgrade tensorflow
(或僅適用于Python 2.7環(huán)境)
此外,開發(fā)人員可能希望添加其他Python模塊以加速不同方面的開發(fā)。例如,Python pandas模塊提供了一個功能強大的工具,用于創(chuàng)建所需的數(shù)據(jù)格式,執(zhí)行不同的數(shù)據(jù)轉(zhuǎn)換,或者只處理機器學(xué)習(xí)模型開發(fā)中經(jīng)常需要的各種數(shù)據(jù)整理操作。
經(jīng)驗豐富的Python開發(fā)人員通常會為Python開發(fā)創(chuàng)建一個虛擬環(huán)境,例如,流行的框架都可以通過Anaconda獲得。開發(fā)人員可以使用容器技術(shù)來簡化devops,也可以找到其所用框架內(nèi)置的合適容器。例如,TensorFlow在Dockerhub上的Docker容器中就支持兩個版本,一個是僅支持CPU的,一個是支持GPU的。Python wheel檔案中也提供了一些框架。例如,Microsoft在CPU和GPU兩個版本中都提供Linux CNTK wheel 文件,開發(fā)人員也可以在Raspberry Pi 3上找到用于安裝TensorFlow的wheel 文件。
數(shù)據(jù)準(zhǔn)備
雖然設(shè)置機器學(xué)習(xí)框架已經(jīng)比較簡單,但真正的工作始于選擇和準(zhǔn)備數(shù)據(jù)。如前所述,數(shù)據(jù)在模型訓(xùn)練中起著核心作用,因此決定著一個推理模型的有效性。之前未提及的事實是,訓(xùn)練集通常包括數(shù)十萬甚至數(shù)百萬個特征向量和標(biāo)簽以達(dá)到足夠的準(zhǔn)確度水平。這些數(shù)據(jù)集的龐大規(guī)模使得對輸入數(shù)據(jù)的隨意檢查變得不可能或基本上無效。然而,糟糕的訓(xùn)練數(shù)據(jù)直接影響模型質(zhì)量。錯誤標(biāo)記的特征向量、缺失數(shù)據(jù),以及“太”干凈的數(shù)據(jù)集可能導(dǎo)致推理模型無法提供準(zhǔn)確的預(yù)測或很好地歸納。對于整體應(yīng)用而言可能更糟糕的是,選擇統(tǒng)計上不具代表性的訓(xùn)練集預(yù)示著模型會因那些缺失的特征向量及其所代表的實體而偏離實際。由于訓(xùn)練數(shù)據(jù)的重要性以及創(chuàng)建數(shù)據(jù)的難度很大,業(yè)界已經(jīng)發(fā)展了大量的標(biāo)記數(shù)據(jù)集,這些數(shù)據(jù)集可從諸如UCI機器學(xué)習(xí)庫等來源獲取。對于僅僅探索不同機器學(xué)習(xí)算法的開發(fā)人員,Kaggle數(shù)據(jù)集通??梢蕴峁┮粋€很有用的起點。
當(dāng)然,對于從事獨特的機器學(xué)習(xí)應(yīng)用開發(fā)的組織來說,模型開發(fā)需要自己獨特的數(shù)據(jù)集。即使有足夠大的可用數(shù)據(jù)池,標(biāo)記數(shù)據(jù)也是一項龐大的工程。實際上,標(biāo)記數(shù)據(jù)的過程主要還是人工來完成的。因此,創(chuàng)建一個準(zhǔn)確標(biāo)記數(shù)據(jù)的系統(tǒng)本身就是一個過程,需要結(jié)合心理學(xué)理解人類如何解釋指令(如標(biāo)簽方式和內(nèi)容),以及技術(shù)支持來加速數(shù)據(jù)的呈現(xiàn)、標(biāo)記和驗證。Edgecase、Figure Eight和Gengo等公司結(jié)合了數(shù)據(jù)標(biāo)簽多種要求方面的專業(yè)知識,提供旨在將數(shù)據(jù)轉(zhuǎn)化為有用的監(jiān)督學(xué)習(xí)培訓(xùn)集的服務(wù)。有了一組合格的標(biāo)記數(shù)據(jù),開發(fā)人員就需要將數(shù)據(jù)分成訓(xùn)練集和測試集,通常使用90:10左右的比例進(jìn)行分割。注意測試集是一個有代表性但又與訓(xùn)練集截然不同的數(shù)據(jù)集。
模型開發(fā)
在許多方面,創(chuàng)建合適的訓(xùn)練和測試數(shù)據(jù)可能比創(chuàng)建實際模型本身更困難。例如,使用TensorFlow,開發(fā)人員可以在TensorFlow的Estimator類中使用內(nèi)置模型類型來構(gòu)建模型。例如,單個調(diào)用如:
classifier = tf.estimator.DNNClassifier(
feature_columns=this_feature_column,
hidden_units=[4,],
n_classes=2)
使用內(nèi)置的DNNClassifier類自動創(chuàng)建一個基本的完全連接的神經(jīng)網(wǎng)絡(luò)模型(見圖1),它包括一個有三個神經(jīng)元的輸入層(支持的特征數(shù)量),一個有四個神經(jīng)元的隱藏層,以及一個有兩個神經(jīng)元的輸出層(支持的標(biāo)簽數(shù)量)。在每個神經(jīng)元內(nèi),相對簡單的激活函數(shù)對其輸入組合執(zhí)行一些轉(zhuǎn)換以生成其輸出。
圖1:最簡單的神經(jīng)網(wǎng)絡(luò)包括輸入層、隱藏層和輸出層,而有用的推理依賴于包含大量隱藏層的深度神經(jīng)網(wǎng)絡(luò)模型,每個隱藏層包含大量神經(jīng)元。 (來源:維基百科)
圖片翻譯:輸入層;隱藏層;輸出層
為了訓(xùn)練模型,開發(fā)人員只需在實例化的估算器對象中調(diào)用訓(xùn)練方法 - 在此示例中為classifier.train(input_fn = this_input_function),并使用TensorFlow數(shù)據(jù)集API通過輸入函數(shù)提供正確形成的數(shù)據(jù)(本示例中為this_input_function)。需要這樣的預(yù)處理或“整形”來將輸入數(shù)據(jù)流轉(zhuǎn)換為具有輸入層所期望的維度(形狀)的矩陣,但是這一預(yù)處理步驟還可能包括數(shù)據(jù)縮放、歸一化以及特定模型所需的任何數(shù)量的變換。
神經(jīng)網(wǎng)絡(luò)是許多高級識別系統(tǒng)的核心,但實際應(yīng)用所采用的神經(jīng)網(wǎng)絡(luò),其結(jié)構(gòu)比本示例要復(fù)雜得多。這些“深度神經(jīng)網(wǎng)絡(luò)”架構(gòu)具有許多隱藏層,每層都有大量神經(jīng)元。雖然開發(fā)人員可以簡單地使用內(nèi)置的Estimator類來添加更多層及更多神經(jīng)元,但成功的模型架構(gòu)往往會混合不同類型的層和功能。
例如,AlexNet是一種卷積神經(jīng)網(wǎng)絡(luò)(CNN)或ConvNet,它在ImageNet競賽(以及之后的許多圖像識別應(yīng)用)中引發(fā)了CNN的廣泛使用,共有八層(見圖2)。每層包含非常多的神經(jīng)元,在第一層中有253440個,第二層及以后依次為186624、64896、64896、43264、4096、4096和1000個神經(jīng)元。不是使用觀察數(shù)據(jù)的特征向量,ConvNets掃描圖像通過一個窗口(n×n像素濾鏡),移動窗口幾個像素(步幅)并重復(fù)該過程,直到圖像被完全掃描。每個過濾結(jié)果都通過ConvNet的各個層來完成圖像識別模型。
圖2:AlexNet演示了使用深度卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)來降低圖像識別中的錯誤率。 (來源:ImageNet大規(guī)模視覺識別競賽)
圖片翻譯:步幅4;最大池化;密集矩陣
即使采用這種“簡單”配置,與前一年的領(lǐng)先解決方案相比,使用CNN可以顯著降低ImageNet大規(guī)模視覺識別競賽(ILSVRC)中的前5個錯誤。 (前5個錯誤是一個常見指標(biāo),表示在該模型的輸入數(shù)據(jù)對可能標(biāo)簽的前五個預(yù)測中,不包括正確標(biāo)簽的推斷百分比。)在隨后的幾年中,領(lǐng)先的參賽作品顯示了層數(shù)的急劇增加,以及前5個錯誤顯著減少(圖3)。
圖3:由于AlexNet在2012年大幅降低了ImageNet前5個錯誤率,因此ILSVRC中表現(xiàn)最佳的模型架構(gòu)具有更深層次的模型架構(gòu)。 (來源:計算機視覺基金會)
圖片翻譯:ImageNet分類前5個錯誤率(%);層;
模型開發(fā)
開發(fā)人員可以使用任何流行的框架來創(chuàng)建ConvNets和其他復(fù)雜的自定義模型。使用TensorFlow,開發(fā)人員使用方法調(diào)用逐層構(gòu)建ConvNet模型,以構(gòu)建卷積層,使用池化層聚合結(jié)果,并對結(jié)果進(jìn)行標(biāo)準(zhǔn)化,通常重復(fù)該組合以根據(jù)需要創(chuàng)建盡可能多的卷積層。實際上,在設(shè)計用于完成CIFAR-10分類集的ConvNet的TensorFlow演示中,前三層是使用三種關(guān)鍵方法構(gòu)建的:tf.nn.conv2d、tf.nn.max_pool和tf.nn.lrn:
# conv1
with tf.variable_scope('conv1') as scope:
kernel = _variable_with_weight_decay('weights',
shape=[5, 5, 3, 64],
stddev=5e-2,
wd=None)
conv = tf.nn.conv2d(images, kernel, [1, 1, 1, 1], padding='SAME')
biases = _variable_on_cpu('biases', [64], tf.constant_initializer(0.0))
pre_activation = tf.nn.bias_add(conv, biases)
conv1 = tf.nn.relu(pre_activation, name=scope.name)
_activation_summary(conv1)
# pool1
pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1],
padding='SAME', name='pool1')
# norm1
norm1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75,
name='norm1')
模型訓(xùn)練
開發(fā)人員使用清單1中所示的訓(xùn)練方法來訓(xùn)練完整的TensorFlow模型。
其中,train_op引用cifar10類對象的訓(xùn)練方法來執(zhí)行訓(xùn)練,直到滿足開發(fā)人員在其他地方定義的停止條件。 cifar10訓(xùn)練方法處理實際的訓(xùn)練周期,包括損失計算、梯度下降、參數(shù)更新,以及將指數(shù)衰減函數(shù)應(yīng)用于學(xué)習(xí)率本身(清單2)。
def train():
"""Train CIFAR-10 for a number of steps."""
with tf.Graph().as_default():
global_step = tf.train.get_or_create_global_step()
# Get images and labels for CIFAR-10.
# Force input pipeline to CPU:0 to avoid operations sometimes ending up on
# GPU and resulting in a slow down.
with tf.device('/cpu:0'):
images, labels = cifar10.distorted_inputs()
# Build a Graph that computes the logits predictions from the
# inference model.
logits = cifar10.inference(images)
# Calculate loss.
loss = cifar10.loss(logits, labels)
# Build a Graph that trains the model with one batch of examples and
# updates the model parameters.
train_op = cifar10.train(loss, global_step)
class _LoggerHook(tf.train.SessionRunHook):
"""Logs loss and runtime."""
def begin(self):
self._step = -1
self._start_time = time.time()
def before_run(self, run_context):
self._step += 1
return tf.train.SessionRunArgs(loss) # Asks for loss value.
def after_run(self, run_context, run_values):
if self._step % FLAGS.log_frequency == 0:
current_time = time.time()
duration = current_time - self._start_time
self._start_time = current_time
loss_value = run_values.results
examples_per_sec = FLAGS.log_frequency * FLAGS.batch_size / duration
sec_per_batch = float(duration / FLAGS.log_frequency)
format_str = ('%s: step %d, loss = %.2f (%.1f examples/sec; %.3f '
'sec/batch)')
print (format_str % (datetime.now(), self._step, loss_value,
examples_per_sec, sec_per_batch))
with tf.train.MonitoredTrainingSession(
checkpoint_dir=FLAGS.train_dir,
hooks=[tf.train.StopAtStepHook(last_step=FLAGS.max_steps),
tf.train.NanTensorHook(loss),
_LoggerHook()],
config=tf.ConfigProto(
log_device_placement=FLAGS.log_device_placement)) as mon_sess:
while not mon_sess.should_stop():
mon_sess.run(train_op)
清單1:在這一來自TensorFlow CIFAR-10 ConvNet的演示示例中,TensorFlow會話mon_sess運行方法執(zhí)行訓(xùn)練周期,引用cifar10實例本身包含的損失函數(shù)和其他訓(xùn)練參數(shù)。 (來源:TensorFlow)
# Decay the learning rate exponentially based on the number of steps.
lr = tf.train.exponential_decay(INITIAL_LEARNING_RATE,
global_step,
decay_steps,
LEARNING_RATE_DECAY_FACTOR,
staircase=True)
tf.summary.scalar('learning_rate', lr)
# Generate moving averages of all losses and associated summaries.
loss_averages_op = _add_loss_summaries(total_loss)
# Compute gradients.
with tf.control_dependencies([loss_averages_op]):
opt = tf.train.GradientDescentOptimizer(lr)
grads = opt.compute_gradients(total_loss)
# Apply gradients.
apply_gradient_op = opt.apply_gradients(grads, global_step=global_step)
清單2:在TensorFlow CIFAR-10 ConvNet實現(xiàn)中,cifar10對象執(zhí)行梯度下降,使用指數(shù)衰減計算損耗,并更新模型參數(shù)。 (來源:TensorFlow)
TensorFlow方法提供了強大的功能和靈活性,但代碼可以說是比較笨拙的。 好消息是,Keras作為一個更直觀的神經(jīng)網(wǎng)絡(luò)API,可以運行在TensorFlow之上。使用Keras,開發(fā)人員只需幾行代碼即可構(gòu)建CIFAR-10 ConvNet,比如添加所需的層、激活函數(shù)、聚合(池)等(見清單3)。
model = Sequential()
model.add(Conv2D(32, (3, 3), padding='same',
input_shape=x_train.shape[1:]))
model.add(Activation('relu'))
model.add(Conv2D(32, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3, 3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes))
model.add(Activation('softmax'))
清單3:Keras提供了一種逐層構(gòu)建ConvNet模型的直觀方法。 (來源:Keras)
在Keras中定義模型之后,開發(fā)人員調(diào)用模型的編譯方法來指定所期望的損耗計算算法和優(yōu)化算法(比如梯度下降)。為了訓(xùn)練模型,開發(fā)人員稱之為模型的擬合方法。 或者,模型的fit_generator方法提供了一種更簡單的訓(xùn)練方法,即使用Python的生成器功能對從Keras預(yù)處理類生成的批量數(shù)據(jù)進(jìn)行處理,以此來訓(xùn)練模型。
要將模型部署到目標(biāo)設(shè)備(如邊緣設(shè)備),開發(fā)人員通常可以從其開發(fā)環(huán)境中導(dǎo)出模型。 例如,使用TensorFlow,開發(fā)人員可以使用TensorFlow freeze_graph.py實用程序,以pb格式導(dǎo)出模型,這是一種基于Google協(xié)議緩沖器的序列化格式。在目標(biāo)設(shè)備中,開發(fā)人員可以使用TensorFlow C ++ API創(chuàng)建TensorFlow運行會話、加載pb文件,并使用應(yīng)用輸入數(shù)據(jù)運行它。對于能夠使用容器的目標(biāo)平臺,開發(fā)人員通??梢栽贒ocker Hub上找到他們喜歡的框架的Docker容器,添加他們的模型執(zhí)行應(yīng)用程序,并將應(yīng)用程序容器導(dǎo)出到他們的目標(biāo)平臺。在實踐中,重新部署模型的過程需要額外注意,特別在將從開發(fā)環(huán)境中提取訓(xùn)練數(shù)據(jù)而構(gòu)建的功能更換為專門為生產(chǎn)環(huán)境的數(shù)據(jù)處理而優(yōu)化的功能時。
開發(fā)方法
TensorFlow、Keras和其他神經(jīng)網(wǎng)絡(luò)框架顯著簡化了構(gòu)建復(fù)雜模型的任務(wù),但創(chuàng)建一個有效地滿足設(shè)計目標(biāo)的模型完全是另一回事。與傳統(tǒng)的軟件開發(fā)不同,開發(fā)有效的模型可能需要更多的推測來嘗試不同的解決方案,以便“看出哪種方案可行”。研究人員正在積極研究能夠創(chuàng)建優(yōu)化模型的算法,但神經(jīng)網(wǎng)絡(luò)優(yōu)化的一般定理仍然難以捉摸。就此而言,創(chuàng)建模型沒有通用的最佳實踐或啟發(fā)式方法:每個應(yīng)用在前端都有其獨特的數(shù)據(jù)特征,而在后端都有性能、準(zhǔn)確性和功耗的獨特要求。
一種有效的方法是自動化模型構(gòu)建工具,例如Google的Cloud AutoML,它使用遷移學(xué)習(xí)和強化學(xué)習(xí)在特定領(lǐng)域找到良好的模型架構(gòu)。到目前為止,Google已經(jīng)發(fā)布了一款還處于早期測試階段的產(chǎn)品AutoML Vision。雖然沒有立即出現(xiàn),但自動化模型構(gòu)建工具的出現(xiàn)將是不可避免的。因為AI工具供應(yīng)商在爭奪機器學(xué)習(xí)的主導(dǎo)地位,想借此改變游戲規(guī)則,因此,AutoML類工具仍然是一個活躍的研究課題。
與此同時,云服務(wù)提供商和框架開發(fā)人員也在不斷改進(jìn)更直接的功能,以簡化機器學(xué)習(xí)解決方案的開發(fā)。開發(fā)人員可以使用TensorFlow調(diào)試器等工具深入了解模型和TensorBoard的內(nèi)部狀態(tài),以便更輕松地可視化和探索復(fù)雜的模型拓?fù)浜凸?jié)點交互。例如,TensorBoard提供了損失與epoch的交互式視圖,可以對模型有效性和學(xué)習(xí)速率適用性做出早期衡量(見圖4)。
圖4:TensorBoard幫助開發(fā)人員可視化模型內(nèi)部結(jié)構(gòu)和訓(xùn)練過程,顯示損失函數(shù)(此處使用損失函數(shù)的交叉條目)與epoch的關(guān)系。 (來源:TensorFlow)
最終,找到最合適的架構(gòu)和配置是經(jīng)驗和反復(fù)試錯的結(jié)果。即使是最有經(jīng)驗的神經(jīng)網(wǎng)絡(luò)研究人員也建議找到最佳機器學(xué)習(xí)架構(gòu)和特定拓?fù)浣Y(jié)構(gòu)的方法是嘗試,看看哪種方法效果最好。從這個意義上說,神經(jīng)網(wǎng)絡(luò)發(fā)展與傳統(tǒng)應(yīng)用開發(fā)有很大不同。不要期望對模型編碼后,就萬事大吉了,經(jīng)驗豐富的機器學(xué)習(xí)開發(fā)人員,特別是神經(jīng)網(wǎng)絡(luò)開發(fā)人員,會將每個模型構(gòu)建視為一個試驗,使用不同的模型架構(gòu)和配置運行多個實驗,以找到最適合自己應(yīng)用需要的模型。
然而,開發(fā)人員可以利用框架提供商和開源社區(qū)提供的大量預(yù)建模型來加速模型開發(fā)過程。預(yù)構(gòu)建模型帶有通用數(shù)據(jù)集,甚至特定應(yīng)用的數(shù)據(jù)集,但很少有開發(fā)人員所期望模型的最佳選擇。然而,采用遷移學(xué)習(xí)方法,這些模型不僅可以加速開發(fā),而且得到的結(jié)果通常比使用自己的數(shù)據(jù)集來訓(xùn)練初級模型更好。實際上,開發(fā)人員可以從很多渠道找到開源的預(yù)訓(xùn)練模型,比如Caffe2 Model Zoo、Microsoft CNTK Model Gallery、Keras和TensorFlow等。
平臺要求
然而,即使可用的模型創(chuàng)建技術(shù)數(shù)量不斷增加,模型選擇的關(guān)鍵約束仍然是目標(biāo)平臺的性能。為多GPU系統(tǒng)而設(shè)計的模型,將無法在基于通用處理器的系統(tǒng)上有效運行。如果沒有適當(dāng)?shù)挠布С郑ㄓ锰幚砥鳠o法快速完成主導(dǎo)機器學(xué)習(xí)算法的矩陣乘法計算(圖5)。
圖5:通用矩陣乘法(gemm)計算是一般機器學(xué)習(xí)的主要方式,特別是神經(jīng)網(wǎng)絡(luò)架構(gòu)。 (來源:IBM)
盡管如此,開發(fā)人員仍然可以使用前面提到的TensorFlow for Raspberry Pi的版本來開發(fā)神經(jīng)網(wǎng)絡(luò)模型,能夠在Raspberry Pi這樣的系統(tǒng)上運行。更普遍地,Arm的計算庫提供了針對Arm Cortex-A系列CPU優(yōu)化的機器學(xué)習(xí)功能,比如Raspberry Pi 3使用的CPU就是Arm處理器。開發(fā)人員甚至可以使用Arm的CMSIS-NN為Arm Cortex-M7 MCU創(chuàng)建普通但有效的神經(jīng)網(wǎng)絡(luò)庫。實際上,Arm介紹過一個示例,NUCLEO Mbed板上的標(biāo)準(zhǔn)216 MHz Cortex-M7處理器,就可以支持為CIFAR-10預(yù)先構(gòu)建的Caffe ConvNet,運行后,它可以在合理的時間內(nèi)完成推理(圖6)。
圖6:Arm展示Caffe CIFAR-10 ConvNet模型能夠在標(biāo)準(zhǔn)Arm Cortex-M7處理器上運行。 (來源:Arm)
FPGA可以提供重要的性能升級和快速開發(fā)平臺。例如, Lattice 半導(dǎo)體公司的SensAI平臺使用神經(jīng)網(wǎng)絡(luò)編譯器,能夠?qū)ensorFlow pb文件和其他文件編譯到Lattice 神經(jīng)網(wǎng)絡(luò)IP核上,以便在其FPGA上實現(xiàn)人工智能。
專用的AI設(shè)備則更進(jìn)一步,它們采用專門的硬件來加速面向大眾市場的機器學(xué)習(xí)應(yīng)用。比如Intel Movidius Neural Compute Stick、NVIDIA Jetson TX2模塊和高通Snapdragon模塊等硬件設(shè)備可讓開發(fā)人員在各種系統(tǒng)中嵌入高性能機器學(xué)習(xí)算法。
專門針對AI應(yīng)用的架構(gòu)旨在減少CPU-內(nèi)存瓶頸。例如,IBM在2018年VLSI電路研討會上描述的AI加速器芯片將用于加速矩陣乘法的處理單元與用于減少片外存儲器訪問的“暫存存儲器”層次結(jié)合在一起(圖7)。同樣地,新興的高級AI芯片利用各種方法將微架構(gòu)中的邏輯和存儲器合并,以加速AI應(yīng)用的各種操作。
圖7:使用了諸如IBM AI芯片中描述的暫存器內(nèi)存層次結(jié)構(gòu)等技術(shù)的新興AI芯片架構(gòu)旨在減少CPU-內(nèi)存瓶頸的影響。 (來源:IBM)
專用框架和架構(gòu)
專用硬件旨在充分發(fā)揮機器學(xué)習(xí)的潛力,IC行業(yè)繼續(xù)提供更加強大的AI處理器。與此同時,框架開發(fā)人員和機器學(xué)習(xí)算法專家也在不斷尋找優(yōu)化框架和神經(jīng)網(wǎng)絡(luò)架構(gòu)的方法,以便更有效地支持資源受限的平臺,包括智能手機、物聯(lián)網(wǎng)邊緣設(shè)備和其他性能一般的系統(tǒng)。雖然Apple Core ML和Android神經(jīng)網(wǎng)絡(luò)API都為各自的環(huán)境提供了解決方案,但TensorFlow Mobile等框架(及其演化版本TensorFlow Lite)提供了更通用的解決方案。
模型結(jié)構(gòu)本身在不斷發(fā)展,以解決嵌入式設(shè)備的資源限制。SqueezeNet就是通過擠壓模型架構(gòu)的元素,從而顯著減少了模型大小和參數(shù)。MobileNet采用不同的架構(gòu)方法,可達(dá)到與其他方法相當(dāng)?shù)膖op-1 精度,但所需要的乘法-加法操作卻少得多(圖8)。機器學(xué)習(xí)公司Neurala使用自己的獨創(chuàng)方法開發(fā)出很小的模型,但仍然能夠達(dá)到很高的精度。
圖8:Google的MobileNet等專用模型架構(gòu)通過減少資源受限的嵌入式應(yīng)用所需的矩陣乘法-加法運算,仍可提供具有競爭力的精度。
算法和工具的融合減少了從頭構(gòu)建機器學(xué)習(xí)模型的需要。開發(fā)人員利用越來越強大的框架和工具,更多地在預(yù)先構(gòu)建的模型上開發(fā),來滿足他們自己的獨特需求。因此,開發(fā)人員可以在流行的平臺上部署推理模型,以執(zhí)行圖像識別等簡單任務(wù)。利用同樣的技術(shù)來創(chuàng)建有用的高性能生產(chǎn)模型絕非易事,但任何開發(fā)人員都非常容易獲得和使用。隨著專用AI硬件在低功耗系統(tǒng)中的發(fā)展,機器學(xué)習(xí)很可能成為嵌入式開發(fā)人員常用的開發(fā)工具。
-
機器學(xué)習(xí)
+關(guān)注
關(guān)注
66文章
8418瀏覽量
132630
發(fā)布評論請先 登錄
相關(guān)推薦
評論