Tensorflow實戰 手寫數字識別(Tensorboard可視化)


一、前言

為了更好的理解Neural Network,本文使用Tensorflow實現一個最簡單的神經網絡,然后使用MNIST數據集進行測試。同時使用Tensorboard對訓練過程進行可視化,算是打響學習Tensorflow的第一槍啦。

看本文之前,希望你已經具備機器學習和深度學習基礎。

機器學習基礎可以看我的系列博文:

https://cuijiahua.com/blog/ml/

深度學習基礎可以看吳恩達老師的公開課:

http://mooc.study.163.com/smartSpec/detail/1001319001.htm

二、MNIST數據集簡介

當我們學習新的編程語言時,通常第一個程序就是打印輸出著名的“Hello World!”。在深度學習中,MNIST數據集就相當於Hello World。

MNIST是一個簡單的計算機視覺數據集,它包含手寫數字的圖像集:

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

 

數據集:

  • train-images-idx3-ubyte 訓練數據圖像 (60,000)
  • train-labels-idx1-ubyte 訓練數據label
  • t10k-images-idx3-ubyte 測試數據圖像 (10,000)
  • t10k-labels-idx1-ubyte 測試數據label

每張圖像是28 * 28像素:

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

我們的任務是使用上面數據訓練一個可以准確識別手寫數字的神經網絡模型,並使用Tensorflow對訓練過程各個參數的變化進行可視化。

三、Tensorboard簡介

本文要使用到Tensorboard,先讓我們看看它究竟是用來干什么的。

當使用Tensorflow訓練大量深層的神經網絡時,我們希望去跟蹤神經網絡的整個訓練過程中的信息,比如迭代的過程中每一層參數是如何變化與分布的,比如每次循環參數更新后模型在測試集與訓練集上的准確率是如何的,比如損失值的變化情況,等等。如果能在訓練的過程中將一些信息加以記錄並可視化得表現出來,是不是對我們探索模型有更深的幫助與理解呢?

Tensorflow官方推出了可視化工具Tensorboard,可以幫助我們實現以上功能,它可以將模型訓練過程中的各種數據匯總起來存在自定義的路徑與日志文件中,然后在指定的web端可視化地展現這些信息。

1、Tensorboard的數據形式:

Tensorboard可以記錄與展示以下數據形式:

(1)標量Scalars

(2)圖片Images

(3)音頻Audio

(4)計算圖Graph

(5)數據分布Distribution

(6)直方圖Histograms

(7)嵌入向量Embeddings

2、Tensorboard的可視化過程:

(1)首先肯定是先建立一個graph,你想從這個graph中獲取某些數據的信息

(2)確定要在graph中的哪些節點放置summary operations以記錄信息

使用tf.summary.scalar記錄標量

使用tf.summary.histogram記錄數據的直方圖

使用tf.summary.distribution記錄數據的分布圖

使用tf.summary.image記錄圖像數據

.....等等

(3)operations並不會去真的執行計算,除非你告訴他們需要去run,或者它被其他的需要run的operation所依賴。而我們上一步創建的這些summary operations其實並不被其他節點依賴,因此,我們需要特地去運行所有的summary節點。但是呢,一份程序下來可能有超多這樣的summary 節點,要手動一個一個去啟動自然是及其繁瑣的,因此我們可以使用tf.summary.merge_all去將所有summary節點合並成一個節點,只要運行這個節點,就能產生所有我們之前設置的summary data。

(4)使用tf.summary.FileWriter將運行后輸出的數據都保存到本地磁盤中

(5)運行整個程序,並在命令行輸入運行tensorboard的指令,之后打開web端可查看可視化的結果

考慮多類情況。非onehot,標簽是類似0 1 2 3...n這樣。而onehot標簽則是顧名思義,一個長度為n的數組,只有一個元素是1.0,其他元素是0.0。例如在n為4的情況下,標簽2對應的onehot標簽就是 0.0 0.0 1.0 0.0使用onehot的直接原因是現在多分類cnn網絡的輸出通常是softmax層,而它的輸出是一個概率分布,從而要求輸入的標簽也以概率分布的形式出現,進而算交叉熵之類。

四、手寫數字識別

現在,我們使用最基礎的手寫數字識別。

1、准備數據集、定義超參數等准備工作

(1)首先是導入需要使用的包:

(2)定義超參數

如果你問,這個超參數為啥要這樣設定,如何選擇最優的超參數?這個問題此處先不討論,超參數的選擇在機器學習建模中最常用的方法就是“交叉驗證法”。而現在假設我們已經獲得了最優的超參數,設置學利率為0.001,dropout的保留節點比例為0.9,最大循環次數為1000。

另外,還要設置兩個路徑,第一個是數據下載下來存放的地方,一個是summary輸出保存的地方。

(3)GPU設置

這里使用GPU進行訓練,如果使用cpu,可以略過此步。如果使用GPU建議進行設置。

上述代碼的意思是使用GPU設備0,最多給GPU分配總共內存的百分之33,並且允許GPU按需申請內存。也就是說,假設一個程序使用一塊GPU內存百分之10就夠了,如果我們沒有指定allow_growth=True,那么程序會直接占用GPU內存的百分之33,因為這個是我們給它分配的。如果我們連0.33,也就是GPU內存的百分之33都沒有指定,那么程序會直接占用整個GPU設備0。雖然占用這么多沒有用,但是我就占着,屬於“占着茅坑不拉屎”。所以,為了充分利用資源,特別是一幫人使用一個服務器的時候,指定下這些參數就很有必要了。

(4)下載數據下載數據是直接調用了tensorflow提供的函數read_data_sets,輸入兩個參數,第一個是下載到數據存儲的路徑,第二個one_hot表示是否要將類別標簽進行獨熱編碼。它首先回去找制定目錄下有沒有這個數據文件,沒有的話才去下載,有的話就直接讀取。所以第一次執行這個命令,速度會比較慢,因為沒有數據集,需要進行下載。

2、數據處理

(1)創建tensorflow默認會話:

為了使設置的GPU參數生效,我們需要在創建會話的時候傳入這個config參數。

(2)創建輸入數據的占位符,分別創建特征數據x,標簽數據y_

在tf.placeholder()函數中傳入了3個參數,第一個是定義數據類型為float32;第二個是數據的大小,特征數據是大小784的向量,標簽數據是大小為10的向量,None表示不定死大小,到時候可以傳入任何數量的樣本;第3個參數是這個占位符的名稱。

mnist下載好的數據集就是很多個1*784的向量,就是已經對28*28的圖片進行了向量化處理。

(3)使用tf.summary.image保存圖像信息

前面也說了,特征數據其實就是圖像的像素數據拉升成一個1*784的向量,現在如果想在tensorboard上還原出輸入的特征數據對應的圖片,就需要將拉升的向量轉變成28 * 28 * 1的原始像素了,於是可以用tf.reshape()直接重新調整特征數據的維度:

將輸入的數據轉換成[28 * 28 * 1]的shape,存儲成另一個tensor,命名為image_shaped_input。
為了能使圖片在tensorbord上展示出來,使用tf.summary.image將圖片數據匯總給tensorbord。
tf.summary.image()中傳入的第一個參數是命名,第二個是圖片數據,第三個是最多展示的張數,此處為10張。

3、初始化參數並保存參數信息到summary

(1)初始化參數w和b

在構建神經網絡模型中,每一層中都需要去初始化參數w,b,為了使代碼簡介美觀,最好將初始化參數的過程封裝成方法function。 創建初始化權重w的方法,生成大小等於傳入的shape參數,標准差為0.1,遵循正態分布的隨機數,並且將它轉換成tensorflow中的variable返回。

創建初始換偏執項b的方法,生成大小為傳入參數shape的常數0.1,並將其轉換成tensorflow的variable並返回。

(2)記錄訓練過程參數變化

我們知道,在訓練的過程在參數是不斷地在改變和優化的,我們往往想知道每次迭代后參數都做了哪些變化,可以將參數的信息展現在tenorbord上,因此我們專門寫一個方法來收錄每次的參數信息。

4、構建神經網絡層

(1)創建第一層隱藏層

創建一個構建隱藏層的方法,輸入的參數有:

  • input_tensor:特征數據
  • input_dim:輸入數據的維度大小
  • output_dim:輸出數據的維度大小(=隱層神經元個數)
  • layer_name:命名空間
  • act=tf.nn.relu:激活函數(默認是relu)

調用隱層創建函數創建一個隱藏層:輸入的維度是特征的維度784,隱藏層的神經元個數是500,也就是輸出的維度。

(2)創建一個dropout層

隨機關閉掉hidden1的一些神經元,並記錄keep_prob,減少保存參數,防止過擬合。

(3)創建一個輸出層

輸入的維度是上一層的輸出:500,輸出的維度是分類的類別種類:10,激活函數設置為全等映射identity。(暫且先別使用softmax,會放在之后的損失函數中一起計算)

5、創造損失函數

使用tf.nn.softmax_cross_entropy_with_logits來計算softmax並計算交叉熵損失,並且求均值作為最終的損失值。

6、訓練

首先,使用AdamOptimizer優化器訓練模型,最小化交叉熵損失。

然后,計算准確率,並用tf.summary.scalar記錄准確率。

7、所有變量初始化

將所有的summaries合並,並且將它們寫到之前定義的log_dir路徑。

8、送入數據集

feed_dict用於獲取數據,如果是train==true,也就是進行訓練的時候,就從mnist.train中獲取一個batch大小為100樣本,並且設置dropout值為0.9。如果是不是train==false,則獲取minist.test的測試數據,並且設置dropout為1,即保留所有神經元開啟。

同時,每隔10步,進行一次測試,並打印一次測試數據集的准確率,然后將測試數據集的各種summary信息寫進日志中。 其余的時候,都是在進行訓練,將訓練集的summary信息並寫到日志中。

整體程序瀏覽:

9、運行程序

運行整個程序,在程序中定義的summary node就會將要記錄的信息全部保存在指定的logdir路徑中了,訓練的記錄會存一份文件,測試的記錄會存一份文件。

運行程序,如果使用GPU進行訓練,等待幾分鍾應該就OK了。

運行效果如下圖所示:

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

可以看到,隨着迭代次數的增加,准確率也在提高。

與此同時,在運行的時候,我們就可以打開Tensorboard查看訓練狀態。使用如下指令:

上述指令logdir指定了存儲log的路徑,在程序里設置的路徑。port指定了查看端口,此處設為8008。

運行上述指令后,我們就可以在瀏覽器查看Tensorboard了。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

如果是遠程登陸,可以在地址欄輸入服務器IP地址加端口號,例如:1.10.12.13:8008,如果是本地登陸,在地址欄輸入localhost:8008即可。

於是我們可以從這個web端看到所有程序中定義的可視化信息了。

五、Tensorboard Web端解釋

看到最上面橙色一欄的菜單,分別有7個欄目,都一一對應着我們程序中定義信息的類型。

1、SCALARS 

展示的是標量的信息,我程序中用tf.summary.scalars()定義的信息都會在這個窗口。 回顧本文程序中定義的標量有:准確率accuracy,dropout的保留率,隱藏層中的參數信息,已經交叉熵損失。這些都在SCLARS窗口下顯示出來了。

點開accuracy,紅線表示test集的結果,藍線表示train集的結果,可以看到隨着循環次數的增加,兩者的准確度也在增加,直達1000次時會到達0.967左右。

藍線有大幅度震動是因為batch的設置問題,在每個batch里,訓練效果好,但是換了一個新batch准確率就會下降,但是整體趨勢還是增加的。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

點開dropout,紅線表示的測試集上的保留率始終是1,藍線始終是0.9。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

點開layer1,查看第一個隱藏層的參數信息。 

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

以上,第一排是偏執項b的信息,隨着迭代的加深,最大值越來越大,最小值越來越小,與此同時,也伴隨着方差越來越大,這樣的情況是我們願意看到的,神經元之間的參數差異越來越大。因為理想的情況下每個神經元都應該去關注不同的特征,所以他們的參數也應有所不同。 

第二排是權值w的信息,同理,最大值,最小值,標准差也都有與b相同的趨勢,神經元之間的差異越來越明顯。w的均值初始化的時候是0,隨着迭代其絕對值也越來越大。

點開layer2,查看第二層的參數信息。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

點開loss,可見損失的降低趨勢。 

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

2、IMAGES 

在程序中我們設置了一處保存了圖像信息,就是在轉變了輸入特征的shape,然后記錄到了image中,於是在tensorflow中就會還原出原始的圖片了: 

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

整個窗口總共展現了10張圖片(根據代碼中的參數10)

3、AUDIO 

這里展示的是聲音的信息,但本案例中沒有涉及到聲音的。

4、GRAPHS 

這里展示的是整個訓練過程的計算圖graph,從中我們可以清洗地看到整個程序的邏輯與過程。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

單擊某個節點,可以查看屬性,輸入,輸出等信息。

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

單擊節點上的“+”字樣,可以看到該節點的內部信息。 

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

5、DISTRIBUTIONS 

這里查看的是神經元輸出的分布,有激活函數之前的分布,激活函數之后的分布等。 

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

6、HISTOGRAMS 

也可以看以上數據的直方圖:

Tensorflow實戰(一):打響深度學習的第一槍 - 手寫數字識別(Tensorboard可視化)

7、EMBEDDINGS 

展示的是嵌入向量的可視化效果,本案例中沒有使用這個功能。

本項目github地址:https://github.com/760730895/-Tensorboard-/tree/master

【. . . . . .本博客僅作個人生活、工作、學習等的日常記錄。說明: (1) 內容有參考其他博主、網頁等,有因“懶”直接粘貼來,會備注出處。若遇雷同,或忘備注,並無故意抄襲之意,請諸“原主”諒解,很感謝您的辛勤"筆記"可供本人參考學習。 (2) 如遇同行,有參考學習者,因個人學識有限,不保證所寫內容完全正確。您對本博文有任何的意見或建議,歡迎留言,感謝指正。 (3) 若您認為本主的全博客還不錯,可以點擊關注,便於互相學習。 (4) 感謝您的閱讀,希望對您有一定的幫助。歡迎轉載或分享,但請注明出處,謝謝。. . . . . .】


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM