前言
網上有很多教程畫caffe的loss圖,當你試過之後才發現根本不適用於FCN,經過我幾天的研究,終於有點小收穫,這篇博客我將介紹兩種方法畫loss圖。
方法一
-
保存訓練日誌
在訓練數據的時候,在訓練命令後面再加一句命令2>&1 | tee out.log,如下圖所示
看到這先彆着急訓練,先介紹一下這個命令。2>&1是Linux下的信息流輸出控制語法,這句命令會將你的輸出信息直接保存在out.log文件中,而且不會在命令窗口中實時顯示訓練信息,如果你不需要在命令窗口顯示信息的話,輸入命令python solve.py 2>&1訓練即可。如果你想要在命令窗口實時顯示訓練數據的話,那就需要tee命令,但是這是Linux下的命令,在win10下不能直接使用,先下載UnxUtils文件,解壓,在文件夾usr\local\wbin下找到tee.exe文件,將tee.exe拷貝到C:\Windows\System32文件夾下。如下圖所示。
此時可以使用tee命令了。如上面所示輸入命令 python solve.py 2>&1 | tee out.log開始訓練,這時你會發現在當前路勁下會出現out.log文件。訓練結束後,所有訓練日誌記錄將會保存在out.log文件中。
-
根據訓練日誌畫loss圖
網上有很多教程說這一步先解析log文件,使用parse_log.py文件對out.log解析。我之所以說網上的caffe教程不適用於FCN就在於這一步,發現使用命令python parse_log.py out.log ./並不會向網上所說的生成.train和.test文件,導致後面畫圖也無法進行。也可能是我哪一步出錯了,如果有大神看到我這篇博客的話,還望指點一二。
這裏將換另一種方法畫圖,用python語句提取log文件數據,將圖畫出來。
在當前文件夾下創建loss.py文件,寫上如下代碼#coding:utf-8 import os import sys import numpy as np import matplotlib.pyplot as plt import math import re import pylab from pylab import figure, show, legend from mpl_toolkits.axes_grid1 import host_subplot fp = open('out.log', 'r') train_iterations = [] learningrate = [] train_loss = [] test_iterations = [] #test_accuracy = [] for ln in fp: if '] Iteration ' in ln and 'loss = ' in ln: arr = re.findall(r'ion \b\d+\b,',ln) train_iterations.append(int(arr[0].strip(',')[4:])) train_loss.append(float(ln.strip().split(' = ')[-1 ])) # get train_iterations and train_loss if '] Iteration ' in ln and 'lr = ' in ln: learningrate.append(float(ln.strip().split(' = ')[-1])) fp.close() a1 = plt.subplot(111) a1.set_title("loss") a1.plot(train_iterations,train_loss) ''' a2 = plt.subplot(212) a2.set_title("learningrate") a2.plot(train_iterations,learningrate) ''' # a1.margins(x=0.2) plt.tight_layout() plt.show() print(train_loss)
運行程序,你將會得到如下圖
到此所有的工作已經結束,當然畫loss圖可能還不夠,可能還需要畫accuracy圖等,目前還沒有對此代碼進行研究,以後將會繼續更新,如果有大神有方法的話,還望指導一二,謝謝了。
方法二
上面說的是畫loss圖的方法一,如果你覺得麻煩的話,可以嘗試用方法二。
修改solve.py文件代碼,參考這篇博客
#coding=utf-8
import sys
sys.path.append('D:/caffe/caffe-master/python')
import caffe
import surgery, score
import numpy as np
import os
import sys
#plot 加載繪製圖像所需要的python庫
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
import math
//根據上述UpdateSmoothedLoss()函數修改爲python語言而來,目的就是更新平均loss
def UpdateSmLoss(loss,losses_,iterval,average_loss,sm_loss):
sizel = len(losses_)
listloss=loss.tolist() #array轉化爲list
if sizel < average_loss:
losses_.append(listloss)
sm_loss = (sm_loss*sizel+listloss)/(sizel+1)
else:
idx = iterval % average_loss
sm_loss += (listloss-losses_[idx]) / average_loss
losses_[idx] = listloss
return sm_loss,losses_
try:
import setproctitle
setproctitle.setproctitle(os.path.basename(os.getcwd()))
except:
pass
vgg_weights = 'vgg16-fcn.caffemodel'
vgg_proto = 'vgg16_deploy.prototxt'
#weights = 'vgg16-fcn.caffemodel'
# init
#caffe.set_device(int(sys.argv[1]))
caffe.set_device(0)
caffe.set_mode_gpu()
#solver = caffe.SGDSolver('solver.prototxt')
#solver.net.copy_from(weights)
solver = caffe.SGDSolver('solver.prototxt')
#parameter 實時繪製所需要的一些參數
niter = 100000 #對應solver.prototxt中的max_iter: 100000
display = 20 #對應solver.prototxt中的display: 20
snapshotnum = 4000 #對應solver.prototxt中的snapshot: 4000
ave_loss = 20 #對應solver.prototxt中的average_loss: 20
#losses_用於存儲當前迭代次數的前average_loss次迭代所產生的loss
losses_ = []
sm_loss = 0 #平均loss
#train_loss 用於存儲每次的sm_loss,以便畫折線圖
train_loss = np.zeros(np.ceil(niter * 1.0 / display))
vgg_net = caffe.Net(vgg_proto, vgg_weights, caffe.TRAIN)
surgery.transplant(solver.net, vgg_net)
del vgg_net
# surgeries
interp_layers = [k for k in solver.net.params.keys() if 'up' in k]
surgery.interp(solver.net, interp_layers)
# scoring
val = np.loadtxt('D:/VOC2012/ImageSets/Segmentation/seg11valid.txt', dtype=str)
#for _ in range(25):
#solver.step(4000)
#score.seg_tests(solver, False, val, layer='score')
plt.close()
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
plt.grid(True)
plt.ion() #開啓交互式繪圖(實現實時繪圖的關鍵語句)
for it in range(niter):
solver.step(1) #python下的step()函數,對應於上述Step()函數
_train_loss = solver.net.blobs['loss'].data #取出每次迭代輸出的loss
[sm_loss,losses_] = UpdateSmLoss(_train_loss,losses_,it,ave_loss,sm_loss) #更新
if it % display == 0 and it !=0: #滿足條件時展示平均loss
ax.scatter(it,sm_loss,c = 'r',marker = 'o') #繪製loss的散點圖
train_loss[it // display - 1] = sm_loss #存儲平均loss
if it > display:
ax.plot([it-20,it],[train_loss[it // display - 2],train_loss[it // display - 1]],'-r') #繪製折線圖
plt.pause(0.0001)
if it % snapshotnum == 0 and it != 0: #對應原solve.py文件中的最後兩句代碼,每snapshotnum次迭代進行一次測試
score.seg_tests(solver, False, val, layer='score')
losses_ = [] #測試後需要清空losses_以及平均loss,對應於每次進入Step()函數都需要對這兩者清空
sm_loss = 0
直接運行程序,就會一邊訓練一邊畫圖。當然每一個方法總有優點和缺點,第二個方法雖然直觀,但是運行起來可能會很卡,而且沒有記錄訓練日誌,如果想要查看某一次訓練的結果的話就不如第一種方法。到此兩種方法已經介紹完了,如果有什麼問題的話,歡迎留言或者發郵箱[email protected]一起討論。