1. 程式人生 > >用pycaffe訓練影象

用pycaffe訓練影象

廢話不多說,本文在python下呼叫caffe來訓練,由於python下圖片轉lmdb比較複雜,所以就直接使用了windows下的介面。如果不會搭建caffe包的,移步這https://blog.csdn.net/zb1165048017/article/details/52980102

資料集是一個二分類的資料集,主要是人臉和非人臉,連結:https://pan.baidu.com/s/1WCErudFafJjP2V1edpV5_g 密碼:q85k

要跑網路,我們要先構建自己的網路,由於資料集圖片是60*60,所以我們沒必要跑太複雜的網路,所以我寫了個比較簡單的網路,最後準確率能達到98%

import caffe
from caffe import layers as L,params as P
#定義你的網路層
def myLayer(lmdb,batch_size,is_deploy):
    n=caffe.NetSpec()
#這裡的source填入你的資料來源lmdb
    n.data,n.label=L.Data(batch_size=batch_size,backend=P.Data.LMDB,source=lmdb,
                          transform_param=dict(scale=1./255),ntop=2)
    n.conv1 = L.Convolution(n.data, kernel_size=3,stride=2, num_output=20, 
                            weight_filler=dict(type='xavier'))
    #特徵圖變為 30*30 
    n.relu1=L.ReLU(n.conv1,in_place=True)
    n.conv2 = L.Convolution(n.relu1, kernel_size=3,stride=2, num_output=60, 
                            weight_filler=dict(type='xavier'))
    #15*15
    n.relu2=L.ReLU(n.conv2,in_place=True)
    n.conv3 = L.Convolution(n.relu1, kernel_size=3,stride=2, num_output=90, 
                            weight_filler=dict(type='xavier'))
    n.relu3=L.ReLU(n.conv3,in_place=True)
    n.score=L.InnerProduct(n.relu3,num_output=2,weight_filler=dict(type='xavier'))
    n.loss=L.SoftmaxWithLoss(n.score,n.label)
    return n.to_proto()
#上面的僅僅是定義,下面的是把網路寫入本地的prototxt檔案中
def writeLayer():
    with open('train.prototxt', 'w') as f:
        f.write(str(myLayer('train_lmdb', 100,0)))
    with open('test.prototxt', 'w') as f:
        f.write(str(myLayer('test_lmdb', 10,0)))

寫完網路層,就是寫solver,solver有兩種方法來定義,我一開始用的第一種writeSolver(),可老是報錯,報錯的原因貌似是pycaffe識別不了“snapshot_prefix”這個屬性,於是我後來採用了第二張寫法writeSolver_2()

def writeSolver():
    solverprototxt=tools.CaffeSolver(trainnet_prototxt_path='train.prototxt',
                                    testnet_prototxt_path='test.prototxt')
#在python下,你可以沒必要每個都去定義,它會自己初始化
    solverprototxt.sp['base_lr']='0.001'
    solverprototxt.sp['weight_decay']='0.001'
    solverprototxt.sp['gamma']='0.0001'
    solverprototxt.sp['power']='0.001'
    solverprototxt.sp['display']='1000'
    solverprototxt.sp['test_iter']='100'
    solverprototxt.sp['max_iter']='5000'
    solverprototxt.sp['lr_policy']="step"
    solverprototxt.sp['snapshot']="1000"
#下面這個snapshot_prefix我把他去掉就能正常跑,加上就一直報錯
#    solverprototxt.sp['snapshot_prefix']="rr"
    solverprototxt.sp['display'] = "1"
    solverprototxt.sp['max_iter'] = "1000"
    solverprototxt.write('solver.prototxt')

from caffe.proto import caffe_pb2
def writeSolver_2():
    s=caffe_pb2.SolverParameter()
    s.train_net = 'train.prototxt'     # 訓練配置檔案
    s.test_net.append('test.prototxt')  # 測試配置檔案
    s.test_interval = 200                   # 測試間隔
    s.test_iter.append(1)                 # 測試迭代次數
    s.max_iter = 78200                      # 最大迭代次數
    s.base_lr = 0.001                       # 基礎學習率
    s.momentum = 0.9                        # momentum係數
    s.weight_decay = 5e-4                   # 權值衰減係數
    s.lr_policy = 'step'                    # 學習率衰減方法
    s.stepsize=26067                        # 此值僅對step方法有效
    s.gamma = 0.1                           # 學習率衰減指數
    s.display = 782                         # 螢幕日誌顯示間隔
    s.snapshot = 2000
    s.snapshot_prefix = 'shapshot'
    s.type = "SGD"                         # 優化演算法
    s.solver_mode = caffe_pb2.SolverParameter.GPU
    with open("solver.prototxt","w") as f:
        f.write(str(s))
    

現在如果分別呼叫上面兩個函式,就可以在本地生成三個檔案(1個solver,另外兩個分別為訓練階段和測試階段的),如圖

好,一切就緒,下面就是跑網路了,如果單純地想讓網路跑起來的話,下面兩句就行了,step就是讓caffe跑的步數

solver=caffe.get_solver('solver.prototxt')
solver.step(200) 

下面我給的訓練包括輸出準確率以及視覺化

def train_layer():
    caffe.set_device(0)
    caffe.set_mode_gpu()
    solver=caffe.get_solver('solver.prototxt')
    niter = 3000
    x_label=[0]
    y_acc=[0]
    acc=0
    for it in range(niter):
        solver.step(1)  # SGD by Caffe   
        solver.test_nets[0].forward()    
#a為最後的score,由於測試批次是10,所以這個a是個1*10的陣列,對應的b也是一個1*10的陣列
        a=solver.test_nets[0].blobs['score'].data.argmax(1)
        b=solver.test_nets[0].blobs['label'].data   
        for j in range(10):
            if(a[j]==b[j]):
                acc+=1                 
        if(it%40==0):
            print '第',it,'次迭代,準確率為:',Decimal(float(acc)/float(10*(it+1))).quantize(Decimal('0.000'))
            x_label.append(it)
            y_acc.append(Decimal(float(acc)/float(10*(it+1))).quantize(Decimal('0.000')))
    plt.plot(x_label, y_acc)
    plt.show()

ok,下面上一段完整的程式碼

import caffe
from caffe import layers as L,params as P
import sys
sys.path.append('F:/caffe/caffe-master/examples/pycaffe')
import tools
def writeSolver():
    solverprototxt=tools.CaffeSolver(trainnet_prototxt_path='train.prototxt',
                                    testnet_prototxt_path='test.prototxt')
#    solverprototxt.sp['base_lr']='0.001'
#    solverprototxt.sp['weight_decay']='0.001'
#    solverprototxt.sp['gamma']='0.0001'
#    solverprototxt.sp['power']='0.001'
#    solverprototxt.sp['display']='1000'
#    solverprototxt.sp['test_iter']='100'
#    solverprototxt.sp['max_iter']='5000'
#    solverprototxt.sp['lr_policy']="step"
#    solverprototxt.sp['snapshot']="1000"
##    solverprototxt.sp['snapshot_prefix']="rr"
#    solverprototxt.sp['display'] = "1"
#    solverprototxt.sp['max_iter'] = "1000"
    solverprototxt.write('solver.prototxt')

from caffe.proto import caffe_pb2
def writeSolver_2():
    s=caffe_pb2.SolverParameter()
    s.train_net = 'train.prototxt'     # 訓練配置檔案
    s.test_net.append('test.prototxt')  # 測試配置檔案
    s.test_interval = 200                   # 測試間隔
    s.test_iter.append(1)                 # 測試迭代次數
    s.max_iter = 78200                      # 最大迭代次數
    s.base_lr = 0.001                       # 基礎學習率
    s.momentum = 0.9                        # momentum係數
    s.weight_decay = 5e-4                   # 權值衰減係數
    s.lr_policy = 'step'                    # 學習率衰減方法
    s.stepsize=26067                        # 此值僅對step方法有效
    s.gamma = 0.1                           # 學習率衰減指數
    s.display = 782                         # 螢幕日誌顯示間隔
    s.snapshot = 2000
    s.snapshot_prefix = 'shapshot'
    s.type = "SGD"                         # 優化演算法
    s.solver_mode = caffe_pb2.SolverParameter.GPU
    with open("solver.prototxt","w") as f:
        f.write(str(s))
    




#original img is 60*60
def myLayer(lmdb,batch_size,is_deploy):
    n=caffe.NetSpec()
    n.data,n.label=L.Data(batch_size=batch_size,backend=P.Data.LMDB,source=lmdb,
                          transform_param=dict(scale=1./255),ntop=2)
    n.conv1 = L.Convolution(n.data, kernel_size=3,stride=2, num_output=20, 
                            weight_filler=dict(type='xavier'))
    #特徵圖變為 30*30 
    n.relu1=L.ReLU(n.conv1,in_place=True)
    n.conv2 = L.Convolution(n.relu1, kernel_size=3,stride=2, num_output=60, 
                            weight_filler=dict(type='xavier'))
    #15*15
    n.relu2=L.ReLU(n.conv2,in_place=True)
    n.conv3 = L.Convolution(n.relu1, kernel_size=3,stride=2, num_output=90, 
                            weight_filler=dict(type='xavier'))
    n.relu3=L.ReLU(n.conv3,in_place=True)
    n.score=L.InnerProduct(n.relu3,num_output=2,weight_filler=dict(type='xavier'))
    n.loss=L.SoftmaxWithLoss(n.score,n.label)
    return n.to_proto()

def writeLayer():
    with open('train.prototxt', 'w') as f:
        f.write(str(myLayer('train_lmdb', 100,0)))
    with open('test.prototxt', 'w') as f:
        f.write(str(myLayer('test_lmdb', 10,0)))
import matplotlib.pyplot as plt
import numpy as np
from decimal import Decimal
def train_layer():
    caffe.set_device(0)
    caffe.set_mode_gpu()
    solver=caffe.get_solver('F:/python_project/8_2/solver.prototxt')
    niter = 3000
    x_label=[0]
    y_acc=[0]
    acc=0
    for it in range(niter):
        solver.step(1)  # SGD by Caffe   
        solver.test_nets[0].forward()    
        a=solver.test_nets[0].blobs['score'].data.argmax(1)
        b=solver.test_nets[0].blobs['label'].data   
        for j in range(10):
            if(a[j]==b[j]):
                acc+=1                 
        if(it%40==0):
            print '第',it,'次迭代,準確率為:',Decimal(float(acc)/float(10*(it+1))).quantize(Decimal('0.000'))
            x_label.append(it)
            y_acc.append(Decimal(float(acc)/float(10*(it+1))).quantize(Decimal('0.000')))
    plt.plot(x_label, y_acc)
    plt.show()
     

writeSolver()
writeLayer()
#solver=caffe.get_solver('F:/python_project/8_2/solver.prototxt')
#solver.step(200) 
train_layer()

下面是我的結果