面向機器智能的TensorFlow實踐_第1頁
面向機器智能的TensorFlow實踐_第2頁
面向機器智能的TensorFlow實踐_第3頁
面向機器智能的TensorFlow實踐_第4頁
面向機器智能的TensorFlow實踐_第5頁
已閱讀5頁,還剩248頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

智能系統(tǒng)與技術(shù)叢書本書紙版由機械工業(yè)出版社于2017年出版,電子版由華章分社(北京華章圖文信息有限公司,北京奧維博世圖書發(fā)行有限全球范圍內(nèi)制作與發(fā)行。版權(quán)所有,侵權(quán)必究第四部分其他提示、技術(shù)與特性譯者序我們正處在一個激動人心的時代,深度學(xué)習(xí)作為近年來最具突破性的技術(shù)之一,極大地推動了人工智能領(lǐng)域的研究進程,并迅速滲透各行各業(yè),同時帶動了一大批如家庭服務(wù)機器人、自動駕駛這樣的新興產(chǎn)業(yè)。不夸張地說,深度學(xué)習(xí)技術(shù)正在深刻地影響著人們的工作、生活和思維方式。為了幫助人們更高效地從事深度學(xué)習(xí)研究和應(yīng)用,并積極分享其研究成果,優(yōu)秀的開源深度學(xué)習(xí)框架如雨后春筍般不斷涌和產(chǎn)品研發(fā)兩端取得的良好平衡,在極短的時間內(nèi)便從眾多優(yōu)秀的深度學(xué)習(xí)框架中脫穎而出,獲得了廣大開發(fā)者的強烈關(guān)注。自強力推動下,不斷快速迭代并大幅提升代碼的效率,平均每周的代碼更新量都超過了萬行,所形成的社區(qū)開創(chuàng)了空前的活躍度。高,學(xué)習(xí)曲線過陡。本書的問世在一定程度上緩解了這個矛盾。本書的幾位作者都來自G循環(huán)神經(jīng)網(wǎng)絡(luò)應(yīng)用到圖像理解和自然語言處理的典型任務(wù)中。難能可貴的是,他們還介紹了在模型部署和編程中可用的諸多實用需要說明的是,這并不是一本機器學(xué)習(xí)理論或深度學(xué)習(xí)的入門讀物,閱讀本書需要讀者對經(jīng)典機器學(xué)習(xí)理論和算法、深度卷出版社相關(guān)主題的后續(xù)圖書。感謝機械工業(yè)出版社張夢玲編輯在本書翻譯過程中給予的諸多幫助,也感謝家人對我無微不至的關(guān)心。歡迎強大的開源庫。本書的內(nèi)容編排第三部分由兩章構(gòu)成,每章都只關(guān)注一種更為復(fù)雜的深度學(xué)習(xí)模型。每章首先對模型進行描述,然后介紹如何用可視化的數(shù)據(jù)流圖表示所要創(chuàng)建的模型。這兩章還將討論為什么要以特定方式構(gòu)建這些模型,并對所涉及的數(shù)學(xué)難點進行講解,之后再介紹),輸出進行測試。第四部分:其他提示、技術(shù)與特性其他精選主題。其他機器學(xué)習(xí)庫·CNTK是微軟公司發(fā)布的首個開源機器學(xué)習(xí)庫,它擁有自己的模框架設(shè)計時,便是從當中的幾個庫汲取了靈感。先修知識此外,讀者若能夠掌握下列知識,則將從本書中獲得更大的收獲:·掌握機器學(xué)習(xí)中更高級的概念,尤其是前饋神經(jīng)網(wǎng)絡(luò)、卷積神經(jīng)網(wǎng)絡(luò)和循環(huán)神經(jīng)網(wǎng)絡(luò)在適宜的時候,筆者會通過一些提示信息幫預(yù)期的收獲通過閱讀本書,讀者將掌握以下內(nèi)容:至此,“動員演講”已經(jīng)結(jié)束,現(xiàn)在讓我們開啟本我們正實實在在地處于“信息時代”。如今,各種數(shù)據(jù)從無窮無盡的渠道不斷涌入:智能手機、手表、汽車、停車計時表、家用電器。幾乎任何一種能夠說出名字的技術(shù)與生俱來都具備與位于云端的某個數(shù)據(jù)庫進行通信的能力。在看似無限的存儲能力的支持下,開發(fā)者們?yōu)閿?shù)據(jù)倉庫選擇了一種“更多即是更好”的方法,存儲著從他們的產(chǎn)品和客戶那里收集到的以拍字節(jié)(PB)為單位計的海量數(shù)據(jù)。與此同時,計算機的性能也在持續(xù)提升。雖然CPU的發(fā)展速度已經(jīng)放緩,但并行處理架構(gòu)取得了爆炸式的發(fā)展。一向主要服務(wù)于計算機游戲的圖形處理單元(GPU)如今已被大量運用于通用計算領(lǐng)域,并拉開了機器學(xué)習(xí)迅猛發(fā)展的序幕。機器學(xué)習(xí)(有時簡記為ML)試圖利用通用的數(shù)學(xué)模型回答涉及數(shù)據(jù)的特定問題。機器學(xué)習(xí)成功應(yīng)用于垃圾郵件檢測、產(chǎn)品推薦(向客戶)、預(yù)測商品的價格等領(lǐng)域已有多年。近年來,一種特殊類型的機器學(xué)習(xí)范式在幾乎所有領(lǐng)域都取得了無數(shù)巨大的成功,它就是深度學(xué)習(xí)?!吧疃葘W(xué)習(xí)”已成為用于描述使用多層神經(jīng)網(wǎng)絡(luò)的過程的標準術(shù)語,多層神經(jīng)網(wǎng)絡(luò)是一類極為靈活的可利用種類繁多的數(shù)學(xué)方法以及不同數(shù)學(xué)方法組合的模型。這類模型極為強大,但直到最近幾年,人們才有能力卓有成效地利用神經(jīng)網(wǎng)絡(luò),其背后原因主要有兩點,一是獲取足夠數(shù)量的數(shù)據(jù)成為現(xiàn)實;二是得益于通用GPU的快速發(fā)展,多層神經(jīng)網(wǎng)絡(luò)擁有了超越深度學(xué)習(xí)的強大之處在于當決定如何最有效地利用數(shù)據(jù)時,它能夠賦予模型更大的靈活性。人們無需盲目猜測應(yīng)當選擇何種輸入。一個調(diào)校好的深度學(xué)習(xí)模型可以接收所有的參數(shù),并自動確定輸入值的有用高階組合。這種能力使得更為復(fù)雜的決策過程成為可能,并使計算機比以往任何時候都更加智能。借助深度學(xué)習(xí),我們可以制造出具有自動駕駛能力的汽車和能夠理解人類語音的電話。由于深度學(xué)習(xí)的出現(xiàn),機器翻譯、人臉識別、預(yù)測分析、機器作曲以及無數(shù)的人工智能任務(wù)都成為可能,或相比以往有了顯著改進。雖然深度學(xué)習(xí)背后的數(shù)學(xué)概念幾十年前便提出,但致力于創(chuàng)建和訓(xùn)練這些深度模型的編程庫是近年來才出現(xiàn)的。遺憾的是,這些庫中的大多數(shù)都會在靈活性和生產(chǎn)價值之間進行取舍。靈活的庫對于研究新的模型架構(gòu)極有價值,但常?;蛘哌\行效率太低,或者無法運用于產(chǎn)品中。另一方面,雖然出現(xiàn)了可托管在分布式硬件上的快速、高效的庫,但它們往往專注于特定類型的神經(jīng)網(wǎng)絡(luò),并不適宜研究新的和更好的模型。這就使決策制定者陷于兩難境地:是應(yīng)當用缺乏靈活性的庫來從事研究,以避免重新實現(xiàn)代碼,還是應(yīng)當在研究階段和產(chǎn)品開發(fā)階段分別使用兩個完全不同的庫?如果選擇前一種方案,可能便無法測試不同類型的神經(jīng)網(wǎng)絡(luò)模型;如果選擇后一種方案,則需要維護可是否擁有這樣的資源?谷歌的深度學(xué)習(xí)研究簡史頗受歡迎的機器學(xué)習(xí)庫,如今已被成功運用于自然語言處理、人工智能、計算機視覺和預(yù)測分析等領(lǐng)域。1.5.1解讀來自官網(wǎng)的單句描述比起前面的聲明,第二個定義更為具體,但對那些數(shù)學(xué)或技術(shù)背景不強的人而言,這可能并非最全面的解釋。下面我們對其進行解構(gòu)。皮書》所描述的一個用于數(shù)值計算的內(nèi)部接口,其內(nèi)部實現(xiàn)仍然由谷歌維護。然而,開源實現(xiàn)與谷歌的內(nèi)部實現(xiàn)之間的差異是由與其他內(nèi)部軟件的連接造成的,并非谷歌有意“將好東西藏著掖著”。谷歌始終都在不斷將內(nèi)部改進推送到公共代碼庫??倷C器學(xué)習(xí)的功能提供了廣泛支持,但它也非常適合做復(fù)雜的數(shù)學(xué)計算。然而,由于本書重點討論機器學(xué)習(xí)(尤其是深度學(xué)習(xí)(通常以箭頭或線段表示)代表了數(shù)值、矩陣或張量。數(shù)據(jù)流圖極為有用的原因如下。首先,許多常見的機器學(xué)習(xí)模型,如神經(jīng)網(wǎng)絡(luò),本身就是以有向圖的形式表示的,采用數(shù)據(jù)他計算設(shè)備上更加容易,即只需將完整的、較大的數(shù)據(jù)流圖分解為一些較小的計算圖,并讓每臺計算設(shè)備負責一個獨立的計算子圖(此外,還需一定的邏輯對不同設(shè)備間的共享信息進行調(diào)度)。矩陣數(shù)學(xué),完全可以按矩陣的方式來看待張量。的信息密度非常大,但并未涵蓋那些真正使一部分。雖然這個最初版本的分布式API有些臃腫,但它極其強大。大多數(shù)其他機器學(xué)習(xí)庫尚不具備這樣的功能,尤其值得注意更高的生產(chǎn)效率。此,本書會涵蓋上述三個軟件的用法。用某些庫時,用戶只能獲取對實現(xiàn)原型有幫助的具有較強剛性的預(yù)建模型,而無法對其進行修改??商峁┓浅S袃r值的見解。其他介于兩者之間的計算機上都有用武之地。眾多開源機器學(xué)習(xí)框架中居于榜首位置的有力競爭者。型所需付出的代價絕對不可小覷。需手工定義每臺設(shè)備的角色,這種工作既乏味又容易出錯。由于它是一種全新的特性,因此可供學(xué)習(xí)的例程較少,想必未來的版周折。然而,如果希望對主代碼庫做出貢獻,谷歌開發(fā)團隊會快速回答你的問題,并查看你所提交的代碼,以便為吸納你的工作成果進行準備。如果你是一名經(jīng)驗豐富的機器學(xué)習(xí)專家,并對其他框架具備深入的了解,你可能會發(fā)現(xiàn)一些自己喜歡的雖小但十分有用的特還未得到本地支持??許多軟件都會使用一些庫和獨立維護的軟件包。對于開發(fā)者而言,這是一件好事,因為這種做法有利于代碼復(fù)用,而且他們可專注于創(chuàng)建新的功能,而無需重復(fù)造輪。然而,這種做法也會付出一定的代價。如果某個程序的正常運行必須依賴于另一個庫,則用戶或這款軟件必須確保任何運行該程序代碼的機器都已安裝了依賴庫。乍看上去,這幾乎不算一個問題——只需隨這款軟件一起安裝所需的依賴庫不就行了?不幸的是,這種方法會帶來一些意想不到的后果,而且常常如此。設(shè)想如下場景:你找到一款出色的軟件——軟件A,下載后開始安裝。前版本號為1.0。軟件A先安裝1.0版的依賴項,然后再對自身進行安裝,一切都進行得很順利。再假設(shè)將來的某個時候,下兼容性。鑒于這個依賴項的發(fā)行方式,無法做到1.0和2.0兩個版本同時運行,因為這將導(dǎo)致使用它時產(chǎn)生二義性(這兩個版本的都會作為依賴項被導(dǎo)入,應(yīng)使用哪個版本?)。最終辛后,你才發(fā)現(xiàn)軟件A與2.0版依賴項不兼容,因此完全被破壞,情況頓時變得很糟。如何才能在同一臺機器上既可運言可采取多種方式避免上述依賴沖突問題?!ごa庫內(nèi)部的軟件包依賴。無需依賴于系統(tǒng)級的軟件包或庫,開發(fā)者可將所需版本的依賴庫放在自己的代碼中,并在局部引用。按照這種方式,軟件所需的所有代碼都是可直接操控的,不會受到外部變動的影響。然而,這種方式并非無懈可擊。首先,它增加了安裝該軟件所需的磁盤空間,這意味著安裝時間更長、使用成本更高。其次,用戶可能已經(jīng)以全局方式安裝了依賴庫,這意味著局部版本完全是多余的,會占用不必要的空間。最后,依賴庫在將來可能會推出修復(fù)若干嚴重安全漏洞的關(guān)鍵的、保持向下兼容性的更新。這時,對代碼庫中依賴庫的更新將無法借助軟件包管理器,而只能由軟件開發(fā)者手工完成。不幸的是,須單獨安裝?!な褂靡蕾嚟h(huán)境。一些軟件包管理器中包含可創(chuàng)建虛擬環(huán)境的相關(guān)軟件。在一個環(huán)境中可完全獨立地維護特定版本的軟件而一個容器的機器(包括虛擬機在內(nèi))都能夠與任何運行該容器的其他機器對其中所包含的軟件獲得完全相同的運行效果。與簡單是虛擬機還是物理的服務(wù)器)上進行部署時,它在不同運行時環(huán)境中的一致性使其成為無價之寶。下文將介紹如何安裝Docker,得創(chuàng)建一個Docker容器鏡像。雖然所需的步驟略多,但卻會大大降低在多服務(wù)器上部署的成本。筆者不推薦既不使用虛擬環(huán)境,),檔。這使得它在依據(jù)探索分析創(chuàng)建報告時極為有用,因為可將創(chuàng)建可視化圖表的代碼直接在圖表的旁邊展示出來,也可利用(根據(jù)操作系統(tǒng)的不同,選擇相應(yīng)的命令):至此,準備工作已完成,接下來創(chuàng)建一個包含該虛擬環(huán)境的目錄,以及將來可能會創(chuàng)建的任意虛擬環(huán)境:$virtualflow deactivate于活動狀態(tài),并運行下列與你的操作系統(tǒng)和Py如果希望使用帶有GPU支持的TensorFlow,那么最可能的選擇是從源碼構(gòu)建和安裝。本節(jié)給出了一個完整的安裝參考實例,詳細介紹了安裝和運行TensorFlow所需的每一具體步驟。請注意,本示例中的操作系統(tǒng)為64位UbuntuLinux發(fā)行版,因此如果你使用的是其他Linux發(fā)行版,則可能需要對某些命令進行修改(如apt-get)。如構(gòu)建TensorFlow需要事先安裝少量依賴庫。按照所安裝的PyBazel是一款基于谷歌內(nèi)部軟件的開源構(gòu)建工具。在本書寫作之時,為從源碼構(gòu)建TensorFlow,需要Bazel,因此我們必須自行安裝該軟件。Bazel官網(wǎng)中有一份非常完整的安裝指南,本節(jié)只介紹一些最基本的步驟。在繼續(xù)下一步之前,請驗證Java已被正確安裝:Java安裝完畢后,還需要安裝少量其他依賴庫:svunzto最后,將所下載的安裝腳本的權(quán)限修改為可執(zhí)行的,并運行它: 重啟bash終端,并運行bazel,以非常棒!接下來,需要安裝一些能夠支持GPU運算的依賴軟件。了下載安裝CUDA和cuDNN所需的所有文件,這個步驟是必需的。注冊鏈接如下:當注冊完成后,你會希望下載CUDA。前往下列鏈接,并使用如下操作指南:2)單擊“Download(下載)”按鈕,將安裝文件保存在你的計算機中。該文件體積較大,因此完成下載可能需要一段較長的時間。3)導(dǎo)航至包含所下載的安裝文件的目錄,并運行下列命令:接下來,需要下載cuDNN,它是一款專為深度神經(jīng)網(wǎng)絡(luò)設(shè)計的基于CUDA的加速庫用在前面創(chuàng)建的賬號登錄后,將看到一份簡短的調(diào)查問卷。完成問卷后,可通過單擊問卷下方的按鈕進入下載頁面。單擊“IAgreetotheTerms...”以接受下載許可協(xié)導(dǎo)航至下載好的.tgz文件,運行下列命令以上便是安裝CUDA所需的所有步驟。由于所有依賴庫都已細心安裝,接下來便可安裝TensorFlow了。進入上述目錄后,運行./configure腳本,將所使用的編譯器、CUDA版本等信息通知給Bazel。請確保已記錄顯卡的“計算能力”數(shù)字(上文中已介紹過):配置完成后,便可利用Bazel創(chuàng)建一個用于創(chuàng)建Python二進制文件的可執(zhí)行程序:執(zhí)行上述命令需要相當長的一段時間,具體時長取決于你的計算機性能。待Bazel完成上述任務(wù)后,運行輸出的可執(zhí)行程序,并傳入一個表示Pythonwheel文件存儲路徑的參數(shù):):如果你擁有多臺硬件配置類似的機器,則可使用該wheel文件在這些機器上實現(xiàn)TensorFlow的快速安裝。獲得更多的選擇(即執(zhí)行下列所有命令):build-essential):就是這樣簡單!之后會彈出一個用于對筆記本重命名的窗口,也可用于修改筆記本文件的名稱(擴展名為.ipynb)。你可使用任何自己喜歡的名稱,在本例中筆者將其命名要運行該單元格,只需同時按下shift鍵和回車鍵。該單元格中的代碼執(zhí)行完成后,其下方會自動創(chuàng)建一個新的單元格。我們注意到左邊方框中的提示符變成了“In[1]:?,這意味著該單元格是在內(nèi)核中運行的第一個代碼塊。在該筆記本中鍵入下列代碼,使用單元格的數(shù)量取決于你的需求。你可利用單元格中的分隔符將相關(guān)代碼很自然地組織在一起。下面這行代碼非常特殊,值得專門介紹:下面逐行分析其余代碼,如果你不理解某些術(shù)語,請不必擔心,后面章節(jié)還會一一進行講解:如果所有軟件均已正確安裝,你將得到與上圖類似的輸出結(jié)果。這雖然只是向前邁來一個良好的體驗。本節(jié)將脫離TensorFlow的語境,介紹一些數(shù)據(jù)流圖的基礎(chǔ)知識,內(nèi)容包括節(jié)點、邊和節(jié)點依賴關(guān)系的定義。此外,為對一些關(guān)鍵原理進行解釋,本章還提供了若干實例。如果你對數(shù)據(jù)流圖已有一定使用經(jīng)驗或已運用自如,可直接跳過本節(jié)。TensorFlow中,數(shù)據(jù)流圖本質(zhì)上是一組鏈接在一起的函數(shù),每個函數(shù)都會將其輸出傳遞給0個、1個或更多位于這個級聯(lián)鏈上的其他函數(shù)。按照這種方式,用戶可利用一些很小的、為人們所充分理解的數(shù)學(xué)函數(shù)構(gòu)造數(shù)據(jù)的復(fù)雜變換。下面來看一個比較簡單的例子。上圖展示了可完成基本加法運算的數(shù)據(jù)流圖。在該圖中,加法運算是用圓圈表示的,它可接收兩個輸入(以指向該函數(shù)的箭頭表示并將1和2之和3輸出(對應(yīng)從該函數(shù)引出的箭頭)。該函數(shù)的運算結(jié)果可傳遞給其他函數(shù),也可直接返回給客戶。該數(shù)據(jù)流圖可用如下簡單公式表示: 上面的例子解釋了在構(gòu)建數(shù)據(jù)流圖時,兩個基礎(chǔ)構(gòu)件——節(jié)點和邊是如何使用的。下面回顧節(jié)點和邊的基本性質(zhì):·節(jié)點(node在數(shù)據(jù)流圖的語境中,節(jié)點通常以圓圈、橢圓和方框表示,代表了對數(shù)據(jù)所做的運算或某種操作。在上例中,“add”對應(yīng)于一個孤立節(jié)點。從運算節(jié)點引出的邊??蓮母拍钌蠈⑦呉暈椴煌琌peration之間的連接,因為它們將信息從一個節(jié)點傳輸?shù)搅硪粋€節(jié)點。下面來看一個更有趣的例子。相比之前的例子,上圖所示的數(shù)據(jù)流圖略復(fù)雜。由于數(shù)據(jù)是從左側(cè)流向右側(cè)的(如箭頭方向所示因此可從最左端開始對這個數(shù)據(jù)流圖進行分析:1)最開始時,可看到兩個值5和3流入該數(shù)據(jù)流圖。它們可能來自另一個數(shù)據(jù)流圖,也可能讀取自某個文件,或是由客戶直接輸入。同樣的數(shù)值輸出給節(jié)點c和節(jié)點d,節(jié)點b對其輸入值3也完成同樣的動作。3)節(jié)點c代表乘法運算。它分別從節(jié)點a和b接收輸入值5和3,并將運算結(jié)果15輸出到節(jié)點e。與此同時,節(jié)點d對相同的兩個輸入執(zhí)行加法運算,并將計算結(jié)4)最后,該數(shù)據(jù)流圖的終點——節(jié)點e是另一個“add”節(jié)點。它接收輸入值15下面說明為何上述圖形表示看起來像是一組公式:e=5·3+(5+3)=23經(jīng)過上述步驟,便完成了計算,這里有一些概念值得重點說明:·上述使用“input”節(jié)點的模式十分有用,因為這使得我們能夠?qū)蝹€輸入值傳遞給大量后繼節(jié)點。如果不這樣做,客戶(或傳入這些初值的其他數(shù)據(jù)源)便不得不將輸入值顯式傳遞給數(shù)據(jù)流圖中的多個節(jié)點。按照這種模式,客戶只需保證一次性傳入恰當?shù)妮斎胫?,而如何對這些輸入重復(fù)使用的細節(jié)便被隱藏起來。稍后,我們將對數(shù)據(jù)流圖的抽象做更深入的探討。·突擊小測驗。哪一個節(jié)點將首先執(zhí)行運算?是乘法節(jié)點c還是加法節(jié)點d?答案是:無從知曉。僅憑上述數(shù)據(jù)流圖,無法推知c和d中的哪一個節(jié)點將率先執(zhí)行。有的讀者可能會按照從左到右、自上而下的順序閱讀該數(shù)據(jù)流圖,從而做出節(jié)點c先運行的假設(shè)。但我們需要指出,在該數(shù)據(jù)流圖中,將節(jié)點d繪制在c的上方也未嘗不可。也可能有些讀者認為這些節(jié)點會并發(fā)執(zhí)行,但考慮到各種實現(xiàn)細節(jié)或硬件的限制,實際情況往往并非總是如此。實際上,最好的方式是將它們的執(zhí)行視為相互獨立。由于節(jié)點c并不依賴于來自節(jié)點d的任何信息,所以節(jié)點c在完成自身的運算時無需關(guān)心節(jié)點d的狀態(tài)如何。反之亦然,節(jié)點d也不需要任何來自節(jié)點c的信息。在本章稍后,還將對節(jié)點依賴關(guān)系進行更深入的介紹。接下來,對上述數(shù)據(jù)流圖稍做修改。主要的變化有兩點:你已經(jīng)注意到,上圖在看起來被其他節(jié)點“隔離”的兩個節(jié)點之間添加了一條邊。一般而言,任何節(jié)點都可將其輸出傳遞給數(shù)據(jù)流圖中的任意后繼節(jié)點,而無論這兩者之間發(fā)生了多少計算。數(shù)據(jù)流圖甚至可以擁有下圖所示的結(jié)構(gòu),它仍然是完全合法的。通過這兩個數(shù)據(jù)流圖,想必你已能夠初步感受到對數(shù)據(jù)流圖的輸入進行抽象所帶來的好處。我們能夠?qū)?shù)據(jù)流圖中內(nèi)部運算的精確細節(jié)進行操控,但客戶只需了解將何種信息傳遞給那兩個輸入節(jié)點則可。我們甚至可以進一步抽象,將上述數(shù)據(jù)流圖表示為如下的黑箱。這樣,我們便可將整個節(jié)點序列視為擁有一組輸入和輸出的離散構(gòu)件。這種抽象方式使得對級聯(lián)在一起的若干個運算組進行可視化更加容易,而無需關(guān)心每個部件的具體細節(jié)。要先理解何為“依賴關(guān)系”。再次觀察下面的數(shù)據(jù)流圖。循環(huán)依賴這個概念其實非常簡單:對于任意節(jié)點A,如果其輸出對于某個后繼節(jié)點B的計算是必需的,則稱節(jié)點A為節(jié)點B的依賴節(jié)點。如果某個節(jié)點A和節(jié)點B彼此不需要來自對方的任何信息,則稱兩者是獨立的。為對此進行可視化,首先觀察當乘法節(jié)點c出于某種原因無法完成計算時會出現(xiàn)何種情況??梢灶A(yù)見,由于節(jié)點e需要來自節(jié)點c的輸出,因此其運算無法執(zhí)行,只能無限等待節(jié)點c的數(shù)據(jù)的到來。容易看出,節(jié)點c和節(jié)點d均為節(jié)點e的依賴節(jié)點,因為它們均將信息直接傳遞到最后的加法函數(shù)。然而,稍加思索便可看出節(jié)點a和節(jié)點b也是節(jié)點e的依賴節(jié)點。如果輸入節(jié)點中有一個未能將其輸入傳遞給數(shù)據(jù)流圖中的下一個函數(shù),情形會怎樣?可以看出,若將輸入中的某一個移除,會導(dǎo)致數(shù)據(jù)流圖中的大部分運算中斷,從而表明依賴關(guān)系具有傳遞性。即,若A依賴于B,而B依賴于C,則A依賴于C。在本例中,最終節(jié)點e依賴于節(jié)點c和節(jié)點d,而節(jié)點c和節(jié)點d均依賴于輸入節(jié)點b。因此,最終節(jié)點e也依賴于輸入節(jié)點b。同理可知節(jié)點e也依賴于輸入節(jié)點a。此外,還可對節(jié)點e的不同依賴節(jié)點進行區(qū)分:1)稱節(jié)點e直接依賴于節(jié)點c和節(jié)點d。即為使節(jié)點e的運算得到執(zhí)行,必須有直接來自節(jié)點c和節(jié)點d的數(shù)據(jù)。2)稱節(jié)點e間接依賴于節(jié)點a和節(jié)點b。這表示節(jié)點a和節(jié)點b的輸出并未直接傳遞到節(jié)點e,而是傳遞到某個(或某些)中間節(jié)點,而這些中間節(jié)點可能是節(jié)點e的直接依賴節(jié)點,也可能是間接依賴節(jié)點。這意味著一個節(jié)點可以是被許多層的中間節(jié)點相隔的另一個節(jié)點的間接依賴節(jié)點(且這些中間節(jié)點中的每一個也是后者的依賴節(jié)點)。最后來觀察將數(shù)據(jù)流圖的輸出傳遞給其自身的某個位于前端的節(jié)點時會出現(xiàn)何種情況。不幸的是,上面的數(shù)據(jù)流圖看起來無法工作。我們試圖將節(jié)點e的輸出送回節(jié)點b,并希望該數(shù)據(jù)流圖的計算能夠循環(huán)進行。這里的問題在于節(jié)點e現(xiàn)在變?yōu)楣?jié)點b的直接依賴節(jié)點;而與此同時,節(jié)點e仍然依賴于節(jié)點b(前文已說明過)。其結(jié)果是節(jié)點b和節(jié)點e都無法得到執(zhí)行,因為它們都在等待對方計算的完成。也許你非常聰明,決定將傳遞給節(jié)點b或節(jié)點e的值設(shè)置為某個初始狀態(tài)值。畢竟,這個數(shù)據(jù)流圖是受我們控制的。不妨假設(shè)節(jié)點e的輸出的初始狀態(tài)值為上圖給出了經(jīng)過幾輪循環(huán)各數(shù)據(jù)流圖中各節(jié)點的狀態(tài)。新引入的依賴關(guān)系制造了一個無窮反饋環(huán),且該數(shù)據(jù)流圖中的大部分邊都趨向于無窮大。然而,出1)由于數(shù)據(jù)流圖中存在無限循環(huán),因此程序無法以優(yōu)雅的方式終止。2)依賴節(jié)點的數(shù)量變?yōu)闊o窮大,因為每輪迭代都依賴于之前的所有輪次的迭代。不幸的是,在統(tǒng)計依賴關(guān)系時,每個節(jié)點都不會只被統(tǒng)計一次,每當其輸出發(fā)生變化時,它便會被再次記為依賴節(jié)點。這就使得追蹤依賴信息變得不可能,而出于多種原因(詳見本節(jié)的最后一部分這種需求是至關(guān)重要的。3)你經(jīng)常會遇到這樣的情況:被傳遞的值要么在正方向變得非常大(從而導(dǎo)致上溢要么在負方向變得非常大(導(dǎo)致下溢或者非常接近于0(使得每輪迭代在加法上失去意義)?;谏鲜隹紤],在TensorFlow中,真正的循環(huán)依賴關(guān)系是無法表示的,這并非壞事。在實際使用中,完全可通過對數(shù)據(jù)流圖進行有限次的復(fù)制,然后將它們并排放置,并將代表相鄰迭代輪次的副本的輸出與輸入串接。該過程通常被稱為數(shù)據(jù)流圖的“展開”(unrolling)。第6章還將對此進行更為詳細的介紹。為了以圖形化的方式展示數(shù)據(jù)流圖的展開效果,下面給出一個將循環(huán)依賴展開5次后的數(shù)據(jù)流圖。對這個數(shù)據(jù)流圖進行分析,便會發(fā)現(xiàn)這個由各節(jié)點和邊構(gòu)成的序列等價于將之前的數(shù)據(jù)流圖遍歷5次。請注意原始輸入值(以數(shù)據(jù)流圖頂部和底部的跳躍箭頭表示)是傳遞給數(shù)據(jù)流圖的每個副本的,因為代表每輪迭代的數(shù)據(jù)流圖的每個副本都需要它們。按照這種方式將數(shù)據(jù)流圖展開,可在保持確定性計算的同時模擬有用的循環(huán)依賴。既然我們已理解了節(jié)點的依賴關(guān)系,接下來便可分析為什么追蹤這種依賴關(guān)系十分有用。不妨假設(shè)在之前的例子中,我們只希望得到節(jié)點c(乘法節(jié)點)的輸出。我們已經(jīng)定義了完整的數(shù)據(jù)流圖,其中包含獨立于節(jié)點c和節(jié)點e(出現(xiàn)在節(jié)點c的后方)的節(jié)點d,那么是否必須執(zhí)行整個數(shù)據(jù)流圖的所有運算,即便并不需要節(jié)點d和節(jié)點e的輸出?答案當然是否定的。觀察該數(shù)據(jù)流圖,不難發(fā)現(xiàn),如果只需要節(jié)點c的輸出,那么執(zhí)行所有節(jié)點的運算便是浪費時間。但這里的問題在于:如何確保計算機只對必要的節(jié)點執(zhí)行運算,而無需手工指定?答案是:利用節(jié)點之間的依賴關(guān)系!這背后的概念相當簡單,我們唯一需要確保的是為每個節(jié)點的直接(而非間接)依賴節(jié)點維護一個列表??蓮囊粋€空棧開始,它最終將保存所有我們希望運行的節(jié)點。從你希望獲得其輸出的節(jié)點開始。顯然它必須得到執(zhí)行,因此令其入棧。接下來查看該輸出節(jié)點的依賴節(jié)點列表,這意味著為計算輸出,那些節(jié)點必須運行,因此將它們?nèi)咳霔?。然后,對所有那些?jié)點進行檢查,看它們的直接依賴節(jié)點有哪些,然后將它們?nèi)咳霔!@^續(xù)這種追溯模式,直到數(shù)據(jù)流圖中的所有依賴節(jié)點均已入棧。按照這種方式,便可保證我們獲得運行該數(shù)據(jù)流圖所需的全部節(jié)點,且只包含所有必需的節(jié)點。此外,利用上述棧結(jié)構(gòu),可對其中的節(jié)點進行排序,從而保證當遍歷該棧時,其中的所有節(jié)點都會按照一定的次序得到運行。唯一需要注意的是需要追蹤哪些節(jié)點已經(jīng)完成了計算,并將它們的輸出保存在內(nèi)存中,以避免對同一節(jié)點反復(fù)計算。按照這種方式,便可確保計算量盡可能地精簡,從而在規(guī)模較大的數(shù)據(jù)流圖上節(jié)省以小時計的寶貴處理時間。2)運行數(shù)據(jù)流圖(在數(shù)據(jù)上)。此豐富。每次只需關(guān)注上述工作流的一部分,有助于更周密地組織自己的代碼,并有助于明確接下來的工作方向。何創(chuàng)建在多次運行中狀態(tài)不斷發(fā)生變化并接收不同數(shù)據(jù)的數(shù)據(jù)流圖。通過上一節(jié)的介紹,我們已對如下數(shù)據(jù)流圖頗為熟悉。下面來逐行解析這段代碼。首先,你會注意到下列導(dǎo)入語句:inastf接下來研究前兩行變量賦值語句:這兩個語句定義了數(shù)據(jù)流圖中的另外兩個節(jié)點,而且它們都使用了e"add.e")最后的這行代碼定義了數(shù)據(jù)流圖的終點e,它使用tf.add的方式與節(jié)點d是一致的。區(qū)的結(jié)果輸出。請注意,這只是整個流程的數(shù)據(jù)流圖定義部分,要想體驗一個數(shù)據(jù)流圖的運行效果,還需在上述代碼之后添加兩行語句,以將數(shù)據(jù)流圖終點的結(jié)果輸下面通過一個練習(xí)來實踐上述內(nèi)容。),可將代碼寫入一個Python文件,然后以非交互方式運行,但運行數(shù)據(jù)流圖所產(chǎn)生的輸出在默認情況下是不會顯示出來的。為),inastfInflowInflow假設(shè)上述導(dǎo)入語句在執(zhí)行時沒有遇到任何問題,則可進入下一部分代碼:這與在上面看到的代碼完全相同,可隨意更改這些常量的數(shù)值或name參數(shù)。在本書中,為了保持前后一致性,筆者會始終使用相)或者執(zhí)行整數(shù)除法,或執(zhí)行浮點數(shù)除法,具體取決于所提供的輸入類型。如果接下來定義數(shù)據(jù)流圖的終點: 你可能已經(jīng)注意到,在調(diào)用上述Op時,沒有顯示任何輸出,這是因為這些語句只是在后臺將一些Op添加到數(shù)據(jù)流圖中,并無任何計算發(fā)生。為運行該數(shù)據(jù)流 ),sess,run(e)至此,我們終于可以看到運行結(jié)果了。執(zhí)行完上述語句后,你應(yīng)當能夠看到所定義的數(shù)據(jù)流圖的輸出。對于本練習(xí)中的數(shù)據(jù)流圖,輸出為23。如果使用了不同sess.run(c)出,請執(zhí)行所有必要的運算來求取這個節(jié)點的輸出”??煞磸?fù)嘗試該函數(shù)的使用,將數(shù)據(jù)流圖中其他節(jié)點的結(jié)果輸出。 棒極了!既然我們已經(jīng)擁有了一個活動狀態(tài)的Session對象,s.graph)):dir='ny-graph"將看到一個橙白主題的歡迎頁面:識。如果單擊這些節(jié)點,還會得到一些關(guān)于它們的信息,如它們依賴于哪些節(jié)點。還會發(fā)現(xiàn),輸入節(jié)點a和b貌似重復(fù)出現(xiàn)了,但如果單擊或?qū)⑹髽藨彝T跇撕炇玖藘纱味眩Ч€是相當驚艷的!正理解了數(shù)據(jù)在數(shù)據(jù)流圖中的流動方式。),在學(xué)習(xí)數(shù)據(jù)流圖的基礎(chǔ)知識時,使用簡單的標量值是很好的選擇。既然我們已經(jīng)掌握了“數(shù)據(jù)流”,下面不妨熟悉一下張量的概念。念,便可對之前的示例數(shù)據(jù)流圖進行修改,使其可使用張量?,F(xiàn)在不再使用兩個獨立的輸入節(jié)點,而是換成了一個可接收向量(或1階張量)的節(jié)點。與之前的版本相比,這個新的流圖有如下優(yōu)點:1)客戶只需將輸入送給單個節(jié)點,簡化了流圖的2)那些直接依賴于輸入的節(jié)點現(xiàn)在只需追蹤一個依賴節(jié)點,而非兩個。3)這個版本的流圖可接收任意長度的向量,從而使其靈活性大大增強。我們還可對這個流圖施加一條嚴格的約束,如要求輸入的長度必須為2(或任何我們希除了調(diào)整變量名稱外,主要改動還有以下兩處:量,然后分別將它們相乘或相加。),),),表構(gòu)成的列表將被轉(zhuǎn)化為2階張量(矩陣),以此類推。下面給到目前為止,我們尚未見到布爾值或字符串,但可將張量視為一種以結(jié)構(gòu)化格式保存任意數(shù)據(jù)的方式。顯然,數(shù)學(xué)函數(shù)無法對字符串進行處理,而字符串解析據(jù)類型。對于某些類型,如字符串,推斷過程是非常簡單的,但對于其他類型,則可能完全無法做出推斷。例如,在Python中,所有整數(shù)都具字符串數(shù)據(jù)類型3.2.3張量的形狀):如,列表[2,3]描述了一個2階張量的形狀,其第1個維上的長度為2,第2個維上的長度為3。注意,無),裹),都可用于定義張量的形狀。下面通過更多的例子來說明這一點:再次提醒:張量只是矩陣的一個超集!無輸入、無輸出的運算是的,這意味著從技術(shù)角度講,有些Op既無任何輸入,也無任何輸出。Op的功能并不只限于數(shù)據(jù)運算,它還可用于如狀態(tài)初始化這樣的任務(wù)。本章中,我們將回顧一些這樣的非數(shù)學(xué)Op,但請記住,并非所有節(jié)點都需要與其他節(jié)點連接。e-"ny___add___op")要在單個文件中定義多個數(shù)據(jù)流圖時,最佳實踐是不使用默認數(shù)據(jù)流圖,或為其立即分配句柄。這樣可以保證各節(jié)點按照一致的方式添加到每個數(shù)據(jù)流圖中。例(本書后續(xù)章節(jié)將對此進行介紹)。 ),些節(jié)點,然后將b的值輸出。我們還可傳入一個數(shù)據(jù)流圖元素的列表:會接收到作為輸出的它們的值。個會話,則事情會變得有些棘手。筆者發(fā)現(xiàn),在運行數(shù)據(jù)流圖時,如果能夠保持一3.2.7利用占位節(jié)點添加輸入之前定義的數(shù)據(jù)流圖并未使用真正的“輸入”,它總是使用相同的數(shù)值5和3。我們真正希望做的是從客戶那里接收輸入值,這樣便可對數(shù)據(jù)流圖中所描述的變換),素與該張量中的其他元素顯著不同的情況出現(xiàn): 現(xiàn)在開始介紹構(gòu)建任何TensorFlow數(shù)據(jù)流圖所必需的核心構(gòu)件。到目前為止,我們只接觸了包含少量節(jié)點和階數(shù)較小的張量的非常簡單的數(shù)據(jù)流圖,但現(xiàn)實世界中的模型往往會包含幾十或上百個節(jié)點,以及數(shù)以百萬計的參數(shù)。為使這種級別的復(fù)雜性可控,TensorFlow當前提供了一種幫助 我們添加到該數(shù)據(jù)流圖中的add和mulOp并未立即顯示出來,所看到的是涵蓋它們的命名作用域??赏ㄟ^單擊位于它們右上角的“+”圖標將名稱作用域的方框在每個作用域內(nèi),可看到已經(jīng)添加到該數(shù)據(jù)流圖中的各個Op,也可將名稱作用域嵌入在其他名稱作用域內(nèi):),時間使用,且在使用時無須遵循任何特定順序。為防止在數(shù)據(jù)流圖中出現(xiàn)從單點引出過多箭頭的問題,只有當常量被使用時,它才會以一個很小的視覺元素的形將一個規(guī)模較大的數(shù)據(jù)流圖分解為一些有意義的簇能夠使對模型的理解和編譯更加方便。3.4練習(xí):綜合運用各種組件進行研究。本質(zhì)上,本練習(xí)所要實現(xiàn)的數(shù)據(jù)流圖與我們接觸的第一個基本模型對應(yīng)相同類型的變換?!つP筒辉俳邮諆蓚€離散標量,而改為接收·使用該數(shù)據(jù)流圖時,將隨時間計算所有輸出的總和?!⒉捎妹Q作用域?qū)?shù)據(jù)流圖進行合理劃現(xiàn)可直觀感受一下本練習(xí)中的數(shù)據(jù)流圖。在解讀該模型時,有一些關(guān)鍵點需要注意:對象是在主要的變換工作流之外發(fā)揮作用的,因此將其放在一個獨立的空間中是完全合理的。才被添加,否則運算將會失控。3.4.1構(gòu)建數(shù)據(jù)流圖 graph=tf.Graph()graph,as____default():們時需要與數(shù)據(jù)流圖中的其他節(jié)點區(qū)分開來,并將它們放入自己的名稱作用域。),除少量關(guān)鍵之處不同外,上述代碼與為之前的模型所編寫的代碼高度相似:法運算,而之前的Op只能接收兩個標量作為輸入。以上便是構(gòu)建數(shù)據(jù)流圖的全部內(nèi)容,但要使這個數(shù)據(jù)流圖能夠運行,還需要完成一些設(shè)置。3.4.2運行數(shù)據(jù)流圖存匯總數(shù)據(jù)的目標文件夾: it)并將匯總數(shù)據(jù)保存下來:個折線圖的橫軸)。),$tensorproved___graph"可將各個方框展開,以便在更細的粒度上觀察它們的結(jié)構(gòu)。現(xiàn)在可以看到輸入層、中間層和輸出層是彼此分離的。對于像本例這樣的簡單模型,這樣的劃分可能有些小題大做,但這種類型的劃分方法是極為有用的。請示了不同時間點上值的變化。單擊該圖表左下方的藍色矩形,它們會像上圖一樣展開。仔細檢查匯總數(shù)據(jù)的結(jié)果,對其進行比較,確保它們都是有意義的,然后向自己表示祝賀!本練習(xí)至此就全部結(jié)束了,希望讀者能夠熟練掌握如何基于虛擬草本練習(xí)的完整代碼如下:4.1有監(jiān)督學(xué)習(xí)簡介本書主要介紹有監(jiān)督學(xué)習(xí)問題。在這類問題中,我們的目標是依據(jù)某個帶標注信息的輸入數(shù)據(jù)集(即其中的每個樣本都標注了真實的或期望的輸出)去訓(xùn)練一個推斷模型。該模型應(yīng)能覆蓋一個數(shù)據(jù)集,并可對不存在于初始訓(xùn)練集中的新樣本的輸出進行預(yù)測。推斷模型即運用到數(shù)據(jù)上的一系列數(shù)學(xué)運算。具體的運算步驟是通過代碼設(shè)置的,并由用于求解某個給定問題的模型確定。模型確定后,構(gòu)成模型的運算也就固定了。在各運算內(nèi)部,有一些與其定義相關(guān)的數(shù)值,如“乘以3”、輸出進行調(diào)整。雖然不同的推斷模型在所使用的運算的數(shù)量、運算的組合方式以及所使用的參數(shù)數(shù)量上千差萬別,但對于訓(xùn)練,我們始終可采用相同的一般結(jié)構(gòu):數(shù)據(jù)流圖的高層、通用訓(xùn)練閉環(huán)我們創(chuàng)建了一個訓(xùn)練閉環(huán),它具有如下功能。·首先對模型參數(shù)進行初始化。通常采用對參數(shù)隨機賦值的方法,但對于比較簡單的模型,也可以將各參數(shù)的初值均設(shè)為0。·讀取訓(xùn)練數(shù)據(jù)(包括每個數(shù)據(jù)樣本及其期望輸出)。通常人們會在這些數(shù)據(jù)送入模型之前,隨機打亂樣本的次序?!ぴ谟?xùn)練數(shù)據(jù)上執(zhí)行推斷模型。這樣,在當前模型參數(shù)配置下,每個訓(xùn)練樣本都會得到一個輸出值?!び嬎銚p失。損失是一個能夠刻畫模型在最后一步得到的輸出與來自訓(xùn)練集的期望輸出之間差距的概括性指標。損失函數(shù)有多種類型,本書會陸續(xù)進行介紹?!ふ{(diào)整模型參數(shù)。這一步對應(yīng)于實際的學(xué)習(xí)過程。給定損失函數(shù),學(xué)習(xí)的目的在于通過大量訓(xùn)練步驟改善各參數(shù)的值,從而將損失最小化。最常見的策略是使用梯度下降算法(接下來的一節(jié)中將對該算法進行介紹)。上述閉環(huán)會依據(jù)所需的學(xué)習(xí)速率、所給定的模型及其輸入數(shù)據(jù),通過大量循環(huán)不斷重復(fù)上述過程。當訓(xùn)練結(jié)束后,便進入評估階段。在這一階段中,我們需要對一個同樣含有期望輸出信息的不同測試集依據(jù)模型進行推斷,并評估模型在該數(shù)據(jù)集上的損失。該測試集中包含了何種樣本,模型是預(yù)先無法獲悉的。通過評估,可以了解到所訓(xùn)練的模型在訓(xùn)練集之外的推廣能力。一種常見的方法是將原始數(shù)據(jù)集一分下面利用上述結(jié)構(gòu)為模型訓(xùn)練和評估定義一個通用的代碼框架:以上便是模型訓(xùn)練和評估的基本代碼框架。首先需要對模型參數(shù)進行初始化;然后為每個訓(xùn)練),),),),);象,并運行訓(xùn)練閉環(huán)。在接下來的幾節(jié)中,將針對不同類型的推斷模型為這些模板方法填充所需的代碼。當對模型的響應(yīng)滿意后,便可將精力放在模型導(dǎo)出,以及用它對所需要使用的數(shù)據(jù)進行推斷上。例如為冰激凌App用戶推薦不同口味的冰激凌。上文曾經(jīng)提到,訓(xùn)練模型意味著通過許多個訓(xùn)練周期更新其參數(shù)(或者用TensorFlow的語言來說,變量)。由于變量都保存在內(nèi)存中,所以若計算機經(jīng)歷長時間訓(xùn)練后突然斷電,所有工作都將丟失。幸運的是,借助tf.train.Saver類可將數(shù)據(jù)流圖中的變量保存到專為使用Saver類,需要對之前的訓(xùn)練閉環(huán)代碼2000等。該文件會保存每個變量的當前值。默認情況下,Saver對象只會保留最近的5個文件,更早的文件都將被自動刪除。變量的值。在上述代碼中,首先檢查是否有檢查點文件存在,并在開始訓(xùn)練閉環(huán)前恢復(fù)各變量的值,還可依據(jù)檢查點文件的名稱恢復(fù)全局迭代次數(shù)。既然已了解了有監(jiān)督學(xué)習(xí)的一般原理,以及如何保存訓(xùn)練進度,接下來將對一些常見的推斷模型進行討論。4.3線性回歸在有監(jiān)督學(xué)習(xí)問題中,線性回歸是一種最簡單的建模手段。給定一個數(shù)據(jù)點集合作為訓(xùn)練集,線性回歸的目標是找到一個與這些數(shù)據(jù)最為吻合的線性函數(shù)。上圖展示了一個2D情形下的線性回歸模型。圖中的點代表訓(xùn)練數(shù)據(jù),而直線代表模型的推斷結(jié)果。下面運用少量數(shù)學(xué)公式解釋線性回歸模型的基本原理。線性函數(shù)的一般表達式為:其矩陣(或張量)形式為:?,xk是一組獨立的預(yù)測變量;在使用模型對新樣本進行預(yù)測時,需要提供這些值。若采用矩陣形式,可一次性提供多個樣本,其中每行對應(yīng)一個?,wk為模型從訓(xùn)練數(shù)據(jù)中學(xué)習(xí)到的參數(shù),或賦予每個變量的“權(quán)值”。下面用代碼來表示這種模型。這里沒有使用權(quán)值的轉(zhuǎn)置,而是將它們定義為單個列向量:接下來需要定義如何計算損失。對于這種簡單的模型,將采用總平方誤差,即模型對每個訓(xùn)練樣本的預(yù)測值與期望輸出之差的平方的總和。從代數(shù)角度看,這個損失函數(shù)實際上是預(yù)測的輸出向量與期望向量之間歐氏距離的平方。對于2D數(shù)據(jù)集,總平方誤差對應(yīng)于每個數(shù)據(jù)點在垂直方向上到所預(yù)測的回歸直線的距離的平方總和。這種損失函數(shù)也稱為L2范數(shù)或L2損失函數(shù)。這里之所以采用平方,是為了避免計算平方根,因為對于最小化損失這個目標,有無平方并無本質(zhì)區(qū)別,但有平方可以節(jié)省一定的計算量。我們需要遍歷i來求和,其中i為數(shù)據(jù)樣本的索引。該函數(shù)的實現(xiàn)如下:接下來便可用數(shù)據(jù)實際訓(xùn)練模型。例如,將準備使用一個將年齡、體重(單位:千克)與血液脂肪含量關(guān)聯(lián)的數(shù)據(jù)集由于這個數(shù)據(jù)集規(guī)模很小,下面直接將其嵌入在代碼中。下一節(jié)將演示如何像實際應(yīng)用場景中那樣從文件中讀取訓(xùn)練數(shù)據(jù)。下面定義模型的訓(xùn)練運算。我們將采用梯度下降算法對模型參數(shù)進行優(yōu)化(下一節(jié)將介紹該算法)。運行上述代碼時,將看到損失函數(shù)的值隨訓(xùn)練步數(shù)的增加呈現(xiàn)逐漸減小的趨勢。模型訓(xùn)練完畢后,便需要對其進行評估。下面計算一個年齡25歲、體重80千克的人的血液脂肪含量,這個數(shù)據(jù)并未在訓(xùn)練集中出現(xiàn)過,但可將預(yù)測結(jié)果與同作為一種快速評估方法,可驗證該模型學(xué)習(xí)到了血液脂肪含量隨體重下降的衰減情況,且輸出值介于原始數(shù)據(jù)訓(xùn)練值的邊界之間。4.4對數(shù)幾率回歸線性回歸模型所預(yù)測的是一個連續(xù)值或任意實數(shù)。下面介紹一種能夠回答Yes-N這個函數(shù)接受單個輸入值。為使該函數(shù)能夠接受多維數(shù)據(jù),或來自訓(xùn)練集中樣本的特征,需要將它們合并為單個值。可利用上述的線性回歸模型表達式。概率。然后,損失應(yīng)當刻畫的是對于特定樣本,模型為其分配一個小于1的值的概率。因此,回答“No”將表示概率值為0,于是損失是模值,并取平方。),借助交叉熵,當模型對期望輸出為“Yes”的樣本的預(yù)測概率接近于0時,罰項的值就會增長到接近于無窮大。這就使得訓(xùn)練完成后,模型不可能做出這樣的錯誤預(yù)測。這使得交叉熵更適合作為該模型的損失函數(shù)。該模型應(yīng)能依據(jù)乘客的年齡、性別和船票的等級推斷他或她是否能夠幸存下來。編寫讀取文件的基本代碼。對于之前編寫的框架,這是一個新的方法。你可加載和解析它,并創(chuàng)建一個批次來讀取排列在某個張量中的多行數(shù)據(jù),以提升推斷計算的效率。數(shù)據(jù),便需要將其轉(zhuǎn)換為數(shù)值型特征。一種比較簡單的方法是這種方式會為這些取值強加一種實際并不存在的線性關(guān)系。我們不能說“三等票是一等票的3倍”,正確的做法是將每個屬性特征擴展為N維的布爾型特征,每個可能的取值對應(yīng)一維。若具備該屬性,則相應(yīng)的維度上取值為1。這樣就可使模型獨立地學(xué)習(xí)到每個可能的取值的重要性。在本例中,持“一等票”的乘客幸存的概率要高于其他乘客。使用屬性數(shù)據(jù)時,通常都是先將其轉(zhuǎn)換為多維布爾型特征,每個可能的取值對應(yīng)一維。這使得模型能夠?qū)γ總€可能的取值獨立加權(quán)。最后,訓(xùn)練模型。為了對訓(xùn)練結(jié)果進行評估,準備對訓(xùn)練集中的一批數(shù)據(jù)進行推斷,并統(tǒng)計已經(jīng)正確預(yù)測的樣本總數(shù)。我們將這種方法稱為度量準確率[1]。運行上述代碼,將得到約80%的準確率??紤]到模型較為簡單,這個結(jié)果還是比較令人滿意的。[1]準確率實際上是正確預(yù)測的樣本總數(shù)占全部樣本的比例?!g者注借助對數(shù)幾率回歸,可對Yes-No型問題的回答進行建?!,F(xiàn)在,希望能夠回答具有多個選項的問題,如“你的出生地是波士頓、倫敦還是悉尼??對于這樣的問題,可使用softmax函數(shù),它是對數(shù)幾率回歸在C個可能不同的值上的推廣。該函數(shù)的返回值為含C個分量的概率向量,每個分量對應(yīng)于一個輸出類別的概率。由于各分量為概率,C個分量之和始終為1,這是因為softmax的公式要求每個樣本必須屬于某個輸出類別,且所有可能的樣本均被覆蓋。如果各分量之和小于1,則意味著存在一些隱藏的類別;若各分量之和大于1,則說明每個樣本可能同時屬于多個類別??梢宰C明,當類別總數(shù)為2時,所得到的輸出概率與對數(shù)幾率回歸模型的輸出完全相同。為實現(xiàn)該模型,需要將之前的模型實現(xiàn)中變量初始化部分稍做修改。由于模型需要計算C個而非1個輸出,所以需要C個不同的權(quán)值組,每個組對應(yīng)一個可能的輸出。因此,會使用一個權(quán)值矩陣而非一個權(quán)值向量。該矩陣的每行都與一個輸入特征對應(yīng),而每列都對應(yīng)于一個輸出類別。輸出類(不同類型的鳶尾花因此權(quán)值矩陣的維數(shù)應(yīng)為4×3。變量初始化代碼如下所示:對數(shù)幾率回歸中對損失計算的考慮也同樣應(yīng)用于擬合一個候選損失函數(shù),因為這里的輸出也是概率值。準備再次使用交叉熵,并對其進行改造以適應(yīng)多類情形。對于單個訓(xùn)練樣本i,交叉熵的形式變?yōu)椋簩⒚總€輸出類別在訓(xùn)練樣本上的損失相加。注意,對于訓(xùn)練樣本的期望類別,yc應(yīng)當為1,對其他情形應(yīng)為0,因此實際上這個和式中只有一個損失值被計入,它度量了模型為真實類別預(yù)測的概率的可信度。為計算訓(xùn)練集上的總損失值,我們將每個訓(xùn)練樣本的損失相加:在代碼層面,TensorFlow為softmax交叉熵函數(shù)提供了兩個實現(xiàn)版本:一個版本針對訓(xùn)練集中每個樣本只對應(yīng)單個類別專門做了優(yōu)另一個版本允許用戶使用包含每個樣本屬于每個類別的概率信息的訓(xùn)練集。例如,可使用像“60%被詢問的人認為這幅圖片與狗有關(guān),25%認為與樹有關(guān),不需要它。在可能的情況下,稀疏版本是更好的選擇,因為它的計算速度非常快。注意,模型的最終輸出將總是單個類別值,這個版本只是為了支持更靈活的訓(xùn)練數(shù)據(jù)。下面定義輸入方法。我們將復(fù)用來自對數(shù)幾率回歸示例中的read_csv函數(shù),但在調(diào)用時會使用數(shù)據(jù)集中的默認值,它們都是數(shù)值型的。個可能的值進行比較。然后,利用tf.argmax找到那個張量中值為真的位置,從而有效地將各類別轉(zhuǎn)化為0~2范圍的整數(shù)。對于訓(xùn)練函數(shù),內(nèi)容完全相同。推斷過程將計算各測試樣本屬于每個類別的概率??衫胻f.argmax函數(shù)來選擇預(yù)測的輸出值中具有最大概率的那個類別。最后,把tf.equal與期望的類別進行運行上述代碼,可以獲得約95%的準確率。4.6多層神經(jīng)網(wǎng)絡(luò)到目前為止,我們已經(jīng)使用過了比較簡單的神經(jīng)網(wǎng)絡(luò),但并未特別聲明。線性回歸模型和對數(shù)幾率回歸模型本質(zhì)上都是單個神經(jīng)元,它具有以下功能:·計算輸入特征的加權(quán)和??蓪⑵靡暈槊總€樣本中輸入特征為1的權(quán)重,稱之為計算特征的),下圖表示了每個神經(jīng)元的輸入、處理和輸出。為求解一些更復(fù)雜的問題,如手寫數(shù)字識別,或識別圖像中的貓和狗,我們需要一個更復(fù)雜的模型。據(jù),一定存在一條直線(對于高維數(shù)據(jù)則為超平面),它可將分別屬于兩個類別的樣本分隔在直線兩側(cè),如下圖所示。在上圖中,無法找到一條直線能夠完美地將黑色點(對應(yīng)布爾值1)和灰色點(對應(yīng)布爾值0)完美區(qū)分,這是因為“異或這個問題在20世紀70年代一度使神經(jīng)網(wǎng)絡(luò)研究失去重要性長達近10年之久,后來的研究人員為了繼續(xù)使用神經(jīng)網(wǎng)絡(luò)解決這種不具神經(jīng)網(wǎng)絡(luò)的輸入端和輸出端之間插入更多的神經(jīng)元,如下圖所示。),神經(jīng)元對應(yīng)一個問題,并依據(jù)這些問題的回答最終決定輸出的結(jié)果。添加隱含層的作用相當于在數(shù)據(jù)分布圖中允許神經(jīng)網(wǎng)絡(luò)繪制一條以上的分隔線。從上圖可以看到,每條分隔線都為向輸入數(shù)據(jù)提出的第一批問題針對平面進行了劃分。然后,再將所有相等的輸出劃分到單個區(qū)域中。甚至在每層中使用不同的激活函數(shù)。本書后續(xù)章節(jié)還將介紹在不同應(yīng)用場景中使用的不同類型的深度神經(jīng)網(wǎng)絡(luò)。4.7梯度下降法與誤差反向傳播算法本節(jié)將對所使用的學(xué)習(xí)算法進行解釋,并以此結(jié)束對機器學(xué)習(xí)基礎(chǔ)的介紹。梯度下降法是一種致力于找到函數(shù)極值點的算法。前面介紹過,所謂“學(xué)習(xí)”便是改進模型參數(shù),以便通過大量訓(xùn)練步驟將損失最小化。有了這個概念,將梯度下降法應(yīng)用于尋找損失函數(shù)的極值點便構(gòu)成了依據(jù)輸入數(shù)據(jù)的模型學(xué)習(xí)。下面給出梯度的定義,以防讀者對此缺乏了解。梯度是一種數(shù)學(xué)運算,通常以符號表示。它與導(dǎo)數(shù)類似,但也可應(yīng)用于輸入為一個向量、輸出為一個標量的函數(shù),損失函數(shù)也屬于這種類型。梯度的輸出是一個由若干偏導(dǎo)數(shù)構(gòu)成的向量,它的每個分量對應(yīng)于函數(shù)對輸入向量的相應(yīng)分量的偏導(dǎo):如果函數(shù)接收的輸入多于一個變量,則應(yīng)考慮偏導(dǎo)數(shù)。在求偏導(dǎo)時,可將當前變量以外的所有變量視為常數(shù),然后運用單變量求導(dǎo)法則。偏導(dǎo)數(shù)所度量的是函數(shù)輸出相對于某個特定輸入變量的變化率,即當輸入變量的值增長時,輸出值的增長。在繼續(xù)下面的內(nèi)容之前,有一點需要強調(diào)。當提及損失函數(shù)的輸入變量時,指的是模型的權(quán)值,而非實際數(shù)據(jù)集的輸入特征。一旦給定數(shù)據(jù)集和所要使用的特征類型,這些輸入特征便固定下來,無法進行優(yōu)化。我們所計算的偏導(dǎo)數(shù)是相對于推斷模型中的每個權(quán)值而言的。之所以關(guān)心梯度,是因為它的輸出向量表明了在每個位置損失函數(shù)增長最快的方向,可將它視為表示了在函數(shù)的每個位置向哪個方向移動函數(shù)值可以增假設(shè)上述曲線對應(yīng)于損失函數(shù)。點表示權(quán)值的當前值,即現(xiàn)在所在的位置。梯度用箭頭表示,表明為了增加損失,需要向右移動。此外,箭頭的長度概念化地表示了如果在對應(yīng)的方向移動,函數(shù)值能夠增長多少。如果向著梯度的反方向移動,則損失函數(shù)的值會相應(yīng)減小。在上述圖表中,如果向梯度的反方向移動,則意味著將向著損失函數(shù)值減少的方向移動。如果沿該方向移動,并再次計算梯度值,并重復(fù)上述過程,直至梯度的模為0,將到達損失函數(shù)的極小值點。這正是我們的目標,該過程的圖形化表示可參考下圖。就是這樣??蓪⑻荻认陆邓惴ǘx為:weightssun)請注意用對梯度進行縮放。該參數(shù)被稱為學(xué)習(xí)速率(learningrate)。這個參數(shù)是必須要使用的,因為梯度向量的長度實際上是一個在“損失函數(shù)單元”中而非“權(quán)值單元”中度量的量,因此需要對梯度進行縮放,使其能夠與權(quán)值相加。學(xué)習(xí)速率并不是模型需要推斷的值,它是一種超參數(shù)(hyperparameter),或?qū)δP偷囊环N手工可配置的設(shè)置,需要為它指定正確的值。如果學(xué)習(xí)速率太小,則找到損失函數(shù)極小值點時可能需要許多輪迭代;如果太大,則算法可能會“跳過”極小值點并且因周期性的“跳躍”而永遠無法找到極小值點,這種現(xiàn)象被),在具體實踐中,無法繪制損失函數(shù),因為通常它都有非常多的變量,因此要想了解是否發(fā)生“超調(diào)”,只能查看損失函數(shù)值隨時間的變化曲線,可利用下圖展示了行為良好的損失函數(shù)隨時間下降的過程,它表明學(xué)習(xí)速率的選取是合適的。下圖展示了當出現(xiàn)“超調(diào)”時,損失函數(shù)隨時間的變化。在調(diào)整學(xué)習(xí)速率時,既需要使其足夠小,保證不至于發(fā)生超調(diào),也要保證它足夠大,以使損失函數(shù)能夠盡快下降,從而可通過較少次數(shù)的迭代更快地完成除了學(xué)習(xí)速率,還有一些其他問題也會影響梯度下降算法的性能。例如,損失函數(shù)的局部極值點。我們再次回到之前的損失函數(shù)曲線示例,如果權(quán)值的初值靠近損失函數(shù)右側(cè)的“谷底”,則該算法的工作過程如下。該算法將找到谷底,并終止迭代,因為它認為自己找到了一個最佳位置。在所有的極值點,梯度的幅度都為0。梯度下降法無法區(qū)分迭代終止時到底是到達了全局最小點還是局部極小點,后者往往只在一個很小的鄰域內(nèi)為最優(yōu)??赏ㄟ^將權(quán)值隨機初始化來改善上述問題。請記住,權(quán)值的初值是手工指定的。通過使用隨機值,可以增加從靠近全局最優(yōu)點附近開始下降的機會。在深度神經(jīng)網(wǎng)絡(luò)的語境(后續(xù)章節(jié)將介紹)中,局部極值點極為常見。一種簡單的解釋方法是考慮相同的輸入如何通過多條不同路徑到達輸出,從而得到相同的結(jié)果。幸運的是,有一些文獻已經(jīng)表明,就損失函數(shù)而言,所有這些極值點都接近等價,與全局最小點相比,它們的劣勢并不明顯。張量形式輸出。我們甚至不需要手工調(diào)用這個梯度計算函數(shù),因為TensorFlow已經(jīng)實現(xiàn)了大量優(yōu)化方法,其中就包括梯度下降法。這就是為什么在介紹梯度下降法原理時只介紹高層公式,而不去深入探究該算法的具體實現(xiàn)和數(shù)學(xué)原理。下面介紹反向傳播算法,它是一種高效計算數(shù)據(jù)流圖中梯度的技術(shù)。以一個單輸入、單輸出的極簡網(wǎng)絡(luò)為例,該網(wǎng)絡(luò)擁有兩個隱含層,每個隱含層都只含單個神經(jīng)元。隱含層和輸出層神經(jīng)元的激活函數(shù)都采用了sigmoid,而損失將通過交叉熵來計算。這樣的網(wǎng)絡(luò)結(jié)構(gòu)如下所示。應(yīng)當注意到其中存在某種模式——每一層的導(dǎo)數(shù)都是后一層的導(dǎo)數(shù)與前一層輸出之積,這正是鏈式法則的奇妙之處,誤差反向傳播算法利用的正是這一特前饋時,從輸入開始,逐一計算每個隱含層的輸出,直到輸出層。然后開始計算導(dǎo)數(shù),并從輸出層經(jīng)各隱含層逐一反向傳播。為了減少計算量,還需對所有已完成計算的元素進行復(fù)用。這便是反向傳播算法名稱的由來。請注意,并未使用sigmoid或交叉熵導(dǎo)數(shù)的定義。完全可以在網(wǎng)絡(luò)中采用不同的激活函數(shù)或損失函數(shù),所得到的結(jié)果大致都是相同的。這是一個非常簡單的示例,但如果某個網(wǎng)絡(luò)中需要計算損失相對上千個權(quán)值的導(dǎo)數(shù),利用該算法將顯著降低訓(xùn)練時間的數(shù)量級。最后需要指出,TensorFlow中包含了少量不同的優(yōu)化算法,它們都是基于計算梯度的梯度下降法。到底哪一種算法更有效,具體取決于輸入數(shù)據(jù)的形狀,以及所要求解的問題的特點。后續(xù)章節(jié)將介紹在構(gòu)建更為復(fù)雜的模型時,Sigmoid隱含層、softmax輸出層以實踐原則,同時也需要對前4章所涵蓋的基礎(chǔ)知識進行拓展,介紹一些術(shù)語、技術(shù)和計算機視覺的基礎(chǔ)知識。由于在各項挑戰(zhàn)中的優(yōu)異表現(xiàn),本章所介紹的那些運用于模型訓(xùn)練中的技術(shù)已被廣泛采用。),人們給予卷積神經(jīng)網(wǎng)絡(luò)(CNN)的關(guān)注一直在持續(xù)得到加強。這類網(wǎng)絡(luò)結(jié)構(gòu)主要用于計算機視覺相關(guān)任務(wù),但處理對象并不局限于圖像。CNN可用于能夠表示為張量(各個分量與其相關(guān)的分量有序排列在一個多維網(wǎng)格中)的任意類型的數(shù)據(jù)。微軟研究院于2014年公開了一篇利用CNN進行語音識別的文對于圖像,張量中的分量為依據(jù)圖像的寬和高的次序排列在一個網(wǎng)格中的像素。同品種的狗的圖像以及圖像中所出現(xiàn)的狗的品種標簽。所構(gòu)建的模型的目標是當給定一幅圖像時,它能夠精確地預(yù)測其中包含的進行評價,因為它們都來自訓(xùn)練集。為找到一個能夠度量模型準確率的公正指標,需要使用大量不曾在訓(xùn)練集中出現(xiàn)的圖像,并用它們創(chuàng)建一個獨立的測試集。這里之所以要強調(diào)圖像的公正性,是因為它是將數(shù)據(jù)集劃分為獨立的測試集、訓(xùn)練集和驗證集的重要考慮因素。在處理輸入時,必須要做的一件事是用數(shù)據(jù)中的大部分來訓(xùn)練一個網(wǎng)絡(luò)。這種劃分使得對模型進行盲測成為可能。如果用參與過訓(xùn)練的圖像對模型進行測試,則很可能會得到一個與訓(xùn)練圖像過分精確匹配的模型,而使其無法對新的輸入產(chǎn)生令人滿意的預(yù)測結(jié)果。測試集的用途是了解模型對不曾出現(xiàn)在訓(xùn)練集中的數(shù)據(jù)表現(xiàn)如何。隨著訓(xùn)練時間的延長和迭代次數(shù)的增加,雖然為提升準確率所做的調(diào)整有可能導(dǎo)致這樣的后果:模型在測試集上的表現(xiàn)越來越好,但面對真實數(shù)據(jù)時性能卻較差。一種比較好的方式是利用一個交叉驗證集檢查最終的模型,以對模型的準確率做出更為客觀的估計。對于圖像數(shù)據(jù),最好是在進行預(yù)處理(如對比度調(diào)整或裁剪)時對原始數(shù)據(jù)集進行劃分,并保證對各個劃分應(yīng)用完全相同的輸入流水線。從技術(shù)角度看,卷積神經(jīng)網(wǎng)絡(luò)是一種至少包含一個層(tf.nn.conv2d)的神經(jīng)網(wǎng)絡(luò),該層的功能是計算其輸入f與一組可配置的卷積核g的卷積,以生成該層的輸出??捎靡环N比較簡明的定義描述卷積:卷積的目的是將卷積核(濾波器)應(yīng)用到某個張量的所有點上,并通過將卷積核在輸入張量上滑動而生成經(jīng)過濾波處理的張量。圖像處理中的邊緣檢測便是濾波輸出的一個典型例子。一個特殊的卷積核被應(yīng)用到圖像中的每個像素,而輸出為一個刻畫了所有邊緣的新圖像。在這種情形下,輸入張量是一幅圖像,而張量中的每個點都對應(yīng)于一個像素所包含的紅色值、綠色值和藍色值。卷積核會遍歷圖像中的每個像素,任何位于邊緣的像素對應(yīng)的卷積輸出值都會增大。一個經(jīng)過簡化的卷積層(其輸入為一幅圖像,而輸出為圖像中的邊緣)[1]如果暫時對卷積運算如何將輸入整合為經(jīng)過濾波處理的輸出或卷積核是什么尚不理解,請不必擔心,本章稍后會介紹如何將它們付諸實踐。從宏觀角度理解何為CNN及其從生物學(xué)中獲得的靈感是其技術(shù)實現(xiàn)的基礎(chǔ)。在1968年,一篇公開發(fā)表的學(xué)術(shù)論文詳細介紹了猴子紋狀皮層(這部分大腦負責處理視覺輸入)的細胞布局。這篇文章討論了沿垂直方向延伸的細胞組是如何整合而與視覺特性匹配的。對靈長類大腦的研究看似與機器學(xué)習(xí)任務(wù)無關(guān),但實際上對使用CNN的深度學(xué)習(xí)發(fā)展起到了非常重要的作用。CNN遵循了一個簡化的信息匹配過程,這非常類似于在猴子紋狀皮層的細胞布局中發(fā)現(xiàn)的結(jié)構(gòu)。當信號經(jīng)過猴子的紋狀皮層時,如果得到某種視覺模式的刺激,某些層便會釋放信號。例如,一個細胞層會在當水平線經(jīng)過它時被激活(增加輸出信號的幅值)。CNN也會呈現(xiàn)出相似的行為,即某些神經(jīng)元構(gòu)成的簇會依據(jù)從訓(xùn)練中學(xué)習(xí)到的模式而激活。例如,經(jīng)過訓(xùn)練,當水平線經(jīng)過一個CNN的某一層時,該層會被激活。匹配水平線的神經(jīng)網(wǎng)絡(luò)是一種有用的架構(gòu),但CNN更進一步,它通過對多種簡單模式分層布局實現(xiàn)復(fù)雜模式的匹配。在CNN的語境中,這些模式被稱為濾波器或卷積核,而訓(xùn)練的目標是調(diào)節(jié)這些卷積核的權(quán)值,直到它們能夠與訓(xùn)練數(shù)據(jù)精確匹配。要訓(xùn)練這些濾波器,需要將多個不同的層級聯(lián),并利用梯度下降法及其變體調(diào)節(jié)網(wǎng)絡(luò)權(quán)值。便很難與復(fù)雜的模式匹配,因為網(wǎng)絡(luò)將被填充過多的信息。一個設(shè)計良好的CNN架構(gòu)會突出那些重要的信息,而將噪聲忽略。本章稍后的內(nèi)容將詳細介紹這些層如何協(xié)同工作。這個架構(gòu)的圖像輸入遵循一種復(fù)雜的格式,以支持圖像的批量加載。批量加載圖像使得可同時對多幅圖像進行處理,但也相應(yīng)地要求使用更為復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。所使用的數(shù)據(jù)結(jié)構(gòu)中包含了與一批圖像進行卷積運算所需的全部信息。TensorFlow的輸入流水線(用于讀取和解碼文件)擁有一種為使用一個批數(shù)據(jù)中象sess、初始化所有的變量和啟動線程執(zhí)行器。如果上述示例代碼在運行時未執(zhí)行上述步驟,將會出現(xiàn)一些變量未定義的錯誤。這段示例代碼創(chuàng)建了一個包含兩幅圖像的圖像批數(shù)據(jù)。每幅圖像的高為2個像素,寬為3個像素,且顏色空間為RGB。執(zhí)行后的輸出的第1組維度有一點值得注意,每個像素的索引都會映射到圖像的寬和高這兩個維度上。若要獲取第1幅圖像的第1個像素,需要用下列方式訪問每一個維度。該語句執(zhí)行后,可得到輸出: 變量image_batch并不會從磁盤直接加載圖像,而是將自身當成作為輸入流水線的一部分而被加載的圖像。使用輸入流水線從磁盤加載的圖像擁有相同的格式和行為。一種常見的做法是創(chuàng)建一些與上述image_batch實例相似的假數(shù)據(jù)對CNN的輸入和輸出進行測試。這種簡化的輸入會使診斷和調(diào)試一些簡單問題更加容易。簡化調(diào)試過程非常重要,因為CNN架構(gòu)極為復(fù)雜,訓(xùn)練經(jīng)常需要耗費數(shù)日。CNN架構(gòu)的第一個復(fù)雜性體現(xiàn)在卷積層的工作機理上。任何圖像被加載和處理后,卷積層通常是網(wǎng)絡(luò)的第一層。這第一個卷積層非常有用,因為它可簡化網(wǎng)絡(luò)的其余部分,并用于調(diào)試。下一節(jié)將重點介紹卷積層的工作機理,以及如何在TensorFlo從名稱可以看出,卷積運算是卷積神經(jīng)網(wǎng)絡(luò)的重要組成。CNN與各種模式精確匹配的能力可歸功于卷積運算的使用。這些運算要求復(fù)雜的輸入,這一點已在上一節(jié)說明過。本節(jié)將對卷積運算及其參數(shù)進行實驗。卷積運算對兩個輸入張量(輸入和卷積核)進行卷積,并輸出一個代表來自每個輸入的信息的張量語,也稱為權(quán)值、濾波器、卷積矩陣或模板。由于本任務(wù)與計算機視覺相關(guān),使用術(shù)語“卷積核”便顯得十分有用,因為這意味著將它視為圖像卷積核。當用于描同權(quán)值的數(shù)量決定了需要學(xué)習(xí)的卷積核的數(shù)量。上述示例代碼中包含了一個卷積核(變量kernel的第1維)。該卷積核的作用是返回一個其第1個通道等于原始輸入值,第2個通道等于原始輸入值兩倍的張量。在本例中,通道用于描述一個秩1張量(向量)的元素。通道這個術(shù)語來自計算機視覺領(lǐng)域,用于描述輸出向量。例如,一幅RGB圖像擁有3個代表了秩1張量像。該張量中的每個元素都表示這幅圖像中的一個像素。該圖像中右下角的像素值將為3.0。寬泛的術(shù)語,但在計算機視覺中,它與使用圖像卷積核的運算的輸出相關(guān),而現(xiàn)在,特征圖通過為輸出添加新層代表了這些張量的卷積。輸入圖像與輸出的特征圖之間的關(guān)系可結(jié)合代碼來分析。訪問輸入批數(shù)據(jù)和特征圖中的元素時使用的是相同的索引。通過訪問輸入批數(shù)據(jù)和特征圖中位置相在這個簡化的例子中,每幅圖像中的每個像素都與卷積核中的相應(yīng)值相乘,并累加到特征圖的相應(yīng)層中。在這個語境中,“層”是指輸出的新維度。在本例中,要想看到卷積的價值是比較困難的。在計算機視覺中,卷積的價值體現(xiàn)在對輸入(本例中為圖像)降維的能力上。一幅2D圖像的維數(shù)包括其寬度、高度和通道數(shù)。如果圖像具有較高的維數(shù),則意味著神經(jīng)網(wǎng)絡(luò)掃描所有圖像以判斷各像素的重要性所需的時間呈指數(shù)級增長。利用卷積運算對圖像降維是通過修改卷積核的strides(跨度)參數(shù)實現(xiàn)的。參數(shù)strides使得卷積核可跳過圖像中的一些像素,從而在輸出中不包strides參數(shù)指定了當圖像維數(shù)較高,且使用了較為復(fù)雜的卷積核時,卷積運算應(yīng)如何進行。當卷積運算用卷積核遍歷輸入時,它利用這個跨度參數(shù)來修改遍歷輸入例如,假設(shè)需要計算一幅較大的圖像和一個較大的卷積核之間的卷積運算。在這個例子中,圖像的高度為6個像素,寬度為6個像素,而深度為1個通道),然后,位置重疊的值相乘,再將這些乘積相加得到卷積的結(jié)果。卷積就是通過這種逐點相乘的方式將兩個輸入整合在一起的。利用下圖可更容易地將卷積運算可上圖所體現(xiàn)的是與之前的代碼完全相同的邏輯。兩個張量進行了卷積運算,但卷積核會跳過輸入中的一些固定數(shù)目的元素。strides顯著降低了輸出的維數(shù),而卷積核允許卷積使用所有的輸入值。在輸入數(shù)據(jù)中,沒有任何元素在被跳過時被移除,但它仍然變成了一個形狀更小的張量。設(shè)置跨度是一種調(diào)整輸入張量維數(shù)的方法。降維可減少所需的運算量,并可避免創(chuàng)建一些完全重疊的感受域。strides參數(shù)的格式與輸入向量相同,即在對輸入使用跨度參數(shù)時,所面臨的一個挑戰(zhàn)是如何應(yīng)對那些不是恰好在輸入的邊界到達盡頭的跨度值。非均勻的跨越通常在圖像尺寸和卷積核尺寸與跨度參數(shù)不匹配時出現(xiàn)。如果圖像尺寸、卷積核尺寸和strides參數(shù)都無法改變,則可采取對圖像填充邊界的方法來處理那些非均勻區(qū)域。當卷積核與圖像重疊時,它應(yīng)當落在圖像的邊界內(nèi)。有時,兩者尺寸可能不匹配,一種較好的補救策略是對圖像缺失的區(qū)域進行填充,即邊界填充?!AME:卷積輸出與輸入的尺寸相同。這里在計算如何跨越圖像時,并不考慮濾波器的尺寸。選用該設(shè)置時,缺失的像素將用0填充,卷積核掃過的像素數(shù)將超過圖像的實際像素數(shù)?!ALID:在計算卷積核如何在圖像上跨越時,需要考慮濾波器的尺寸。這會使卷積核盡量不越過圖像的邊界。在某些情形下,可能邊界擇。當指定跨度參數(shù)后,如果輸入和卷積核能夠很好地工作,則推薦使用VALID。關(guān)于這在TensorFlow中,濾波器參數(shù)用于指定與輸入進行卷積運算的卷積核。濾波器通常用于中,攝影者可借助濾波器對所拍攝的圖片做出大幅度的修改。攝影者之所以能夠利用濾波器對圖片進行修改,是因為濾波器能夠識別到達透鏡的光線的特定屬性。例如,紅色透鏡濾波器會吸收(或阻止)不同于紅色的每種頻率的光,使得只有紅色光可通過該濾波器。在計算機視覺中,卷積核(濾波器)常用于識別數(shù)字圖像中的重要屬性。當某些濾波器感興趣的特征在圖像中存在時,濾波器會使用特定模式突出這些特征。若將除紅色外的所有顏色值減小,則可得到一個紅色濾波器的卷積核。在這種情形下,紅色值將保持不變,而其他任何匹配的顏色值將被減小。本章一開始所展示的例子使用了一個專為邊緣檢測設(shè)計的卷積核。邊緣檢測卷積將一幅圖像與一個邊緣檢測卷積核進行卷積所得到的在這個簡單的示例中,也可使用許多其他的常見卷積核。這些卷積核中的每一個都會突出圖像中的不同模式,從而得到不同的結(jié)果。下列卷積核通過增加顏色的變化幅度可產(chǎn)生銳化效果。這個卷積核的作用是增加卷積核中心位置像素的灰度,并降低周圍像素的灰度。這種灰度的調(diào)整能夠匹配那些具有較強灰度的像素的模式,并提升它們的灰度,從而使輸出在視覺上呈現(xiàn)出銳化的效果。請注意,這里的卷積核四角的元素均為0,并不會對“+”形狀的模式產(chǎn)生影響。這些卷積核在比較初級的層次上能夠與圖像中的一些模式匹配。卷積神經(jīng)網(wǎng)絡(luò)通過使用從訓(xùn)練過程中學(xué)習(xí)到的復(fù)雜卷積核不但可以匹配邊緣,還可以匹配更為復(fù)雜的模式。在訓(xùn)練過程中,這些卷積核的初值通常隨機設(shè)定,隨著訓(xùn)練迭代的進行,它們的值會由CNN的學(xué)習(xí)層自動調(diào)整。當CNN訓(xùn)練完成一輪迭代后,它接收一幅圖像,并將其與某個卷積核進行卷積,然后依據(jù)預(yù)測結(jié)果與該圖像真實標簽是否一致,對卷積核中的參數(shù)進一步調(diào)整。例如,若一幅牧羊犬的照片被CNN模型預(yù)測為斗牛犬,則卷積核參數(shù)將適當調(diào)整以試圖更好地匹配牧羊犬圖片。積層可多次出現(xiàn),但通常也會包含其他類型的層。這些層聯(lián)合起來構(gòu)成了成功的CNN架構(gòu)所必需的要素。形是使用不同的層類型支持某個卷積層。這些層有助于減少過擬合,并可加速訓(xùn)練過程和降低內(nèi)存占用率。本章所涵蓋的層主要集中于那些在CNN架構(gòu)采用了一種可對所有不同類型的卷積層中的卷積運算進行加速的技術(shù)。它將一個卷積核應(yīng)用于一個新的特征圖,后者的每一部分都填充了與卷積核相同的值。當該卷積核遍歷新圖像時,任何重疊的部分都相加在一起。這就很好地這些函數(shù)與其他層的輸出聯(lián)合使用可生成特征圖。它們用于對某些運算的結(jié)果進行平滑(或微分)。其目標是為神經(jīng)網(wǎng)絡(luò)引入非線性。非線性意味著輸入和輸出的關(guān)系是一條曲線,而非直線[1]。曲線能夠刻畫輸入中更為復(fù)雜的變化。例如,非線性映射能夠描述那些大部分時間值都很小,但在某個單點會周期性地出現(xiàn)極值的輸入。為神經(jīng)網(wǎng)絡(luò)引入非線性可使其對在數(shù)據(jù)中發(fā)現(xiàn)的復(fù)雜模式進行訓(xùn)練。2)該函數(shù)應(yīng)是可微分的,以保證該函數(shù)定義域內(nèi)的任意一點上導(dǎo)數(shù)介紹,并通過一些示例代碼片段來說明其用),依據(jù)某個可配置的概率將輸出設(shè)為0.0。當引入少量隨機性有助于訓(xùn)練時,這過強時。這種層會為所學(xué)習(xí)到的輸出添加少量噪注意:這種層應(yīng)當只在訓(xùn)練階段使用。如果在測試階段使用該層,它所引入的隨機噪聲將對結(jié)果產(chǎn)生誤導(dǎo)。在這個例子中,輸出有50%的概率能夠得到保持。跳躍遍歷某個張量,并從被卷積核覆蓋的元素中找出最大的數(shù)值作為卷積結(jié)果。當輸入數(shù)據(jù)的灰度與圖像中的重要性相關(guān)時,這種池化方式非常有用。在于它是在單個通路上能夠?qū)嵤┑淖钚?shù)量的跳躍遍歷一個張量,并將被卷積核覆蓋的各深度值取平均。當整個卷積核都非常重要時,若需實現(xiàn)值的縮減,平均池化是非常有用的,例如輸入張量寬度和高對該張量中的所有分量求和,再除以張量中分量的個數(shù):上述代碼所完成的運算正是上式,但通過減小卷積核的尺寸,改變輸出的尺寸便成為可能。些層需要為數(shù)據(jù)流圖添加大量非核心的節(jié)點。在使用這些層之前,投入一些精力了解相關(guān)基礎(chǔ)知識是非常值得的。多目前尚未介紹,但應(yīng)熟練掌握。每個卷積核都是一個可訓(xùn)練的變量(CNN的目),設(shè)置,而一旦設(shè)置完成,便無需再次編寫。對于高級用戶而言,該層可幫助他們節(jié)省大量時間。這個例子創(chuàng)建了一個全連接層,并

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論