自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

TensorFlow從基礎(chǔ)到實戰(zhàn):一步步教你創(chuàng)建交通標(biāo)志分類神經(jīng)網(wǎng)絡(luò)

人工智能 深度學(xué)習(xí)
TensorFlow 已經(jīng)成為了現(xiàn)在最流行的深度學(xué)習(xí)框架,相信很多對人工智能和深度學(xué)習(xí)有興趣的人都躍躍欲試。對于初學(xué)者來說,TensorFlow 也是一個非常好的選擇,它有非常豐富的入門學(xué)習(xí)資料和龐大的開發(fā)者社區(qū)。近日,數(shù)據(jù)科學(xué)學(xué)習(xí)平臺 DataCamp 發(fā)表了一篇針對 TensorFlow 初學(xué)者的教程,從向量和張量的基本概念說起,一步步實現(xiàn)了一個分類交通標(biāo)志圖像的神經(jīng)網(wǎng)絡(luò)。

[[198754]]

TensorFlow 已經(jīng)成為了現(xiàn)在最流行的深度學(xué)習(xí)框架,相信很多對人工智能和深度學(xué)習(xí)有興趣的人都躍躍欲試。對于初學(xué)者來說,TensorFlow 也是一個非常好的選擇,它有非常豐富的入門學(xué)習(xí)資料和龐大的開發(fā)者社區(qū)。近日,數(shù)據(jù)科學(xué)學(xué)習(xí)平臺 DataCamp 發(fā)表了一篇針對 TensorFlow 初學(xué)者的教程,從向量和張量的基本概念說起,一步步實現(xiàn)了一個分類交通標(biāo)志圖像的神經(jīng)網(wǎng)絡(luò)。

深度學(xué)習(xí)是機(jī)器學(xué)習(xí)的一個子領(lǐng)域,包含了一系列受大腦的結(jié)構(gòu)和功能啟發(fā)得到的算法。

[[198755]] 

TensorFlow 是谷歌開發(fā)的第二個機(jī)器學(xué)習(xí)框架,可用于設(shè)計、構(gòu)建和訓(xùn)練深度學(xué)習(xí)模型。你可以使用 TensorFlow 庫進(jìn)行數(shù)值計算,這本身似乎并沒有什么特別的,但這些計算是使用數(shù)據(jù)流圖完成的。在這些圖中,節(jié)點表示數(shù)學(xué)運算,而邊則表示數(shù)據(jù)——通常是多維的數(shù)組或張量,在這些邊之間傳遞。

看到了吧?TensorFlow 的名字就源自神經(jīng)網(wǎng)絡(luò)在多維數(shù)組或張量上執(zhí)行的這種運算!它本質(zhì)上就是張量的流。這就是目前你需要了解的關(guān)于張量的所有內(nèi)容,但在接下來的章節(jié)中,我們還會更加深入!

這份 TensorFlow 入門教程將會以一種交互式的方式為你呈現(xiàn)如何進(jìn)行深度學(xué)習(xí):

  • 首先你將了解張量。
  • 然后,本教程將簡單介紹幾種在你的系統(tǒng)上安裝 TensorFlow 的方式,以便你能上手練習(xí)以及在你的工作空間中加載數(shù)據(jù)。
  • 之后,你將了解一些 TensorFlow 基礎(chǔ)知識:你會看到你可以輕松開始執(zhí)行一些簡單計算。
  • 之后,你將開始進(jìn)入實際工作:你將加載比利時交通標(biāo)志數(shù)據(jù),然后使用簡單的統(tǒng)計和繪圖工具對其進(jìn)行探索。
  • 在你的探索中,你將看到你需要操作數(shù)據(jù),以便你能將其饋送給你的模型。所以你需要花時間調(diào)整你的圖片的大小,并將其轉(zhuǎn)換成灰度圖像。
  • 接下來,你終于可以開始做你自己的神經(jīng)網(wǎng)絡(luò)模型了!你將一層層地構(gòu)建起你的模型。
  • 一旦設(shè)置好了架構(gòu),你就可以使用它來迭代式地訓(xùn)練你的模型,并且最終通過給它饋送一些測試數(shù)據(jù)來評估它。
  • 最后,你將得到一些用于未來進(jìn)步的建議指導(dǎo),以便你了解你能用你剛構(gòu)建好的模型做什么以及你該如何繼續(xù)使用 TensorFlow 進(jìn)行學(xué)習(xí)。

你也可以在這里下載本教程:https://github.com/Kacawi/datacamp-community/blob/master/TensorFlow%20Tutorial%20For%20Beginners/TensorFlow%20Tutorial%20For%20Beginners.ipynb

另外,你可能也會對下面三個課程感興趣:

  • Python 深度學(xué)習(xí):https://www.datacamp.com/courses/deep-learning-in-python
  • DataCamp 的 Keras 教程:https://www.datacamp.com/community/tutorials/deep-learning-python
  • 使用 R 語言的 Keras 教程:https://www.datacamp.com/community/tutorials/keras-r-deep-learning

介紹張量

為了很好地了解張量,最好先了解一點線性代數(shù)和向量計算的知識。你在引言中已經(jīng)讀到了,張量在 TensorFlow 中是作為多維數(shù)據(jù)數(shù)組實現(xiàn)的,但為了完全理解張量及其在機(jī)器學(xué)習(xí)領(lǐng)域的應(yīng)用,也許還是需要更多一些介紹。

平面向量(plane vector)

在你了解平面向量之前,我們先簡單澄清一下「向量」的概念。向量是特殊類型的矩陣(即數(shù)字構(gòu)成的矩形陣列)。因為向量是有序的數(shù)字集合,所以它們往往被看作是列矩陣:它們只有一列和一定數(shù)量的行。換句話說,你也可以將向量看作是有一個方向的標(biāo)量。

記住:標(biāo)量是「5 米」或「60 米/秒」這樣的量,而向量則是「向北 5 米」或「向東 60 米/秒」這樣的量。這兩者之間的不同很顯然:向量有一個方向。但是,到目前為止你看到的這些例子與你在機(jī)器學(xué)習(xí)問題中實際操作的向量可能相差很大。這很正常;數(shù)學(xué)向量的長度是純數(shù)字:是絕對的。而方向則是相對的:它的度量是相對于某個參考方向,并且有弧度或度作單位。你通常假設(shè)方向是正的,并且從參考方向按逆時針方向旋轉(zhuǎn)。

 

當(dāng)然在視覺上你可以將向量表示成箭頭,如上圖所示。這意味著你可以將向量看作是有方向和長度的箭頭。方向又箭頭的頭表示,而長度則由箭頭的長度表示。

那么什么又是平面向量呢?

平面向量是最簡單的張量配置。它們就像是你上面看到的常規(guī)向量,唯一的不同是它們處在一個向量空間中。為了更好地理解這一點,讓我們從一個例子開始:你有一個 2×1 的向量。也就是說該向量屬于一次配對兩個數(shù)的實數(shù)集?;蛘邠Q句話說,它們是一個二維空間的一部分。在這種情況,你可以使用箭頭或射線在坐標(biāo) (x,y) 平面表示向量。

從一個標(biāo)準(zhǔn)位置(其中向量的起點為 (0,0))的坐標(biāo)平面出發(fā),你可以通過查看該向量的第一行來推導(dǎo) x 坐標(biāo),同時你也可以在第二行找到 y 坐標(biāo)。當(dāng)然,并不一定總是要維持這種標(biāo)準(zhǔn)位置,向量可以在平面內(nèi)平行移動而不發(fā)生改變。

注:類似地,對于大小為 3×1 的向量,那就是在談?wù)撘粋€三維空間。你可以將該向量表示成一個三維圖形,帶有指向其向量速度位置的箭頭:它們被畫在標(biāo)準(zhǔn)的 x, y 和 z 軸上。

將這些向量表示到坐標(biāo)平面上是很好的,但本質(zhì)上,這些向量可以用來執(zhí)行運算,為了幫助做到這一點,你可以將你的向量表示成基礎(chǔ)或單位向量。

單位向量是指幅度為 1 的向量,通常用帶有「帽子」的小寫字母表示。如果你想將一個二維或三維向量表示成兩個或三個正交分量(比如 x 軸、y 軸和 z 軸)的和,單位向量可以非常方便。

而且比如當(dāng)你考慮將一個向量表示成分量的和時,你會發(fā)現(xiàn)你在討論分量向量,其是兩個或三個向量,它們的和即是原來給出的向量。

提示:這個視頻用簡單的家用物品解釋了張量:https://www.youtube.com/watch?v=f5liqUk0ZTw

張量

平面向量以及余向量(covector)和線性運算符(linear operator)這三者有一個共同點:它們都是張量的特定案例。你仍然記得前一節(jié)中如何將向量特征化為帶有一個方向的標(biāo)量。那么,張量就是一種帶有幅度和多個方向的物理實體的一種數(shù)學(xué)表征。

而且,就向你通過單個數(shù)字表示一個標(biāo)量,3 個數(shù)字的序列表示一個三維空間中的向量一樣,三維空間中的張量可以通過具有 3R 個數(shù)字的數(shù)組表示。

這里的 R 表示張量的秩(rank):比如在一個三維空間中,一個第二秩張量(second-rank tensor)可以用 3^2=9 個數(shù)字表示。在一個 N 維空間中,標(biāo)量仍然只需要一個數(shù)字,而向量則需要 N 個數(shù)字,張量則需要 N^R 個數(shù)字。這就是為什么你常會聽到人們說標(biāo)量是 0 秩的張量:因為沒有方向,你可以使用一個數(shù)字表示它。

記住這一點,就能輕松識別和區(qū)分標(biāo)量、向量和張量了:標(biāo)量可以用單個數(shù)字表示,向量是一個有序的數(shù)字集合,張量是一個數(shù)字的陣列。

張量的獨特之處在于分量和基向量的組合:基向量在參考系之間按一種方式變換,分量也只按這樣一種方式變換以保證分量和基向量之間的組合不變。

安裝 TensorFlow

現(xiàn)在你對 TensorFlow 已經(jīng)有了一定程度的了解了,那就讓我們開始上手安裝這個庫吧。這里需要說明一下,TensorFlow 提供了 Python、C++、Haskell、Java、Go、Rust 的 API,另外還有一個用于 R 語言的第三方軟件包 tensorflow.

提示:如果你想知道更多 R 語言的深度學(xué)習(xí)軟件包,可以參閱《keras: Deep Learning in R》:https://www.datacamp.com/community/tutorials/keras-r-deep-learning#gs.aLGxTIg

在本教程中,你要下載可以用 Python 編寫你的深度學(xué)習(xí)項目的 TensorFlow 版本。在 TensorFlow 安裝頁面 https://www.tensorflow.org/install/,你可以看到一些使用 virtualenc、pip、Docker 和 lastly 安裝 TensorFlow 的最常見方式和最新說明,當(dāng)然另外也有其它一些在你的個人計算機(jī)上安裝 TensorFlow 的方法。

注:如果你用的 Windows,你也可使用 Conda 安裝 TensorFlow。但是因為這種安裝方式是社區(qū)提供支持的,最好還是參考官方的安裝說明:https://www.tensorflow.org/install/install_windows

現(xiàn)在你應(yīng)該已經(jīng)完成了安裝,現(xiàn)在需要再次檢查你是否正確安裝了 TensorFlow,你可以將其導(dǎo)入到別名 tf 之下的工作空間:

  1. import tensorflow as tf 

注:在上面的代碼中使用的別名 tf 是一種慣例——使用這個別名既能讓你與其他在數(shù)據(jù)科學(xué)項目中使用 TensorFlow 的開發(fā)者保持一致,也有助于開源 TensorFlow 項目。

TensorFlow 入門:基礎(chǔ)知識

你將能寫一般的 TensorFlow 程序,你可以將其作為一個塊(chunk)運行;當(dāng)你使用 Python 時,一眼看上去這或許有點矛盾。但是,如果你愿意,你也可以使用 TensorFlow 的 Interactive Session,讓你可以對 TensorFlow 進(jìn)行更交互式的操作。當(dāng)你習(xí)慣了 IPython 時,這會非常方便。

對于這個教程,我們的重點是第二個選項:這將有助于你通過 TensorFlow 上手深度學(xué)習(xí)。但在你深入之前,先讓我們嘗試一些輕量級的,之后再進(jìn)入重量級挑戰(zhàn)。

首先,在別名 tf 下導(dǎo)入 tensorflow 庫,正如你在前一節(jié)看到的那樣。然后初始化兩個實際上是常量的變量。將一個 4 個數(shù)字的數(shù)組傳遞到 constant( ) 函數(shù)。

注:你可能也可以傳入一個整數(shù),但通常不會這樣,你會發(fā)現(xiàn)你操作的是數(shù)組。正如引言中介紹的那樣,張量就是關(guān)于數(shù)組!所以要確保你傳遞的是數(shù)組。接下來,你可以使用 multiply() 來將你的兩個變量相乘。結(jié)果存儲在 result 變量中。最后,在 print() 函數(shù)的幫助下顯示 result 結(jié)果。

 

注:你已經(jīng)在上面的 DataCamp Light 代碼塊中定義了常量,但你也可以使用另外兩種類型的值,即占位符(placeholder)和變量(variable)。占位符是指沒有分配的值,在你開始運行該 session 時會被初始化。正如其名,它只是張量的一個占位符,在 session 運行時總是得到饋送。變量是指值可以變化的量。而前面你已經(jīng)見過的常量的值則不會變化。

這幾行代碼的結(jié)果是計算圖中的一個抽象張量。但是可能與你預(yù)期的相反,result 實際上沒有得到計算;它只是定義了模型,但沒有運行進(jìn)程來計算結(jié)果。你可以在顯示輸出中看到,其中并沒有你希望看到的結(jié)果(比如 30)。這意味著 TensorFlow 的評估很懶惰!

但是,如果你確實想看到這個結(jié)果,你就必須以一種交互式會話的方式運行這段代碼。做到這一點的方式有好幾個,下面展示了在 DataCamp Light 代碼塊中的情況:

 

注:你可以使用以下代碼來啟動一個交互式 Session,運行 result,并在顯示輸出 output 之后再次自動關(guān)閉 Session。 

 

在上面的代碼塊中,你剛剛定義了一個默認(rèn) Session,但要知道你也可以傳遞選項。比如說,你可以指定 config 參數(shù),然后使用 ConfigProto 協(xié)議緩沖來為你的 session 增加配置選項。

比如說,如果你為你的 Session 增加了 config=tf.ConfigProto(log_device_placement=True),你就可以確保你錄入了運算分配到的 GPU 和 CPU 設(shè)備。然后你就可以了解在該 session 中每個運算使用了哪個設(shè)備。比如當(dāng)你為設(shè)備配置使用軟約束時,你也可使用下面的配置 session: config=tf.ConfigProto(allow_soft_placement=True).

現(xiàn)在你已經(jīng)裝好了 TensorFlow,并且將其導(dǎo)入到了你的工作空間,你也了解了操作這個軟件包的基礎(chǔ)知識?,F(xiàn)在是時候調(diào)整一下方向,關(guān)注一下數(shù)據(jù)了。就像了解其它事情一樣,首先你要花時間探索和更好地了解你的數(shù)據(jù),然后才能開始建模你的神經(jīng)網(wǎng)絡(luò)。

比利時交通標(biāo)志:背景

盡管交通是一個通常你們都知道的主題,但不妨也簡單了解一下這個數(shù)據(jù)集中的數(shù)據(jù),看你在開始之前是否已經(jīng)明白了一切。本質(zhì)上,這一節(jié)將讓你快速了解你進(jìn)一步學(xué)習(xí)本教程所需的領(lǐng)域知識。

當(dāng)然,因為我是比利時人,所以用了比利時的交通標(biāo)志數(shù)據(jù)。這里給出了一些有趣的軼事:

  • 比利時交通標(biāo)志通常為荷蘭語和法語。了解這一點當(dāng)然不錯,但對于你要操作的數(shù)據(jù)集,這并不重要!
  • 比利時的交通標(biāo)志分成六大類:警告標(biāo)志、優(yōu)先標(biāo)志、禁令標(biāo)志、強(qiáng)制性標(biāo)志、與停車和在路上等待相關(guān)的標(biāo)志、指示牌。
  • 在 2017 年 1 月 1 日,比利時移除了超過 30,000 塊交通標(biāo)志。它們都是與速度相關(guān)的優(yōu)先標(biāo)志。
  • 談到移除,在比利時(而且可以擴(kuò)展到整個歐盟),過多的交通標(biāo)志一直以來都是一個討論話題。

加載和探索數(shù)據(jù)

現(xiàn)在你已經(jīng)得到了更多一些背景信息,該下載數(shù)據(jù)了:http://btsd.ethz.ch/shareddata/。你應(yīng)該下載 BelgiumTS for Classification (cropped images) 右邊的兩個壓縮包: BelgiumTSC_Training 和 BelgiumTSC_Testing。

提示:如果你已經(jīng)下載了這些文件或者將會在完成本教程后下載,那就看看你下載的數(shù)據(jù)的文件夾結(jié)構(gòu)!你將看到測試和訓(xùn)練數(shù)據(jù)文件夾包含了 61 個子文件夾,這是你將在本教程中使用的用于分類任務(wù)的 62 種類型的交通標(biāo)志。另外,你會發(fā)現(xiàn)這些文件的文件擴(kuò)展名是 .ppm,即 Portable Pixmap Format。你已經(jīng)下載好了交通標(biāo)志圖片!

讓我們先把這些數(shù)據(jù)導(dǎo)入到你的工作空間。讓我們先從出現(xiàn)在用戶定義函數(shù)(UDF)load_data() 下面的代碼行開始:

  • 首先,設(shè)置你的 ROOT_PATH。這個路徑是帶有你的訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)的目錄。
  • 接下來,你可以借助 join() 函數(shù)為 ROOT_PATH 增加特定的路徑。你將這兩個特定的路徑存儲在 train_data_directory 和 test_data_directory 中
  • 之后,你可以調(diào)用 load_data() 函數(shù),并將 train_data_directory 作為它的參數(shù)。
  • 現(xiàn)在 load_data() 啟動并自己開始收集 train_data_directory 下的所有子目錄;為此它借助了一種被稱為列表推導(dǎo)式(list comprehension)的方法——這是一種構(gòu)建列表的自然方法。基本上就是說:如果在 train_data_directory 中發(fā)現(xiàn)了一些東西,就雙重檢查這是否是一個目錄;如果是,就將其加入到你的列表中。注意:每個子目錄都代表了一個標(biāo)簽。
  • 接下來,你必須循環(huán)遍歷這些子目錄。首先你要初始化兩個列表:labels 和 imanges。然后你要收集這些子目錄的路徑以及存儲在這些子目錄中的圖像的文件名。之后,你可以使用 append() 函數(shù)來收集這兩個列表中的數(shù)據(jù)。
  1. def load_data(data_directory): 
  2.     directories = [d for d in os.listdir(data_directory)  
  3.                    if os.path.isdir(os.path.join(data_directory, d))] 
  4.     labels = [] 
  5.     images = [] 
  6.     for d in directories: 
  7.         label_directory = os.path.join(data_directory, d) 
  8.         file_names = [os.path.join(label_directory, f)  
  9.                       for f in os.listdir(label_directory)  
  10.                       if f.endswith(".ppm")] 
  11.         for f in file_names: 
  12.             images.append(skimage.data.imread(f)) 
  13.             labels.append(int(d)) 
  14.     return images, labels 
  15.  
  16. ROOT_PATH = "/your/root/path" 
  17. train_data_directory = os.path.join(ROOT_PATH, "TrafficSigns/Training"
  18. test_data_directory = os.path.join(ROOT_PATH, "TrafficSigns/Testing"
  19.  
  20. images, labels = load_data(train_data_directory)  

注意在上面的代碼塊中,訓(xùn)練數(shù)據(jù)和測試數(shù)據(jù)分別位于名為 Training 和 Testing 的文件夾中,這兩個文件夾都是另一個目錄 TrafficSigns 的子目錄。在一個本地機(jī)器上,其路徑可能是這樣的:/Users/yourName/Downloads/TrafficSigns,之后帶有兩個子文件夾 Training 和 Testing。

交通標(biāo)志統(tǒng)計數(shù)據(jù)

加載好你的數(shù)據(jù)后,就可以做些數(shù)據(jù)檢查(data inspection)了!首先你可以使用 images 數(shù)組的 ndim 和 size 屬性做一些相當(dāng)簡單的分析:

注意 images 和 labels 變量都是列表,所以你可能需要使用 np.array() 將這些變量轉(zhuǎn)換成你工作空間中的數(shù)組。這里已經(jīng)為你做好了!

 

注:響應(yīng)輸出的 images[0] 實際上是由數(shù)組中的數(shù)組表示的單個圖像。一開始這可能看起來與直覺相反,但隨著你在機(jī)器學(xué)習(xí)或深度學(xué)習(xí)應(yīng)用中對圖像操作的進(jìn)一步理解,你會習(xí)慣的。

接下來,你也可以簡單看看 labels,但現(xiàn)在你應(yīng)該不會太過驚訝了:

 

這些數(shù)字能讓你了解你的導(dǎo)入有多成功以及你的數(shù)據(jù)的確切大小。大略看看,一切都是按照你預(yù)期的方式執(zhí)行的,而且如果你考慮到你正在處理數(shù)組中的數(shù)組,那么你會看到數(shù)組的大小是相當(dāng)大的。

提示:試試將以下屬性添加到你的數(shù)組中,即使用 flags、itemsize 和 nbytes 屬性獲取關(guān)于內(nèi)存布局(memory layout)、一個數(shù)組元素的字節(jié)長度和總消耗字節(jié)數(shù)的更多信息。你可以在上面的 DataCamp Light 塊中的 IPython 控制臺中測試這些屬性!

接下來,你也可以看看這些交通標(biāo)志數(shù)據(jù)的分布情況:

 

干得漂亮!現(xiàn)在讓我們仔細(xì)看看你做出的直方圖!

 

你可以清楚地看到,所有類型的交通標(biāo)志都在該數(shù)據(jù)集中得到了平等地表示。這是后面你開始建模神經(jīng)網(wǎng)絡(luò)之前操作你的數(shù)據(jù)時所需要處理的東西。

大略來看,你可以看到該數(shù)據(jù)集中有的標(biāo)簽的分量比其它標(biāo)簽更重:標(biāo)簽 22、32、38 和 61 顯然出類拔萃?,F(xiàn)在記住這一點,在下一節(jié)你會更深入地了解!

可視化交通標(biāo)志數(shù)據(jù)

前面的小型分析和檢查已經(jīng)讓你對這些數(shù)據(jù)有所了解了,但是當(dāng)你的數(shù)據(jù)基本上是由圖像構(gòu)成時,你應(yīng)該通過可視化的方式來探索你的數(shù)據(jù)。

我們先來看看一些隨機(jī)的交通標(biāo)志:

  • 首先,確保你在常用別名 plt 下導(dǎo)入了 matplotlib 軟件包的 pyplot 模塊。
  • 然后,你需要創(chuàng)建一個帶有 4 個隨機(jī)數(shù)字的列表。這些會被用于從 images 數(shù)組中選擇你在前一節(jié)檢查過的交通標(biāo)志。在這個案例中,你會選擇 300、2250、3650 和 4000.
  • 接下來,對于列表長度中的每個元素,即從 0 到 4,你要創(chuàng)建一個沒有軸的子圖(subplot)(這樣它們就不會關(guān)注所有東西,而只會單獨關(guān)注于圖像!)。在這些子圖中,你將展示與索引 i 中數(shù)字相符的 images 數(shù)組中的特定圖像。在第一次循環(huán)中,你會把 300 傳遞給 images[],在第二輪傳遞 2250,依此類推。最后你需要調(diào)整子圖使它們之間具有足夠的寬度。
  • 最后使用 show() 函數(shù)展示你的圖表!

代碼如下:

  1. # Import the `pyplot` module of `matplotlib` 
  2. import matplotlib.pyplot as plt 
  3.  
  4. # Determine the (random) indexes of the images that you want to see  
  5. traffic_signs = [300, 2250, 3650, 4000] 
  6.  
  7. # Fill out the subplots with the random images that you defined  
  8. for i in range(len(traffic_signs)): 
  9.     plt.subplot(1, 4, i+1) 
  10.     plt.axis('off'
  11.     plt.imshow(images[traffic_signs[i]]) 
  12.     plt.subplots_adjust(wspace=0.5) 
  13.  
  14. plt.show()  

因為該數(shù)據(jù)集包含 62 個標(biāo)簽,你大概也猜到了這些交通標(biāo)志彼此之間存在差異。

但你還注意到了什么?仔細(xì)看看下面的圖像:

[[198757]] 

這四張圖像的大小不一樣!

顯然你可以嘗試調(diào)整包含在 traffic_signs 列表中的數(shù)字,并對這個觀察進(jìn)行更全面的跟蹤。但實際上,這是一個重要的觀察結(jié)果——當(dāng)你開始操作你的數(shù)據(jù)以便將其輸入神經(jīng)網(wǎng)絡(luò)時,你會需要將這個觀察結(jié)果考慮進(jìn)來。

讓我們通過輸出包含在這些子圖中的特定圖像的形狀(shape)、最小值和最大值來確認(rèn)圖片大小不同的假設(shè)。

下面的代碼與前面用來創(chuàng)建上面的圖的代碼非常相似,但不同的地方在于你將交替大小和圖像,而不只是繪制接連的圖像。

  1. # Import `matplotlib` 
  2. import matplotlib.pyplot as plt 
  3.  
  4. # Determine the (random) indexes of the images 
  5. traffic_signs = [300, 2250, 3650, 4000] 
  6.  
  7. # Fill out the subplots with the random images and add shape, min and max values 
  8. for i in range(len(traffic_signs)): 
  9.     plt.subplot(1, 4, i+1) 
  10.     plt.axis('off'
  11.     plt.imshow(images[traffic_signs[i]]) 
  12.     plt.subplots_adjust(wspace=0.5) 
  13.     plt.show() 
  14.     print("shape: {0}, min: {1}, max: {2}".format(images[traffic_signs[i]].shape,  
  15.                                                   images[traffic_signs[i]].min(),  
  16.                                                   images[traffic_signs[i]].max()))  

注:你如何在 shape: {0}, min: {1}, max: {2} 串上使用 format() 方法來填充你定義的參數(shù) {0}、{1} 和 {2}。

 

現(xiàn)在你已經(jīng)看到了松散的圖像,你可能還需要再看看你在數(shù)據(jù)探索的開始階段輸出的直方圖:你可以通過繪制所有 62 個類的整體情況以及屬于每個類的一張圖像來輕松做到這一點。

  1. # Import the `pyplot` module as `plt` 
  2. import matplotlib.pyplot as plt  
  3.  
  4. # Get the unique labels  
  5. unique_labels = set(labels) 
  6.  
  7. # Initialize the figure 
  8. plt.figure(figsize=(15, 15)) 
  9.  
  10. Set a counter 
  11. i = 1 
  12.  
  13. For each unique label, 
  14. for label in unique_labels: 
  15.     # You pick the first image for each label 
  16.     image = images[labels.index(label)] 
  17.     # Define 64 subplots  
  18.     plt.subplot(8, 8, i) 
  19.     # Don't include axes 
  20.     plt.axis('off'
  21.     # Add a title to each subplot  
  22.     plt.title("Label {0} ({1})".format(label, labels.count(label))) 
  23.     # Add 1 to the counter 
  24.     i += 1 
  25.     # And you plot this first image  
  26.     plt.imshow(image) 
  27.      
  28. # Show the plot 
  29. plt.show()  

注:即使你定義了 64 個子圖,也并不是它們所有都會展示圖像(因為總共只有 62 個標(biāo)簽!)。再注意一下,你不需要包含任何軸以確保閱讀器的注意不會偏離主要主題:交通標(biāo)志!

 

正如你基本上在上述直方圖中猜到的那樣,具有標(biāo)簽 22、32、38 和 61 的交通標(biāo)志要多得多。上面的假設(shè)在這幅圖中得到了確認(rèn):你可以看到標(biāo)簽 22 有 375 個實例,標(biāo)簽 32 有 316 實例,標(biāo)簽 38 有 285 個實例,標(biāo)簽 61 有 282 個實例。

你可能要問一個有趣的問題:所有這些實例之間有什么聯(lián)系嗎——也許它們都是指示標(biāo)志?

讓我們仔細(xì)看看:你可以看到標(biāo)簽 22 和 32 是禁令標(biāo)志,而標(biāo)簽 38 和 61 則分別是指示標(biāo)志和優(yōu)先標(biāo)志。這意味著這四者之間并沒有直接的聯(lián)系,只是禁令標(biāo)志大量存在,占到了該數(shù)據(jù)集的一半。

特征提取

現(xiàn)在你已經(jīng)全面探索了你的數(shù)據(jù),是時候開始實戰(zhàn)了!讓我們簡要回顧一下你的發(fā)現(xiàn),以確保你沒有忘記操作中的任何步驟。

  • 圖像的大小是不同的;
  • 存在 62 個標(biāo)簽或目標(biāo)值(因為你的標(biāo)簽始于 0,終于 61);
  • 交通標(biāo)志值的分布相當(dāng)不平衡;數(shù)據(jù)集中大量存在的標(biāo)志之間實際上并沒有任何聯(lián)系。

現(xiàn)在你已經(jīng)清楚了解了你需要改進(jìn)的內(nèi)容,你可以從加工你的數(shù)據(jù)開始,以使其可以用于神經(jīng)網(wǎng)絡(luò)或任何你想讓用來處理該數(shù)據(jù)的模型中——你將重新調(diào)整圖像的大小,并將這些保存在 images 數(shù)組中的圖像轉(zhuǎn)換成灰度圖像。進(jìn)行這種顏色轉(zhuǎn)換的主要原因是顏色在你正嘗試解決的這種分類問題上作用不大。但是對于檢測任務(wù)來說,顏色確實發(fā)揮了很大作用!所以在這些案例中,不需要進(jìn)行這樣的轉(zhuǎn)換!

重調(diào)圖像大小

為了解決不同圖像大小的問題,你需要重調(diào)圖像大小。你可以使用 skimage 或 Scikit-Image 庫輕松實現(xiàn)這一目標(biāo);Scikit-Image 是一個用于圖像處理的算法的集合。

在這個案例中,transform 模塊用起來很方便,因為其提供了一個 resize() 函數(shù);你將看到你會使用列表推導(dǎo)式(再一次!)來將每張圖像的大小調(diào)整為 28×28 像素。再一次,你將看到你實際構(gòu)建列表的方式:對于每一張你在 images 數(shù)組中找到的圖像,你都可以執(zhí)行從 skimage 庫借用的變換運算。最后,你將結(jié)果存儲在 images28 變量中:

  1. # Import the `transform` module from `skimage` 
  2. from skimage import transform  
  3.  
  4. # Rescale the images in the `images` array 
  5. images28 = [transform.resize(image, (28, 28)) for image in images]  

是不是很簡單?

注:圖像現(xiàn)在是 4 維的:如果你將 images28 轉(zhuǎn)換成一個數(shù)組,并且如果你將屬性 shape 連接到它,你就會看到輸出的結(jié)果表明 images28 的維度為 (4575, 28, 28, 3)。這些圖像是 784 維的(因為你的圖像是 28×28 像素的)。

你可以借助 traffic_signs 變量,通過復(fù)用上面你用過的代碼來給出 4 張隨機(jī)圖像的圖表,從而對大小調(diào)整操作進(jìn)行檢查。只是不要忘記將所有的參考都從 images 改成 images28。

結(jié)果如下:

 

注:因為你調(diào)整過大小了,所以你的 min 和 max 值都已經(jīng)改變了;現(xiàn)在它們似乎全部都在同一個范圍內(nèi),這是一件非常好的事,因為你不再需要規(guī)范化你的數(shù)據(jù)了!

將圖像轉(zhuǎn)換成灰度圖像

正如本節(jié)介紹中提到的那樣,在嘗試解決分類問題時,圖像的顏色的作用更小。所以你也需要麻煩一下,將圖像轉(zhuǎn)換成灰度圖像。但是注意,你也可以自己試試看如果不做這一步,對你的模型的最終結(jié)果有什么影響。就像調(diào)整圖像大小一樣,你也可以使用 Scikit-Image 庫來解決;在這個案例中,我們要在你需要的地方使用 color 模塊中的 rgb2gray() 函數(shù)。這非常好用,而且很簡單!

但是,不要忘記將 image28 變量轉(zhuǎn)換回數(shù)組,因為 rgb2gray() 函數(shù)并不使用數(shù)組作為參數(shù)。

  1. # Import `rgb2gray` from `skimage.color` 
  2. from skimage.color import rgb2gray 
  3.  
  4. Convert `images28` to an array 
  5. images28 = np.array(images28) 
  6.  
  7. Convert `images28` to grayscale 
  8. images28 = rgb2gray(images28) 

 

再通過輸出一些圖像的圖表來檢查一下你的灰度轉(zhuǎn)換;這里,你可以再次復(fù)用并稍微調(diào)整一些代碼來顯示調(diào)整后的圖像:

  1. import matplotlib.pyplot as plt 
  2.  
  3. traffic_signs = [300, 2250, 3650, 4000] 
  4.  
  5. for i in range(len(traffic_signs)): 
  6.     plt.subplot(1, 4, i+1) 
  7.     plt.axis('off'
  8.     plt.imshow(images28[traffic_signs[i]], cmap="gray"
  9.     plt.subplots_adjust(wspace=0.5) 
  10.      
  11. # Show the plot 
  12. plt.show()  

注:你確實必須指定顏色圖(即 cmap),并將其設(shè)置為 gray 以給出灰度圖像的圖表。這是因為 imshow() 默認(rèn)使用一種類似熱力圖的顏色圖。更多信息參閱:https://stackoverflow.com/questions/39805697/skimage-why-does-rgb2gray-from-skimage-color-result-in-a-colored-image

提示:因為在本教程中你已經(jīng)復(fù)用了這個函數(shù)很多次,所以你可以看看你是如何使其成為一個函數(shù)的 :)

這兩個步驟是非?;A(chǔ)的;其它你可以在你的數(shù)據(jù)上嘗試的操作包括數(shù)據(jù)增強(qiáng)(旋轉(zhuǎn)、模糊、位移、改變亮度……)等。如果你愿意,你也可以通過你發(fā)送圖像的方式來設(shè)置整個數(shù)據(jù)操作運算的流程。

使用 TensorFlow 做深度學(xué)習(xí)

現(xiàn)在你已經(jīng)探索并操作好了你的數(shù)據(jù),該使用 TensorFlow 軟件包來構(gòu)建你的神經(jīng)網(wǎng)絡(luò)架構(gòu)了!

建模神經(jīng)網(wǎng)絡(luò)

就像你可以用 Keras 做的那樣,現(xiàn)在是時候一層層構(gòu)建你的神經(jīng)網(wǎng)絡(luò)了。

如果你還沒試過,就先將 tensorflow 導(dǎo)入到慣例別名 tf 的工作空間中。然后你可以借助 Graph() 對圖進(jìn)行初始化。你可以使用這個函數(shù)來定義計算。注意如果只有這個圖,那你就不能計算任何東西,因為它不保留任何值。它只是定義你想在之后運行的運算。

在這個案例中,你可以使用 as_default() 設(shè)置一個默認(rèn)背景,該函數(shù)會返回一個背景管理器,可使這個特定圖成為默認(rèn)的圖。如果你想在這同一個流程中創(chuàng)建多個圖,你也可以使用這種方法:使用這個函數(shù),如果你不明確創(chuàng)建一個新圖,那你就為所有將被加入的運算設(shè)置了一個全局默認(rèn)圖。

  • 接下來,你就可以將運算加入到你的圖中了。在 Keras 中,你需要先構(gòu)建你的模型,然后在編譯它,你要定義一個損失函數(shù)、一個優(yōu)化器和一個指標(biāo)。而使用 TensorFlow,你一步就能完成上述操作:
  • 首先,你要為輸入和標(biāo)簽定義占位符,因為你尚未輸入「真實」數(shù)據(jù)。記住占位符是未分配的值,可以在你運行它時被 session 初始化。所以當(dāng)你運行該 session 結(jié)束時,這些占位符會獲取你在 run() 函數(shù)中傳遞的數(shù)據(jù)集中的值。
  • 然后構(gòu)建你的網(wǎng)絡(luò)。首先使用 flatten() 函數(shù)展平輸入,其會給你一個形狀為 [None, 784] 的數(shù)組,而不是 [None, 28, 28]——這是你的灰度圖像的形狀。
  • 在你展平了輸入之后,構(gòu)建一個全連接層,其可以生成大小為 [None, 62] 的 logits。logits 是運行在早期層未縮放的輸出上的函數(shù),其使用相對比例來了解單位是否是線性的。
  • 構(gòu)建出多層感知器后,就可以定義損失函數(shù)了。損失函數(shù)的選擇取決于當(dāng)前的任務(wù):在這個案例中,你可以使用 sparse_softmax_cross_entropy_with_logits(),其可以計算 logits 和標(biāo)簽之間的稀疏 softmax 交叉熵。換句話說,它測量的是離散分類任務(wù)中的概率誤差,在這些任務(wù)中,類別是互斥的。這意味著每一個條目(entry)都是一個單獨的類別。在這種情況下,一個交通標(biāo)志只會有一個標(biāo)簽。記住這一點,回歸(regression)被用于預(yù)測連續(xù)值,而分類(classification)則被用于預(yù)測離散值或數(shù)據(jù)點的類別。你可以使用 reduce_mean() 來包裹這個函數(shù),它可以計算一個張量的維度上各個元素的均值。
  • 你也需要定義一個訓(xùn)練優(yōu)化器;最流行的優(yōu)化算法包括隨機(jī)梯度下降(SGD)、ADAM 和 RMSprop。取決于你選擇的算法,你需要調(diào)節(jié)特定的參數(shù),比如學(xué)習(xí)率或動量。在這個案例中,你要選擇 ADAM,并將其學(xué)習(xí)率定義為 0.001。
  • 最后,你可以在進(jìn)入訓(xùn)練之前初始化要執(zhí)行的運算。

現(xiàn)在你已經(jīng)用 TensorFlow 創(chuàng)造出了你的第一個神經(jīng)網(wǎng)絡(luò)!

  1. # Import `tensorflow`  
  2. import tensorflow as tf  
  3.  
  4. # Initialize placeholders  
  5. x = tf.placeholder(dtype = tf.float32, shape = [None, 28, 28]) 
  6. y = tf.placeholder(dtype = tf.int32, shape = [None]) 
  7.  
  8. # Flatten the input data 
  9. images_flat = tf.contrib.layers.flatten(x) 
  10.  
  11. # Fully connected layer  
  12. logits = tf.contrib.layers.fully_connected(images_flat, 62, tf.nn.relu) 
  13.  
  14. # Define a loss function 
  15. loss = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels = y,  
  16.                                                                     logits = logits)) 
  17. # Define an optimizer  
  18. train_op = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss) 
  19.  
  20. Convert logits to label indexes 
  21. correct_pred = tf.argmax(logits, 1) 
  22.  
  23. # Define an accuracy metric 
  24. accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))  

如果你想,你可以顯示輸出大部分變量的值以快速了解和檢查你剛剛編寫的東西:

  1. print("images_flat: ", images_flat) 
  2.  
  3. print("logits: ", logits) 
  4.  
  5. print("loss: ", loss) 
  6.  
  7. print("predicted_labels: ", correct_pred)  

提示:如果看到了「module ‘pandas’ has no attribute ‘computation’」這樣的錯誤提示,可以通過在命令行運行 pip install –upgrade dask 來升級 dask 軟件包。參見這個帖子了解更多:https://stackoverflow.com/questions/43833081/attributeerror-module-object-has-no-attribute-computation

運行神經(jīng)網(wǎng)絡(luò)

現(xiàn)在你已經(jīng)一層層地構(gòu)建好了你的模型,可以跑起來了!要做到這一點,首先你需要使用 Session() 初始化一個 session,你可以將你在之前一節(jié)定義的圖 graph 傳遞給該函數(shù)。接下來,將同樣在前一節(jié)定義的初始化運算 init 變量傳遞給 run(),并通過該函數(shù)運行該 session。

接下來,你可以使用這些初始化的 session 來啟動 epoch 或訓(xùn)練循環(huán)。在這個案例中,你可以選擇 201,因為你需要注冊最新的 loss_value;在訓(xùn)練循環(huán)中,使用你在前一節(jié)定義的訓(xùn)練優(yōu)化器和損失(或準(zhǔn)確度)指標(biāo),運行這個 session。你也可以傳遞一個 feed_dict 參數(shù),你可以使用它將數(shù)據(jù)傳遞給模型。每 10 個 epoch 之后,你會獲得一個日志,能給你提供更多有關(guān)模型的損失或成本的信息。

正如你在 TensorFlow 基礎(chǔ)知識一節(jié)看到的那樣,我們不需要人工關(guān)閉 session;TensorFlow 會自動完成。但是,如果你想嘗試不同的設(shè)置,當(dāng)你將你的 session 定義為 sess 時,你可能將需要使用 sess.close(),就像在下列代碼塊中一樣:

  1. tf.set_random_seed(1234) 
  2. sess = tf.Session() 
  3.  
  4. sess.run(tf.global_variables_initializer()) 
  5.  
  6. for i in range(201): 
  7.         print('EPOCH', i) 
  8.         _, accuracy_val = sess.run([train_op, accuracy], feed_dict={x: images28, y: labels}) 
  9.         if i % 10 == 0: 
  10.             print("Loss: ", loss) 
  11.         print('DONE WITH EPOCH' 

記住,你也可以運行下面這段代碼,但這段代碼會在之后立即關(guān)閉 session,就像你在本教程的引言中看到的那樣:

  1. tf.set_random_seed(1234) 
  2.  
  3. with tf.Session() as sess: 
  4.     sess.run(tf.global_variables_initializer()) 
  5.     for i in range(201): 
  6.         _, loss_value = sess.run([train_op, loss], feed_dict={x: images28, y: labels}) 
  7.         if i % 10 == 0: 
  8.             print("Loss: ", loss)  

注:你使用了 global_variables_initializer(),因為不提倡使用 initialize_all_variables() 函數(shù)。

現(xiàn)在你已經(jīng)成功訓(xùn)練了你的模型!并不是很難吧?

評估你的神經(jīng)網(wǎng)絡(luò)

訓(xùn)練完了并不是結(jié)束;你還需要對你的神經(jīng)網(wǎng)絡(luò)進(jìn)行評估。在這個案例中,你可以通過選取隨機(jī) 10 張圖像并比較預(yù)測標(biāo)簽和真實標(biāo)簽來簡單了解你的模型的表現(xiàn)。

你首先可以顯示輸出它們,但為什么不使用 matplotlib 來得到交通標(biāo)志本身的圖表并進(jìn)行視覺比較呢?

  1. # Import `matplotlib` 
  2. import matplotlib.pyplot as plt 
  3. import random 
  4.  
  5. # Pick 10 random images 
  6. sample_indexes = random.sample(range(len(images28)), 10) 
  7. sample_images = [images28[i] for i in sample_indexes] 
  8. sample_labels = [labels[i] for i in sample_indexes] 
  9.  
  10. # Run the "correct_pred" operation 
  11. predicted = sess.run([correct_pred], feed_dict={x: sample_images})[0] 
  12.                          
  13. # Print the real and predicted labels 
  14. print(sample_labels) 
  15. print(predicted) 
  16.  
  17. # Display the predictions and the ground truth visually. 
  18. fig = plt.figure(figsize=(10, 10)) 
  19. for i in range(len(sample_images)): 
  20.     truth = sample_labels[i] 
  21.     prediction = predicted[i] 
  22.     plt.subplot(5, 2,1+i) 
  23.     plt.axis('off'
  24.     color='green' if truth == prediction else 'red' 
  25.     plt.text(40, 10, "Truth:        {0}\nPrediction: {1}".format(truth, prediction),  
  26.              fontsize=12, color=color) 
  27.     plt.imshow(sample_images[i],  cmap="gray"
  28.  
  29. plt.show()  

 

但是,僅僅查看隨機(jī)圖像并不能讓你了解你的模型的表現(xiàn)究竟如何。所以你需要加載測試數(shù)據(jù)。

  1. # Import `skimage` 
  2. from skimage import transform 
  3.  
  4. Load the test data 
  5. test_images, test_labels = load_data(test_data_directory) 
  6.  
  7. # Transform the images to 28 by 28 pixels 
  8. test_images28 = [transform.resize(image, (28, 28)) for image in test_images] 
  9.  
  10. Convert to grayscale 
  11. from skimage.color import rgb2gray 
  12. test_images28 = rgb2gray(np.array(test_images28)) 
  13.  
  14. # Run predictions against the full test set
  15. predicted = sess.run([correct_pred], feed_dict={x: test_images28})[0] 
  16.  
  17. # Calculate correct matches  
  18. match_count = sum([int(y == y_) for y, y_ in zip(test_labels, predicted)]) 
  19.  
  20. # Calculate the accuracy 
  21. accuracy = match_count / len(test_labels) 
  22.  
  23. # Print the accuracy 
  24. print("Accuracy: {:.3f}".format(accuracy))  

注:你要使用 load_data() 函數(shù),你在本教程開始時定義了這個函數(shù)。

記住使用 sess.close() 關(guān)閉 session,以防你沒有使用 with tf.Session() as sess: 來啟動你的 TensorFlow session。

接下來看什么?

如果你想繼續(xù)使用這個教程中的數(shù)據(jù)集和模型,可以嘗試下面的東西:

在你的數(shù)據(jù)上應(yīng)用正則化 LDA,之后再將其應(yīng)用于你的模型。這個建議來自于一篇原始論文:http://btsd.ethz.ch/shareddata/publications/Mathias-IJCNN-2013.pdf,是由收集并分析這個數(shù)據(jù)集的研究者寫的。

正如在本教程中說的那樣,你也可以在這些交通標(biāo)志數(shù)據(jù)上執(zhí)行一些其它的數(shù)據(jù)增強(qiáng)操作。此外,你也可以嘗試進(jìn)一步調(diào)整這個網(wǎng)絡(luò)——你目前創(chuàng)造的這個網(wǎng)絡(luò)還相當(dāng)簡單。

早停(early stopping):在你訓(xùn)練神經(jīng)網(wǎng)絡(luò)時,要一直關(guān)注訓(xùn)練和測試誤差。當(dāng)兩個誤差都下降又突然升高時要停止訓(xùn)練——這是神經(jīng)網(wǎng)絡(luò)開始過擬合訓(xùn)練數(shù)據(jù)的征兆。

一定要看 Nishant Shukla 寫的書《Machine Learning With TensorFlow》:https://www.manning.com/books/machine-learning-with-tensorflow

提示:另外也看看 TensorFlow Playground(http://playground.tensorflow.org)和 TensorBoard(https://www.tensorflow.org/get_started/summaries_and_tensorboard)。

如果你想繼續(xù)處理圖像,肯定不能錯過 DataCamp 的 scikit-learn 教程:https://www.datacamp.com/community/tutorials/machine-learning-python,在這個教程中你將了解如何用 PCA、K-均值和支持向量機(jī)(SVM)來處理 MNIST 數(shù)據(jù)集。你也可以看看其它使用了比利時交通標(biāo)志數(shù)據(jù)集的教程,比如:https://github.com/waleedka/traffic-signs-tensorflow/blob/master/notebook1.ipynb 

責(zé)任編輯:龐桂玉 來源: 36大數(shù)據(jù)
相關(guān)推薦

2017-12-25 11:50:57

LinuxArch Linux

2020-12-24 11:19:55

JavaMapHashMap

2009-08-14 11:35:01

Scala Actor

2010-04-07 13:05:57

2017-01-19 21:08:33

iOS路由構(gòu)建

2018-06-11 15:30:12

2019-03-05 14:09:27

Docker存儲容器

2019-07-09 15:23:22

Docker存儲驅(qū)動

2018-12-24 10:04:06

Docker存儲驅(qū)動

2017-01-06 15:13:25

LinuxVim源代碼

2010-08-10 11:31:36

路由器配置NAT

2009-04-15 09:29:07

2010-08-12 10:02:16

路由器NAT

2010-03-04 16:28:17

Android核心代碼

2016-11-02 18:54:01

javascript

2024-11-18 17:12:18

C#編程.NET

2011-09-05 12:36:08

路由器限速linux路由器

2024-07-22 14:48:26

網(wǎng)絡(luò)SSH

2011-05-10 10:28:55

2024-08-30 08:30:29

CPU操作系統(tǒng)寄存器
點贊
收藏

51CTO技術(shù)棧公眾號