使用 TensorFlow 和 Python 進行深度學習(附視頻中字)
CDA字幕組 翻譯整理
本文為 CDA 數據分析師原創作品,轉載需授權
TensorFlow是谷歌研發的開源框架。本講座介紹了如何使用TensorFlow創建深度學習應用程序,以及與其他Python機器學習庫進行比較。
CDA字幕組對該視頻進行了漢化,附有中文字幕的視頻如下:
使用TensorFlow和Python進行深度學習(一)針對不方面開視頻的小夥伴,CDA字幕組也貼心的整理了文字版本,如下:
(文末有彩蛋! )
我叫Ian Lewis,我是谷歌雲平台團隊的開發者大使(Developer Advocate)。來自日本東京,我在東京居住了大約10年。如果你們有任何問題,可以關注一下我的Twitter賬號 @IanMLewis。
下面我將說明一下PyCon JP(PyCon大會:Python語言社群全球性的盛會)。PyCon JP是日本的PyCon大會。我們從2011年就開始做PyCon JP,有意思的是PyCon JP實際上始於2010年的PyCon新加坡。當時我和PyCon JP其他的創始人相遇在這個會議。之後我們聚在一起,覺得在日本也需要類似的會議,所以就有了PyCon JP。一開始還是一個小型的PyCon,六個月後在2011年我們做了一場真正像樣的PyCon。所以如果你有興趣的話,可以在PyCon JP註冊報名,和我們一起交流。
關於機器學習
介紹一下今天的主題,深度學習。我將會介紹一下深度學習的背景,談一談深度學習是什麼。你們當中有多少人了解機器學習科學家,以及數據科學家?好的,很多人都知道。如果不了解的話,可能會覺得這個講座有點無聊。希望在我講TensorFlow時,你們能夠有所收穫。
深度學習是特定的一種機器學習,特定的神經網路。當中的深度部分來自深度神經網路。神經網路指的是取輸入到網路中,輸入連接到節點,當中包括激活函數。這些將用於輸入,之後輸入被導出,作為神經網路的輸出。
我們用一張貓的圖片當例子。輸入就是圖片的像素,經過神經網路得到輸出。比如分類,告訴我們這是貓還是狗等等。這些相互連接並傳遞內容的被稱為張量(tensor)。
這裡介紹一下背景,這些神經網路擅長什麼?
神經網路擅長兩類主要問題,一種是分類問題。比如這是我的輸入屬於哪個類別。這張照片是狗還是貓還是人類等等,因此它擅長添加標籤或者分類等等。另一種是回歸,回歸是構建數學函數 描述你手裡的數據。所以你得到很多類型的輸出。
比起回歸,我將多講講分類問題。想像你們有一些分類問題,假設你有一些數據。比如圖中的藍色和橘色的數據。可以認為這些是人的身高比上體重,藍色和橘色的點分別是成人和小孩的分組。你想構建網路或程序,能夠通過人的身高體重來判斷是成人還是孩子。這是一個很容易解決的問題,你可以在兩者之間畫一條線就行了。
但是這是例子可以通過神經網路解決。假設你有更複雜的問題比如像這個,輸入數據不夠清晰。那你該使用哪種函數或者分類方法區分這些數據。在這個例子里如果你有一個非常簡單的神經網路,沒有辦法收斂(converge)。無法解決區分這兩類數據的問題。所以為了解決這個問題,你需要開發一個更複雜的神經網路 深度更深。你可以添加中間這些隱藏層,可以讓你利用神經網路進行更複雜的識別和分類。根據我怎麼構建,這個可能收斂或者不能。但為了解決這類問題,需要一個更複雜的神經網路。
那麼神經網路的核心有什麼?核心是一個大型函數,輸入一個張量,輸出另一個張量。中間步驟在張量進行操作,從而生成輸出。這類問題就相當於,就像有多少人了解矩陣乘法,這個是高中數學知識。你會對這些張量進行這類操作,通過乘以權重和添加偏差等等。就像流水線一樣,為了得到輸出一遍一遍地重複。但進行乘法要用到的中間權重。實際上構成了你的神經網路。
介紹下TensorFlow名字的由來。TensorFlow指張量(tensor)如何流過(flow)神經網路。
但是張量是什麼?你們都很熟悉矩陣乘法或矩陣,比如向量或者簡單的數組。你將如何把它在編程語言中執行。因此你有許多值組成的數組。矩陣可能是向量的二維或三維版本,你可能在編程語言中有類似這樣的三維矩陣。
張量實質上是任意類型的矩陣,所以它是任意維數的。因此你有由任意數量組成的數組在你的應用中作為數組執行,這就是張量。只要維數匹配,你就可以在張量上進行矩陣乘法。當實際執行時,神經網路時完全連接的。在輸出張量上,每個輸入值連接輸出值。這意味著,每個連接都有相應的權重。你所做的就是進行加法或乘法。把輸入帶入神經網路,後面加上一些偏差。
這個例子很簡單。加上偏差,得到輸出向量。比如這裡有三個輸出值,分別代表三個不同類別。比如對於輸入圖像,分為貓 、狗 、人。輸出則是百分比或者輸出值。顯示輸入圖像與特定分類的匹配度。這個特定值的數值不會太友好,它只是一個數字,代表一個特定的值。反映你手上的圖片多大程度上是人 狗,還是貓。
對這類神經網路,最後你通常會需要增加softmax函數。softmax的作用是選出最大值,或者對所有數據進行標準化。從而得到的輸出值在0到1之間。給出一個百分比,說明圖像是貓、狗還是人。假設得出一張我的圖片是人的可能性為85%,似乎有點低。但你能懂當中的意思。
人工神經網路很厲害的一點是,一開始你不需要太了解數據。你可以開始用數據訓練模型,然後使用反向傳播來繼續訓練模型。更新權重和偏差,從而提高模型的性能。這正是由我剛才提到的反向傳播來完成的,只需為神經網路提供損失函數(loss function)或者代價函數(cost function)。計算期望值和神經網路的實際值之間的差值。
我的圖片應該是人,那麼期望值應該是百分之百,表示這個圖片上是人。而人工神經網路可能得出圖片是人的概率為85%,使用代價函數得到15%的差值。用這個值更新神經網路的權重和偏差,儘可能讓實際值接近期望值。反覆迭代,該過程最終會得出最優的權重和偏差。整個過程需要使用一些輸入數據。比如這是一張圖片,這是對應的標籤,或者模型應該得到的正確輸出值。以上是關於神經網路的一些背景知識。
突破性進展
我花了一半時間為大家介紹這些內容。為什麼要講這些內容?無外乎是機器學習領域取得的眾多突破性進展。
接下來的問題是如何訓練模型,如何確定哪些值是預期得到的。因此你需要一些已經匹配的訓練數據,期望值和數據相匹配。
我們為什麼要討論機器學習? 機器學習為什麼成了最近的熱詞?
因為機器學習領域出現了眾多的突破性進展,讓我們能利用它解決實際問題。直到最近,我們能夠用機器學習解決一些特定領域的問題,以輔助我們人類完成一些事情。然而我們很難把它做成產品,讓它變得容易上手、便於使用。
這是我們在谷歌使用的Inception模型,用於訓練圖像以及給圖像匹配標籤。接下來我詳細介紹一下它的背景。
這是深度神經網路。我之前提到的神經網路具有矩陣乘法,但類似這樣的深度神經網路,加上"深度(deep)"的關鍵字或者深度方面。設想每個網路,採用諸如此類的矩陣乘法對輸入數據進行操作。
比如輸入是一張1M大小的圖片,設想其中每個都有一個轉換為張量的圖片。一張1M大小的圖片可能包含成千上萬個像素點。它們構成張量中數以千計的維度。接下來你需要反覆迭代,即對張量值進行數千次乘法運算。不斷迭代,整個運行一遍。能夠想像這是一個龐大的組合問題。為了訓練模型需要完成多少計算,假設一張圖片跑一次,而你現在有數以百萬計的訓練圖像。你需要對這些圖片進行訓練,需要成千上萬甚至上百萬次,不難想像這是一個超大規模的問題。
我們研究發現對這類深度神經網路而言,結構越複雜,層數越多,模型預測性能越好。因此對於大量的輸入,如果採用一個大型的深度神經網路,那麼同樣的訓練集可以獲得更多的值。但問題是深度神經網路需要大量的計算。為此人們通常構建大型的矩陣,或者有大量GPU的機器用來訓練模型。通常需要數小時數天或數周來訓練一個模型。僅為了運行一個測試,確保特定的模型或者特定的神經網路能夠發揮性能。
研究人員需要反覆操作,只為獲得一個可用的模型。一些研究人員開始利用超級計算機進行訓練,目的是加快速度。然而這對大多數人是不可能的。你需要提前租用超級計算機。對於沒有超級計算機來處理這類機器學習模型的人,他們實際上利用深度神經網路。
在谷歌,我們擁有大量的計算機設備。雖然我們沒有超級計算機,但我們有許多計算機。我們另闢蹊徑,但是我們通過在谷歌利用機器學習取得了眾多重大突破。
這些是我們研發的產品。你如果熟悉谷歌圖片,可以在你的相冊簿批量添加一組圖片,然後通過關鍵詞搜索你想要的圖片。例如"雕像" "婚禮" 任何關鍵詞,系統將搜索到與你輸入的關鍵詞或標籤相匹配的圖片。你不需要提前標記這些圖片,也不需要教它這些圖片是什麼。根據之前訓練過的模型它已經知道了。這很擅長開發產品和現實中的應用。
另外一件我們正在做的是識別圖片里的文字。我們有很多街景數據或街景圖片。我們想要獲得現實中商鋪的名字等。因此我們需要通過圖片,從圖片中得出文本。從而得到索引,弄清楚這些商鋪的位置。我們在致力於解決這類問題。
你可能聽過AlphaGo,這是一個運用機器學習神經網路的項目。它會下圍棋,而且聽說下得很不錯。
在Google中機器學習的應用越來越多。這是最近的現象,可以注意到這張圖裡。在2014年之前 Google中應用機器學習項目的數量有著輕微的增長,但是2014年之後就出現了飛速的增長。說明了機器學習近年來發展有多迅速。
這是谷歌中的一個項目,稱為谷歌大腦。用於構建這類神經網路。我們的方式是,通過將神經網路的問題分配到很多機器上,並同時在很多機器上進行訓練和預測。這讓我們能夠利用Inception模型,在使用ImageNet時能夠提升40倍的速度。正如之前展示的圖,ImageNet是非常著名的數據集,用於機器學習和訓練。同時我們還用RankBrain對搜索結果進行排序的機器學習模型。我們用約50到500個機器節點,來訓練這類模型。
TensorFlow
接下來我們來講TensorFlow。TensorFlow是谷歌研發的庫,用於構建這類機器學習模型。TensorFlow是開源的庫,使用Python。同時是用來構建神經網路的通用機器學習庫。去年11月我們對它進行了開源。現在已經被用於許多機器學習項目。
TensorFlow的名字源於我之前提過的,即讓張量(tensor)在管道中流動(flow)。從而有張量的數據流通過神經網路。這個思路來自於為這些張量繪製的流程圖。它有一些很酷的特徵,比如說能夠靈活直觀地構建圖像框架,支持線程、隊列和非同步運算。可以在CPU GPU或任何支持TensorFlow的設備上運行。它會在圖中進行操作 並對其進行分解,分配到許多的CPU和GPU上。
TensorFlow的核心數據結構在於圖(graph)。操作就是圖中的節點,值的張量在操作間傳遞。包括其他內容比如常量(constants)即在訓練時不改變的量。這些可以在訓練時或者更新模型時改變,但在單次訓練中是不會改變的。還有佔位符(placeholders)和變數(variables)。佔位符類似於神經網路中的輸入,而變數則是在訓練神經網路時不斷更新的。一般來說,有作為神經網路輸入的佔位符,以及變數類似在訓練中進行更新的權重或者偏差。會話(session)則用於封裝運行所在的環境,它的作用類似於把操作映射到設備上。這張幻燈片是非排他性列表,包括TensorFlow所支持的操作。我們有一些TensorFlow中所支持的操作。
這是在Jupiter notebook上運行TensorFlow的例子。我將用非常基礎的MNIST例子進行講解,MNIST是用於機器學習的經典數據集,包括許多手寫數字的圖片。你要做的就是,用這些數字進行光學字元識別(OCR)或者字元識別,從而確定每個圖片代表什麼數字。
如果是1,那麼你希望輸出文本是1。現在我要載入測試數據,在訓練數據集中進行測試。訓練圖片共有55000張,每張圖片都被表述或映射到張量中,大小為784個維度,每一張圖片都有784個像素,即28乘28。
我調出一張圖,這是訓練數據集中的第6張圖。實際輸出是這樣。這是數字8的圖片,如果看到原始的輸入圖像,輸入圖像中的值都代表圖像中的一個特定像素。從0到1,代表這個圖像多暗。如果是0,像素則為白色。如果是1或者接近1,像素則比較暗。
然後看到這裡,這些是訓練數據。這是訓練數據輸出的形狀。是10維的,大小為10的數組。輸出為0、1。訓練數據是0或1,或是任何一個值。這說明了訓練數據代表什麼。這是輸入圖像的實際訓練標籤,這裡為8。在第8個位置有個1,說明這個圖片為8。我們將用它訓練神經網路。
這是我之前展示的圖片。就像你訓練神經網路一樣會看到每個像素,並為特定像素分配一個權重。因為我將會做一個相當淺的神經網路,只有一個隱藏層。這會要給每個像素分配權重,表示這個像素或者圖片是否代表特定數字。這裡的藍色表示正權重值(positive weight),紅色表示負權重值(negative weight)。所以藍色區域的像素表示為0。1、2也是同理。具體看到這個,這個類似實際數字的權重。你可以看到,這裡的8看起來很像8。
一旦完成這一步,你可以設置神經網路。要如何實際訓練它。這實際定義神經網路。我創建了X作為佔位符,這是神經網路的輸入。所以X是輸入,形狀為784維度。這意味著大小不一定為55000,它可以是任意大小。接著分配這些變數,因此權重和偏差將在訓練中更新。
然後我要定義在值上進行的操作。這裡要進行矩陣乘法,這是我要進行的預定義操作之一。用X乘以W 並且乘以所有的權重,即進行這個矩陣乘法。最後加上B,加上偏差。接著在上面運行softmax。這能夠讓我在神經網路中進行訓練。
現在要定義訓練步驟,這定義了我將在神經網路上進行的反向傳播。在這裡我定義一個佔位符,這是為了損失函數。在這個例子中我將用到交叉熵(cross-entropy)。這是損失函數的一種,你可以嘗試其他幾個。但這是一個非常簡單的例子。
我將使用梯度下降優化器,這是用來更新權重和偏差的方法。當出現差異時你可以使用梯度下降,從而明確該如何更新權重和偏見,應該更新多少。你將使用這個優化器,嘗試找出輸出的差異,然後映射到需要更新的權重和偏差的差異上。這將告訴我如何將交叉熵函數最小化,進行可視化後是這樣。有初始值,接著使用梯度下降優化器。從而明確該如何改變這些值,以獲得更好的輸出。為了得到更好的值需要反覆重複該過程。這裡存在找到本地最小值的問題,這是調整值的不錯方式。
接下來我將在神經網路中,使用優化器或者反向傳播從而進行訓練。這將對會話進行初始化,即對TensorFlow的訓練會話進行初始化。然後它會循環,對數據進行數千次的小批量處理。我將取訓練集,選出100個值。有意思的是,我不必對整個55000張圖像的訓練集進行循環,也不必每次訓練。我可以隨機選取一百個值,並且僅在每個小批次中進行訓練。
這很有意思,如果你喜歡統計你在做的是選出整個訓練集,然後選出當中的隨機樣本進行訓練,這將得到訓練集的代表性樣本。從統計上來說,最終得到的結果近似於對整個訓練集進行訓練。這類似於你想知道比起其他總統候選人,人們是否喜歡這個候選人。你不需要問每一個美國人或者每個州的人。你可以對隨機人群進行詢問,得到的結果與實際結果很相近。這樣可以節省很多的時間,只需運行實際數據的百分之五,從而節省大量時間。
接下來可以對神經網路進行測試,看其效果如何。這是在TensorFlow中使用的另一種操作,使用argmax函數。這個Y值是從神經網路得出的值,這個質數Y是訓練集中得出的實際值,是正確的值。我將對兩者都運行argmax函數,這將在輸出的每個向量中得出0或者1。最後得出我的神經網路正確率為91%,這實際上很糟糕。十個圖像中有一個是不正確的,但這是一個非常簡單的例子。
你可以開始做更複雜的例子 使用MNIST,MNIST當中最好的正確率可以達到99.997%。如果用神經網路做的更多,可以得到更正確的數值。
TensorFlow的官網也是很不錯的,當中有很多教程。比如這個針對初學者的MNIST例子,關於在TensorFlow上使用MNIST訓練集。如果想通過更複雜的操作得到更好的結果,可以試試下一個教程,針對專家的MNIST教程。給原來的神經網路增加了些複雜性,從而提高5%或6%的正確率。還有一些其他教程,比如使用卷積神經網路 遞歸神經網路等等。有很多例子,都是簡單易懂的。這讓TensorFlow成為機器學習中非常出色的庫。
在這裡出於趣味性,我使用MNIST和Theano庫,運行了相同的訓練數據。Theano庫與TensorFlow的方式很類似,使用方法也類似。在這裡我會使用TensorFlow例子中,這裡你所做的非常類似。在Theano中存在共享對象(shared object),這會用於權重和偏差,而不是用變數。接著你可以對神經網路進行定義,使用相同的softmax 再加上偏差。然後對損失函數和訓練步驟定義相同的交叉熵。有點不同的是需要進行反向傳播。這裡是反向傳播,這是梯度下降函數。可以給出代價函數的交叉熵,以及權重和偏差。但需要自己進行更新。
之後就可以用Theano建立訓練模型,然後做數千次批次訓練 。接著測試,在這裡我得到89%正確率。會得到相同的正確率,因為操作類型是相同的。Theano和TensorFlow的區別在於庫核心部分的構成。
TensorFlow能夠讓你更容易分解操作,並且映射到特定的設備中。然而 Theano是核心庫,這讓它很難或幾乎不可能映射到多個GPU或多個設備進行訓練。
TensorFlow的與眾不同在於分散式訓練,這能夠對各個GPU和CUP進行映射。並且支持許多不同類型的分散式訓練。比如數據並行(data parallelism),以及模型並行(model parallelism)等等。數據並行和模型並行中存在一些取捨,兩者得到的結果不同。模型並行會分解模型的不同部分,然後在不同設備不同機器上訓練相同的數據。數據並行則是在多台機器上運行相同的模型,並拆分數據。兩者都有不同的優缺點。
在谷歌,我們傾向於使用數據並行。但是模型並行性適用於許多不同類型的任務。TensorFlow兩者都支持。我不會介紹過多的細節,比如數據並行、同步模型、非同步模型。如果你感興趣的話,可以之後和我聊聊。
當你對這類機器學習模型或訓練進行分配時,會存在一些問題。你需要在各個機器之間傳輸大量的數據,取決於如何分解或分配訓練。因此你需要一個快速的神經網路,因為操作在單個GPU上需要花費幾納秒,但是通過網路傳輸數據需要幾毫秒。分布數據的能力上存在數量級的差異。問題的瓶頸在於機器之間的網路。
在谷歌我們致力於這類問題。為了使機器間的連接儘可能快,因此我們計劃建立一個雲版本,稱為Cloud ML。支持在谷歌數據中心運行TensorFlow,能夠充分利用谷歌數據中心的硬體,從而進行分散式訓練。這可以幫助你減少時間。原來需要8小時如今在20個節點上只需32分鐘,快了近15倍。
除了能夠利用GPU以及這類硬體,我們也在開發自己的硬體用於機器學習和矩陣乘法。這稱為Tensor Processing Unit(TPU)。這是我們在谷歌開發的一種ASIC,為了獲得更好的性能。GPU是非常耗能的,所以我們開發了一些耗電少的產品。但是這些是專門針對機器學習的。我們也計劃把這些作為雲計算學習的一部分。
如果你們對TensorFlow感興趣,可以看看這些網站。上面有很多例子和教程。這也是TensorFlow很不錯的地方。這些教程真的很棒,編寫的很好,簡單易懂。
還可以看看bit.ly/tensorflow-workshop,很適合構建TensorFlow模型。包括基礎和進階的MNITS例子,還包括如何使用kubernetes,以及使用TensorFlow Serving,構建機器學習的產品版本。如果你感興趣的話 一定要看看,謝謝大家來聽講座。
CDA字幕組召集令CDA數據分析師旗下的CDA字幕組開始招募啦!
我們發掘了一批優質的數據分析視頻,只要你有責任心有時間,有一定的英文翻譯、聽譯能力,最重要的是熱愛數據分析,那麼就來加入我們吧!
申請報名:
推薦閱讀:
※Python數據分析及可視化實例之詞袋word2bow(28)
※P 站非會員查看人氣作品
※Kaggle HousePrice : LB 0.11666(前15%), 用搭積木的方式(2.實踐-特徵工程部分)
※python 中用filter求素數的時候,這裡的篩選函數是什麼意思啊?
※詳解Python項目開發時自定義模塊中對象的導入和使用