用pycaffe訓練影象
阿新 • • 發佈:2018-11-27
廢話不多說,本文在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()
下面是我的結果