人工智能(AI)庫TensorFlow 踩坑日記之一

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

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

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

 

TensorFlow 介紹github

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

官網地址:http://www.tensorflow.org/   請用***訪問編程

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

固然還有其餘AI庫,不過大多數都是由python 寫的數組

.net 的AI庫叫 Accord.net (由於我本職是.net的,so……)有興趣的同窗能夠去看看,有不少機器學習的工具類,不過惋惜當時我在研究的時候只有BP算法,尚未卷積算法的相關。網絡

寫這篇博文的時候,據說微軟又開放了一個AI庫,可是tensorflow比較早。因此仍是繼續搞tensorFlowsession

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:文中代碼都是用圖片,由於只是摘取部分核心代碼,並不能直接運行,因此諸君不用複製去調試了,理解要緊。

傳送門:踩坑日記之二

相關文章
相關標籤/搜索