與 TensorFlow 的初次相遇

與 TensorFlow 的初次相遇

https://jorditorres.org/wp-content/uploads/2016/02/TensorFlowBookCover.png

原文:First Contact With TensorFlow

譯者:飛龍

協(xié)議:CC BY-NC-SA 4.0

前言一

由于計(jì)算,海量數(shù)據(jù)存儲(chǔ)和互聯(lián)網(wǎng)技術(shù)等關(guān)鍵領(lǐng)域的共同發(fā)展墅冷,機(jī)器學(xué)習(xí)領(lǐng)域呈現(xiàn)了巨大的發(fā)展酒奶。許多人的日常生活中的許多技術(shù)和事件崎岂,直接或間接地受到自動(dòng)學(xué)習(xí)的影響瘦穆。語(yǔ)音識(shí)別抡柿,手機(jī)上的圖像分類(lèi)或垃圾郵件檢測(cè)等技術(shù)的例子,使得一些應(yīng)用成為可能爵赵,它們只出現(xiàn)在十年前科幻小說(shuō)中吝秕。股票市場(chǎng)模型或醫(yī)療模型中的學(xué)習(xí)的使用,對(duì)我們的社會(huì)產(chǎn)生了巨大的影響空幻。此外烁峭,具有巡航控制,無(wú)人機(jī)和各種機(jī)器人的汽車(chē)將在不久的將來(lái)影響社會(huì)秕铛。

深度學(xué)習(xí)是機(jī)器學(xué)習(xí)的一個(gè)子類(lèi)型约郁,自 2006 年重新發(fā)現(xiàn)以來(lái),無(wú)疑是爆發(fā)性擴(kuò)張的領(lǐng)域之一但两。事實(shí)上鬓梅,硅谷的許多創(chuàng)業(yè)公司都專(zhuān)注于此,而谷歌谨湘,F(xiàn)acebook绽快,微軟或 IBM 等大型科技公司都有開(kāi)發(fā)和研究團(tuán)隊(duì)芥丧。深度學(xué)習(xí)甚至引起了大學(xué)之外和研究領(lǐng)域的興趣:許多專(zhuān)業(yè)雜志(如 Wired)甚至是通用雜志(如紐約時(shí)報(bào),Bloomberg 或 BBC)為這個(gè)主題撰寫(xiě)了很多文章坊罢。

這種興趣促使許多學(xué)生娄柳,企業(yè)家和投資者加入深度學(xué)習(xí)。由于產(chǎn)生的所有興趣艘绍,幾個(gè)軟件包已被制作成“開(kāi)源”的赤拒。作為庫(kù)的主要推動(dòng)者之一,我們?cè)?2012 年作為博士生在伯克利(Caffe)開(kāi)發(fā)了它诱鞠。我可以說(shuō)挎挖,TensorFlow 將成為研究人員和中小企業(yè)公司用于實(shí)現(xiàn)他們的深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的想法的主要工具之一,它出現(xiàn)在本書(shū)中并由 Google(加州)設(shè)計(jì)航夺,我自 2013 年以來(lái)一直在那里研究它蕉朵。對(duì)此的保證是參與該項(xiàng)目的工程師和頂尖研究人員的數(shù)量,它最終得到了開(kāi)源阳掐。

我希望這本入門(mén)書(shū)能夠幫助有興趣在這個(gè)非常有趣的領(lǐng)域開(kāi)始冒險(xiǎn)的讀者始衅。我要感謝作者,我很高興了解到它傳播這項(xiàng)技術(shù)的努力缭保。在開(kāi)源項(xiàng)目發(fā)布兩個(gè)月后汛闸,他在創(chuàng)紀(jì)錄的時(shí)間內(nèi)寫(xiě)了這本書(shū)(首先是西班牙語(yǔ)版本)侈净。這是巴塞羅那活力的另一個(gè)例子齐婴,它有興趣成為這一技術(shù)場(chǎng)景中的參與者之一,無(wú)疑將影響我們的未來(lái)宗雇。

Oriol Vinyals钳恕,Google Brain 的研究科學(xué)家

前言二

教育是你用來(lái)改變世界的最有力的武器别伏。

Nelson Mandela

本書(shū)的目的是有助于將這些知識(shí)轉(zhuǎn)播給工程師,它們希望在激動(dòng)人心的機(jī)器學(xué)習(xí)世界中擴(kuò)展智慧忧额。我相信任何具有工程背景的人都可能會(huì)發(fā)現(xiàn)厘肮,深度學(xué)習(xí)和機(jī)器學(xué)習(xí)的應(yīng)用對(duì)他們的工作很有價(jià)值。

鑒于我的背景睦番,讀者可能會(huì)想知道為什么我提出了編寫(xiě)這種新的深度學(xué)習(xí)技術(shù)的挑戰(zhàn)类茂。我的研究重點(diǎn)是逐步從超級(jí)計(jì)算架構(gòu)和運(yùn)行時(shí)轉(zhuǎn)向大數(shù)據(jù)工作負(fù)載的執(zhí)行中間件,最近轉(zhuǎn)向大規(guī)模數(shù)據(jù)的機(jī)器學(xué)習(xí)平臺(tái)抡砂。

正是作為一名工程師大咱,而不是數(shù)據(jù)科學(xué)家,我認(rèn)為我可以為這一主題貢獻(xiàn)這種介紹性的方法注益,并且它對(duì)早期階段的許多工程師都有幫助;然后他們會(huì)選擇深入了解他們的需求溯捆。

我希望這本書(shū)能為這個(gè)我非常喜愛(ài)的教育世界增添一些價(jià)值丑搔。我認(rèn)為知識(shí)就是解放厦瓢,應(yīng)該讓所有人都能獲得。因此啤月,本書(shū)的內(nèi)容將在網(wǎng)站 www.JordiTorres.eu/TensorFlow 上完全免費(fèi)提供煮仇。如果讀者發(fā)現(xiàn)內(nèi)容有用并認(rèn)為適當(dāng)補(bǔ)償作者的寫(xiě)作,網(wǎng)站上有一個(gè)標(biāo)簽可以用于捐贈(zèng)谎仲。另一方面浙垫,如果讀者更喜歡選擇紙質(zhì)副本,你可以通過(guò) Amazon.com 購(gòu)買(mǎi)該書(shū)郑诺。

本書(shū)還提供西班牙語(yǔ)版本夹姥。事實(shí)上,這本書(shū)是西班牙語(yǔ)的翻譯辙诞,該書(shū)于去年 1 月完成,并在 GEMLeB Meetup(Grup d'Estudi de Machine Learning de Barcelona)中展示曹铃,我是其中一個(gè)共同組織者忍坷。

感謝你閱讀本書(shū)旬薯!它使我感到安慰,并證明了我寫(xiě)作的努力娱挨。那些了解我的人碉碉,知道技術(shù)傳播是我的激情之一。它激勵(lì)我繼續(xù)學(xué)習(xí)蜡吧。

Jordi Torres,2016 年 2 月

一種實(shí)用的方法

告訴我返咱,我會(huì)忘記钥庇。教我,我會(huì)記得咖摹。讓我參與评姨,我會(huì)學(xué)習(xí)。

本杰明·富蘭克林

深度學(xué)習(xí)的一個(gè)常見(jiàn)應(yīng)用包括模式識(shí)別楞艾。因此参咙,當(dāng)你開(kāi)始編程時(shí)龄广,有個(gè)傳統(tǒng)是打印“Hello World”硫眯,與它相同蕴侧,在深度學(xué)習(xí)中,通常構(gòu)造用于識(shí)別手寫(xiě)數(shù)字的模型 [1]两入。我將提供的第一個(gè)神經(jīng)網(wǎng)絡(luò)示例净宵,也將允許我介紹這種名為 TensorFlow 的新技術(shù)。

但是裹纳,我不打算寫(xiě)一本關(guān)于機(jī)器學(xué)習(xí)或深度學(xué)習(xí)的研究書(shū)籍择葡,我只想盡快為每個(gè)人提供這個(gè)新的機(jī)器學(xué)習(xí)軟件包 TensorFlow。因此剃氧,我向我的數(shù)據(jù)科學(xué)家們道歉敏储,為了與普通讀者分享這些知識(shí),我允許自己進(jìn)行某些簡(jiǎn)化朋鞍。

讀者會(huì)在這里找到我在課堂上使用的常規(guī)結(jié)構(gòu)已添;這會(huì)邀請(qǐng)你在學(xué)習(xí)的同時(shí)使用計(jì)算機(jī)的鍵盤(pán)。我們稱(chēng)之為“從實(shí)踐中學(xué)習(xí)”滥酥,而我作為 UPC 教授的經(jīng)歷告訴我更舞,這種方法對(duì)于嘗試開(kāi)始新主題的工程師來(lái)說(shuō)非常有效。

出于這個(gè)原因坎吻,這本書(shū)具有實(shí)用性缆蝉,因此我盡可能地減少了理論部分。然而瘦真,當(dāng)學(xué)習(xí)過(guò)程需要時(shí)刊头,文本中已包含某些數(shù)學(xué)細(xì)節(jié)。

我假設(shè)讀者對(duì)機(jī)器學(xué)習(xí)有一些基本的理解诸尽,所以我將使用一些流行的算法逐步組織讀者在 TensorFlow 中的訓(xùn)練原杂。

在第一章中,除了介紹TensorFlow將扮演重要角色的場(chǎng)景之外弦讽,我還借此機(jī)會(huì)解釋TensorFlow程序的基本結(jié)構(gòu)污尉,并簡(jiǎn)要解釋它在內(nèi)部維護(hù)的數(shù)據(jù)。

在第二章中往产,通過(guò)線性回歸的一個(gè)例子被碗,我將介紹一些代碼基礎(chǔ)知識(shí),同時(shí)仿村,如何調(diào)用學(xué)習(xí)過(guò)程中的各種重要組件锐朴,如損失函數(shù)或梯度下降優(yōu)化算法。

在第三章中蔼囊,我展示了一個(gè)聚類(lèi)算法焚志,我將詳細(xì)介紹 TensorFlow 的基本數(shù)據(jù)結(jié)構(gòu)衣迷,稱(chēng)為tensor(張量),以及 TensorFlow 包提供的用于創(chuàng)建和管理張量的不同類(lèi)和函數(shù)酱酬。

第四章詳細(xì)介紹了如何構(gòu)建識(shí)別手寫(xiě)數(shù)字的單層神經(jīng)網(wǎng)絡(luò)壶谒。這將允許我們歸納上面提出的所有概念,以及查看創(chuàng)建和測(cè)試模型的整個(gè)過(guò)程膳沽。

下一章首先介紹基于前一章中所見(jiàn)的神經(jīng)網(wǎng)絡(luò)概念汗菜,并介紹如何構(gòu)建多層神經(jīng)網(wǎng)絡(luò)來(lái)獲得更好的手寫(xiě)數(shù)字識(shí)別結(jié)果。它將更詳細(xì)地介紹所謂的卷積神經(jīng)網(wǎng)絡(luò)挑社。

在第六章中陨界,我們將討論一個(gè)更具體的問(wèn)題,利用 GPU 提供的計(jì)算能力痛阻,可能不是所有讀者都感興趣菌瘪。如第 1 章所述,GPU 在神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過(guò)程中發(fā)揮著重要作用阱当。

本書(shū)以后記結(jié)束俏扩,其中我強(qiáng)調(diào)了一些結(jié)論。我想強(qiáng)調(diào)的是斗这,本書(shū)中的代碼示例可以從本書(shū) [2] 的 github 倉(cāng)庫(kù)下載动猬。

1. TensorFlow 基礎(chǔ)知識(shí)

在本章中,我將簡(jiǎn)要介紹 TensorFlow 的代碼及其編程模型表箭。在本章的最后赁咙,讀者可以在他們的個(gè)人計(jì)算機(jī)上安裝 TensorFlow 軟件包。

開(kāi)源軟件包

學(xué)術(shù)界已經(jīng)對(duì)機(jī)器學(xué)習(xí)進(jìn)行了數(shù)十年的調(diào)查免钻,但直到近幾年彼水,它的滲透率在企業(yè)中也有所增加。這要?dú)w功于它已經(jīng)擁有的大量數(shù)據(jù)以及現(xiàn)在可用的前所未有的計(jì)算能力极舔。

在這種情況下凤覆,毫無(wú)疑問(wèn),在 Alphabet 的支持下拆魏,谷歌是機(jī)器學(xué)習(xí)技術(shù)在其所有虛擬計(jì)劃和產(chǎn)品中發(fā)揮關(guān)鍵作用的最大公司之一盯桦。

去年10月,當(dāng) Alphabet 宣布那個(gè)季度谷歌的業(yè)績(jī)渤刃,銷(xiāo)售額和利潤(rùn)大幅增加時(shí)拥峦,首席執(zhí)行官桑達(dá)皮采清楚地說(shuō):“機(jī)器學(xué)習(xí)是一種核心的,變革性的方式卖子,我們正在重新思考我們正在做的一切”略号。

從技術(shù)上講,我們正面臨著谷歌不是唯一一個(gè)重要角色的時(shí)代變遷。其他技術(shù)公司玄柠,如微軟突梦,F(xiàn)acebook,亞馬遜和蘋(píng)果等眾多公司也在增加對(duì)這些領(lǐng)域的投資羽利。

在此背景下宫患,幾個(gè)月前谷歌在開(kāi)源許可證(Apache 2.0)下發(fā)布了 TensorFlow 引擎。想要將機(jī)器學(xué)習(xí)納入其項(xiàng)目和產(chǎn)品的開(kāi)發(fā)人員和研究人員可以使用 TensorFlow铐伴,就像 Google 在內(nèi)部使用 Gmail撮奏,Google 照片俏讹,搜索当宴,語(yǔ)音識(shí)別等不同的商業(yè)產(chǎn)品一樣。

TensorFlow 最初是由 Google Brain Team 開(kāi)發(fā)的泽疆,目的是進(jìn)行機(jī)器學(xué)習(xí)和深度神經(jīng)網(wǎng)絡(luò)研究户矢,但該系統(tǒng)足以應(yīng)用于各種其他機(jī)器學(xué)習(xí)問(wèn)題。

由于我是一名工程師殉疼,而且我正在與工程師交談梯浪,因此本書(shū)將深入了解數(shù)據(jù)流圖如何表示算法。TensorFlow 可以看作是使用數(shù)據(jù)流圖進(jìn)行數(shù)值計(jì)算的庫(kù)瓢娜。圖中的節(jié)點(diǎn)表示數(shù)學(xué)運(yùn)算挂洛,而圖的邊表示多維數(shù)據(jù)數(shù)組(張量),它們將節(jié)點(diǎn)互連眠砾。

TensorFlow 圍繞構(gòu)建和操作計(jì)算圖的基本思想構(gòu)建虏劲,象征性地表示要執(zhí)行的數(shù)值運(yùn)算。這使得 TensorFlow 現(xiàn)在可以從 Linux 64 位平臺(tái)(如 Mac OS X)以及 Android 或 iOS 等移動(dòng)平臺(tái)中利用 CPU 和 GPU褒颈。

這個(gè)新軟件包的另一個(gè)優(yōu)點(diǎn)是它的可視 TensorBoard 模塊柒巫,它提供了大量有關(guān)如何監(jiān)視和顯示算法運(yùn)行的信息。在創(chuàng)建更好的模型的過(guò)程中谷丸,能夠測(cè)量和顯示算法的行為是非常重要的堡掏。我感覺(jué)目前許多模型都是通過(guò)一個(gè)小型的盲目過(guò)程,通過(guò)試錯(cuò)來(lái)調(diào)優(yōu)刨疼,明顯浪費(fèi)資源泉唁,以及最重要時(shí)間。

TensorFlow 服務(wù)

最近 Google 推出了 TensorFlow 服務(wù) [3]揩慕,這有助于開(kāi)發(fā)人員將他們的 TensorFlow 機(jī)器學(xué)習(xí)模型(即使如此亭畜,也可以擴(kuò)展來(lái)服務(wù)其他類(lèi)型的模型)投入生產(chǎn)。TensorFlow 服務(wù)是一個(gè)開(kāi)源服務(wù)系統(tǒng)(用 C++ 編寫(xiě))漩绵,現(xiàn)在可以在 Apache 2.0 許可下在 GitHub 上獲得贱案。

TensorFlow 和 TensorFlow 服務(wù)有什么區(qū)別? 在 TensorFlow 中,開(kāi)發(fā)人員更容易構(gòu)建機(jī)器學(xué)習(xí)算法宝踪,并針對(duì)某些類(lèi)型的數(shù)據(jù)輸入進(jìn)行訓(xùn)練侨糟,TensorFlow 服務(wù)專(zhuān)門(mén)使這些模型可用于生產(chǎn)環(huán)境。我們的想法是開(kāi)發(fā)人員使用 TensorFlow 訓(xùn)練他們的模型瘩燥,然后他們使用 TensorFlow 服務(wù)的 API 來(lái)響應(yīng)來(lái)自客戶端的輸入秕重。

這允許開(kāi)發(fā)人員根據(jù)實(shí)際數(shù)據(jù)大規(guī)模試驗(yàn)不同的模型,并隨時(shí)間變化厉膀,保持穩(wěn)定的架構(gòu)和 API溶耘。

典型的流水線是將訓(xùn)練數(shù)據(jù)提供給學(xué)習(xí)器,學(xué)習(xí)器輸出模型服鹅,模型在被驗(yàn)證之后準(zhǔn)備好部署到 TensorFlow 服務(wù)系統(tǒng)凳兵。 隨著時(shí)間的推移和新數(shù)據(jù)的出現(xiàn)偷遗,改進(jìn)模型嗡靡,啟動(dòng)和迭代我們的模型是很常見(jiàn)的幅慌。事實(shí)上雀哨,在 Google 的博文中 [4] 中相速,他們提到在谷歌盗迟,許多流水線都在持續(xù)運(yùn)行延旧,隨著新數(shù)據(jù)的出現(xiàn)埋酬,產(chǎn)生了新的模型版本厌漂。

TensorFlowServing

開(kāi)發(fā)人員用來(lái)與 TensorFlow 服務(wù)進(jìn)行通信的前端實(shí)現(xiàn)萨醒,基于 gRPC ,這是一種來(lái)自 Google 的高性能開(kāi)源RPC框架苇倡。

如果你有興趣了解 TensorFlow 服務(wù)的更多信息富纸,我建議你先閱讀服務(wù)架構(gòu)概述 [5] 部分,設(shè)置你的環(huán)境并開(kāi)始閱讀基礎(chǔ)教程 [6]雏节。

TensorFlow 的安裝

是時(shí)候做一些事情了胜嗓。從現(xiàn)在開(kāi)始,我建議你交替閱讀和在計(jì)算機(jī)上練習(xí)钩乍。

TensorFlow 有 Python API(以及 C/C++)辞州,需要安裝 Python 2.7(我假設(shè)任何閱讀本書(shū)的工程師都知道如何操作)。

通常寥粹,在使用 Python 時(shí)变过,應(yīng)使用虛擬環(huán)境virtualenvvirtualenv是一種工具涝涤,用于在同一臺(tái)計(jì)算機(jī)的不同部分中保持不同項(xiàng)目所需的 Python 依賴關(guān)系媚狰。如果我們使用virtualenv來(lái)安裝 TensorFlow,這將不會(huì)覆蓋需要 TensorFlow 的其他項(xiàng)目的現(xiàn)有 Python 包版本阔拳。

首先崭孤,如果尚未安裝pipvirtualenv,則應(yīng)安裝,如下面的腳本所示:

# Ubuntu/Linux 64-bit 
$ sudo apt-get install python-pip python-dev python-virtualenv 
# Mac OS X 
$ sudo easy_install pip
$ sudo pip install --upgrade virtualenv

~/tensorflow目錄中的環(huán)境virtualenv

$ virtualenv --system-site-packages ~/tensorflow

下一步是激活virtualenv辨宠。這可以按如下方式完成:

$ source ~/tensorflow/bin/activate #  with bash 
$ source ~/tensorflow/bin/activate.csh #  with csh  
(tensorflow)$

我們工作的虛擬環(huán)境的名稱(chēng)遗锣,將從現(xiàn)在開(kāi)始顯示在每個(gè)命令行的開(kāi)頭。激活virtualenv后嗤形,你可以使用pip在其中安裝 TensorFlow:

# Ubuntu/Linux 64-bit, CPU only:
(tensorflow)$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.7.1-cp27-none-linux_x86_64.whl 

# Mac OS X, CPU only:
(tensorflow)$ sudo easy_install --upgrade six
(tensorflow)$ sudo pip install --upgrade https://storage.googleapis.com/tensorflow/mac/tensorflow-0.7.1-cp27-none-any.whl

我建議你訪問(wèn)此處提供的官方文檔精偿,來(lái)確保你安裝的是最新版本。

如果運(yùn)行代碼的平臺(tái)具有 GPU赋兵,要使用的包不同笔咽。我建議你訪問(wèn)官方文檔,了解你的 GPU 是否符合支持 Tensorflow 所需的規(guī)范霹期。運(yùn)行 Tensorflow GPU 需要安裝其他軟件叶组,所有信息都可以在下載和設(shè)置 TensorFlow [7] 網(wǎng)頁(yè)上找到。對(duì)于使用 GPU 的更多信息经伙,我建議閱讀第 6 章扶叉。

最后,當(dāng)你完成后帕膜,你應(yīng)該按如下方式禁用虛擬環(huán)境:

(tensorflow)$ deactivate

鑒于本書(shū)的介紹性質(zhì),我們建議讀者訪問(wèn)上述官方文檔頁(yè)面溢十,來(lái)查找安裝 Tensorflow 的其他方法的更多信息垮刹。

我在 TensorFlow 中的第一個(gè)代碼

正如我在開(kāi)始時(shí)提到的那樣,我們將通過(guò)很少的理論和大量練習(xí)來(lái)探索 TensorFlow 星球张弛。開(kāi)始吧荒典!

從現(xiàn)在開(kāi)始,最好使用任何文本編輯器編寫(xiě) python 代碼并使用擴(kuò)展名.py保存(例如test.py)吞鸭。要運(yùn)行代碼寺董,使用命令python test.py就足夠了。

為了獲得 TensorFlow 程序的第一印象刻剥,我建議編寫(xiě)一個(gè)簡(jiǎn)單的乘法程序遮咖;代碼看起來(lái)像這樣:

import tensorflow as tf
  
a = tf.placeholder("float")
b = tf.placeholder("float")

y = tf.mul(a, b)

sess = tf.Session()

print sess.run(y, feed_dict={a: 3, b: 3})

在此代碼中,在導(dǎo)入 Python 模塊tensorflow之后造虏,我們定義“符號(hào)”變量御吞,稱(chēng)為占位符,以便在程序執(zhí)行期間操作它們漓藕。然后陶珠,我們將這些變量作為參數(shù),調(diào)用 TensorFlow 提供的乘法函數(shù)享钞。tf.mul是 TensorFlow 為操縱張量而提供的眾多數(shù)學(xué)運(yùn)算之一揍诽。在這個(gè)時(shí)候,張量可以認(rèn)為是動(dòng)態(tài)大小的多維數(shù)據(jù)數(shù)組。

主要運(yùn)算如下表所示:

運(yùn)算 描述
tf.add 加法
tf.sub 減法
tf.mul 乘法
tf.div 除法
tf.mod
tf.abs 返回絕對(duì)值
tf.neg 返回負(fù)值
tf.sign 返回標(biāo)志
tf.inv 返回倒數(shù)
tf.square 計(jì)算平方
tf.round 返回最接近的整數(shù)
tf.sqrt 計(jì)算平方根
tf.pow 計(jì)算指數(shù)
tf.exp 計(jì)算自然指數(shù)
tf.log 計(jì)算自然對(duì)數(shù)
tf.maximum 返回最大值
tf.minimum 返回最小值
tf.cos 計(jì)算余弦
tf.sin 計(jì)算正弦

TensorFlow 還為程序員提供了許多函數(shù)暑脆,來(lái)對(duì)矩陣執(zhí)行數(shù)學(xué)運(yùn)算交排。一些列在下面:

運(yùn)算 描述
tf.diag 返回具有給定對(duì)角線值的對(duì)角張量
tf.transpose 返回參數(shù)的轉(zhuǎn)置
tf.matmul 返回由參數(shù)列出的兩個(gè)張量的張量積
tf.matrix_determinant 返回由參數(shù)指定的方陣的行列式
tf.matrix_inverse 返回由參數(shù)指定的方陣的逆

下一步,最重要的一步是創(chuàng)建一個(gè)會(huì)話來(lái)求解指定的符號(hào)表達(dá)式饵筑。實(shí)際上埃篓,到目前為止,這個(gè) TensorFlow 代碼尚未執(zhí)行任何操作根资。我要強(qiáng)調(diào)的是架专,TensorFlow 既是表達(dá)機(jī)器學(xué)習(xí)算法的接口,又是運(yùn)行它們的實(shí)現(xiàn)玄帕,這是一個(gè)很好的例子部脚。

程序通過(guò)使用Session()創(chuàng)建會(huì)話來(lái)與 Tensorflow 庫(kù)交互;只有在我們調(diào)用run()方法時(shí)才會(huì)創(chuàng)建這個(gè)會(huì)話裤纹,這就是它真正開(kāi)始運(yùn)行指定代碼的時(shí)候委刘。在此特定示例中,使用feed_dict參數(shù)將變量的值傳給run()方法鹰椒。這里锡移,相關(guān)代碼求解表達(dá)式,并且從顯示器返回 9 作為結(jié)果漆际。

通過(guò)這個(gè)簡(jiǎn)單的例子淆珊,我試圖介紹在 TensorFlow 中編程的常規(guī)方法,首先指定整個(gè)問(wèn)題奸汇,并最終創(chuàng)建一個(gè)可以運(yùn)行相關(guān)計(jì)算的會(huì)話施符。

然而,有時(shí)我們感興趣的是構(gòu)造代碼的更多的靈活性擂找,插入操作來(lái)構(gòu)建某個(gè)圖戳吝,這些操作運(yùn)行它的一部分。例如贯涎,當(dāng)我們使用 Python 的交互式環(huán)境時(shí)听哭,例如 IPython [8],就會(huì)發(fā)生這種情況柬采。為此欢唾,TesorFlow 提供了tf.InteractiveSession()類(lèi)。

這種編程模型的動(dòng)機(jī)超出了本書(shū)的范圍粉捻。但是礁遣,為了繼續(xù)下一章,我們只需要知道所有信息都在內(nèi)部保存在圖結(jié)構(gòu)中肩刃,它包含所有操作和數(shù)據(jù)的信息祟霍。

該圖描述了數(shù)學(xué)運(yùn)算杏头。節(jié)點(diǎn)通常實(shí)現(xiàn)數(shù)學(xué)運(yùn)算,但它們也可以表示數(shù)據(jù)輸入沸呐,輸出結(jié)果或讀/寫(xiě)持久變量醇王。邊描述節(jié)點(diǎn)與其輸入和輸出之間的關(guān)系,同時(shí)攜帶張量崭添,即 TensorFlow 的基本數(shù)據(jù)結(jié)構(gòu)寓娩。

將信息表示為圖允許 TensorFlow 知道事務(wù)之間的依賴關(guān)系,并異步并行地將操作分配給設(shè)備呼渣,當(dāng)這些操作已經(jīng)具有可用的相關(guān)張量(在邊緣輸入中指示)時(shí)棘伴。

因此,并行性是使我們能夠加速一些計(jì)算昂貴的算法的執(zhí)行的因素之一屁置,但也因?yàn)?TensorFlow 已經(jīng)有效地實(shí)現(xiàn)了一組復(fù)雜的操作焊夸。此外,大多數(shù)這些操作都具有關(guān)聯(lián)的內(nèi)核蓝角,這些內(nèi)核是為特定設(shè)備(如 GPU)設(shè)計(jì)的操作的實(shí)現(xiàn)阱穗。下表總結(jié)了最重要的操作/內(nèi)核 [9]:

操作組 操作
數(shù)學(xué) 加,減使鹅,乘揪阶,除,指數(shù)并徘,對(duì)數(shù)遣钳,大于,小于麦乞,等于
排列 連接,切片劝评,分割姐直,常數(shù),階蒋畜,形狀声畏,打亂
矩陣 MatMul,MatrixInverse姻成,MatrixDeterminant
神經(jīng)網(wǎng)絡(luò) SoftMax插龄,Sigmoid,ReLU科展,Convolution2D均牢,MaxPool
檢查點(diǎn) 保存,還原
隊(duì)列和同步 Enqueue才睹,Dequeue徘跪,MutexAcquire甘邀,MutexRelease
流量控制 合并,切換垮庐,進(jìn)入松邪,離開(kāi),NextIteration

顯示面板 Tensorboard

為了使其更加全面哨查,TensorFlow 包含了名為 TensorBoard 的可視化工具來(lái)調(diào)試和優(yōu)化程序的功能逗抑。TensorBoard 可以以圖形方式查看計(jì)算圖任何部分的參數(shù)和細(xì)節(jié)的不同類(lèi)型的統(tǒng)計(jì)信息。

TensorBoard 模塊顯示的數(shù)據(jù)在 TensorFlow 執(zhí)行期間生成寒亥,并存儲(chǔ)在跟蹤文件中邮府,其數(shù)據(jù)來(lái)自摘要操作。在 TensorFlow 的文檔頁(yè)面 [10] 中护盈,你可以找到 Python API 的詳細(xì)說(shuō)明挟纱。

我們調(diào)用它的方式非常簡(jiǎn)單:從命令行中使用 Tensorflow 命令啟動(dòng)服務(wù),它包含要跟蹤的文件作為參數(shù)腐宋。

(tensorflow)$ tensorboard --logdir=

你只需要使用http//localhost:6006 /從瀏覽器中 [11] 訪問(wèn)本地套接字 6006紊服。

名為 TensorBoard 的可視化工具超出了本書(shū)的范圍。對(duì)于 Tensorboard 如何工作的更多詳細(xì)信息胸竞,讀者可以訪問(wèn) TensorFlow 教程頁(yè)面中的 TensorBoard 圖形可視化 [12] 部分欺嗤。

2. TensorFlow 中的線性回歸

在本章中,我將開(kāi)始使用簡(jiǎn)單模型:線性回歸來(lái)探索 TensorFlow 編程卫枝〖灞基于這個(gè)例子,我將介紹一些代碼基礎(chǔ)知識(shí)校赤,以及吆玖,如何調(diào)用學(xué)習(xí)過(guò)程中的各種重要組件沾乘,如函數(shù)函數(shù)或算法梯度下降幅狮。

變量之間的關(guān)系模型

線性回歸是一種用于衡量變量之間關(guān)系的統(tǒng)計(jì)技術(shù)贤徒。它的有趣之處在于實(shí)現(xiàn)它的算法在概念上不復(fù)雜固阁,并且還可以適應(yīng)各種各樣的情況誉己。由于這些原因,我發(fā)現(xiàn)用線性回歸的例子開(kāi)始深入研究 TensorFlow 很有意思筹我。

請(qǐng)記住,在兩個(gè)變量(簡(jiǎn)單回歸)和兩個(gè)以上變量(多元回歸)的情況下哥谷,線性回歸擬合因變量和自變量之間的關(guān)系xi和隨機(jī)項(xiàng)b岸夯。

在本節(jié)中麻献,我將創(chuàng)建一個(gè)簡(jiǎn)單的示例來(lái)解釋 TensorFlow 如何工作,假設(shè)我們的數(shù)據(jù)模型對(duì)應(yīng)簡(jiǎn)單的線性回歸y = W * x + b猜扮。為此奸攻,我使用一個(gè)簡(jiǎn)單的 Python 程序在二維空間中創(chuàng)建數(shù)據(jù)鳄哭,然后我會(huì)要求 TensorFlow 在這些點(diǎn)上尋找最適合的直線沦零。

首先要做的是導(dǎo)入我們將用于生成點(diǎn)的 NumPy 包默辨。我們創(chuàng)建的代碼如下:

import numpy as np
 
num_points = 1000
vectors_set = []
for i in xrange(num_points):
         x1= np.random.normal(0.0, 0.55)
         y1= x1 * 0.1 + 0.3 + np.random.normal(0.0, 0.03)
         vectors_set.append([x1, y1])
 
x_data = [v[0] for v in vectors_set]
y_data = [v[1] for v in vectors_set]

從代碼中可以看出,我們根據(jù)關(guān)系y = 0.1 * x + 0.3生成了點(diǎn)鲜漩,盡管有一些正態(tài)分布的變化源譬,因此這些點(diǎn)并不完全對(duì)應(yīng)一條線,讓我們編寫(xiě)一個(gè)更有趣的例子孕似。

在我們的例子中踩娘,所得到的點(diǎn)云是:

https://jorditorres.org/wp-content/uploads/2016/02/image014.png

讀者可以使用以下代碼查看它們(這里,我們需要導(dǎo)入matplotlib包的一些函數(shù)喉祭,運(yùn)行pip install matplotlib [13]):

import matplotlib.pyplot as plt
 
plt.plot(x_data, y_data, 'ro', label='Original data')
plt.legend()
plt.show()

這些點(diǎn)是我們將考慮的模型的訓(xùn)練數(shù)據(jù)集的數(shù)據(jù)养渴。

損失函數(shù)和梯度下降算法

下一步是訓(xùn)練我們的學(xué)習(xí)算法,以便能夠獲得從輸入數(shù)據(jù)x_data估計(jì)的輸出值y泛烙。在這種情況下理卑,正如我們事先所知,它是線性回歸蔽氨,我們只能用兩個(gè)參數(shù)表示我們的模型:Wb藐唠。

目標(biāo)是生成 TensorFlow 代碼,它能夠找到最佳的參數(shù)Wb鹉究,它來(lái)自輸入數(shù)據(jù)x_data宇立,將其擬合到輸出數(shù)據(jù)y_data,我們這里它是一條直線自赔,由y_data = W * x_data + b定義妈嘹。讀者知道W應(yīng)接近 0.1 且b為 0.3,但 TensorFlow 不知道它绍妨,必須自己實(shí)現(xiàn)润脸。

解決此類(lèi)問(wèn)題的一種標(biāo)準(zhǔn)方法是,遍歷數(shù)據(jù)集的每個(gè)值并修改參數(shù)Wb他去,以便每次都能獲得更精確的答案津函。為了確定我們是否在這些迭代中有所改進(jìn),我們將定義一個(gè)損失函數(shù)(也稱(chēng)為“誤差函數(shù)”)來(lái)衡量某條線有多“好”(實(shí)際上是有多“壞”)孤页。

該函數(shù)接收參數(shù)Wb,并根據(jù)線與數(shù)據(jù)的擬合程度返回一個(gè)誤差值涩馆。在我們的例子中行施,我們可以使用均方誤差 [14] 作為損失函數(shù)允坚。利用均方誤差,我們得到“誤差”的平均值蛾号,基于實(shí)際值與算法每次迭代估計(jì)值之間距離稠项。

稍后,我將詳細(xì)介紹損失函數(shù)及其替代方法鲜结,但對(duì)于這個(gè)介紹性示例展运,均方誤差有助于我們一步一步向前推進(jìn)。

現(xiàn)在是時(shí)候用 TensorFlow 編寫(xiě)我 解釋過(guò)的所有內(nèi)容了精刷。為此拗胜,首先我們將使用以下語(yǔ)句創(chuàng)建三個(gè)變量:

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

現(xiàn)在,我們可以繼續(xù)前進(jìn)怒允,只知道方法Variable的調(diào)用定義了一個(gè)變量埂软,駐留在 TensorFlow 的內(nèi)部圖數(shù)據(jù)結(jié)構(gòu)中,我在上面已經(jīng)說(shuō)過(guò)了纫事。 稍后我們將回到方法參數(shù)的更多信息勘畔,但是現(xiàn)在我認(rèn)為最好繼續(xù)前進(jìn)來(lái)推進(jìn)第一種方法。

現(xiàn)在丽惶,通過(guò)定義這些變量炫七,我們可以基于每個(gè)點(diǎn)與函數(shù)y = W * x + b計(jì)算的點(diǎn)之間的距離,來(lái)表示我們之前討論的損失函數(shù)钾唬。之后万哪,我們可以計(jì)算其平方和的平均值。 在 TensorFlow 中知纷,此損失函數(shù)表示如下:

loss = tf.reduce_mean(tf.square(y - y_data))

如我們所見(jiàn)壤圃,此表達(dá)式計(jì)算我們知道的y_data點(diǎn)與從輸入x_data計(jì)算的點(diǎn)y之間的平方距離的平均值。

此時(shí)琅轧,讀者可能已經(jīng)懷疑最適合我們數(shù)據(jù)的直線是誤差值較小的直線伍绳。 因此,如果我們使誤差函數(shù)最小乍桂,我們將找到我們數(shù)據(jù)的最佳模型冲杀。

目前沒(méi)有太多細(xì)節(jié),這就是使函數(shù)最小的優(yōu)化算法睹酌,稱(chēng)為梯度下降 [15]权谁。 理論上,梯度下降是一種算法憋沿,它接受由一組參數(shù)定義的函數(shù)旺芽,它以一組初始參數(shù)值開(kāi)始,并迭代地移向一組使函數(shù)最小的值。 在函數(shù)梯度 [16] 的負(fù)方向上移動(dòng)來(lái)實(shí)現(xiàn)迭代式最小化采章。 通常計(jì)算距離平方來(lái)確保它是正的并且使誤差函數(shù)可微分以便計(jì)算梯度运嗜。

算法從一組參數(shù)的初始值開(kāi)始(在我們的例子中為Wb),然后算法以某種方式迭代地調(diào)整這些變量的值悯舟,在過(guò)程結(jié)束時(shí)担租,變量的值使成本函數(shù)最小。

要在 TensorFlow 中使用此算法抵怎,我們只需執(zhí)行以下兩個(gè)語(yǔ)句:

optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

現(xiàn)在奋救,這足以讓 TensorFlow 在其內(nèi)部數(shù)據(jù)結(jié)構(gòu)中創(chuàng)建相關(guān)數(shù)據(jù),并且在這個(gè)結(jié)構(gòu)中也實(shí)現(xiàn)了一個(gè)可以由train調(diào)用的優(yōu)化器反惕,它是針對(duì)定義的成本函數(shù)的梯度下降算法尝艘。稍后,我們將討論名為學(xué)習(xí)率的函數(shù)參數(shù)(在我們的示例中承璃,值為 0.5)利耍。

運(yùn)行算法

正如我們之前所見(jiàn),在代碼的這個(gè)位置上盔粹,特定于 TensorFlow 庫(kù)的調(diào)用隘梨,只向其內(nèi)部圖添加了信息,而 TensorFlow 的運(yùn)行時(shí)尚未運(yùn)行任何算法舷嗡。因此轴猎,與前一章的示例一樣,我們必須創(chuàng)建會(huì)話进萄,調(diào)用run方法并傳遞train作為參數(shù)捻脖。另外,因?yàn)樵诖a中我們已經(jīng)指定了變量中鼠,所以我們必須先使用以下調(diào)用對(duì)它們進(jìn)行初始化:

init = tf.initialize_all_variables()
 
sess = tf.Session()
sess.run(init)

現(xiàn)在我們可以開(kāi)始迭代過(guò)程可婶,這將允許我們找到Wb的值,它定義最適合輸入點(diǎn)的模型直線援雇。 訓(xùn)練過(guò)程一直持續(xù)到模型在訓(xùn)練數(shù)據(jù)上達(dá)到所需的準(zhǔn)確度矛渴。 在我們的特定示例中,如果我們假設(shè)只有 8 次迭代就足夠了惫搏,代碼可能是:

for step in xrange(8):
   sess.run(train)
print step, sess.run(W), sess.run(b)

運(yùn)行此代碼的結(jié)果表明具温,Wb的值接近我們事先知道的值。 在我的例子中筐赔,print的結(jié)果是:

(array([ 0.09150752], dtype=float32), array([ 0.30007562], dtype=float32))

并且铣猩,如果我們使用以下代碼以圖形方式顯示結(jié)果:

plt.plot(x_data, y_data, 'ro')
plt.plot(x_data, sess.run(W) * x_data + sess.run(b))
plt.legend()
plt.show()

我們可以用圖形方式,看到參數(shù)W = 0.0854b = 0.299定義的直線茴丰,只需 8 次迭代:

https://jorditorres.org/wp-content/uploads/2016/02/image016.png

請(qǐng)注意达皿,我們只執(zhí)行了八次迭代來(lái)簡(jiǎn)化說(shuō)明天吓,但如果我們運(yùn)行更多,參數(shù)值會(huì)更接近預(yù)期值鳞绕。 我們可以使用以下語(yǔ)句來(lái)打印Wb的值:

print(step, sess.run(W), sess.run(b))

在我們的例子中失仁,print輸出是:

(0, array([-0.04841119], dtype=float32), array([ 0.29720169], dtype=float32))
(1, array([-0.00449257], dtype=float32), array([ 0.29804006], dtype=float32))
(2, array([ 0.02618564], dtype=float32), array([ 0.29869056], dtype=float32))
(3, array([ 0.04761609], dtype=float32), array([ 0.29914495], dtype=float32))
(4, array([ 0.06258646], dtype=float32), array([ 0.29946238], dtype=float32))
(5, array([ 0.07304412], dtype=float32), array([ 0.29968411], dtype=float32))
(6, array([ 0.08034936], dtype=float32), array([ 0.29983902], dtype=float32))
(7, array([ 0.08545248], dtype=float32), array([ 0.29994723], dtype=float32))

你可以觀察到算法以W = -0.0484b = 0.2972(在我們的例子中)的初始值開(kāi)始,然后算法以一種方式迭代調(diào)整變量的值使損失函數(shù)最小们何。

你還可以檢查損失函數(shù)是否隨之減少

print(step, sess.run(loss))

在這種情況下,print輸出是:

(0, 0.015878126)
(1, 0.0079048825)
(2, 0.0041520335)
(3, 0.0023856456)
(4, 0.0015542418)
(5, 0.001162916)
(6, 0.00097872759)
(7, 0.00089203351)

我建議讀者在每次迭代時(shí)繪圖控轿,讓我們可以直觀地觀察算法如何調(diào)整參數(shù)值冤竹。 在我們的例子中,8 個(gè)截圖是:

https://jorditorres.org/wp-content/uploads/2016/02/image018.png

正如讀者可以看到的茬射,在算法的每次迭代中鹦蠕,直線更適合數(shù)據(jù)。 梯度下降算法如何更接近最小化損失函數(shù)的參數(shù)值在抛?

由于我們的誤差函數(shù)由兩個(gè)參數(shù)(Wb)組成钟病,我們可以將它可視化為二維表面。 該二維空間中的每個(gè)點(diǎn)代表一條直線刚梭。 每個(gè)點(diǎn)的函數(shù)高度是該直線的誤差值肠阱。 在該表面上,一些直線產(chǎn)生的誤差值小于其他直線朴读。 當(dāng) TensorFlow 運(yùn)行梯度下降搜索時(shí)屹徘,它將從該表面上的某個(gè)位置開(kāi)始(在我們的示例中,點(diǎn)W = -0.04841119b = 0.29720169)并向下移動(dòng)來(lái)查找具有最小誤差的直線衅金。

要在此誤差函數(shù)上運(yùn)行梯度下降噪伊,TensorFlow 會(huì)計(jì)算其梯度。 梯度將像指南針一樣氮唯,總是引導(dǎo)我們向下走鉴吹。 為了計(jì)算它,TensorFlow 將對(duì)誤差函數(shù)微分惩琉,在我們的情況下意味著它需要計(jì)算Wb的偏導(dǎo)數(shù)豆励,它表明每次迭代中要移動(dòng)的方向。

之前提到的學(xué)習(xí)率參數(shù)控制每次迭代期間 TensorFlow 的每一步的下降程度琳水。 如果我們引入的參數(shù)太大肆糕,我們可能會(huì)越過(guò)最小值。 但是在孝,如果我們讓 TensorFlow 采取較小步驟诚啃,則需要多次迭代才能達(dá)到最小值。 因此私沮,使用良好的學(xué)習(xí)率至關(guān)重要始赎。 有不同的技術(shù)來(lái)調(diào)整學(xué)習(xí)率參數(shù)的值,但它超出了本入門(mén)書(shū)的范圍。 確保梯度下降算法正常工作的一種好方法造垛,是確保每次迭代中的誤差減小魔招。

請(qǐng)記住,為了便于讀者測(cè)試本章所述的代碼五辽,你可以從本書(shū)的 Github [17] 下載regression.py办斑。 在這里,你將發(fā)現(xiàn)所有東西都在一起以便跟蹤:

import numpy as np

num_points = 1000
vectors_set = []
for i in xrange(num_points):
         x1= np.random.normal(0.0, 0.55)
         y1= x1 * 0.1 + 0.3 + np.random.normal(0.0, 0.03)
         vectors_set.append([x1, y1])

x_data = [v[0] for v in vectors_set]
y_data = [v[1] for v in vectors_set]

import matplotlib.pyplot as plt

#Graphic display
plt.plot(x_data, y_data, 'ro')
plt.legend()
plt.show()

import tensorflow as tf

W = tf.Variable(tf.random_uniform([1], -1.0, 1.0))
b = tf.Variable(tf.zeros([1]))
y = W * x_data + b

loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

init = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init)

for step in xrange(8):
     sess.run(train)
     print(step, sess.run(W), sess.run(b))
     print(step, sess.run(loss))

     #Graphic display
     plt.plot(x_data, y_data, 'ro')
     plt.plot(x_data, sess.run(W) * x_data + sess.run(b))
     plt.xlabel('x')
     plt.xlim(-2,2)
     plt.ylim(0.1,0.6)
     plt.ylabel('y')
     plt.legend()
     plt.show()

在本章中杆逗,我們已經(jīng)開(kāi)始探索 TensorFlow 軟件包的可能性乡翅,首先采用直觀方法處理兩個(gè)基本組件:損失函數(shù)和梯度下降算法,使用基本線性回歸算法來(lái)介紹罪郊。 在下一章中蠕蚜,我們將詳細(xì)介紹 TensorFlow 包使用的數(shù)據(jù)結(jié)構(gòu)。

3. TensorFlow 中的聚類(lèi)

前一章中介紹的線性回歸是一種監(jiān)督學(xué)習(xí)算法悔橄,我們使用數(shù)據(jù)和輸出值(或標(biāo)簽)來(lái)構(gòu)建適合它們的模型靶累。但我們并不總是擁有標(biāo)記數(shù)據(jù),盡管如此癣疟,我們也希望以某種方式分析它們挣柬。在這種情況下,我們可以使用無(wú)監(jiān)督學(xué)習(xí)算法争舞,例如聚類(lèi)凛忿。聚類(lèi)方法被廣泛使用,因?yàn)樗ǔJ菙?shù)據(jù)分析的初步篩選的好方法竞川。

在本章中店溢,我將介紹名為 K-means 的聚類(lèi)算法。它肯定是最受歡迎的委乌,廣泛用于自動(dòng)將數(shù)據(jù)分組到相關(guān)的子集中床牧,以便子集中的所有元素彼此更相似。在此算法中遭贸,我們沒(méi)有任何目標(biāo)或結(jié)果變量來(lái)預(yù)測(cè)估計(jì)值戈咳。

我還將使用本章來(lái)介紹 TensorFlow 的知識(shí),并在更詳細(xì)地介紹名為tensor(張量)的基本數(shù)據(jù)結(jié)構(gòu)壕吹。我將首先解釋這種類(lèi)型的數(shù)據(jù)是什么樣的著蛙,并展示可以在其上執(zhí)行的轉(zhuǎn)換。然后耳贬,我將使用張量在案例研究中展示 K-means 算法的使用踏堡。

基本數(shù)據(jù)結(jié)構(gòu):張量

TensorFlow 程序使用稱(chēng)為張量的基本數(shù)據(jù)結(jié)構(gòu)來(lái)表示其所有數(shù)據(jù)。張量可以被認(rèn)為是動(dòng)態(tài)大小的多維數(shù)據(jù)數(shù)組咒劲,其具有靜態(tài)數(shù)據(jù)類(lèi)型的屬性顷蟆,可以從布爾值或字符串到各種數(shù)字類(lèi)型诫隅。下面是 Python 中的主要類(lèi)型及其等價(jià)物的表格截亦。

TensorFlow 中的類(lèi)型 Python 中的類(lèi)型 描述
DT_FLOAT tf.float32 32 位浮點(diǎn)
DT_INT16 tf.int16 16 位整數(shù)
DT_INT32 tf.int32 32 位整數(shù)
DT_INT64 tf.int64 64 位整數(shù)
DT_STRING tf.string 字符串
DT_BOOL tf.bool 布爾值

另外阐枣,每個(gè)張量擁有階(Rank)小渊,這是其維度的數(shù)量脏榆。例如,以下張量(在 Python 中定義為列表)的階為 2:

t = [[1,2,3]冤留,[4,5,6]譬巫,[7,8,9]]

張量可以有任何階捣鲸。二階張量通常被認(rèn)為是矩陣漫贞,一階張量將是向量沛硅。零階被認(rèn)為是標(biāo)量值。

TensorFlow 文檔使用三種類(lèi)型的命名約定來(lái)描述張量的維度:形狀(Shape)绕辖,階(Rank)和維數(shù)(Dimension Number)。下表顯示了它們之間的關(guān)系擂红,以便使跟蹤 TensorFlow 文檔更容易:

形狀 維數(shù)
[] 0 0-D
[D0] 1 1-D
[D0, D1] 2 2-D
[D0, D1, D2] 3 3-D
[D0, D1, ... Dn] n n-D

這些張量可以通過(guò)一系列 TensorFlow 軟件包提供的轉(zhuǎn)換進(jìn)行操作仪际。 下面,我們將在下表中討論其中的一些內(nèi)容昵骤。

在本章中树碱,我們將詳細(xì)介紹其中一些內(nèi)容。 可以在 TensorFlow 的官方網(wǎng)站 [18] 上找到完整的轉(zhuǎn)換列表和詳細(xì)信息变秦。

| 操作 | 描述 |
| tf.shape | 獲取張量的形狀 |
| tf.size | 獲取張量的大小 |
| tf.rank | 獲取張量的階 |
| tf.reshape | 改變張量的形狀成榜,保持包含相同的元素 |
| tf.squeeze | 刪除大小為 1 的張量維度 |
| tf.expand_dims | 將維度插入張量 |
| tf.slice | 刪除部分張量 |
| tf.split | 將張量沿一個(gè)維度劃分為多個(gè)張量 |
| tf.tile | 將一個(gè)張量多次復(fù)制,并創(chuàng)建新的張量 |
| tf.concat | 在一個(gè)維度上連接張量 |
| tf.reverse | 反轉(zhuǎn)張量的特定維度 |
| tf.transpose | 轉(zhuǎn)置張量中的維度 |
| tf.gather | 根據(jù)索引收集部分 |

例如蹦玫,假設(shè)你要將2×2000(2D 張量)的數(shù)組擴(kuò)展為立方體(3D 張量)赎婚。 我們可以使用tf.expand_ dims函數(shù),它允許我們向張量插入一個(gè)維度:

vectors = tf.constant(conjunto_puntos)
extended_vectors = tf.expand_dims(vectors, 0)

在這種情況下樱溉,tf.expand_dims將一個(gè)維度插入到由參數(shù)給定的一個(gè)張量中(維度從零開(kāi)始)挣输。

從視覺(jué)上看,上述轉(zhuǎn)變?nèi)缦拢?/p>

https://jorditorres.org/wp-content/uploads/2016/02/image023.gif

如你所見(jiàn)福贞,我們現(xiàn)在有了 3D 張量撩嚼,但我們無(wú)法根據(jù)函數(shù)參數(shù)確定新維度 D0 的大小。

如果我們使用get_shape()操作獲得此tensor的形狀挖帘,我們可以看到?jīng)]有關(guān)聯(lián)的大型昀觥:

print expanded_vectors.get_shape()

它可能會(huì)顯示:

TensorShape([Dimension(1), Dimension(2000), Dimension(2)])

在本章的后面,我們將看到拇舀,由于 TensorFlow 形狀廣播逻族, 張量的許多數(shù)學(xué)處理函數(shù)(如第一章所示),能夠發(fā)現(xiàn)大小未指定的維度的大小你稚,瓷耙,并為其分配這個(gè)推導(dǎo)出的值朱躺。

TensorFlow 中的數(shù)據(jù)存儲(chǔ)

在介紹 TensorFlow 的軟件包之后,從廣義上講搁痛,有三種主要方法可以在 TensorFlow 程序上獲取數(shù)據(jù):

  1. 來(lái)自數(shù)據(jù)文件长搀。
  2. 數(shù)據(jù)作為常量或變量預(yù)加載。
  3. 那些由 Python 代碼提供的鸡典。

下面源请,我簡(jiǎn)要介紹其中的每一個(gè)。

  1. 數(shù)據(jù)文件

通常彻况,從數(shù)據(jù)文件加載初始數(shù)據(jù)谁尸。這個(gè)過(guò)程并不復(fù)雜,鑒于本書(shū)的介紹性質(zhì)纽甘,我邀請(qǐng)讀者訪問(wèn)TensorFlow 的網(wǎng)站 [19]良蛮,了解如何從不同文件類(lèi)型加載數(shù)據(jù)。你還可以查看 Python 代碼input_data.py [20](可在 Github 上找到)悍赢,它從文件中加載 MNIST 數(shù)據(jù)(我將在下面幾章使用它)决瞳。

  1. 變量和常量

當(dāng)談到小集合時(shí),也可以預(yù)先將數(shù)據(jù)加載到內(nèi)存中左权;創(chuàng)建它們有兩種基本方法皮胡,正如我們?cè)谇懊娴睦又锌吹降哪菢樱?/p>

  • constant(…)用于常量
  • Variable(…)用于變量

TensorFlow 包提供可用于生成常量的不同操作。在下表中赏迟,你可以找到最重要的操作的摘要:

操作 描述
tf.zeros_like 創(chuàng)建一個(gè)張量屡贺,所有元素都初始化為 0
tf.ones_like 創(chuàng)建一個(gè)張量,所有元素都初始化為 1
tf.fill 創(chuàng)建一個(gè)張量锌杀,其中所有元素都初始化為由參數(shù)給出的標(biāo)量值
tf.constant 使用參數(shù)列出的元素創(chuàng)建常量張量

在 TensorFlow 中甩栈,在模型的訓(xùn)練過(guò)程中,參數(shù)作為變量保存在存儲(chǔ)器中抛丽。 創(chuàng)建變量時(shí)谤职,可以使用由函數(shù)參數(shù)定義的張量作為初始值,該值可以是常量值或隨機(jī)值亿鲜。 TensorFlow 提供了一系列操作允蜈,可生成具有不同分布的隨機(jī)張量:

操作 描述
tf.random_normal 具有正態(tài)分布的隨機(jī)值
tf.truncated_normal 具有正態(tài)分布的隨機(jī)值,但消除那些幅度大于標(biāo)準(zhǔn)差 2 倍的值
tf.random_uniform 具有均勻分布的隨機(jī)值
tf.random_shuffle 在第一維中隨機(jī)打亂張量元素
tf.set_random_seed 設(shè)置隨機(jī)種子

一個(gè)重要的細(xì)節(jié)是蒿柳,所有這些操作都需要特定形狀的張量作為函數(shù)的參數(shù)饶套,并且創(chuàng)建的變量具有相同的形狀。 通常垒探,變量具有固定的形狀妓蛮,但TensorFlow提供了在必要時(shí)對(duì)其進(jìn)行重塑的機(jī)制。

使用變量時(shí)圾叼,必須在構(gòu)造圖之后蛤克,在使用run()函數(shù)執(zhí)行任何操作之前顯式初始化這些變量捺癞。 正如我們所看到的,為此可以使用tf.initialize_all_variables()构挤。 通過(guò) TensorFlow 的tf.train.Saver()類(lèi)髓介,可以在訓(xùn)練模型時(shí)和之后將變量保存到磁盤(pán)上,但是這個(gè)類(lèi)超出了本書(shū)的范圍筋现。

  1. 由Python代碼提供

最后唐础,我們可以使用我們所謂的“符號(hào)變量”或占位符來(lái)在程序執(zhí)行期間操作數(shù)據(jù)。調(diào)用是placeholder()矾飞,參數(shù)為元素類(lèi)型和張量形狀一膨,以及可選的名稱(chēng)。

從 Python 代碼調(diào)用Session.run()Tensor.eval()的同時(shí)洒沦,張量由feed_dict參數(shù)中指定的數(shù)據(jù)填充豹绪。回想第 1 章中的第一個(gè)代碼:

import tensorflow as tf
a = tf.placeholder("float")
b = tf.placeholder("float")
y = tf.mul(a, b)
sess = tf.Session()
print sess.run(y, feed_dict={a: 3, b: 3})

在最后一行代碼中申眼,調(diào)用sess.run()時(shí)森篷,我們傳遞兩個(gè)張量ab的值到feed_dict參數(shù)。

通過(guò)張量的簡(jiǎn)要介紹豺型,我希望從現(xiàn)在起讀者可以毫不費(fèi)力地讀懂下面幾章的代碼。

K-Means 算法

K-Means 是一種無(wú)監(jiān)督算法买乃,可以解決聚類(lèi)問(wèn)題姻氨。 它的過(guò)程遵循一種簡(jiǎn)單易行的方法,通過(guò)一定數(shù)量的簇(假設(shè)k簇)對(duì)給定數(shù)據(jù)集進(jìn)行聚類(lèi)剪验。 簇內(nèi)的數(shù)據(jù)點(diǎn)是同構(gòu)的肴焊,不同簇的點(diǎn)是異構(gòu)的,這意味著子集中的所有元素與其余元素相比更為相似功戚。

算法的結(jié)果是一組K個(gè)點(diǎn)娶眷,稱(chēng)為質(zhì)心,它們是所得的不同組的焦點(diǎn)啸臀,以及點(diǎn)集的標(biāo)簽届宠,這些點(diǎn)分配給其中一個(gè)簇。 簇內(nèi)的所有點(diǎn)與質(zhì)心的距離都比任何其他質(zhì)心更近乘粒。

如果我們想要直接最小化誤差函數(shù)(所謂的 NP-hard 問(wèn)題)豌注,那么簇的生成是一個(gè)計(jì)算上很昂貴的問(wèn)題。因此灯萍,已經(jīng)創(chuàng)建了一些算法轧铁,通過(guò)啟發(fā)式在局部最優(yōu)中快速收斂。 最常用的算法使用迭代優(yōu)化技術(shù)旦棉,它在幾次迭代中收斂齿风。

一般來(lái)講药薯,這種技術(shù)有三個(gè)步驟:

  • 初始步驟(步驟 0):確定K個(gè)質(zhì)心的初始集合。
  • 分配步驟(步驟 1):將每個(gè)觀測(cè)值分配到最近的組救斑。
  • 更新步驟(步驟 2):計(jì)算每個(gè)新組的新質(zhì)心童本。

有幾種方法可以確定初始K質(zhì)心。 其中一個(gè)是在數(shù)據(jù)集中隨機(jī)選擇K個(gè)觀測(cè)值并將它們視為質(zhì)心系谐;這是我們將在我們的示例中使用的那個(gè)巾陕。

分配(步驟 1)和更新(步驟 2)的步驟在循環(huán)中交替,直到認(rèn)為算法已經(jīng)收斂為止纪他,這可以是鄙煤,例如,當(dāng)點(diǎn)到組的分配不再改變的時(shí)候茶袒。

由于這是一種啟發(fā)式算法梯刚,因此無(wú)法保證它收斂于全局最優(yōu),結(jié)果取決于初始組薪寓。 因此亡资,由于算法通常非常快向叉,通常使用不同的初始質(zhì)心值重復(fù)執(zhí)行多次锥腻,然后權(quán)衡結(jié)果。

要在 TensorFlow 中開(kāi)始編寫(xiě) K-means 的示例母谎,我建議首先生成一些數(shù)據(jù)作為測(cè)試平臺(tái)瘦黑。 我建議做一些簡(jiǎn)單的事情,比如在 2D 空間中隨機(jī)生成 2,000 個(gè)點(diǎn)奇唤,遵循二維正態(tài)分布來(lái)繪制一個(gè)空間幸斥,使我們能夠更好地理解結(jié)果。 例如咬扇,我建議使用以下代碼:

num_puntos = 2000
conjunto_puntos = []
for i in xrange(num_puntos):
   if np.random.random() > 0.5:
     conjunto_puntos.append([np.random.normal(0.0, 0.9), np.random.normal(0.0, 0.9)])
   else:
     conjunto_puntos.append([np.random.normal(3.0, 0.5), np.random.normal(1.0, 0.5)])

正如我們?cè)谇耙徽轮兴龅哪菢蛹自幔覀兛梢允褂靡恍?Python 圖形庫(kù)來(lái)繪制數(shù)據(jù)。 我建議像以前一樣使用 matplotlib懈贺,但這次我們還將使用基于 matplotlib 的可視化包 Seaborn 和數(shù)據(jù)操作包 pandas经窖,它允許我們使用更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。

如果未安裝這些軟件包梭灿,則必須先使用pip執(zhí)行此操作钠至,然后才能運(yùn)行以下代碼。

要顯示隨機(jī)生成的點(diǎn)胎源,我建議使用以下代碼:

import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns

df = pd.DataFrame({"x": [v[0] for v in conjunto_puntos],
        "y": [v[1] for v in conjunto_puntos]})
sns.lmplot("x", "y", data=df, fit_reg=False, size=6)
plt.show()

此代碼生成二維空間中的點(diǎn)圖棉钧,如下面的截圖所示:

https://jorditorres.org/wp-content/uploads/2016/02/image024.png

在 TensorFlow 中實(shí)現(xiàn)的 k-means 算法將上述點(diǎn)分組,例如在四個(gè)簇中涕蚤,可能像這樣(基于 Shawn Simister 在他的博客中展示的模型 [21]):

import numpy as np
vectors = tf.constant(conjunto_puntos)
k = 4
centroides = tf.Variable(tf.slice(tf.random_shuffle(vectors),[0,0],[k,-1]))

expanded_vectors = tf.expand_dims(vectors, 0)
expanded_centroides = tf.expand_dims(centroides, 1)

assignments = tf.argmin(tf.reduce_sum(tf.square(tf.sub(expanded_vectors, expanded_centroides)), 2), 0)

means = tf.concat(0, [tf.reduce_mean(tf.gather(vectors, tf.reshape(tf.where( tf.equal(assignments, c)),[1,-1])), reduction_indices=[1]) for c in xrange(k)])

update_centroides = tf.assign(centroides, means)

init_op = tf.initialize_all_variables()

sess = tf.Session()
sess.run(init_op)

for step in xrange(100):
   _, centroid_values, assignment_values = sess.run([update_centroides, centroides, assignments])

我建議讀者使用以下代碼檢查assignment_values張量中的結(jié)果宪卿,該代碼生成像上面那樣的圖:

data = {"x": [], "y": [], "cluster": []}

for i in xrange(len(assignment_values)):
  data["x"].append(conjunto_puntos[i][0])
  data["y"].append(conjunto_puntos[i][1])
  data["cluster"].append(assignment_values[i])

df = pd.DataFrame(data)
sns.lmplot("x", "y", data=df, fit_reg=False, size=6, hue="cluster", legend=False)
plt.show()

截圖以及我的代碼執(zhí)行結(jié)果如下圖所示:

https://jorditorres.org/wp-content/uploads/2016/02/image026.png

新的組

我假設(shè)讀者可能會(huì)對(duì)上一節(jié)中介紹的 K-means 代碼感到有些不知所措的诵。 好吧,我建議我們一步一步詳細(xì)分析它佑钾,特別是觀察涉及的張量以及它們?cè)诔绦蛑腥绾无D(zhuǎn)換西疤。

首先要做的是將所有數(shù)據(jù)移到張量。 在常數(shù)張量中休溶,我們使初始點(diǎn)保持隨機(jī)生成:

vectors = tf.constant(conjunto_vectors)

按照上一節(jié)中介紹的算法代赁,為了開(kāi)始我們必須確定初始質(zhì)心。 隨著我前進(jìn)兽掰,一個(gè)選項(xiàng)可能是芭碍,從輸入數(shù)據(jù)中隨機(jī)選擇K個(gè)觀測(cè)值。 一種方法是使用以下代碼孽尽,它向 TensorFlow 表明窖壕,它必須隨機(jī)地打亂初始點(diǎn)并選擇前K個(gè)點(diǎn)作為質(zhì)心:

k = 4
centroides = tf.Variable(tf.slice(tf.random_shuffle(vectors),[0,0],[k,-1]))

K個(gè)點(diǎn)存儲(chǔ)在 2D 張量中。 要知道這些張量的形狀杉女,我們可以使用tf.Tensor.get_shape()

print vectors.get_shape()
print centroides.get_shape()

TensorShape([Dimension(2000), Dimension(2)])
TensorShape([Dimension(4), Dimension(2)])

我們可以看到vectors是一個(gè)數(shù)組瞻讽,D0 維包含 2000 個(gè)位置,每個(gè)位置一個(gè)向量熏挎,D1 的位置是每個(gè)點(diǎn)x, y速勇。 相反,centroids是一個(gè)矩陣坎拐,維度 D0 有四個(gè)位置快集,每個(gè)質(zhì)心一個(gè)位置,D1 和vectors相同廉白。

接下來(lái),算法進(jìn)入循環(huán)乖寒。 第一步是為每個(gè)點(diǎn)計(jì)算其最接近的質(zhì)心猴蹂,根據(jù)平方歐幾里德距離 [22](只能在我們想要比較距離時(shí)使用):

https://jorditorres.org/wp-content/uploads/2016/02/image028.jpg

為了計(jì)算該值,使用tf.sub(vectors, centroides楣嘁。 我們應(yīng)該注意到磅轻,雖然減法的兩個(gè)張量都有 2 個(gè)維度,但它們?cè)谝粋€(gè)維度上大小不同(維度 D0 為 2000 和 4)逐虚,實(shí)際上它們也代表不同的東西聋溜。

為了解決這個(gè)問(wèn)題,我們可以使用之前討論過(guò)的一些函數(shù)叭爱,例如tf.expand_dims撮躁,以便在兩個(gè)張量中插入一個(gè)維度。 目的是將兩個(gè)張量從 2 維擴(kuò)展到 3 維來(lái)使尺寸匹配买雾,以便執(zhí)行減法:

expanded_vectors = tf.expand_dims(vectors, 0)
expanded_centroides = tf.expand_dims(centroides, 1)

tf.expand_dims在每個(gè)張量中插入一個(gè)維度把曼;在vectors張量的第一維(D0)杨帽,以及centroides張量的第二維(D1)。 從圖形上看嗤军,我們可以看到注盈,在擴(kuò)展后的張量中浑侥,每個(gè)維度具有相同的含義:

https://jorditorres.org/wp-content/uploads/2016/02/image031.gif

它似乎得到了解決堆巧,但實(shí)際上,如果你仔細(xì)觀察(在插圖中概述)茵臭,在每種情況下都有大小無(wú)法確定的些維度震叮。 請(qǐng)記住胧砰,使用get_shape()函數(shù)我們可以發(fā)現(xiàn):

print expanded_vectors.get_shape()
print expanded_centroides.get_shape()

輸出如下:

TensorShape([Dimension(1), Dimension(2000), Dimension(2)])
TensorShape([Dimension(4), Dimension(1), Dimension(2)])

使用 1 表示沒(méi)有指定大小。

但我已經(jīng)展示 TensorFlow 允許廣播冤荆,因此tf.sub函數(shù)能夠自己發(fā)現(xiàn)如何在兩個(gè)張量之間將元素相減朴则。

直觀地,并且觀察先前的附圖钓简,我們看到兩個(gè)張量的形狀匹配乌妒,并且在這些情況下,兩個(gè)張量在一定維度上具有相同的尺寸外邓。 這些數(shù)學(xué)撤蚊,如 D2 維度所示。 相反损话,在維度 D0 中只有expanded_centroides的定義大小侦啸。

在這種情況下,如果我們想要在此維度內(nèi)對(duì)元素執(zhí)行減法丧枪,則 TensorFlow 假定expanded_vectors張量的維度 D0 必須是相同的大小光涂。

對(duì)于expended_centroides張量的維度 D1 的大小也是如此,其中 TensorFlow 推導(dǎo)出expanded_vectors張量的尺寸 D1 的大小拧烦。

因此忘闻,在分配步驟(步驟 1)中,算法可以用 TensorFlow 代碼的這四行表示恋博,它計(jì)算平方歐幾里德距離:

diff=tf.sub(expanded_vectors, expanded_centroides)
sqr= tf.square(diff)
distances = tf.reduce_sum(sqr, 2)
assignments = tf.argmin(distances, 0)

而且齐佳,如果我們看一下張量的形狀,我們會(huì)看到它們分別對(duì)應(yīng)diff债沮,sqr炼吴,distanceassign,如下所示:

TensorShape([Dimension(4), Dimension(2000), Dimension(2)])
TensorShape([Dimension(4), Dimension(2000), Dimension(2)])
TensorShape([Dimension(4), Dimension(2000)])
TensorShape([Dimension(2000)])

也就是說(shuō)疫衩,tf.sub函數(shù)返回了張量dist硅蹦,其中包含質(zhì)心和向量的坐標(biāo)的差(維度 D1 表示數(shù)據(jù)點(diǎn),D0 表示質(zhì)心,每個(gè)坐標(biāo)x, y在維度 D2 中表示)提针。

sqr張量包含它們的平方命爬。 在dist張量中,我們可以看到它已經(jīng)減少了一個(gè)維度辐脖,它在tf.reduce_sum函數(shù)中表示為一個(gè)參數(shù)饲宛。

我用這個(gè)例子來(lái)解釋 TensorFlow 提供的幾個(gè)操作,它們可以用來(lái)執(zhí)行減少?gòu)埩烤S數(shù)的數(shù)學(xué)運(yùn)算嗜价,如tf.reduce_sum艇抠。在下表中,你可以找到最重要的操作摘要久锥。

操作 描述
tf.reduce_sum 沿一個(gè)維度計(jì)算元素總和
tf.reduce_prod 沿一個(gè)維度計(jì)算元素的乘積
tf.reduce_min 沿一個(gè)維度計(jì)算元素最小值
tf.reduce_max 沿一個(gè)維度計(jì)算元素最大值
tf.reduce_mean 沿一個(gè)維度計(jì)算元素平均值

最后家淤,使用tf.argmin實(shí)現(xiàn)分配,它返回張量的某個(gè)維度的最小值的索引(在我們的例子中是 D0瑟由,記得它是質(zhì)心)絮重。 我們還有tf.argmax操作:

手術(shù) 描述
tf.argmin 沿某個(gè)維度返回最小值的索引
tf.argmax 沿某個(gè)維度返回最大值的索引

事實(shí)上,上面提到的 4 條語(yǔ)句可以在一行代碼中匯總歹苦,正如我們?cè)谏弦还?jié)中看到的那樣:

assignments = tf.argmin(tf.reduce_sum(tf.square(tf.sub(expanded_vectors, expanded_centroides)), 2), 0)

但無(wú)論如何青伤,內(nèi)部的tensors,以及它們定義為節(jié)點(diǎn)和執(zhí)行的內(nèi)部圖的操作殴瘦,就像我們之前描述的那樣狠角。

計(jì)算新的質(zhì)心

在那段代碼中,我們可以看到means張量是k張量的連接結(jié)果蚪腋,它們對(duì)應(yīng)屬于每個(gè)簇的每個(gè)點(diǎn)的平均值丰歌。

接下來(lái),我將評(píng)論每個(gè) TensorFlow 操作屉凯,這些操作涉及計(jì)算屬于每個(gè)簇的每個(gè)點(diǎn)的平均值 [23]立帖。

  • 使用equal,我們可以得到布爾張量(Dimension(2000))悠砚,它(使用true)表示assignments張量K個(gè)簇匹配的位置晓勇,當(dāng)時(shí)我們正在計(jì)算點(diǎn)的平均值。
  • 使用where構(gòu)造一個(gè)張量(Dimension(1) x Dimension(2000))哩簿,帶有布爾張量中值為true的位置,布爾張量作為參數(shù)接收的布爾張量酝静。
  • reshape構(gòu)造張量(Dimension(2000) x Dimension(1))节榜,其中vectors張量?jī)?nèi)的點(diǎn)的索引屬于簇c
  • gather構(gòu)造張量(Dimension(1) x Dimension(2000))别智,它收集形成簇c的點(diǎn)的坐標(biāo)宗苍。
  • 使用reduce_mean,構(gòu)造張量Dimension(1) x Dimension(2),其中包含屬于簇c的所有點(diǎn)的平均值讳窟。

無(wú)論如何让歼,如果讀者想要深入研究代碼,正如我常說(shuō)的那樣丽啡,你可以在 TensorFlow API 頁(yè)面上找到有關(guān)這些操作的更多信息谋右,以及非常具有說(shuō)明性的示例 [24]。

圖表執(zhí)行

最后补箍,我們必須描述上述代碼中改执,與循環(huán)相對(duì)應(yīng)的部分,以及使用means張量的新值更新質(zhì)心的部分坑雅。

為此辈挂,我們需要?jiǎng)?chuàng)建一個(gè)操作,它將means張量的值分配到質(zhì)心中裹粤,而不是在執(zhí)行操作run()時(shí)终蒂,更新的質(zhì)心的值在循環(huán)的下一次迭代中使用:

update_centroides = tf.assign(centroides, means)

在開(kāi)始運(yùn)行圖之前,我們還必須創(chuàng)建一個(gè)操作來(lái)初始化所有變量:

init_op = tf.initialize_all_variables()

此時(shí)一切準(zhǔn)備就緒遥诉。 我們可以開(kāi)始運(yùn)行圖了:

sess = tf.Session()
sess.run(init_op)

for step in xrange(num_steps):
   _, centroid_values, assignment_values = sess.run([update_centroides, centroides, assignments])

在此代碼中拇泣,每次迭代中,更新每個(gè)初始點(diǎn)的質(zhì)心和新的簇分配突那。

請(qǐng)注意挫酿,代碼指定了三個(gè)操作,它必須查看run()調(diào)用的執(zhí)行愕难,并按此順序運(yùn)行早龟。 由于要搜索三個(gè)值,sess.run()會(huì)在訓(xùn)練過(guò)程中返回元素為三個(gè) numpy 數(shù)組的數(shù)據(jù)結(jié)構(gòu)猫缭,內(nèi)容為相應(yīng)張量葱弟。

由于update_centroides是一個(gè)結(jié)果是不返回的參數(shù)的操作,因此返回元組中的相應(yīng)項(xiàng)不包含任何內(nèi)容猜丹,因此被排除芝加,用_來(lái)表示 [25] 。

對(duì)于其他兩個(gè)值射窒,質(zhì)心和每個(gè)簇的分配點(diǎn)藏杖,我們有興趣在完成所有num_steps次迭代后在屏幕上顯示它們。

我們可以使用簡(jiǎn)單的打印脉顿。 輸出如下:

print centroid_values

[[ 2.99835277e+00 9.89548564e-01]
[ -8.30736756e-01 4.07433510e-01]
[ 7.49640584e-01 4.99431938e-01]
[ 1.83571398e-03 -9.78474259e-01]]

我希望讀者的屏幕上有類(lèi)似的值蝌麸,因?yàn)檫@表明他已成功執(zhí)行了本書(shū)這一章中展示的代碼。

我建議讀者在繼續(xù)之前嘗試更改代碼中的任何值艾疟。 例如num_points来吩,特別是k的數(shù)量敢辩,并使用生成圖的先前代碼查看它如何更改assignment_values張量中的結(jié)果。

請(qǐng)記住弟疆,為了便于測(cè)試本章所述的代碼戚长,可以從 Github [26] 下載。 包含此代碼的文件名是Kmeans.py怠苔。

在本章中同廉,我們展示了 TensorFlow 的一些知識(shí),特別是基本數(shù)據(jù)結(jié)構(gòu)張量嘀略,它來(lái)自實(shí)現(xiàn) KMeans 聚類(lèi)算法的 TensorFlow 代碼示例恤溶。

有了這些知識(shí),我們就可以在下一章中逐步使用 TensorFlow 構(gòu)建單層神經(jīng)網(wǎng)絡(luò)帜羊。

4. TensorFlow 中的單層神經(jīng)網(wǎng)絡(luò)

在前言中咒程,我評(píng)論說(shuō)深度學(xué)習(xí)的一個(gè)常見(jiàn)用途包括模式識(shí)別。 考慮到這一點(diǎn)讼育,就像初學(xué)者通過(guò)在屏幕上打印“Hello World”開(kāi)始學(xué)習(xí)編程語(yǔ)言一樣帐姻,在深度學(xué)習(xí)中,我們首先要識(shí)別手寫(xiě)數(shù)字奶段。

在本章中饥瓷,我將介紹如何在 TensorFlow 中逐步構(gòu)建具有單個(gè)層的神經(jīng)網(wǎng)絡(luò)。 這個(gè)神經(jīng)網(wǎng)絡(luò)將識(shí)別手寫(xiě)數(shù)字痹籍,它基于 TensorFlow 的初學(xué)者教程 [27] 的不同示例之一呢铆。

鑒于本書(shū)的介紹風(fēng)格,我選擇引導(dǎo)讀者蹲缠,同時(shí)通過(guò)示例的某些步驟簡(jiǎn)化了一些概念和理論上的原因棺克。

如果讀者在閱讀本章后有興趣了解這個(gè)示例的理論概念,我建議閱讀神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí) [28]线定,可在線獲取娜谊,它介紹了這個(gè)例子,但深入研究理論概念斤讥。

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

MNIST 數(shù)據(jù)集由一組包含手寫(xiě)數(shù)字的黑白圖像組成纱皆,包含60,000 多個(gè)用于訓(xùn)練模型的示例,以及 10,000 個(gè)用于測(cè)試它的示例芭商。 MNIST 數(shù)據(jù)集可以在 MNIST 數(shù)據(jù)庫(kù) [29] 中找到派草。

這個(gè)數(shù)據(jù)集非常適合大多數(shù)開(kāi)始在實(shí)例上進(jìn)行模式識(shí)別的人,而不必花時(shí)間進(jìn)行數(shù)據(jù)預(yù)處理或格式化铛楣,這是處理圖像時(shí)的兩個(gè)非常重要的步驟近迁,但時(shí)間很長(zhǎng)。

黑白圖像(二值)已經(jīng)標(biāo)準(zhǔn)化為20×20像的素圖像蛉艾,保留了寬高比钳踊。 對(duì)于這種情況,我們注意到圖像包含灰色像素 [30]勿侯,是歸一化算法的結(jié)果(將所有圖像的分辨率降低到最低級(jí)別之一)拓瞪。 之后,通過(guò)計(jì)算質(zhì)心并將其移動(dòng)到幀的中心助琐,圖像以28×28像素幀為中心祭埂。 圖像類(lèi)似于此處顯示的圖像:

https://jorditorres.org/wp-content/uploads/2016/02/image034.png

此外,本例所需的學(xué)習(xí)類(lèi)型是監(jiān)督學(xué)習(xí)兵钮;圖像用它們代表的數(shù)字標(biāo)記蛆橡。 這是最常見(jiàn)的機(jī)器學(xué)習(xí)形式。

在這種情況下掘譬,我們首先收集數(shù)字圖像的大數(shù)據(jù)集泰演,每個(gè)數(shù)字都用其值標(biāo)記。 在訓(xùn)練期間葱轩,模型接受圖像并以得分向量的形式產(chǎn)生輸出睦焕,每個(gè)類(lèi)別一個(gè)得分。 我們希望所需類(lèi)別在所有類(lèi)別中得分最高靴拱,但這在訓(xùn)練之前不太可能發(fā)生垃喊。

我們計(jì)算一個(gè)目標(biāo)函數(shù)來(lái)衡量輸出分?jǐn)?shù)和所需分?jǐn)?shù)模式之間的誤差(正如我們?cè)谇懊嬲鹿?jié)中所做的那樣)。 然后袜炕,模型修改其內(nèi)部可調(diào)參數(shù)本谜,稱(chēng)為權(quán)重,來(lái)減少此誤差偎窘。 在典型的深度學(xué)習(xí)系統(tǒng)中乌助,可能存在數(shù)億個(gè)這樣的可調(diào)節(jié)權(quán)重,以及用于訓(xùn)練機(jī)器的數(shù)億個(gè)標(biāo)記示例评架。 我們將考慮一個(gè)較小的例子眷茁,來(lái)幫助理解這種模型的工作原理。

要輕松下載數(shù)據(jù)纵诞,你可以使用從 Google 的網(wǎng)站 [32] 獲取腳本input_data.py[31]上祈,但它為你上傳到的這本書(shū)的 github 上。 只需將代碼input_data.py下載到使用 TensorFlow 編寫(xiě)神經(jīng)網(wǎng)絡(luò)的同一工作目錄中浙芙。 在你的應(yīng)用程序中登刺,你只需要按以下方式導(dǎo)入和使用:

import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

執(zhí)行這兩條指令后,你將在mnist.train中獲得完整的訓(xùn)練數(shù)據(jù)集嗡呼,并在mnist.test中設(shè)置測(cè)試數(shù)據(jù)纸俭。 如前所述,每個(gè)元素由一個(gè)圖像組成南窗,標(biāo)記為xs揍很,并且其對(duì)應(yīng)的標(biāo)簽ys郎楼,以便更容易表達(dá)處理代碼。 請(qǐng)記住窒悔,所有數(shù)據(jù)集呜袁,訓(xùn)練和測(cè)試集都包含xsys;此外简珠,訓(xùn)練圖像通過(guò)mnist.train.images引用阶界,訓(xùn)練標(biāo)簽通過(guò)mnist.train.labels引用。

如前所述聋庵,圖像由28×28像素形成膘融,并且可以表示為數(shù)字矩陣。 例如祭玉,數(shù)字 1 的圖像之一可以表示為:

https://jorditorres.org/wp-content/uploads/2016/02/image036-1000x388.png

其中每個(gè)位置表示 0 到 1 之間每個(gè)像素的缺失度氧映。 該矩陣可以表示為28×28 = 784個(gè)數(shù)的數(shù)組。 實(shí)際上脱货,圖像已經(jīng)變換為 784 維度的向量空間中的一堆點(diǎn)中屯耸。 只是當(dāng)我們將結(jié)構(gòu)減少到 2 維時(shí),我們可能會(huì)丟失部分信息蹭劈,對(duì)于某些計(jì)算機(jī)視覺(jué)算法疗绣,這可能會(huì)影響他們的結(jié)果,但對(duì)于本教程中使用的最簡(jiǎn)單的方法铺韧,這不會(huì)是一個(gè)問(wèn)題锄禽。

總而言之捧存,我們?cè)?2D 中擁有張量mnist.train.images静尼,其中調(diào)用函數(shù)get_shape()表示其形狀:

TensorShape([Dimension(60000), Dimension(784)])

第一維索引每個(gè)圖像和第二維是每個(gè)像素挖炬。 張量的每個(gè)元素是 0 到 1 之間的每個(gè)像素的強(qiáng)度。

此外料仗,我們有 0 到 9 之間的數(shù)字形式的標(biāo)簽湾盗,表示每個(gè)圖像代表哪個(gè)數(shù)字。 在這個(gè)例子中立轧,我們將標(biāo)簽表示為 10 個(gè)位置的向量格粪,其中所表示數(shù)字的對(duì)應(yīng)位置是 1 而其余為 0。 所以mnist.train.labels es是形如TensorShape([Dimension(60000), Dimension10)])的張量氛改。

人造神經(jīng)元

雖然本書(shū)并未關(guān)注神經(jīng)網(wǎng)絡(luò)的理論概念帐萎,但簡(jiǎn)要而直觀地介紹神經(jīng)元如何學(xué)習(xí)訓(xùn)練數(shù)據(jù),將有助于讀者了解正在發(fā)生的事情胜卤。 那些已經(jīng)了解該理論并且只是尋求如何使用 TensorFlow 的讀者可以跳過(guò)本節(jié)疆导。

讓我們看一個(gè)神經(jīng)元如何學(xué)習(xí)的簡(jiǎn)單但說(shuō)明性的例子。 假設(shè)有一組標(biāo)記為“方形”和“圓形”的點(diǎn)葛躏。 給定一個(gè)新的點(diǎn)X澈段,我們想知道對(duì)應(yīng)哪個(gè)標(biāo)簽:

https://jorditorres.org/wp-content/uploads/2016/02/Screen-Shot-2016-02-16-at-09.30.14.png

通常的近似可能是繪制一條劃分兩組的直線并將其用作分類(lèi)器:

https://jorditorres.org/wp-content/uploads/2016/02/Screen-Shot-2016-02-16-at-09.30.09.png

在這種情況下悠菜,輸入數(shù)據(jù)由形狀為(x, y)的向量表示,表示此二維空間中的坐標(biāo)败富,并且我們的函數(shù)返回“0”或“1”(線上方或下方)來(lái)了解如何將其歸類(lèi)為“方形”或“圓形”李剖。 在數(shù)學(xué)上,正如我們?cè)诰€性回歸章節(jié)中所學(xué)到的囤耳,“直線”(分類(lèi)器)可以表示為y = W * x + b

推廣時(shí)偶芍,神經(jīng)元必須學(xué)習(xí)權(quán)重W(與輸入數(shù)據(jù)X維度相同)和偏移量b(在神經(jīng)元中稱(chēng)為偏置)充择,來(lái)學(xué)習(xí)如何分類(lèi)這些值。 利用它們匪蟀,神經(jīng)元將計(jì)算權(quán)重輸入XW的加權(quán)和椎麦,并添加偏移b;最后神經(jīng)元將應(yīng)用非線性“激活”函數(shù)來(lái)產(chǎn)生“0”或“1”的結(jié)果材彪。

神經(jīng)元的功能可以更正式地表示為:

https://jorditorres.org/wp-content/uploads/2016/02/image043.png

在為我們的神經(jīng)元定義了這個(gè)函數(shù)后观挎,我們想知道神經(jīng)元如何從帶有“方塊”和“圓圈”的標(biāo)記數(shù)據(jù)中學(xué)習(xí)參數(shù)Wb,以便稍后標(biāo)記新點(diǎn)X段化。

第一種方法可以類(lèi)似于我們對(duì)線性回歸所做的嘁捷,即用已知的標(biāo)記數(shù)據(jù)喂養(yǎng)神經(jīng)元,并將獲得的結(jié)果與真實(shí)的結(jié)果進(jìn)行比較显熏。 然后雄嚣,在迭代時(shí),調(diào)整Wb來(lái)使誤差最小化喘蟆,如第 2 章中線性回歸線所示缓升。

一旦我們得到Wb參數(shù),我們就可以計(jì)算加權(quán)和蕴轨,現(xiàn)在我們需要函數(shù)將存儲(chǔ)在z中的結(jié)果轉(zhuǎn)換為01港谊。 有幾個(gè)可用的激活函數(shù),對(duì)于這個(gè)例子橙弱,我們可以使用一個(gè)名為 sigmoid [33] 的流行函數(shù)歧寺,返回 0 到 1 之間的實(shí)數(shù)值。

https://jorditorres.org/wp-content/uploads/2016/02/image046.png

看看公式棘脐,我們發(fā)現(xiàn)它將傾向于返回接近 0 或 1 的值成福。 如果輸入z足夠大且為正,則exp(-z)為零荆残,然后y為 1奴艾。 如果輸入z足夠大且為負(fù),則exp(-z)也會(huì)變?yōu)榇笳龜?shù)内斯,因此分母變大蕴潦,最終y變?yōu)?0像啼。 如果我們繪制函數(shù),它將如下所示:

https://jorditorres.org/wp-content/uploads/2016/02/image045.png

從這里我們已經(jīng)介紹了如何定義神經(jīng)元潭苞,但神經(jīng)網(wǎng)絡(luò)實(shí)際上是以不同方式互相連接忽冻,并使用不同激活函數(shù)的神經(jīng)元組合。 鑒于本書(shū)的范圍此疹,我不會(huì)涉及神經(jīng)網(wǎng)絡(luò)的所有擴(kuò)展僧诚,但我向你保證它真的令人興奮。

只是提到神經(jīng)網(wǎng)絡(luò)的一個(gè)特定情況(其中第 5 章基于)蝗碎,神經(jīng)元組織為層的形式湖笨,其中下層(輸入層)接收輸入,上層(輸出層)生成響應(yīng)值蹦骑。 神經(jīng)網(wǎng)絡(luò)可以有幾個(gè)中間層慈省,稱(chēng)為隱藏層。 表示這種情況的直觀方式是:

https://jorditorres.org/wp-content/uploads/2016/02/image049.gif

在這些網(wǎng)絡(luò)中眠菇,每層的神經(jīng)元與前一層的神經(jīng)元通信來(lái)接收信息边败,然后將其結(jié)果傳遞給下一層的神經(jīng)元。

如前所述捎废,除了Sigmoid之外還有更多的激活函數(shù)笑窜,每個(gè)激活函數(shù)具有不同的屬性。例如登疗,當(dāng)我們想要在輸出層將數(shù)據(jù)分類(lèi)為兩個(gè)以上的類(lèi)時(shí)怖侦,我們可以使用 Softmax [34] 激活函數(shù),它是 sigmoid 函數(shù)的泛化谜叹。 Softmax 能夠獲得每個(gè)類(lèi)的概率匾寝,因此它們的和為 1,最可能的結(jié)果是概率最高的結(jié)果荷腊。

一個(gè)簡(jiǎn)單的例子:Softmax

請(qǐng)記住艳悔,要解決的問(wèn)題是,給定輸入圖像女仰,我們得到它屬于某個(gè)數(shù)字的概率猜年。 例如,我們的模型可以預(yù)測(cè)疾忍,圖像 80% 是“9”乔外,但是有 5% 的機(jī)會(huì)為“8”(由于可疑性較低的痕跡),并且還給出一罩,一定的低概率為任何其他數(shù)字杨幼。 識(shí)別手寫(xiě)數(shù)字存在一些不確定性,我們無(wú)法以 100% 的置信度識(shí)別數(shù)字。 在這種情況下差购,概率分布使我們更好地了解我們對(duì)預(yù)測(cè)的信心四瘫。

因此,我們有一個(gè)輸出向量欲逃,其中包含不同輸出標(biāo)簽的概率分布找蜜,這是多余的。 這是一個(gè)具有 10 個(gè)概率值的向量稳析,每個(gè)概率值對(duì)應(yīng)于 0 到 9 的每個(gè)數(shù)字洗做,并且所有概率總和為 1。

如前所述彰居,我們通過(guò)使用激活函數(shù)為 softmax 的輸出層來(lái)實(shí)現(xiàn)此目的诚纸。 具有 softmax 函數(shù)的神經(jīng)元的輸出,取決于其層的其他神經(jīng)元的輸出裕菠,因?yàn)樗鼈兊乃休敵霰仨毧偤蜑?1。

softmax 函數(shù)有兩個(gè)主要步驟:首先闭专,計(jì)算屬于某個(gè)標(biāo)簽的圖像的“證據(jù)”奴潘,然后將證據(jù)轉(zhuǎn)換為每個(gè)可能標(biāo)簽的概率。

歸屬的證據(jù)

測(cè)量某個(gè)圖像屬于特定類(lèi)別/標(biāo)簽的證據(jù)影钉,通常的近似是計(jì)算像素強(qiáng)度的加權(quán)和画髓。 當(dāng)高強(qiáng)度的像素恰好不在給定類(lèi)中時(shí),該權(quán)重為負(fù)平委,如果該像素在該類(lèi)中頻繁出現(xiàn)奈虾,則該權(quán)重為正。

讓我們看一個(gè)圖形示例:假設(shè)一個(gè)數(shù)學(xué)“0”的學(xué)習(xí)模型(我們將看到以后如何學(xué)習(xí))廉赔。 此時(shí)肉微,我們將模型定義為“某事物”,其中包含了解數(shù)字是否屬于特定類(lèi)的信息蜡塌。 在這種情況下碉纳,我們選擇了如下所示的模型,其中紅色(或 b/n 版本的亮灰色)代表負(fù)例(也就是馏艾,減少對(duì)“0”中存在的那些像素的支持)劳曹,而藍(lán)色(b/n 版的深灰色)代表了正例±拍Γ看看它:

https://jorditorres.org/wp-content/uploads/2016/02/image050.png

想象一下28×28像素的白紙铁孵,并畫(huà)上“0”。 通常我們的零將繪制在藍(lán)色區(qū)域中(請(qǐng)記住房资,我們?cè)?code>20×20繪圖區(qū)域周?chē)粝铝艘恍┛臻g蜕劝,稍后將其居中)。

很明顯,如果我們的繪圖穿過(guò)紅色區(qū)域熙宇,很可能我們沒(méi)有繪制零鳖擒。 因此,使用一種度量標(biāo)準(zhǔn)烫止,獎(jiǎng)勵(lì)那些踩到藍(lán)色區(qū)域的像素蒋荚,并懲罰那些踩到紅色區(qū)域的像素,似乎是合理的馆蠕。

現(xiàn)在考慮“3”:很明顯期升,我們的模型的“0”的紅色區(qū)域?qū)土P它為“0”的概率。 但是如果參考模型是下面的那個(gè)互躬,通常形成“3”的像素將遵循藍(lán)色區(qū)域播赁; “0”的繪制也會(huì)進(jìn)入紅色區(qū)域。

https://jorditorres.org/wp-content/uploads/2016/02/image052.png

我希望看到這兩個(gè)例子的讀者理解吼渡,所解釋的近似如何讓我們估計(jì)哪張圖代表哪個(gè)數(shù)字容为。

下圖顯示了從 MNIST 數(shù)據(jù)集中學(xué)習(xí)的十個(gè)不同標(biāo)簽/類(lèi)的示例(從 Tensorflow [35] 的示例中提取)寺酪。 請(qǐng)記住坎背,紅色(亮灰色)表示負(fù)權(quán)重,藍(lán)色(深灰色)表示正值寄雀。

https://jorditorres.org/wp-content/uploads/2016/02/image054.png

以更正式的方式得滤,我們可以說(shuō)給出輸入x的類(lèi)i的證據(jù)表示為:

https://jorditorres.org/wp-content/uploads/2016/02/image056.png

其中i表示類(lèi)(在我們的情況下,介于 0 和 9 之間)盒犹,j是對(duì)輸入圖像求和的索引懂更。 最后,Wi表示上述權(quán)重急膀。

請(qǐng)記住沮协,一般來(lái)說(shuō),模型還包括一個(gè)表示偏置的額外參數(shù)卓嫂,增加了一些基本不確定性皂股。 在我們的情況下,公式最終就像這樣:

https://jorditorres.org/wp-content/uploads/2016/02/image058.png

對(duì)于每個(gè)i(在 0 和 9 之間)命黔,我們得到 784 個(gè)元素(28×28)的矩陣Wi呜呐,其中每個(gè)元素j乘以輸入圖像的相應(yīng)分量j,共有 784 個(gè)分量悍募,然后加上bi蘑辑。矩陣演算和索引的圖形視圖是這樣的:

https://jorditorres.org/wp-content/uploads/2016/02/image061.gif

歸屬概率

我們?cè)u(píng)論說(shuō),第二步是計(jì)算概率坠宴。 具體來(lái)說(shuō)洋魂,我們使用 softmax 函數(shù)將證據(jù)總和轉(zhuǎn)換為預(yù)測(cè)概率,表示為y

https://jorditorres.org/wp-content/uploads/2016/02/image062.png

請(qǐng)記住,輸出向量必須是和為 1 的概率函數(shù)副砍。 為了標(biāo)準(zhǔn)化每個(gè)成分衔肢,softmax 函數(shù)使用每個(gè)輸入的指數(shù)值,然后按如下方式對(duì)它們進(jìn)行標(biāo)準(zhǔn)化:

https://jorditorres.org/wp-content/uploads/2016/02/image064.png

使用指數(shù)時(shí)獲得的效果是權(quán)重的乘法效應(yīng)豁翎。 此外角骤,當(dāng)一個(gè)類(lèi)的證據(jù)很小時(shí),這個(gè)類(lèi)的支持由之前權(quán)重的一小部分減少心剥。 此外邦尊,softmax 對(duì)權(quán)重進(jìn)行歸一化,使它們總和為 1优烧,從而產(chǎn)生概率分布蝉揍。

這種函數(shù)的一個(gè)有趣的事實(shí)是,好的預(yù)測(cè)將有一個(gè)接近 1 的輸出值畦娄,而所有其他輸出將接近零又沾;在弱預(yù)測(cè)中,某些標(biāo)簽可能會(huì)顯示類(lèi)似的支持熙卡。

在 TensorFlow 中編程

在簡(jiǎn)要描述了算法做了什么來(lái)識(shí)別數(shù)字之后杖刷,我們可以在 TensorFlow 中實(shí)現(xiàn)它。 為此再膳,我們可以快速了解張量應(yīng)如何存儲(chǔ)我們的數(shù)據(jù)和模型參數(shù)挺勿。 為此曲横,下圖描述了數(shù)據(jù)結(jié)構(gòu)及其關(guān)系(來(lái)幫助讀者輕松回憶我們的每個(gè)問(wèn)題):

https://jorditorres.org/wp-content/uploads/2016/02/image066.png

首先喂柒,我們創(chuàng)建兩個(gè)變量來(lái)包含權(quán)重W和偏置b

W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

這些變量是使用tf.Variable函數(shù)和變量的初始值創(chuàng)建的;在這種情況下禾嫉,我們用包含零的常數(shù)張量初始化張量灾杰。

我們看到W的形狀為[Dimension(784), Dimension(10)],由其參數(shù)定義熙参,常數(shù)張量tf.zerosW一樣為[784,10]艳吠。偏置b也是一樣,由其參數(shù)將形狀規(guī)定為[Dimension(10)]孽椰。

矩陣W具有該大小昭娩,因?yàn)槲覀兿胍獮?10 個(gè)可能的數(shù)字中的每一個(gè)乘以 784 個(gè)位置的圖像向量,并在與b相加之后產(chǎn)生一定數(shù)量的證據(jù)黍匾。

在使用 MNIST 進(jìn)行研究的情況下栏渺,我們還創(chuàng)建了二維張量來(lái)保存x點(diǎn)的信息,使用以下代碼行??:

x = tf.placeholder("float", [None, 784])

張量x將用于存儲(chǔ) MNIST 圖像锐涯,作為 784 個(gè)浮點(diǎn)向量(我們使用None指示維度可以是任何大锌恼铩;在我們的例子中它將等于學(xué)習(xí)過(guò)程中包含的元素?cái)?shù)量)。

現(xiàn)在我們定義了張量霎终,我們可以實(shí)現(xiàn)我們的模型滞磺。 為此,TensorFlow 提供了幾個(gè)操作莱褒,即tf.nn.softmax(logits, name=None)击困。它是其中一個(gè)可用的操作,實(shí)現(xiàn)了前面描述的 softmax 函數(shù)保礼。 參數(shù)必須是張量沛励,并且名稱(chēng)可選。 該函數(shù)返回類(lèi)型和形狀與傳遞的參數(shù)張量相同的張量炮障。

在我們的例子中袭厂,我們?yōu)檫@個(gè)函數(shù)提供了圖像向量x乘以權(quán)重矩陣W加上b的結(jié)果張量:

y = tf.nn.softmax(tf.matmul(x,W) + b)

一旦指定了模型實(shí)現(xiàn)乡数,我們就可以使用迭代訓(xùn)練算法,指定必要的代碼來(lái)獲得權(quán)重W和偏置b。 對(duì)于每次迭代颁虐,訓(xùn)練算法獲得訓(xùn)練數(shù)據(jù),應(yīng)用神經(jīng)網(wǎng)絡(luò)并將獲得的結(jié)果與預(yù)期結(jié)果進(jìn)行比較枫笛。

要確定模型何時(shí)足夠好法精,我們必須定義“足夠好”的含義。 正如在前面的章節(jié)中所看到的系馆,通常的方法是定義相反的東西:模型使用損失函數(shù)的“壞”的程度送漠。 在這種情況下,目標(biāo)是獲得使函數(shù)最小的Wb的值由蘑,它指示模型“壞”的程度闽寡。

結(jié)果輸出與訓(xùn)練數(shù)據(jù)的預(yù)期輸出之間的誤差有不同的度量標(biāo)準(zhǔn)。 一個(gè)常見(jiàn)的度量是均方誤差或平方歐幾里德距離尼酿,這是以前見(jiàn)過(guò)的爷狈。 盡管如此,一些研究在神經(jīng)網(wǎng)絡(luò)中為此目的提出了其他指標(biāo)裳擎,例如在我們的例子中使用的交叉熵誤差涎永。 此度量標(biāo)準(zhǔn)的計(jì)算方式如下:

https://jorditorres.org/wp-content/uploads/2016/02/image068.png

其中y是概率的預(yù)測(cè)分布,y'是從訓(xùn)練數(shù)據(jù)集的標(biāo)簽中獲得的實(shí)際分布鹿响。 我們不會(huì)詳細(xì)討論交叉熵背后的數(shù)學(xué)及其在神經(jīng)網(wǎng)絡(luò)中的位置羡微,因?yàn)樗h(yuǎn)比本書(shū)的預(yù)期范圍復(fù)雜得多;只是表明當(dāng)兩個(gè)分布相同時(shí)有最小值惶我。 同樣妈倔,如果讀者想要了解此函數(shù)的細(xì)節(jié),我們建議閱讀神經(jīng)網(wǎng)絡(luò)和深度學(xué)習(xí) [36]指孤。

要實(shí)現(xiàn)交叉熵度量启涯,我們需要一個(gè)新的占位符來(lái)表示正確的標(biāo)簽:

y_ = tf.placeholder("float", [None,10])

用這個(gè)占位符贬堵,我們可以使用以下代碼行實(shí)現(xiàn)交叉熵,代表我們的損失函數(shù):

cross_entropy = -tf.reduce_sum(y_*tf.log(y))

首先结洼,我們使用 TensorFlow 中的內(nèi)置函數(shù)tf.log()計(jì)算每個(gè)元素y的對(duì)數(shù)黎做,然后我們將它們乘以每個(gè)y_元素。 最后松忍,使用tf.reduce_sum蒸殿,我們對(duì)張量的所有元素求和(稍后我們將看到圖像以批量的形式訪問(wèn),在這種情況下鸣峭,交叉熵的值對(duì)應(yīng)于圖像批量y而不是單個(gè)圖像)宏所。

在迭代中,一旦確定了樣本的誤差摊溶,我們必須更正模型(在我們的例子中是修改參數(shù)Wb)來(lái)減少下一次迭代中計(jì)算和預(yù)期輸出之間的差異爬骤。

最后,它仍然只是指定了這個(gè)迭代式最小化過(guò)程莫换。 在神經(jīng)網(wǎng)絡(luò)中有幾種用于此目的的算法霞玄;我們將使用反向傳播(誤差向后傳播)算法,并且如其名稱(chēng)所示拉岁,它向后傳播在輸出處獲得的誤差坷剧,來(lái)重新計(jì)算W的權(quán)重,尤其是對(duì)于多層神經(jīng)網(wǎng)絡(luò)很重要喊暖。

該方法與先前看到的梯度下降方法一起使用惫企,該方法使用交叉熵?fù)p失函數(shù),允許我們計(jì)算每次迭代時(shí)參數(shù)必須改變多少陵叽,以便在每個(gè)時(shí)刻使用可用的本地信息來(lái)減少誤差狞尔。 在我們的例子中,直觀地說(shuō)咨跌,它包括在每次迭代時(shí)稍微改變權(quán)重W(這一點(diǎn)由學(xué)習(xí)率超參數(shù)表示沪么,表示變化的速度)來(lái)減少錯(cuò)誤硼婿。

由于在我們的例子中我們只有一層神經(jīng)網(wǎng)絡(luò)锌半,我們不會(huì)進(jìn)入反向傳播方法。 只需記得 TensorFlow 知道整個(gè)計(jì)算圖寇漫,允許它應(yīng)用優(yōu)化算法來(lái)找到訓(xùn)練模型的訓(xùn)練函數(shù)的正確梯度刊殉。

因此,在我們使用 MNIST 圖像的示例中州胳,以下代碼行表明我們使用反向傳播算法和梯度下降算法來(lái)最小化交叉熵记焊,學(xué)習(xí)率為 0.01:

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

到這里之后,我們已經(jīng)指定了所有問(wèn)題栓撞,我們可以通過(guò)實(shí)例化tf.Session()來(lái)開(kāi)始計(jì)算遍膜,它負(fù)責(zé)在系統(tǒng)碗硬,CPU 或 GPU 上的可用設(shè)備中執(zhí)行 TensorFlow 操作:

sess = tf.Session()

接下來(lái),我們可以執(zhí)行初始化所有變量的操作:

sess.run(tf.initialize_all_variables())

從現(xiàn)在開(kāi)始瓢颅,我們可以開(kāi)始訓(xùn)練我們的模型恩尾。 執(zhí)行時(shí),train_step的返回參數(shù)將梯度下降應(yīng)用于所涉及的參數(shù)挽懦。 因此翰意,可以通過(guò)重復(fù)執(zhí)行train_step來(lái)實(shí)現(xiàn)模型的訓(xùn)練。 假設(shè)我們要迭代 1000 次train_step信柿;我們必須指定以下代碼行:

for i in range(1000):
   batch_xs, batch_ys = mnist.train.next_batch(100)
   sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

循環(huán)內(nèi)的第一行指定冀偶,對(duì)于每次迭代,挑選從訓(xùn)練數(shù)據(jù)集中隨機(jī)采樣的 100 個(gè)數(shù)據(jù)輸入的批量渔嚷。 我們可以在每次迭代時(shí)使用所有訓(xùn)練數(shù)據(jù)进鸠,但為了使第一個(gè)示例更加靈活,我們每次都使用一個(gè)小樣本形病。 第二行表示之前獲得的輸入必須提供給相應(yīng)的占位符堤如。

最后,基于梯度下降的機(jī)器學(xué)習(xí)算法可以利用 TensorFlow 自動(dòng)微分的功能窒朋。 TensorFlow 用戶只需定義預(yù)測(cè)模型的計(jì)算架構(gòu)搀罢,將其與目標(biāo)函數(shù)組合,然后只需添加數(shù)據(jù)即可侥猩。

TensorFlow 已經(jīng)管理了學(xué)習(xí)過(guò)程背后的相關(guān)微分榔至。 當(dāng)執(zhí)行minimize()方法時(shí),TensorFlow 識(shí)別損失函數(shù)所依賴的變量集欺劳,并計(jì)算每個(gè)變量的梯度唧取。 如果你想知道如何實(shí)現(xiàn)微分,可以查看ops/gradients.py文件 [37]划提。

模型評(píng)估

訓(xùn)練后必須評(píng)估模型枫弟,來(lái)查看有多“好”(或多“壞”)。 例如鹏往,我們可以計(jì)算預(yù)測(cè)中命中和未命中的百分比淡诗,看看哪些例子是正確預(yù)測(cè)的。 在前面的章節(jié)中伊履,我們看到tf.argmax(y, 1)函數(shù)韩容,根據(jù)張量的給定軸返回最高值的索引。 實(shí)際上唐瀑,tf.argmax(y, 1)是對(duì)于每個(gè)輸入的群凶,概率最高的標(biāo)簽,而 tf.argmax(y_, 1)是正確標(biāo)簽哄辣。 使用tf.equal方法请梢,我們可以比較我們的預(yù)測(cè)是否與正確的標(biāo)簽重合:

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))

指令返回布爾列表赠尾。 要確定哪些預(yù)測(cè)部分是正確的,我們可以將值轉(zhuǎn)換為數(shù)值變量(浮點(diǎn))并執(zhí)行以下操作:

accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

例如毅弧,[True, False, True, True]將變?yōu)?code>[1, 0, 1, 1]萍虽,平均值將為 0.75,表示準(zhǔn)確率形真。 現(xiàn)在我們可以使用mnist.test作為feed_dict參數(shù)來(lái)查詢我們的測(cè)試數(shù)據(jù)集的準(zhǔn)確率:

print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

我的大約為 91%杉编。 這些結(jié)果好嗎? 我認(rèn)為它們太棒了咆霜,因?yàn)檫@意味著讀者已經(jīng)能夠使用 TensorFlow 編程并執(zhí)行第一個(gè)神經(jīng)網(wǎng)絡(luò)邓馒。

另一個(gè)問(wèn)題是其他模型可能提供更好的準(zhǔn)確性,在下一章中介紹包含更多層的神經(jīng)網(wǎng)絡(luò)蛾坯。

讀者將在本書(shū) github [38] 的文件RedNeuronalSimple.py中找到本章中使用的全部代碼光酣。 為了提供它的全局視圖,我將把它放在一起:

import input_data
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)

import tensorflow as tf

x = tf.placeholder("float", [None, 784])
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))

matm=tf.matmul(x,W)
y = tf.nn.softmax(tf.matmul(x,W) + b)
y_ = tf.placeholder("float", [None,10])

cross_entropy = -tf.reduce_sum(y_*tf.log(y))
train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

sess = tf.Session()
sess.run(tf.initialize_all_variables())

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
    correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))
    print sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels})

5. TensorFlow 中的多層神經(jīng)網(wǎng)絡(luò)

在本章中脉课,我將與讀者一起編寫(xiě)一個(gè)簡(jiǎn)單的深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)救军,該網(wǎng)絡(luò)使用與前一章相同的 MNIST 數(shù)字識(shí)別問(wèn)題。

隨著我的前進(jìn)倘零,深度學(xué)習(xí)神經(jīng)網(wǎng)絡(luò)由疊在一起的多個(gè)層組成唱遭。 具體來(lái)說(shuō),在本章中我們將構(gòu)建一個(gè)卷積網(wǎng)絡(luò)呈驶,這是深度學(xué)習(xí)的典型例子拷泽。 卷?yè)P(yáng)神經(jīng)網(wǎng)絡(luò)由 Yann LeCunn 等人于 1998 年推出并推廣。 這些卷積網(wǎng)絡(luò)最近引領(lǐng)了圖像識(shí)別領(lǐng)域的最新技術(shù)袖瞻;例如:在我們的數(shù)字識(shí)別案例中司致,它們的準(zhǔn)確度高于 99%。

在本章的其余部分聋迎,我將以示例代碼為主脂矫,我將解釋這些網(wǎng)絡(luò)的兩個(gè)最重要的概念:卷積和池化,而不輸入?yún)?shù)的細(xì)節(jié)霉晕,鑒于本書(shū)的介紹性質(zhì)庭再。 但是,讀者將能夠運(yùn)行所有代碼娄昆,我希望它能讓你了解卷積網(wǎng)絡(luò)背后的通用思想佩微。

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

卷積神經(jīng)網(wǎng)絡(luò)(也稱(chēng)為 CNN 或 CovNets)是深度學(xué)習(xí)的一個(gè)特例缝彬,并且在計(jì)算機(jī)視覺(jué)領(lǐng)域產(chǎn)生了重大影響萌焰。

CNN 的典型特征是它們幾乎總是將圖像作為輸入,這產(chǎn)生了更有效的實(shí)現(xiàn)并且減少所需參數(shù)的數(shù)量谷浅。 讓我們看看我們的 MNIST 數(shù)字識(shí)別示例:在讀取 MNIST 數(shù)據(jù)并使用 TensorFlow 定義占位符之后扒俯,就像我們?cè)谏弦粋€(gè)示例中所做的那樣:

import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

import tensorflow as tf

x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])

我們可以重建輸入數(shù)據(jù)圖像的原始形狀奶卓。 我們可以這樣做:

x_image = tf.reshape(x, [-1,28,28,1])

這里我們將輸入形狀更改為 4D 張量,第二維和第三維對(duì)應(yīng)于圖像的寬度和高度撼玄,而最后一維對(duì)應(yīng)于顏色通道的數(shù)量夺姑,在這種情況下為 1。

通過(guò)這種方式掌猛,我們可以將神經(jīng)網(wǎng)絡(luò)的輸入視為大小為28×28的二維空間盏浙,如圖所示:

https://jorditorres.org/wp-content/uploads/2016/02/image072-300x282.png

定義卷積神經(jīng)網(wǎng)絡(luò)有兩個(gè)基本原則:濾波器和特征映射。 這些原則可以表示為特定的神經(jīng)元分組荔茬,我們將很快看到废膘。 但首先,鑒于它們?cè)?CNN 中的重要性慕蔚,我們將簡(jiǎn)要介紹這兩個(gè)原則丐黄。

直覺(jué)上,我們可以說(shuō)卷積層的主要目的是檢測(cè)圖像中的特征或視覺(jué)特征孔飒,考慮邊緣灌闺,線條,顏色斑點(diǎn)等坏瞄。 這是由我們剛剛討論過(guò)的桂对,連接輸入層的隱藏層來(lái)處理的。 在我們感興趣的 CNN 的案例中鸠匀,輸入數(shù)據(jù)沒(méi)有完全連接到第一個(gè)隱藏層的神經(jīng)元接校;這只發(fā)生在輸入神經(jīng)元中的一個(gè)小型局部空間中,輸入神經(jīng)元存儲(chǔ)圖像像素值狮崩。 這可以看作:

https://jorditorres.org/wp-content/uploads/2016/02/image074.png

更確切地說(shuō)蛛勉,在給定的示例中,隱藏層的每個(gè)神經(jīng)元與輸入層的5×5小區(qū)域(因此是 25 個(gè)神經(jīng)元)連接睦柴。

我們可以認(rèn)為這是一個(gè)大小為5×5的窗口诽凌,它滑過(guò)包含輸入圖像的整個(gè)28×28大小的輸入層。 窗口滑過(guò)整個(gè)神經(jīng)元層坦敌。 對(duì)于窗口的每個(gè)位置侣诵,隱藏層中都有一個(gè)處理該信息的神經(jīng)元。

我們可以通過(guò)假設(shè)窗口從圖像的左上角開(kāi)始來(lái)可視化狱窘;這將信息提供給隱藏層的第一個(gè)神經(jīng)元杜顺。 然后窗口向右滑動(dòng)一個(gè)像素;我們將這個(gè)5×5區(qū)域與隱藏層中的第二個(gè)神經(jīng)元連接起來(lái)蘸炸。 我們繼續(xù)這樣躬络,直到整個(gè)空間從上到下,從左到右被窗口覆蓋搭儒。

https://jorditorres.org/wp-content/uploads/2016/02/image076.png

分析我們提出的具體案例穷当,我們觀察到提茁,給定一個(gè)大小為28×28的輸入圖像和一個(gè)大小為5×5的窗口,在第一個(gè)隱藏層中產(chǎn)生了24×24的神經(jīng)元馁菜,因?yàn)槲覀冎荒苓@樣做茴扁,在觸及輸入圖像的右下邊緣之前,將窗口向下移動(dòng) 23 次汪疮,向右移動(dòng) 23 次峭火。 這假設(shè)窗口每次只移動(dòng) 1 個(gè)像素,因此新窗口與剛剛前進(jìn)的舊窗口重疊智嚷。

但是躲胳,可以在卷積層中一次移動(dòng)多于 1 個(gè)像素,該參數(shù)稱(chēng)為stride(步長(zhǎng))纤勒。 另一個(gè)擴(kuò)展是用零(或其他值)填充邊緣坯苹,以便窗口可以在圖像的邊緣上滑動(dòng),這可以產(chǎn)生更好的結(jié)果摇天。 控制此功能的參數(shù)稱(chēng)為padding(填充)[39]粹湃,你可以使用該參數(shù)確定填充的大小。 鑒于本書(shū)的介紹性質(zhì)泉坐,我們不會(huì)進(jìn)一步詳細(xì)介紹這兩個(gè)參數(shù)为鳄。

鑒于我們的研究案例,并遵循前一章的形式腕让,我們將需要一個(gè)偏置值b和一個(gè)5×5的權(quán)重矩陣W來(lái)連接隱層和輸入層的神經(jīng)元孤钦。CNN的一個(gè)關(guān)鍵特性是,該權(quán)重矩陣W和偏置b在隱藏層中的所有神經(jīng)元之間共享纯丸;我們對(duì)隱藏層中的神經(jīng)元使用相同的Wb偏形。 在我們的情況下,這是24×24(576)個(gè)神經(jīng)元觉鼻。 讀者應(yīng)該能夠看到俊扭,與完全連接的神經(jīng)網(wǎng)絡(luò)相比,這大大減少了人們需要的權(quán)重參數(shù)坠陈。 具體而言萨惑,由于共享權(quán)重矩陣W,這從 14000(5x5x24x24)減少到僅 25(5x5)仇矾。

這個(gè)共享矩陣W和偏置b通常在 CNN 的上下文中稱(chēng)為核或過(guò)濾器庸蔼。 這些過(guò)濾器類(lèi)似于用于修飾圖像的圖像處理程序,在我們的例子中用于查找微分特征贮匕。 我建議查看 GIMP [40] 手冊(cè)中的示例姐仅,以便了解卷積過(guò)程的工作原理。

矩陣和偏置定義了核。 核只檢測(cè)圖像中的某個(gè)相關(guān)特征萍嬉,因此建議使用多個(gè)核乌昔,每個(gè)核對(duì)應(yīng)我們想要檢測(cè)的每個(gè)特征隙疚。 這意味著 CNN 中的完整卷積層由幾個(gè)核組成壤追。 表示幾個(gè)核的常用方法如下:

https://jorditorres.org/wp-content/uploads/2016/02/image078.png

第一個(gè)隱藏層由幾個(gè)核組成。 在我們的例子中供屉,我們使用 32 個(gè)核行冰,每個(gè)核由5×5的權(quán)重矩陣W和偏置b定義,偏置b也在隱層的神經(jīng)元之間共享伶丐。

為了簡(jiǎn)化代碼,我定義了以下兩個(gè)與權(quán)重矩陣W和偏置b相關(guān)的函數(shù):

def weight_variable(shape):
    initial = tf.truncated_normal(shape, stddev=0.1)
    return tf.Variable(initial)

def bias_variable(shape):
    initial = tf.constant(0.1, shape=shape)
    return tf.Variable(initial)

在沒(méi)有詳細(xì)說(shuō)明的情況下,習(xí)慣上用一些隨機(jī)噪聲初始化權(quán)重荆姆,偏置值略微為正忱嘹。

除了我們剛才描述的卷積層之外,通常卷積層后面跟著一個(gè)所謂的池化層录别。 池化層簡(jiǎn)單地壓縮來(lái)自卷積層的輸出朽色,并創(chuàng)建卷積層輸出的信息的緊湊版本。 在我們的示例中组题,我們將使用卷積層的2×2區(qū)域葫男,我們使用池化將它的數(shù)據(jù)匯總到單個(gè)點(diǎn):

https://jorditorres.org/wp-content/uploads/2016/02/image080.png

有幾種方法可以執(zhí)行池化來(lái)壓縮信息;在我們的示例中崔列,我們將使用名為最大池化的方法梢褐。 通過(guò)僅保留所考慮的2×2區(qū)域中的最大值來(lái)壓縮信息。

如上所述赵讯,卷積層由許多核組成盈咳,因此,我們將分別對(duì)每個(gè)核應(yīng)用最大池化边翼。 通常猪贪,可以有多層池化和卷積:

https://jorditorres.org/wp-content/uploads/2016/02/image082.png

這使24×24的卷積層結(jié)果,被對(duì)應(yīng)12×12的最大池化層轉(zhuǎn)換為12×12的空間讯私,其中每個(gè)塊來(lái)源于2×2的區(qū)域热押。 請(qǐng)注意,與卷積層不同斤寇,數(shù)據(jù)是平鋪的桶癣,而不是由滑動(dòng)窗口創(chuàng)建的。

直觀上娘锁,我們可以解釋最大池化牙寞,來(lái)確定特定特征是否存在于圖像中的任何位置,特征的確切位置不如對(duì)于其他特征的相對(duì)位置重要。

模型的實(shí)現(xiàn)

在本節(jié)中间雀,我將基于可在 TensorFlow [41] 網(wǎng)站上找到的高級(jí)示例(Deep MNIST for experts)悔详,提供編寫(xiě) CNN 的示例代碼。 正如我在開(kāi)始時(shí)所說(shuō)的那樣惹挟,參數(shù)的許多細(xì)節(jié)需要處理和理論方法茄螃,比本書(shū)中給出的更詳細(xì)。 因此连锯,我將僅概述代碼归苍,而不涉及 TensorFlow 參數(shù)的許多細(xì)節(jié)。

正如我們已經(jīng)看到的运怖,我們必須為卷積和池化層定義幾個(gè)參數(shù)拼弃。 我們將在每個(gè)維度中使用大小為 1 的步幅(這是滑動(dòng)窗口的步長(zhǎng))和零填充模型。 我們將應(yīng)用的池化是2×2的最大池化摇展。 與上面類(lèi)似吻氧,我建議使用以下兩個(gè)通用函數(shù)來(lái)編寫(xiě)涉及卷積和最大池化的更清晰的代碼。

def conv2d(x, W):
    return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')


def max_pool_2x2(x):
    return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

現(xiàn)在是時(shí)候?qū)崿F(xiàn)第一個(gè)卷積層咏连,然后是池化層盯孙。 在我們的示例中,我們有 32 個(gè)過(guò)濾器捻勉,每個(gè)過(guò)濾器的窗口大小為5×5镀梭。 我們必須定義一個(gè)張量,來(lái)保持這個(gè)權(quán)重矩陣W的形狀為[5,5,1,32]:前兩個(gè)維度是窗口的大小踱启,第三個(gè)是通道的數(shù)量报账,在我們的例子中為 1 。 最后一個(gè)定義了我們想要使用的過(guò)濾器數(shù)量埠偿。 此外透罢,我們還需要為 32 個(gè)權(quán)重矩陣中的每一個(gè)定義偏置。 使用先前定義的函數(shù)冠蒋,我們可以在 TensorFlow 中編寫(xiě)它羽圃,如下所示:

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

ReLU(整流線性單元)激活函數(shù)最近成為深度神經(jīng)網(wǎng)絡(luò)隱藏層中使用的默認(rèn)激活函數(shù)。 這個(gè)簡(jiǎn)單的函數(shù)返回max(0, x)抖剿,因此它為負(fù)值返回 0朽寞,否則返回x。 在我們的示例中斩郎,我們將在卷積層之后的隱藏層中使用此激活函數(shù)脑融。

我們編寫(xiě)的代碼首先將卷積應(yīng)用于輸入圖像x_image,它在 2D 張量W_conv1中缩宜,返回圖像卷積的結(jié)果肘迎,然后加上偏置甥温,最終應(yīng)用 ReLU 激活函數(shù)。 最后一步妓布,我們將最大池化應(yīng)用于輸出:

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

在構(gòu)建深度神經(jīng)網(wǎng)絡(luò)時(shí)姻蚓,我們可以將多個(gè)層疊在一起。 為了演示如何執(zhí)行此操作匣沼,我將創(chuàng)建一個(gè)帶有 64 個(gè)過(guò)濾器和5×5窗口的輔助卷積層狰挡。 在這種情況下,我們必須傳遞 32 作為我們需要的通道數(shù)肛著,因?yàn)樗乔耙粚拥妮敵龃笮圆兵。?/p>

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

由于我們將5×5窗口應(yīng)用于步長(zhǎng)為 1 的12×12空間跺讯,因此卷積的結(jié)果輸出具有8×8的維數(shù)枢贿。 下一步是將一個(gè)全連接的層添加到8×8輸出,然后將其輸入到最后的 softmax 層刀脏,就像我們?cè)谇耙徽轮兴龅哪菢印?/p>

我們將使用 1024 個(gè)神經(jīng)元的一層局荚,允許我們處理整個(gè)圖像。 權(quán)重和偏置的張量如下:

W_fc1 = weight_variable([8 * 8 * 64, 1024])
b_fc1 = bias_variable([1024])

請(qǐng)記住愈污,張量的第一個(gè)維度表示來(lái)自第二個(gè)卷積層的大小為8x8的 64 個(gè)過(guò)濾器耀态,而第二個(gè)參數(shù)是層中神經(jīng)元的數(shù)量,我們可以自由選擇(在我們的例子中是 1024)暂雹。

現(xiàn)在首装,我們想將張量展開(kāi)為向量。 我們?cè)谇耙徽轮锌吹胶脊颍瑂oftmax 需要將向量形式的展開(kāi)圖像作為輸入仙逻。 這通過(guò)將權(quán)重矩陣W_fc1與展開(kāi)向量相乘,加上偏置b_fc1涧尿,再應(yīng)用 ReLU 激活函數(shù)來(lái)實(shí)現(xiàn):

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])

h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

下一步將使用稱(chēng)為 dropout 的技術(shù)減少神經(jīng)網(wǎng)絡(luò)中的有效參數(shù)量系奉。 這包括刪除節(jié)點(diǎn)及其傳入和傳出連接。 丟棄和保留哪些神經(jīng)元是隨機(jī)決定的姑廉。 為了以一致的方式執(zhí)行此操作缺亮,我們將在代碼中為丟棄或保留的神經(jīng)元分配概率。

在沒(méi)有太多細(xì)節(jié)的情況下桥言,dropout 降低了模型的過(guò)擬合風(fēng)險(xiǎn)萌踱。 當(dāng)隱藏層具有大量神經(jīng)元并因此可以產(chǎn)生非常富有表現(xiàn)力的模型時(shí),這可能發(fā)生号阿;在這種情況下并鸵,可能會(huì)對(duì)隨機(jī)噪聲(或誤差)建模。 這被稱(chēng)為過(guò)擬合倦西,如果與輸入的維度相比能真,模型具有大量參數(shù),則更有可能。 最好是避免這種情況粉铐,因?yàn)檫^(guò)擬合的模型具有較差的預(yù)測(cè)表現(xiàn)疼约。

在我們的模型中,我們應(yīng)用 dropout蝙泼,它包括在最終的 softmax 層之前使用 dropout 函數(shù) tf.nn.dropout程剥。 為此,我們構(gòu)造一個(gè)占位符來(lái)存儲(chǔ)在 dropout 期間保留神經(jīng)元的概率:

keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

最后汤踏,我們將 softmax 層添加到我們的模型中织鲸,就像前一章中所做的那樣。 請(qǐng)記住溪胶,sofmax 返回輸入屬于每個(gè)類(lèi)的概率(在我們的例子中為數(shù)字)搂擦,以便總概率加起來(lái)為 1。 softmax 層代碼如下:

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

模型的訓(xùn)練和評(píng)估

我們現(xiàn)在通過(guò)調(diào)整卷積層和及全連接層中的所有權(quán)重哗脖,來(lái)準(zhǔn)備訓(xùn)練我們剛剛定義的模型瀑踢,并獲得我們的帶標(biāo)簽的圖像的預(yù)測(cè)。 如果我們想知道模型的執(zhí)行情況才避,我們必須遵循上一章中的示例橱夭。

以下代碼與前一章中的代碼非常相似,但有一個(gè)例外:我們用 ADAM 優(yōu)化器替換梯度下降優(yōu)化器桑逝,因?yàn)樵撍惴▽?shí)現(xiàn)了不同的優(yōu)化器棘劣,根據(jù)文獻(xiàn) [42],它具有某些優(yōu)點(diǎn)楞遏。

我們還需要在feed_dict參數(shù)中包含附加參數(shù)keep_prob茬暇,該參數(shù)控制我們之前討論過(guò)的 dropout 層的概率。

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

sess = tf.Session()

sess.run(tf.initialize_all_variables())
for i in range(20000):
  batch = mnist.train.next_batch(50)
  if i%100 == 0:
     train_accuracy = sess.run( accuracy, feed_dict={x:batch[0], y_: batch[1], keep_prob: 1.0})
     print("step %d, training accuracy %g"%(i, train_accuracy))
  sess.run(train_step,feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"% sess.run(accuracy, feed_dict={ x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

與之前的模型一樣橱健,整個(gè)代碼可以在本書(shū)的 Github 頁(yè)面上找到而钞,可以驗(yàn)證該模型的準(zhǔn)確率達(dá)到 99.2%。

以下是使用 TensorFlow 構(gòu)建拘荡,訓(xùn)練和評(píng)估深度神經(jīng)網(wǎng)絡(luò)的簡(jiǎn)要介紹臼节。 如果讀者設(shè)法運(yùn)行提供的代碼,他或她已經(jīng)注意到該網(wǎng)絡(luò)的訓(xùn)練時(shí)間明顯長(zhǎng)于前幾章的訓(xùn)練時(shí)間珊皿;你可以想象网缝,擁有更多層的網(wǎng)絡(luò)需要花費(fèi)更長(zhǎng)的時(shí)間來(lái)訓(xùn)練。 我建議你閱讀下一章蟋定,其中解釋了如何使用 GPU 進(jìn)行訓(xùn)練粉臊,這將減少你的訓(xùn)練時(shí)間。

本章的代碼可以在本書(shū) github 頁(yè)面 [43] 的CNN.py中找到驶兜,用于研究目的的代碼在下面:

import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)
import tensorflow as tf

x = tf.placeholder("float", shape=[None, 784])
y_ = tf.placeholder("float", shape=[None, 10])

x_image = tf.reshape(x, [-1,28,28,1])
print "x_image="
print x_image

def weight_variable(shape):
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)

def bias_variable(shape):
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)

def conv2d(x, W):
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')

def max_pool_2x2(x):
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])

h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)

W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])

h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)

W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])

h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)

keep_prob = tf.placeholder("float")
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)

W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])

y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)

cross_entropy = -tf.reduce_sum(y_*tf.log(y_conv))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float"))

sess = tf.Session()

sess.run(tf.initialize_all_variables())

for i in range(200):
   batch = mnist.train.next_batch(50)
   if i%10 == 0:
     train_accuracy = sess.run( accuracy, feed_dict={ x:batch[0], y_: batch[1], keep_prob: 1.0})
     print("step %d, training accuracy %g"%(i, train_accuracy))
   sess.run(train_step,feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})

print("test accuracy %g"% sess.run(accuracy, feed_dict={ 
       x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

6. 并行

2015 年 11 月發(fā)布的第一個(gè) TensorFlow 軟件包扼仲,已準(zhǔn)備好在具有可用 GPU 的服務(wù)器上運(yùn)行远寸,并同時(shí)在其中執(zhí)行訓(xùn)練操作。 2016 年 2 月屠凶,更新添加了分布式和并行化處理的功能驰后。

在這個(gè)簡(jiǎn)短的章節(jié)中,我將介紹如何使用 GPU矗愧。 對(duì)于那些想要了解這些設(shè)備如何工作的讀者灶芝,有些參考文獻(xiàn)將在上一節(jié)中給出。但是唉韭,鑒于本書(shū)的介紹性夜涕,我不會(huì)詳細(xì)介紹分布式版本,但對(duì)于那些感興趣的讀者属愤,一些參考將在上一節(jié)中給出女器。

帶有 GPU 的執(zhí)行環(huán)境

支持 GPU 的 TensorFlow 軟件包需要 CudaToolkit 7.0 和 CUDNN 6.5 V2。 對(duì)于安裝環(huán)境春塌,我們建議訪問(wèn) cuda 安裝 [44] 網(wǎng)站晓避,為了不會(huì)深入細(xì)節(jié)簇捍,同時(shí)信息也是最新的只壳。

在 TensorFlow 中引用這些設(shè)備的方法如下:

  • /cpu:0:引用服務(wù)器的 CPU。
  • /gpu:0:服務(wù)器的 GPU(如果只有一個(gè)可用)暑塑。
  • /gpu:1:服務(wù)器的第二個(gè) GPU吼句,依此類(lèi)推。

要知道我們的操作和張量分配在哪些設(shè)備中事格,我們需要?jiǎng)?chuàng)建一個(gè)sesion惕艳,選項(xiàng)log_device_placementTrue。 我們?cè)谙旅娴睦又锌吹剿?/p>

import tensorflow as tf
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)

sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
printsess.run(c)

當(dāng)讀者在計(jì)算機(jī)中測(cè)試此代碼時(shí)驹愚,應(yīng)出現(xiàn)類(lèi)似的輸出:

. . .
Device mapping:
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c, pci bus id: 0000:08:00.0
. . .
b: /job:localhost/replica:0/task:0/gpu:0
a: /job:localhost/replica:0/task:0/gpu:0
MatMul: /job:localhost/replica:0/task:0/gpu:0
…
[[ 22.28.]
[ 49.64.]]
…

此外远搪,使用操作的結(jié)果,它通知我們每個(gè)部分的執(zhí)行位置逢捺。

如果我們想要在特定設(shè)備中執(zhí)行特定操作谁鳍,而不是讓系統(tǒng)自動(dòng)選擇設(shè)備,我們可以使用變量tf.device來(lái)創(chuàng)建設(shè)備上下文劫瞳,因此所有操作都在上下文將分配相同的設(shè)備倘潜。

如果我們?cè)谙到y(tǒng)中擁有更多 GPU,則默認(rèn)情況下將選擇具有較低標(biāo)識(shí)符的 GPU志于。 如果我們想要在不同的 GPU 中執(zhí)行操作涮因,我們必須明確指定它。 例如伺绽,如果我們希望先前的代碼在 GPU#2 中執(zhí)行养泡,我們可以使用tf.device('/gpu:2')嗜湃,如下所示:

import tensorflow as tf

with tf.device('/gpu:2'):
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3], name='a')
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2], name='b')
c = tf.matmul(a, b)
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
printsess.run(c)

多個(gè) GPU 的并行

如果我們有更多的 GPU,通常我們希望一起使用它們來(lái)并行地解決同樣的問(wèn)題澜掩。 為此净蚤,我們可以構(gòu)建我們的模型,來(lái)在多個(gè) GPU 之間分配工作输硝。 我們?cè)谙乱粋€(gè)例子中看到它:

import tensorflow as tf

c = []
for d in ['/gpu:2', '/gpu:3']:
with tf.device(d):
a = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[2, 3])
b = tf.constant([1.0, 2.0, 3.0, 4.0, 5.0, 6.0], shape=[3, 2])
c.append(tf.matmul(a, b))
with tf.device('/cpu:0'):
sum = tf.add_n(c)

# Creates a session with log_device_placement set to True.
sess = tf.Session(config=tf.ConfigProto(log_device_placement=True))
print sess.run(sum)

正如我們所看到的今瀑,代碼與前一代碼相同,但現(xiàn)在我們有 2 個(gè) GPU点把,由tf.device指定橘荠,它們執(zhí)行乘法(兩個(gè) GPU 在這里都做同樣的操作,以便簡(jiǎn)化示例代碼)郎逃,稍后 CPU 執(zhí)行加法哥童。 假設(shè)我們將log_device_placement設(shè)置為true,我們可以在輸出中看到褒翰,操作如何分配給我們的設(shè)備 [45]贮懈。

. . .
Device mapping:
/job:localhost/replica:0/task:0/gpu:0 -> device: 0, name: Tesla K40c
/job:localhost/replica:0/task:0/gpu:1 -> device: 1, name: Tesla K40c
/job:localhost/replica:0/task:0/gpu:2 -> device: 2, name: Tesla K40c
/job:localhost/replica:0/task:0/gpu:3 -> device: 3, name: Tesla K40c
. . .


. . .

Const_3: /job:localhost/replica:0/task:0/gpu:3
I tensorflow/core/common_runtime/simple_placer.cc:289] Const_3: /job:localhost/replica:0/task:0/gpu:3
Const_2: /job:localhost/replica:0/task:0/gpu:3
I tensorflow/core/common_runtime/simple_placer.cc:289] Const_2: /job:localhost/replica:0/task:0/gpu:3
MatMul_1: /job:localhost/replica:0/task:0/gpu:3
I tensorflow/core/common_runtime/simple_placer.cc:289] MatMul_1: /job:localhost/replica:0/task:0/gpu:3
Const_1: /job:localhost/replica:0/task:0/gpu:2
I tensorflow/core/common_runtime/simple_placer.cc:289] Const_1: /job:localhost/replica:0/task:0/gpu:2
Const: /job:localhost/replica:0/task:0/gpu:2
I tensorflow/core/common_runtime/simple_placer.cc:289] Const: /job:localhost/replica:0/task:0/gpu:2
MatMul: /job:localhost/replica:0/task:0/gpu:2
I tensorflow/core/common_runtime/simple_placer.cc:289] MatMul: /job:localhost/replica:0/task:0/gpu:2
AddN: /job:localhost/replica:0/task:0/cpu:0
I tensorflow/core/common_runtime/simple_placer.cc:289] AddN: /job:localhost/replica:0/task:0/cpu:0
[[44.56.]
[98.128.]]
. . .

GPU 的代碼示例

為了總結(jié)這一簡(jiǎn)短的章節(jié),我們提供了一段代碼优训,其靈感來(lái)自 DamienAymeric 在 Github [46] 中共享的代碼朵你,計(jì)算An + Bnn=10揣非,使用 Python datetime包抡医,將 1 GPU 的執(zhí)行時(shí)間與 2 個(gè) GPU 進(jìn)行比較。

首先早敬,我們導(dǎo)入所需的庫(kù):

import numpy as np
import tensorflow as tf
import datetime

我們使用numpy包創(chuàng)建兩個(gè)帶隨機(jī)值的矩陣:

A = np.random.rand(1e4, 1e4).astype('float32')
B = np.random.rand(1e4, 1e4).astype('float32')

n = 10

然后忌傻,我們創(chuàng)建兩個(gè)結(jié)構(gòu)來(lái)存儲(chǔ)結(jié)果:

c1 = []
c2 = []

接下來(lái),我們定義matpow()函數(shù)搞监,如下所示:

defmatpow(M, n):
    if n < 1: #Abstract cases where n < 1
       return M
    else:
       return tf.matmul(M, matpow(M, n-1))

正如我們所見(jiàn)水孩,要在單個(gè) GPU 中執(zhí)行代碼,我們必須按如下方式指定:

with tf.device('/gpu:0'):
    a = tf.constant(A)
    b = tf.constant(B)
    c1.append(matpow(a, n))
    c1.append(matpow(b, n))

with tf.device('/cpu:0'):
sum = tf.add_n(c1)

t1_1 = datetime.datetime.now()

with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
sess.run(sum)
t2_1 = datetime.datetime.now()

對(duì)于 2 個(gè) GPU 的情況琐驴,代碼如下:

with tf.device('/gpu:0'):
    #compute A^n and store result in c2
    a = tf.constant(A)
    c2.append(matpow(a, n))
 
with tf.device('/gpu:1'):
    #compute B^n and store result in c2
    b = tf.constant(B)
    c2.append(matpow(b, n))

with tf.device('/cpu:0'):
    sum = tf.add_n(c2) #Addition of all elements in c2, i.e. A^n + B^n
    t1_2 = datetime.datetime.now()

with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess:
    # Runs the op.
    sess.run(sum)
t2_2 = datetime.datetime.now()

最后俘种,我們打印計(jì)算時(shí)間的結(jié)果:

print "Single GPU computation time: " + str(t2_1-t1_1)
print "Multi GPU computation time: " + str(t2_2-t1_2)

TensorFlow 的分布式版本

正如我之前在本章開(kāi)頭所說(shuō),2016 年 2 月棍矛,Google 發(fā)布了 TensorFlow 的分布式版本安疗,該版本由 gRPC 支持,這是一個(gè)用于進(jìn)程間通信的高性能開(kāi)源 RPC 框架(TensorFlow 服務(wù)使用的相同協(xié)議)够委。

對(duì)于它的用法荐类,必須構(gòu)建二進(jìn)制文件,因?yàn)榇藭r(shí)包只提供源代碼茁帽。 鑒于本書(shū)的介紹范圍玉罐,我不會(huì)在分布式版本中解釋它屈嗤,但如果讀者想要了解它,我建議從 TensorFlow 的分布式版本的官網(wǎng)開(kāi)始 [47]吊输。

與前面的章節(jié)一樣饶号,本書(shū)中使用的代碼可以在本書(shū)的 Github [48] 中找到。 我希望本章足以說(shuō)明如何使用 GPU 加速代碼季蚂。

后記

探索是促進(jìn)創(chuàng)新的引擎茫船。創(chuàng)新促進(jìn)經(jīng)濟(jì)增長(zhǎng)。讓我們一起去探索吧扭屁。

Edith Widder

在這里算谈,我提供了一個(gè)介紹性指南,解釋了如何使用 TensorFlow料滥,為這種技術(shù)提供熱身然眼,這無(wú)疑將在迫在眉睫的技術(shù)場(chǎng)景中發(fā)揮主導(dǎo)作用。 事實(shí)上葵腹,還有 TensorFlow 的其他替代方案高每,每個(gè)方案最適合特定問(wèn)題;我想邀請(qǐng)讀者探索 TensorFlow 包之外的內(nèi)容践宴。

這些包有很多不同之處鲸匿。 有些更專(zhuān)業(yè),有些更不專(zhuān)業(yè)浴井。 有些比其他更難安裝晒骇。 其中一些有很好的文檔,而另一些盡管運(yùn)作良好磺浙,但更難找到如何使用它們的詳細(xì)信息。

重要的是:之后的日子里归薛,TensorFlow 由谷歌發(fā)布辜荠,我在推文 [49] 中讀到了 2010-2014 期間无蜂,新的深度學(xué)習(xí)包每 47 天發(fā)布一次,2015 年每 22 天發(fā)布一次伦泥。 這很驚人,不是嗎锦溪? 正如我在本書(shū)的第一章中提出的那樣不脯,作為讀者的起點(diǎn),可以在 Awesome Deep Learning [50] 找到一個(gè)廣泛的列表刻诊。

毫無(wú)疑問(wèn)防楷,2015 年 11 月,隨著 Google TensorFlow 的發(fā)布则涯,深度學(xué)習(xí)的格局受到影響复局,現(xiàn)在它是 Github 上最受歡迎的開(kāi)源機(jī)器學(xué)習(xí)庫(kù) [51]冲簿。

請(qǐng)記住,Github 的第二個(gè)最著名的機(jī)器學(xué)習(xí)項(xiàng)目是 Scikit-learn [52]亿昏,事實(shí)上的 Python 官方的通用機(jī)器學(xué)習(xí)框架峦剔。 這些用戶可以通過(guò) Scikit Flow(skflow)[53] 使用 TensorFlow,這是來(lái)自 Google 的 TensorFlow 的簡(jiǎn)化接口角钩。

實(shí)際上吝沫,Scikit Flow 是 TensorFlow 庫(kù)的高級(jí)包裝,它允許使用熟悉的 Scikit-Learn 方法訓(xùn)練和擬合神經(jīng)網(wǎng)絡(luò)递礼。 該庫(kù)涵蓋了從線性模型到深度學(xué)習(xí)應(yīng)用的各種需求野舶。

在我看來(lái),在 TensorFlow 分布式宰衙,TensorFlow 服務(wù)和 Scikit Flow 發(fā)布后平道,TensorFlow 將成為事實(shí)上的主流深度學(xué)習(xí)庫(kù)。

深度學(xué)習(xí)大大提高了語(yǔ)音識(shí)別供炼,視覺(jué)對(duì)象識(shí)別一屋,對(duì)象檢測(cè)和許多其他領(lǐng)域的最新技術(shù)水平。 它的未來(lái)會(huì)是什么袋哼? 根據(jù) Yann LeCun冀墨,Yoshua Bengio 和 Geoffrey Hilton 在 Nature 雜志上的精彩評(píng)論,答案是無(wú)監(jiān)督學(xué)習(xí) [54]涛贯。 他們期望從長(zhǎng)遠(yuǎn)來(lái)看诽嘉,無(wú)監(jiān)督學(xué)習(xí)比監(jiān)督學(xué)習(xí)更重要。 正如他們所提到的弟翘,人類(lèi)和動(dòng)物的學(xué)習(xí)基本上沒(méi)有受到監(jiān)督:我們通過(guò)觀察世界來(lái)發(fā)現(xiàn)它的結(jié)構(gòu)虫腋,而不是通過(guò)被告知每個(gè)物體的名稱(chēng)。

他們對(duì)系統(tǒng)的未來(lái)進(jìn)展有很多期望稀余,系統(tǒng)將 CNN 與遞歸神經(jīng)網(wǎng)絡(luò)(RNN)相結(jié)合悦冀,并使用強(qiáng)化學(xué)習(xí)。 RNN 處理一個(gè)輸入睛琳,該輸入一次編碼一個(gè)元素盒蟆,在其隱藏單元中維護(hù)序列的所有過(guò)去元素的歷史的信息。 對(duì)于 TensorFlow 中 RNN 實(shí)現(xiàn)的介紹师骗,讀者可以查看 TensorFlow 教程中的循環(huán)神經(jīng)網(wǎng)絡(luò) [55] 部分历等。

此外,深度學(xué)習(xí)還面臨許多挑戰(zhàn)辟癌;訓(xùn)練它們的時(shí)間推動(dòng)了新型超級(jí)計(jì)算機(jī)系統(tǒng)的需求寒屯。 為了將最佳的知識(shí)分析與新的大數(shù)據(jù)技術(shù)和新興計(jì)算系統(tǒng)的強(qiáng)大功能相結(jié)合,以前所未有的速度解釋大量異構(gòu)數(shù)據(jù)愿待,仍然需要進(jìn)行大量研究浩螺。

科學(xué)進(jìn)步通常是大型社區(qū)的跨學(xué)科靴患,長(zhǎng)期和持續(xù)努力的結(jié)果,而不是突破要出,深度學(xué)習(xí)和機(jī)器學(xué)習(xí)一般也不例外鸳君。 我們正在進(jìn)入一個(gè)非常激動(dòng)人心的跨學(xué)科研究時(shí)期,其中像巴塞羅那那樣的生態(tài)系統(tǒng)患蹂,如 UPC 和 BSC-CNS或颊,在高性能計(jì)算和大數(shù)據(jù)技術(shù)方面具有豐富的知識(shí),將在這個(gè)新場(chǎng)景中發(fā)揮重要作用传于。

參考

[1] The MNIST database of handwritten digits. [Online]. Available at:http://yann.lecun.com/exdb/mnist [Accessed: 16/12/2015].

[2]_ Github_, (2016) Fist Contact with TensorFlow. Source code [Online]. Available at:https://github.com/jorditorresBCN/TutorialTensorFlow[Accessed: 16/12/2015].

[3]_ TensorFlow Serving_[Online]. Available at: http://tensorflow.github.io/serving/[Accessed: 24/02/2016].

[4] Google Research Blog [Online]. Available at: http://googleresearch.blogspot.com.es/2016/02/running-your-models-in-production-with.html?m=1[Accessed: 24/02/2016].

[5]_ TensorFlow Serving_-Architecture Overview[Online]. Available at: http://tensorflow.github.io/serving/[Accessed: 24/02/2016].

[6] TensorFlow Serving– Serving a TensorFlow Model [Online]. Available at:http://tensorflow.github.io/serving/serving_basic [Accessed: 24/02/2016].

[7] TensorFlow, (2016) Download & Setup [Online]. Available at: https://www.tensorflow.org/versions/master/get_started/os_setup.html#download-and-setup[Accessed: 16/12/2015].

[8] Wikipedia, (2016). IPython. [Online]. Available at: https://en.wikipedia.org/wiki/IPython [Accessed: 19/03/2016].

[9] TensorFlow: Large-scale machine learning on heterogeneous systems, (2015). [Online]. Available at:http://download.tensorflow.org/paper/whitepaper2015.pdf[Accessed: 20/12/2015].

[10] TensorFlow, (2016)Python API – Summary Operations. [Online]. Available at:https://www.tensorflow.org/versions/master/api_docs/python/train.html#summary-operations [Accessed: 03/01/2016].

[11] I recommend using Google Chrome to ensure proper display.

[12]TensorFlow, (2016) TensorBoard: Graph Visualization.[Online]. Available at:https://www.tensorflow.org/versions/master/how_tos/graph_viz/index.html[Accessed: 02/01/2016].

[13] One reviewer of this book has indicated that he also had to install the package_python-gi-cairo_.

[14] Wikipedia, (2016). Mean Square Error. [Online]. Available at: https://en.wikipedia.org/wiki/Mean_squared_error [Accessed: 9/01/2016].

[15] Wikipedia, (2016). Gradient descent. [Online]. Available at: https://en.wikipedia.org/wiki/Gradient_descent [Accessed: 9/01/2016].

[16] Wikipedia, (2016). Gradient. [Online]. Available at: https://en.wikipedia.org/wiki/Gradient[Accessed: 9/01/2016].

[17] Github, (2016) Book source code [Online]. Available at:https://github.com/jorditorresBCN/TutorialTensorFlow. [Accessed: 16/12/2015].

[18] TensorFlow, (2016) API de Python – Tensor Transformations [Online]. Available at:https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html [Accessed: 16/12/2015].

[19] TensorFlow, (2016) Tutorial – Reading Data [Online]. Available at:https://www.tensorflow.org/versions/master/how_tos/reading_data[Accessed: 16/12/2015].

[20] Github, (2016) TensorFlow Book – Jordi Torres. [Online]. Available at:https://github.com/jorditorresBCN/LibroTensorFlow/blob/master/input_data.py[Accessed: 19/02/2016].

[21] Github, (2016) Shawn Simister. [Online]. Available at: https://gist.github.com/narphorium/d06b7ed234287e319f18 [Accessed: 9/01/2016].

[22] Wikipedia, (2016). Squared Euclidean distance. [Online]. Available at:https://en.wikipedia.org/wiki/Euclidean_distance#Squared_Euclidean_distance[Accessed: 9/01/2016].

[23] In my opinion, the level of explanation of each operation it’s enough for the purpose of this book.

[24] TensorFlow, (2016) Python API. [online]. Available in: https://www.tensorflow.org/versions/master/api_docs/index.html [Accessed: 19/02/2016].

[25]Actually “_” is like any other variable, but many Python users, by convention, we use it to discard results.

[26] Github, (2016) TensorFlow Book – Jordi Torres. [online]. Available at: https://github.com/jorditorresBCN/LibroTensorFlow [Accessed: 19/02/2016].

[27] TensorFlow, (2016) Tutorial MNIST beginners. [online]. Available at:https://www.tensorflow.org/versions/master/ tutorials/mnist/beginners[Accessed: 16/12/2015].

[28] Neural Networks and Deep Learning.Michael Nielsen. [online]. Available at: http://neuralnetworksanddeeplearning.com/index.html [Accessed: 6/12/2015].

[29] The MNIST database of handwritten digits.[online]. Available at:http://yann.lecun.com/exdb/mnist [Accessed: 16/12/2015].

[30] Wikipedia, (2016). Antialiasing [online]. Available at: https://en.wikipedia.org/wiki/Antialiasing[Accessed: 9/01/2016].

[31]_ Github_, (2016) Book TensorFlow – Jordi Torres. [online]. Available at:https://github.com/jorditorresBCN/LibroTensorFlow/blob/master/input_data.py [Accessed: 9/01/2016].

[32] Google (2016) TensorFlow. [online]. Available at: https://tensorflow.googlesource.com[Accessed: 9/01/2016].

[33] Wikipedia, (2016). Sigmoid function [online]. Avaliable at: https://en.wikipedia.org/wiki/Sigmoid_function [Accessed: 12/01/2016].

[34] Wikipedia, (2016). Softmax function [online]. Available at: https://en.wikipedia.org/wiki/Softmax_function [Accessed: 2/01/2016].

[35] TensorFlow, (2016) Tutorial MNIST beginners. [online]. Available at:https://www.tensorflow.org/versions/master/tutorials/mnist/beginners[Accessed: 16/12/2015].

[36] Neural Networks & Deep Learning.Michael Nielsen. [online]. Available at:http://neuralnetworksanddeeplearning.com/index.html[Accessed: 6/12/2015].

[37] TensorFlow Github: tensorflow/tensorflow/python/ops/gradients.py [Online]. Available at:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/ops/gradients.py[Accessed: 16/03/2016].

[38]_ Github_, (2016) Libro TensorFlow – Jordi Torres. [online]. Available at:https://github.com/jorditorresBCN/LibroTensorFlow[Accessed: 9/01/2016].

[39] The reader can read more about the details of these parameters on the course website of CS231 –Convolutional Neural Networks for Visual Recognition(2015) [online]. Available at:http://cs231n.github.io/convolutional-networks[Accessed: 30/12/2015].

[40] GIMP –_Image processing software by GNU,_Convlution matrix documentation available at:https://docs.gimp.org/es/plug-in-convmatrix.html[Accessed: 5/1/2016].

[41] TensorFlow, (2016_) Tutorials: Deep MNIST for experts_. [on line]. Availbile at:https://www.tensorflow.org/versions/master/tutorials/mnist/pros/index.html [Consulted on: 2/1/2016]

[42] TensorFlow, (2016)Python API. ADAM Optimizer[on líne]. Available at:https://www.tensorflow.org/versions/master/ api_docs/python/train.html#AdamOptimizer[Accessed: 2/1/2016].

[43] Github, (2016) Source code of this book [on líne]. Availible at: https://github.com/jorditorresBCN/TutorialTensorFlow [Consulted on: 29/12/2015].

[44] TensorFlow, (2016) GPU-related issues. [online]. Available at: https://www.tensorflow.org/versions/master/get_started/os_setup.html#gpu-related-issues[Accessed: 16/12/2015].

[45] This output is result of using a server with 4 Tesla K40 GPUs from theBarcelona Supercomputing Center (BSC-CNS).

[46]_ Github_(2016) AymericDamien. [online]. Available at: https://github.com/aymericdamien/TensorFlow-Examples [Accessed: 9/1/2015].

[47] Distributed TensorFlow, (2016) [online]. Available at: https://github.com/tensorflow/tensorflow/tree/master/tensorflow/core/distributed_runtime[Accessed: 16/12/2015].

[48] Github, (2016) Source code of this book [on líne]. Availible at: https://github.com/jorditorresBCN/TutorialTensorFlow [Consulted on: 29/12/2015].

[49] Twitter (11/11/2015). Kyle McDonald:_2010-2014: new deep learning toolkit is released every 47 days._2015: every 22 days.[Online]. Available at:https://twitter.com/kcimc/status/664217437840257024[Accessed: 9/01/2016].

[50] GitHub,(2016)Awesome Deep Learning. [Online]. Available at: https://github.com/ChristosChristofidis/awesome-deep-learning[Accessed: 9/01/2016].

[51] Explore GitHub, Machine learning: [Online]. Available at:https://github.com/showcases/machine-learning [Accessed on: 2/01/2016]

[52] Scikit-Learn GitHub: [Online]. Available at:https://github.com/scikit-learn/scikit-learn[Accessed: 2/3/2016]

[53] Tensorflow/skflow GitHub: [Online]. Available at:https://github.com/tensorflow/skflow[Accessed: 2/1/2016]

[54] Yann LeCun, Yoshua Bengio and Geoffrey Hinton (2015). “Deep Learning”. Nature 521: 436–444 doi:10.1038/nature14539. Available at:http://www.nature.com/nature/journal/v521/n7553/full/nature14539.html [Accessed: 16/03/2016].

[55] TensorFlow, (2016) Tutorial – Recurrent Neural Networks [Online]. Available at:https://www.tensorflow.org/versions/r0.7/tutorials/recurrent/index.html[Accessed: 16/03/2016].

[56] Hello World en TensorFlow. Spanish version of this book [Online]. Available at:https://jorditorres.org/libro-hello-world-en-tensorflow/[Accessed: 16/03/2016].

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末囱挑,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子沼溜,更是在濱河造成了極大的恐慌平挑,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件系草,死亡現(xiàn)場(chǎng)離奇詭異通熄,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)找都,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)唇辨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人能耻,你說(shuō)我怎么就攤上這事赏枚。” “怎么了晓猛?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵饿幅,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我鞍帝,道長(zhǎng)诫睬,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任帕涌,我火速辦了婚禮,結(jié)果婚禮上续徽,老公的妹妹穿的比我還像新娘蚓曼。我一直安慰自己,他們只是感情好钦扭,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布纫版。 她就那樣靜靜地躺著,像睡著了一般客情。 火紅的嫁衣襯著肌膚如雪其弊。 梳的紋絲不亂的頭發(fā)上癞己,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音梭伐,去河邊找鬼痹雅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛糊识,可吹牛的內(nèi)容都是我干的绩社。 我是一名探鬼主播,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼赂苗,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼愉耙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起拌滋,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤朴沿,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后败砂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體赌渣,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年吠卷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了锡垄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡祭隔,死狀恐怖货岭,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疾渴,我是刑警寧澤千贯,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站搞坝,受9級(jí)特大地震影響搔谴,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜桩撮,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一敦第、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧店量,春花似錦芜果、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春舀射,著一層夾襖步出監(jiān)牢的瞬間窘茁,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工脆烟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留山林,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓浩淘,卻偏偏與公主長(zhǎng)得像捌朴,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子张抄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容