Tensorflow 的安裝和用InceptionV3訓練新的影象分類模型
Tensorflow的安裝
1.Tensorflow簡介
Tensorflow是一個谷歌釋出的人工智慧開發工具,於2015年年底開源。在開源之前一直是在谷歌內部使用,維護性比較好,裡面的很多工具也比較新。Tensorflow是採用C++和python寫成的,給的介面也是C++和python,但是更支援python。下面是Tensorflow和其他幾個深度學習或機器學習工具的比較:
谷歌稱以後的學術文章也大都使用該工具,所以如果要跟進谷歌的學術進展,可能要對這個工作做一定了解的。
Tensorflow安裝
Tensorflow目前只能在Linux或者Mac下使用,其安裝還是比較簡單的,它提供了
一.在安裝Tensorflow之前先安裝CUDA和CUDNN.
1.安裝cuda
在https://developer.nvidia.com/cuda-downloads中,選擇和自己系統相對應的且合適的CUDA版本。我的選擇依次是:Linux—x86_64—ubuntu—14.04—deb(local).選擇好後開始下載。下載好後進入下載的目錄中在命令列輸入如下命令:
sudo dpkg -i cuda-repo-ubuntu1404-7-5-local_7.5-18_amd64.deb
sudo apt-get update
sudo apt-get install cuda
2.安裝cudnn
https://developer.nvidia.com/rdp/cudnn-download安裝cudnn,需要首先註冊,隨便填填就好,之後選擇cuDNN v5.1 Library for Linux 下載後,cd至下載目錄,在命令列中輸入如下命令:
tar xvzf cudnn-7.5-linux-x64-v5.1-ga.tgz
sudo cp cuda/include/cudnn.h /usr/local/cuda/include
sudo cp cuda/lib64/libcudnn* /usr/local/cuda/lib64
sudo chmod a+r /usr/local/cuda/include/cudnn.h /usr/local/cuda/lib64/libcudnn*
安裝好後,在home 路徑下的.profile中新增路徑:
export CUDA_HOME=/usr/local/cuda
export DYLD_LIBRARY_PATH="$DYLD_LIBRARY_PATH:$CUDA_HOME/lib"
export PATH="$CUDA_HOME/bin:$PATH"
安裝完成後,可以用編譯cuda-sample中的案例來時一下:
$ cp -r /usr/local/cuda/samples ~/cuda-samples
$ pushd ~/cuda-samples
$ make
$ popd
$ ~/cuda-samples/bin/x86_64/darwin/release/deviceQuery
最終會顯示您的GPU的配置等一些資訊。編譯過程比較緩慢。
最後,在安裝tensorflow的根目錄下,使用./configure命令來確認配置。
會出現這樣的畫面,除了一些地方需要輸入y或cuda和cudnn的型號來確認外,一路enter。
但是實際上我並沒有得到上面的那些setting up,而是綠色的IFNO標誌,後面是一些download命令,我在谷歌上搜索了一些,這樣也是表示正常的意思,至於為什麼顯示的不統一,我猜測應該是和CUDA,或者tensorflow的版本有關。當顯示configuration finished後,說明GPU已經設定好的。
二.安裝virtualenv並下載tensorflow檔案
推薦在virtualenv下安裝tensorflow,這樣tensorflow就對其他python環境沒有影響,想刪掉就直接刪除這個資料夾就行。
1.首先安裝virtualenv
sudo pip install virtualenv
接著安裝virtualenvwrapper,這是一個virtualenv的管理工具,可以方便得管理多個virtualenv環境,並可以將它們放在一個資料夾下面。
Sudo pip install virtualenvwrapper
環境配置:
export WORKON_HOME='~/.virtualenvs'
source /usr/local/bin/virtualenvwrapper.sh
建立一個tensorflow虛擬環境:
mkmkvirtualenv tensorflow
可以看見命令列的最開頭變化了。
之後下載tensorflow的原始碼:git clone https://github.com/tensorflow/tensorflow。下載後可能在Home目錄下,我一般習慣將其拷貝到.virtualenv/tensorflow/bin/python2.7/dist-package目錄下。
三.安裝Bazel編譯器
因為我們tensorflow原始碼編譯(不知道為什麼,tensorflow的二進位制安裝方法安裝後的tensorflow,功能比原始碼編譯的少,這也是我在實踐中發現的),所以首先安裝這個編譯器。
1.如果電腦的系統是Ubuntu14.04或以下,需要安裝Oracle JDK 8。
sudo add-apt-repository ppa:webupd8team/java
最後會出現這個,中間的沒有找到任何絕對信任的金鑰不用管。
接著sudo apt-get update
接著sudo apt-get install oracle-java8-installer
這一步需要下載檔案,所以需要等一會。
最後在sudo apt-get update一下。
2.安裝必要的包:sudo apt-get install pkg-config zip g++ zlib1g-dev unzip
chmod +x bazel-version-installer-os.sh
/bazel-version-installer-os.sh --user
完成後記得新增路徑,按照命令列中的說明在在home目錄下的.bashrc中新增路徑。
至此bazel安裝完畢
四.tensorflow編譯
下面的命令推薦在下載的tensorflow檔案的根目錄下執行(即第二步下載的tensorflow資料夾中)
1.首先安裝其他依賴:sudo apt-get install python-numpy swig python-dev。
2.安裝完畢後對tensorflow原始碼的pip包進行編譯和安裝。
bazel build -c opt //tensorflow/tools/pip_package:build_pip_package
這個比較慢,大概需要20分鐘左右。如果您有GPU,推薦讓GPU參與編譯這一步(如下),可以提高編譯的速度,大概需要600s左右。
bazel build -c opt --config=cuda //tensorflow/tools/pip_package:build_pip_package
之後執行:
bazel-bin/tensorflow/tools/pip_package/build_pip_package /tmp/tensorflow_pkg
sudo pip install /tmp/tensorflow_pkg/tensorflow-0.10.0-py2-none-any.whl
3.按照教程,下面是一個為開發而進行的設定,目的似乎是設定路徑(我也沒看懂),總之按照這個設定。
bazel build -c opt //tensorflow/tools/pip_package:build_pip_package
# To build with GPU support:
bazel build -c opt
--config=cuda //tensorflow/tools/pip_package:build_pip_package
mkdir _python_build
cd _python_build
下面的命令有可能需要root許可權。
ln-s ../bazel-bin/tensorflow/tools/pip_package/build_pip_package.runfiles/org_tensorflow/* .
ln -s ../tensorflow/tools/pip_package/* .
python setup.py develop
五.測試
這樣tensorflow就安裝和設定完畢了。下面是用minist資料集來進行測試。
cd tensorflow/models/image/mnist
python convolutional.py
會在命令列出現如下,如果開啟了GPU,還會在這之前有一段GPU成功啟動的說明:
Successfully downloaded train-images-idx3-ubyte.gz 9912422 bytes.
Successfully downloaded train-labels-idx1-ubyte.gz 28881 bytes.
Successfully downloaded t10k-images-idx3-ubyte.gz 1648877 bytes.
Successfully downloaded t10k-labels-idx1-ubyte.gz 4542 bytes.
Extracting data/train-images-idx3-ubyte.gz
Extracting data/train-labels-idx1-ubyte.gz
Extracting data/t10k-images-idx3-ubyte.gz
Extracting data/t10k-labels-idx1-ubyte.gz
Initialized!
Epoch 0.00
Minibatch loss: 12.054, learning rate: 0.010000
Minibatch error: 90.6%
Validation error: 84.6%
Epoch 0.12
Minibatch loss: 3.285, learning rate: 0.010000
Minibatch error: 6.2%
Validation error: 7.0%
……
六.問題說明
我在這過程中遇到過很多問題,其中的很多解決方法已經寫在安裝的過程中了,下面是幾個不是很常見的問題:
1.當有這樣的問題時:
ImportError: libcudart.so.7.0: cannot open shared object file: No such file or directory:
請在.profile檔案中中新增如下:
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/cuda/lib64"export CUDA_HOME=/usr/local/cuda
2.在進行minist出現如下問題:
__new__ if not newclass.is_abstract(): AttributeError: type object 'NewBase' has no attribute 'is_abstract'
請執行如下的命令,好像是重新安裝python的six模組。
sudo pip install six --upgrade --target="/usr/lib/python2.7/dist-packages"
利用Tensorflow訓練影象分類的模型
我在剛進行訓練模型的時候,是想靠自己拆開一個模型,之後再進行訓練的方法。後來發現在我不徹底弄清模型的原理並搞到模型的原始碼之前我是不可能去訓練的。後來發現tensorflow就提供了這樣一個工具,它雖然沒有公開深度學習網路的模型原始碼,卻給出了儲存好的模型和訓練的程式碼。這樣就直接可以拿來訓練了。
這個模型是谷歌的Inceptionv3(http://arxiv.org/abs/1512.00567)。在2012年的imageNet上進行訓練,並在2012ImageNet上取得了3.4%的top-5準確率(人類的只有5%)
這麼一個複雜的網路若是直接自己訓練,起碼需要幾天甚至十幾天的時間。所以這裡我採用遷移學習的方法。即前面的層的引數都不變,而只訓練最後一層的方法。最後一層是一個softmax分類器,這個分類器在原來的網路上是1000個輸出節點(ImageNet有1000個類),所以需要刪除網路的最後的一層,變為所需要的輸出節點數量,然後再進行訓練。
Tensorflow中採用的方法是這樣的:將自己的訓練集中的每張影象輸入網路,最後在瓶頸層(bottleneck),就是倒數第二層,會生成一個2048維度的特徵向量,將這個特徵儲存在一個txt檔案中,再用這個特徵來訓練softmax分類器。
具體的方法如下:
1.編譯和預處理
在tensorflow的根目錄下的命令列中輸入編譯retrian的命令:
bazel build -c opt --copt=-mavx tensorflow/examples/image_retraining:retrain。
這兩種方法我都試過,後面一種在提取bottleneck特徵的時候比前面的一種快了10倍左右。
編譯完成後,實際上就可以使用了,就是這麼簡單。但是建議還是改動一下tensorflow/examples/image_retraining目錄下的retrain的python指令碼,因為裡面的預設路徑是/tmp,這個資料夾一旦電腦關機所有資料都會清除。建議把裡面所有的這個路徑都改為另外的路徑。之後在該路徑下將自己的訓練資料集放好。
訓練資料集是有格式要求的:
a.資料集應該這樣設定,訓練集資料夾下放置多個子資料夾,每個子資料夾就是一個類,裡面包含該類的所有影象。
b.影象應該是jpg或者jpeg格式。
2.訓練
在設定好資料集後,執行
bazel-bin/tensorflow/examples/image_retraining/retrain --image_dir ~/XXX
image_dir ~/XXX是訓練資料集的路徑XXX是資料集的名稱。
這時就開始訓練了。訓練過程中會首先下載原來的Inception網路,儲存在ImageNet的資料夾下。
第一個檔案是網路的圖結構,第二個檔案是一個測試影象,第三個一個對映,從最後1000個節點中的而每一個對映到一個編碼,第四個也是一個對映,是從編碼對映到人能夠識別的名詞,例如:節點的表示是第234個節點,而這個節點對映到的編碼是nb20003,這個編碼對映到的名詞是熊貓(僅舉例,數字和編碼以及名詞是隨意假設的)。這些對映關係和編碼是在ImageNet 2012測試集中定義的。
下載後開始提取每張訓練影象的bottleneck特徵。這個過程大概1s提取5張影象。在提取完成後就開始訓練。訓練過程比較快。下面是我的訓練結果,我訓練了8000(可以在retrain.py中設定)次,一開始很奇怪為什麼不需要設定softmax的輸出節點數目,後來看了程式碼才知道它是根據訓練集中的類別數量來自動設定的。
下面是我的訓練結果:
最後的測試結果是93.2%。這個成績好麼?其實並不好,這說明這個模型的15個類的Top5的準確率比ImageNet的1000個類的Top5準確率還低。但是鑑於沒有那麼多的訓練資料集和那麼多的時間來從頭訓練整個網路,這個結果已經算是還不錯。
這時候如果開啟image_dir路徑,可以在下面發現多處了兩個檔案,分別是output.pb和output.txt。第一個檔案是訓練後的圖結構,第二個是從節點到名詞的對映,這裡不會給出中間的編碼對映——除非您自己定義一個對映關係。
接下來怎麼利用訓練好的模型來進行訓練呢?首先還是回到下載下來的ImageNet資料夾中,這時候如果執行tensorflow/model/ImageNet中的classify.py,會發現命令列中出現如下:
這是對資料夾中的測試影象進性預測的結果。
這時,我們將訓練出的output_graph檔案放到該資料夾下,替換掉原有的圖檔案(可以把output_graph檔案重新命名為原來的圖檔名,這樣就不需要改動程式碼了)。再執行classfy.py檔案就可以用自己的模型來對影象進行分類了。給出的結果是Top5對應的節點數以及相應的概率。如果需要輸出名詞,需要自己定義對映關係。
但是這樣還是隻會對一張影象進行分類,我改動了classify_image的指令碼,讓它可以對多個檔案分類。如果您想自己嘗試改寫指令碼讓它可以對多個檔案分類,那可能您會遇到這樣的情況:大概在預測10幾個檔案後,突然報錯,說圖的結構不能大於2G,這是因為每訓練一個圖,就會在圖中增加一個點,當增加到一個程度,圖的結構就會超過2G。這需要在每訓練一個圖片後重置圖,在我改寫的指令碼中已經克服了這個問題,但是這也使得分類的速度變慢,大概1.5s一張影象。這個指令碼會輸出top-2的準確率,如下:
分別是檔名,top1結果,top1置信度,top2結果,top2置信度。
我改動後的,可以支援多影象輸入的classify_image可以在: http://pan.baidu.com/s/1qYq3yck中獲得。
總結
這是我近十天來摸索tensorflow的心得(前面時間摸索Overfeat了)。Tensorflow的上手還是比較難得,它的一些思想理念(圖和張量)還是很難理解的。比較重要的心得是Don’t be a hero。有問題不要閉門造車,如果嘗試了下沒解決就第一時間找人交流,如果別人也沒有解決方法,再想辦法從網上搜,再實在沒辦法再去看原始碼和問題提示自己找問題所在。此外,還了解一些包括linux還有python的工具,相信這會對我後面的學術和工程都有幫助。
但是還是感覺走了很多的彎路,中間浪費了太多現在看起來可以避免浪費的時間,我想這就是因為我沒有跟他人交流很多的原因吧。
補充:額。。。好久沒上部落格了,我最近一年多都是在研究弱監督學習問題了,所以對深度學習沒怎麼繼續做下去了。這個部落格不知怎麼圖片被吞了,想要完整的可以從http://pan.baidu.com/s/1i4FhNwh下載。