1. 程式人生 > >AI相關 TensorFlow -卷積神經網絡 踩坑日記之一

AI相關 TensorFlow -卷積神經網絡 踩坑日記之一

一個 模糊 結果 隊列 二維 圖片路徑 降維 支持 日記

上次寫完粗淺的BP算法 介紹

本來應該繼續把 卷積神經網絡算法寫一下的

但是最近一直在踩 TensorFlow的坑。所以就先跳過算法介紹直接來應用場景,原諒我吧。

TensorFlow 介紹

TF是google開源出來的人工智能庫,由python語言寫的

官網地址:http://www.tensorflow.org/ 請用科學上網訪問

中文地址:http://www.tensorfly.cn/

當然還有其他AI庫,不過大多數都是由python 寫的

.net 的AI庫叫 Accord.net (因為我本職是.net的,so……)有興趣的同學可以去看看,有很多機器學習的工具類,不過可惜當時我在研究的時候只有BP算法,還沒有卷積算法的相關。

寫這篇博文的時候,聽說微軟又開放了一個AI庫,但是我不看好微軟在這方面的能力。所以還是繼續搞tensorFlow

TensorFlow 在支持GPU 並行運算上做的挺多。這個庫的入手程度相對其他AI庫稍容易點。而且有很多教程代碼,包括卷積,對抗網絡,循環網絡算法。

聲明一下踩坑日誌系列主要是針對卷積。

阿爾法狗的核心部分就是用的TensorFlow,真佩服google說開源就開源。國內的童鞋就沒這種魄力呀。

好了,廢話不說,開始

安裝方法推薦

因為我用的是windows機

所以我推薦的安裝環境是 python 3.5.2 +PyCharm

這篇博文寫時,最新的python是3.6

嘗試過安裝3.6跟tensorFlow有不兼容問題,後來換了3.5.2 就可以了。

我安裝的版本是tensorFlow1.1

不排除之後的版本已經修復這個問題。

我推薦的安裝方法超簡單,但是網上有很多非常復雜的安裝,在此踩一下。

十幾個字搞定:

安裝好python 之後設置好環境變量,然後安裝PyCharm 打開=》setting =》project Interpreter 選擇剛才安裝好的3.5.2

點下面的綠色+ 號 搜索 tensorFolw ,install package! 完成。

技術分享

教程代碼介紹

關於教程部分我建議先看一下極客學院的翻譯教程文檔。

傳送門在此 http://wiki.jikexueyuan.com/project/tensorflow-zh/tutorials/overview.html

另外下載一下 github上的源碼

https://github.com/tensorflow/tensorflow

最簡單的教程是

MNIST

這裏官網例子上有一個坑,因為訓練數據會從外網鏈接上下載,我剛入門那個時候這個鏈接是404。所以只能另外找這個包,現在這個問題雖然已經修復了,但是我擔心那個網站也不是很靠譜。有需要的可以留下郵箱,不多人的話我直接發給你們。

這裏我講一下tensorFlow幾個比較晦澀的概念,請結合那個教程一起看

張量 tensor :張量是TF最基本的元素,基本上所有的接口都是需要張量作為輸入。

張量其實是對基本類型的一層包裝,就是說tensor可以包裝是int string array 各種類型。最重要的用途是用來描述多維數組

比如 這個方法生成的tensor

tf.zeros([100,100]) 就是代表正式運行的時候會生成一個二維數組,第一維有100個索引,每個裏面有100個0  
tf.random_normal([784, 200], stddev=0.35) 代表隨機生成一個二維數組 ,784是一維,每個裏面有200個元素。總共就是784*100個隨機數。 sttddev是這個正態分布的偏差值,我覺得可以理解為平均的差值。用來調整數值分布的密度。

生成一個tensor的方式有很多,也可以用

tf.constant() 直接輸入常量

這裏大家肯定已經很奇怪了,數組就數組,string 就string,幹嘛還要包裝起來成了tensor

其實這個tensor除了常量tensor之外,其他比方說隨機數組,在調用的時候裏面都沒有值的,只是聲明說要生成這麽一堆數據,但是實際上要等到 session.run 的時候數據才會生成。

所以其實tensorFlow 編程就是用這些方法聲明要構建一個怎麽樣的算法,這個過程叫做構建圖。然後再N次的session.run 這個算法來訓練。所以調試的時候很麻煩的地方是,常常是構建圖的時候沒問題,但是這個算法圖正式跑的時候各種出錯,但是很難定位是由於哪個數據進行到什麽地方出錯的。幸好有 tfdbg的模塊可以調試,我下面會講一下在tfdbg上踩的坑。

checkpoint :相當於保存點,就是用來訓練到一半的時候保存當時所有張量的值,然後下次可以通過一個saver的鬼東西讀取checkpoint的所有環境,繼續訓練。

這個非常有用,因為數據量特大的時候可以要跑好幾天,這樣就可以分段進行的,也不怕中途死機。。。。(別問我為啥會死機,說多了都是淚)

MNSIT 這個教程代碼是比較簡易的卷積算法,訓練集很小。

稍大一點的教程是:cifar10 

技術分享

cifar10 的算法比較全面一點

技術分享

由2層 (卷積層+最大池化+歸一層)+2層全連接層。不知道全連接層是什麽東西的,請參考BP算法。
卷積層我這裏簡單說一下,就是由一個k*k 的數據矩陣(卷積核),去跟圖像做卷積運算。卷積過程參考下圖

 技術分享
這個過程的作用主要是提取圖像特征,不同的卷積核對圖像的處理效果是不同的。
比如模糊效果,銳化效果,黑白效果,輪廓效果。都是可以直接設定不同卷積核來達到。
所以這裏說的是“提取特征”
池化就是降維,提取特征出來的圖片數據量非常大,池化效果比如3*3範圍內取一個最大值。那麽原本90*90的圖片就變成 30*30了。
這就是最大池化。Maxpool
歸一化的算法也挺多,但是通俗一點講,就是比方說做完卷積之後 數據可能是這樣 [255,244,266,7777,433] 太大了不好計算,也增加計算壓力。歸一化一種最簡單的辦法就是 取個最大值,對每個數做一次 除法
[255/7777,244/7777,266/7777,7777/7777,433/7777]
這樣得出來的值就都在 0-1 之間了。這就是傳說中歸“一”化。
卷積層+最大池化+歸一層最終得出一張圖片的各種特征,然後傳給全鏈接層,根據誤差值調整網絡裏的所有參數,最終達到跟真實值一致。然後跑一下測試集評估結果。
卷積我這裏就不細說了,詳細的內容我推薦這篇文章 :http://www.36dsj.com/archives/24006

cifar10+imagenet 改代碼

當然cifar10 還是不能拿來用的。畢竟是教程代碼

那麽現在如果要投入實用,其實有2個問題要解決

1,擴大訓練集

2,因為評估代碼用的一打圖片打包成一個.bin 文件 所以得改成接收1張jpg圖片然後輸出結果。

第一個問題

先下載imagenet 訓練集 ILSVRC2012

這個朋友有地址 http://www.cnblogs.com/zjutzz/p/6083201.html

1000種分類,每一種分類有1000張圖片 就是一百萬張圖片 壓縮包140G。下載大半天,解壓又是大半天。推薦用7z解壓。神速。

但是沒有中文分類的名字

所以還得看這裏 中文對照表 http://blog.csdn.net/u010165147/article/details/72848497

下載好之後再說一個坑。裏面有部分圖片是出錯格式的。大概有幾百張吧。其實量也很小。如果你們找到沒問題數據包的就不要我這個了。

不過因為代碼讀取的時候會出錯,所以可能訓練到幾十萬步的時候突然來那麽一下,前功盡棄,還很難鎖定是哪張出錯了。

後來我瘋了,因為可以看到出錯圖片的字節數,所以根據字節數查看文件,然後刪了它,然後再跑幾十萬步之後,又出錯,又刪了它。

但是幾百張圖可能出錯。- -!哈哈哈哈哈(此處苦笑)。。讓我死吧。

然後我就用tfdbg 或者 tensorbroad 來查出那些出錯的圖片路徑。但是……我把圖片路徑裝到一個tf隊列裏,tfdbg不能顯示隊列內容。F!

tensorbroad 開啟後一直顯示沒找到監控數據,然而數據文件一直存在的。F!

找了很多辦法,花了很多時間之後宣告放棄。另覓良方。

幹了一陣子傻事之後,我突然受到上天的啟發,感覺真神上身。“為啥我不用try catch呢!”

因為這個方法在第一天的時候被我否定了,因為讀圖的方法

技術分享

decode_jpeg 一直是這裏報錯,但是我直接try catch 這一段代碼是無效的。因為正如我上面說的,這裏只是構建圖,構建了想要解碼圖片的算法而已,並沒有真正解碼,所以圖片格式錯誤不會被catch到。

但是。。。。。。

我可以在session.run 的時候try catch啊!!!!

我可以在session.run 的時候try catch啊!!!!

我可以在session.run 的時候try catch啊!!!!

結果繞了一大圈,還是最開始的辦法最靠譜。“師傅,把那塊磚頭往我這裏砸,對,就是這裏,腦門上,用力”。

我大致講一下我對cifar10的修改,用來裝載這100萬張圖片

首先

cifar10_input.py 代碼裏
distorted_inputs 方法主要是用來加載

技術分享

這六個bin文件

技術分享

每個文件裏是一堆圖片跟標簽的打包。

再看

read_cifar10()方法裏

技術分享

FiedLength 讀取器會根據固定長度的一段段的讀取文件。所以這個bin文件裏面一張圖的長度就是 32*32*3(RGB3個通道的意思)+label的長度。

現在imagenet解壓出來的格式是

技術分享

這裏明顯不同了,怎麽辦?

不幹了!刪代碼!卸載系統!

說笑了,默默的打開IDE。。。

還是

cifar10_input.py文件
主要改這個方法

技術分享

這個方法主要是從bin文件裏讀取了固定長度的,然後把label切出來放到 result.label 把原本圖片數據轉換成3維數組tersor(reshape)。然後稍微把數組的維度轉換一下。就是最後 transpone 改為了[1,2,0] 就是原本depth*height*width 改為 height*width*depth

技術分享

這裏我換成
WholeFileReader 讀取整個文件。然後
resize_images 成32*32
因為label 是分類名稱,也是圖片所在文件夾的名稱,所以我在外面把圖片文件夾名稱都丟到一個label的string隊列裏,然後裏面做出隊 depuqeue。

核心部分就完了。
剩下一個問題就是讀取單張圖片然後跑一下評估代碼
cifar10_eval.py
得出結果。然後就可以投入實用了。

cifar10_eval.py代碼還需要改一下

技術分享

新增這個方法,圖片必須改成32*32大小的,這個可以用其他自己熟悉的代碼處理,把圖片讀取成數組,然後按照bin文件的格式打包成一個。剩下就是按照eval原有的代碼,只改一下讀取bin文件的路徑就可以。

技術分享

最後run之後把

predictions輸出就可以了
這裏就能拿到label了,然後根據上面的中文對照表得出分類名稱。大功告成。
然而。。。。。。
這篇文章叫做踩坑日誌,所以最大的坑在最後。
不知道為啥,訓練了100W步之後每次去測試跑結果,都是

技術分享

有毒啊!!!

國際慣例 原文地址http://www.cnblogs.com/7rhythm/p/7091624.html

轉載請註明出處。PS:文中代碼都是用圖片,因為只是摘取部分核心代碼,並不能直接運行,所以諸君不用復制去調試了,理解要緊。

《未完待續……》等待之二




AI相關 TensorFlow -卷積神經網絡 踩坑日記之一