人工智能(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

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

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

阿爾法狗的核心部分就是用的TensorFlow,真佩服google說開源就開源。

好了,廢話不說,開始

 

安裝方法推薦

因為我用的是windows機

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

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

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

我安裝的版本是tensorFlow1.1

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

tensorFlow1.2已經修復此問題

 

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

十幾個字搞定:

安裝好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算法,全連接層就是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 之間了。這就是傳說中歸“一”化。

卷積層+最大池化+歸一層最終得出一張圖片的各種特征數組,然后傳給全鏈接層,根據誤差值調整網絡里的所有參數,最終達到跟真實值一致。然后跑一下測試集評估結果。
卷積我這里就不細說了。
(我后來寫的算法綜述中有介紹CNN卷積神經網絡的一些內容,補充性的看一下吧 傳送門:點我點我
 

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啊!!!!

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

(結果是try catch也不太行,還是會有一些錯誤導致session報錯,然后程序停止。

最后的辦法是用一個圖片批量處理工具,把所有圖過一遍,去掉那些不可讀的圖片。)

 

OK,前戲完結。

cifar10 的詳細源碼解析這里就不講了,大家自行搜索。

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

首先

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

 

這六個bin文件

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

再看

read_cifar10()方法里

FixedLength 讀取器會根據固定長度的一段段的讀取文件。所以這個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*depth這里是指顏色通道,紅綠藍3種。

 

 

這里我換成
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:文中代碼都是用圖片,因為只是摘取部分核心代碼,並不能直接運行,所以諸君不用復制去調試了,理解要緊。

傳送門:踩坑日記之二

 

 

 



 
        

 


免責聲明!

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



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