caffe中python接口的使用


下面是基於我自己的接口,我是用來分類一維數據的,可能不具通用性:

(前提,你已經編譯了caffe的python的接口)

 

添加 caffe塻塊的搜索路徑,當我們import caffe時,可以找到。

對於這一步,一般我們都會把 cafffe 模塊的搜索路經永久地加到先加$PYTHONPATH中去,如可以把 export PYTHONPATH=/path/to/caffe/python:$PYTHONPATH 寫到 .bashrc中。而下面的做法,只是臨時的做法哦;

improt sys
#sys.path為一個列表,用什么方法加入都好啊,我用insert直接插到首位
sys.path.insert(0, ‘caffe_python的路徑,我的為~/down/caffe/python/')

 

設置使用的設備:

在用顯卡並行運算算的時候,如果多顯卡的時候,輸入它們的序號表示使用哪一塊卡,如果單顯卡的話(比如我的筆記本電腦,應該都為0,表示第一塊)。

caffe.set_device(0)
caffe.set_mode_gpu()
 
caffe.set_mode_cpu()    #使用caffe的GPU模式

 

設定網絡的solver:

選中我們的solver_prototxt文件,里面就是設定了網絡的訓練次數啦,各參數的值啦等啦。

solver = None
#選用SGD算法來進行運算;
solver = caffe.SGDSolver('你的網絡的lenet_solver.prototxt 文件‘)
# 執行完上面的語句以后,網絡的相應的權值與偏置會根據我們的定義進行賦值的;

 

caffe中的數據保存及調用:

在caffe中,我們的網絡可以分為訓練網絡與測試網絡哦,訓練網絡用solver.net.blobs、solver.net.params;對面測試網絡,用solver.test_nets[i].blobs、solver.test_nets[i].params(其中 i 表示 第幾個測試網絡,從0開始。例如,我們就一個測試網絡的話,我們就寫為:solver.test_nets[0].blobs。)

下面,我們以訓練網絡為例子,看看caffe中的數據的存儲與調用方法。 caffe的 數據都是放在 blobs塊中的,我覺得這個好牛逼啊,太統一了。

 

solver.net.blobs 里面放的為每一層layer輸出的data、對輸出結點求的導數 diff,另外還有幾個如count等參數,不過我們基本用不到的,不要關注一下data數據就可以了。

#solver.net.blobs為一個字典的數據類型,里面的key值為各個layer 的名字,value為caffe的blob塊;
 
solver.net.blobs
#輸出: 
rderedDict([('data', <caffe._caffe.Blob at 0x7f7bde968398>),
            ('label', <caffe._caffe.Blob at 0x7f7bde968488>),
            ('conv1', <caffe._caffe.Blob at 0x7f7bde968578>),
            ('pool1', <caffe._caffe.Blob at 0x7f7bde968e60>),
            ('conv2', <caffe._caffe.Blob at 0x7f7bde9686e0>),
            ('pool2', <caffe._caffe.Blob at 0x7f7bde968cf8>),
            ('ip1', <caffe._caffe.Blob at 0x7f7bde968c80>),
            ('ip2', <caffe._caffe.Blob at 0x7f7bde968c08>),
            ('loss', <caffe._caffe.Blob at 0x7f7bde968b90>)])

#我們可以訪問Blob塊里的內容了,通過看Blob塊的源碼你會發現里面有data, diff,count等內容的。
#我們以conv1層為例子,我們訪問 conv1的輸出的數據,可以通過下面的語句:
solver.net.blobs['data'].data      
solver.net.blobs['data'].diff  
#如果想看它們的數據結構,可以通過下面的語句得到:
solver.net.blobs['data'].data.shape
solver.net.blobs['data'].diff.shape
#另外,還可以通過reshape()transpose()等操作對它們變形,應該是對數組的操作之類的吧。
 

 

solver.net.params為一個字典的數據類型,里面放的是與連接的權值及偏置相關的數據,如:data(表示權值的大小),diff(對於權值的導數),還有 count 之類的,我們只關注一個 data 就可以了吧。

solver.net.params[網絡的名字][0]

#solver.net.params為一個字典的數據類型,key值為layer 的名字,value為caffe的blob塊的容器哦;
solver.net.forward()
#輸出為:
solver.net.params
orderedDict([ ('conv1', <caffe._caffe.BlobVec at 0x7f7bffd68578>),
            ('conv2', <caffe._caffe.BlobVec at 0x7f7bde9ff6e0>),
            ('ip1', <caffe._caffe.BlobVec at 0x7f7bde968f80>),
            ('ip2', <caffe._caffe.BlobVec at 0x7f7bde968408>)])
#下面,我們可以訪問Blob塊里的內容了。#們以conv1層為例子,具體如下:
 
#sover.net.params['conv1'][0]里面放是與連接權值相關的數據;可以通過下面方式訪問:
solver.net.params['conv1'][0].data  
solver.net.params['conv1'][0].diff
#solver.net.params['conv1'][1]里面放的是與偏置相關的的值、導數等;可以通過下面方式訪問:
solver.net.params['conv1'][1].data 
solver.net.params['conv1'][1].diff
 
#同樣,我們可以還可以通過它們進行 shape()、reshape()、transpose()等操作

 

前向傳播與反向傳播

進行一次前向傳播:使用 solver.net.forward或 solver.test_nets[i].forward 語句: 它干了點什么呢?它把數據從輸入層到最后的輸出層傳播了一個遍,把相應的每一層網絡的輸出值賦於blobs,網絡輸入的的數據個數為你的net的定義文件里的patch_size的大小。

#訓練數據作為輸入,進行一次前向傳播:
solver.net.forward()
 
#假如有300個數據,我們的patch_size的大小為100,那么:
solver.net.forward()    #數據為1-100;
solver.net.forward()    #數據為101-200
solver.net.forward()    #數據為201-300
solver.net.forward()    #數據為1-100
#另外,我們可以設置forward開始的地方,如下面所示:
solver.net.forward(start ='conv1')          #表示從conv1開始,這樣的話,data層這不用傳用新的數據了。

 

進行反向傳播:使用:solver.net.forward,基本是都是我們的訓練網絡會進行反向傳播的。反向傳播做了點什么事呢?把會求出相應的導數啦,即blobs塊里面的diff變量。

記住:它不會去更新權值與偏置的;

# 進行一次反向傳播
solver.net.forward()

 

進行完整的一次計算(minibatch):solver.step(1):(包括數據的前向傳播,誤差反向傳播,以及網絡權值的update)

#當我們完整地進行一次權值更新地時候,我們可以調用下面的語句
#把意思就是:訓練網絡進行一次正向與反向傳播,並進行更新權值與偏置;
sover.step(n)表示進行n次訓練。

# 表示進行n次訓練。
sover.step(n)

 

 

 

注意:當我們用python接口運行caffe時,我們就可以控制它的Loop過程了,然后跟蹤很多變量,干點自己想干的事啦等。 除此之外,與直接用caffe的C++代碼且沒有什么差別,並且在sover prototxt定義的相關操作都會進行的,如logging, snapshot, test等。

 

2017年3月10日添加,有點亂,沒有整理:

 
 

solver.solve(), 會進行完整的梯度訓練,直至在solver中規定的max_iter.

 

用 caffe_root/python/draw_net.py 畫出 網絡的結構圖:

第一點:需要安裝:graphviz, 可以直接通過 sudo apt-get install graphviz,安裝就可以了。

第二點:安裝pydot 模塊,可以通過 pip pydot安裝,注意:pydot 不支持python3, 所以,我們也可以安裝 pydotplus來代替, pip install pydotplus;

現在,就可以運行 draw_net.py 畫圖了,例子如下:

./draw_net.py my_net.prototxt my_picture.png

 

caffe中,在訓練過程中,關於進行snapshot的相關問題:

除了我們可以在solver.prototxt 文件里定義相關的snapshot外,我們呢,也可以在訓練過程中,進行手動 保存;在進行snapshot時,會保存下面兩個文件:

.caffemodel :

The caffemodel, which is output at a specified interval while training, is a binary contains the current state of the weights for each layer of the network.

.solverstate:

The solverstate, which is generated alongside, is a binary contains the information required to continue training the model from where it last stopped.

方法一: solver.snapshot(), 可以在訓練過程中,手動進行snapshot.,它會保存 .caffenodel與 .solverstate兩個文件;常用於進行恢復訓練過程;(保存的路徑為solver.prototxt 文件里面定義的路徑)

方法二:net.save(), 它只會保存一下 .caffemodel文件,常用於進行測試時。 使用方法:如, net. save(‘my_path/my_weights.caffemodel’);

 

關於在pycaffe中載入solver.ptototxt 文件的問題:

兩個方法:

第一,當使用 caffe.SGDSolver(‘solver文件’)時,無論你的solver文件中定義的solver_type是什么,都會用SGD方法;

第二,solver = caffe.get_solver(‘里面是solver.prototxt文件’);

 

怎么導入網絡以及它的相關權值進行測試呢,可以這么做:

第一,直接進行導入權值進行測試時,我們可能用到:
net = caffe.Net(網絡的定義文件, caffemodel的權值保存文件,選擇:caffe.TEST)  ,因為一個.prototxt文件中可以即定義train,也定義test,對應的caffe.TRAIN與caffe.TEST.
如一個例子:
net = caffe.Net('models/bvlc_reference_caffenet/deploy.prototxt',
                'models/bvlc_reference_caffenet/bvlc_reference_caffenet.caffemodel',
                caffe.TEST)

 

第二,在預訓練的基礎上再訓練網絡時,我們不僅僅導入了預訓練的權值,還導入 solver.prototxt

如果我們要在預訓練的基礎上再用新定義的solver.prototxt文件訓練我們的網絡,我們可以這么做:(區別就是我們不會隨機初始化權值,而是直接導入pretrained的權值)

my_solver = caffe.get_solver(net_solver.prototxt)

my_solver.net.copy_from(pretraind.caffemodel)

 

2017年8月14日補:

solver.iter : 這是一個變量,它會標識了迭代次數;

 

 

 

QQ截圖20170502214151

 

 

 

 


免責聲明!

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



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