Windows下FCN保存訓練日誌並畫loss曲線圖

前言

網上有很多教程畫caffe的loss圖,當你試過之後才發現根本不適用於FCN,經過我幾天的研究,終於有點小收穫,這篇博客我將介紹兩種方法畫loss圖。

方法一

  1. 保存訓練日誌
    在訓練數據的時候,在訓練命令後面再加一句命令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文件中。
    在這裏插入圖片描述

  2. 根據訓練日誌畫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]一起討論。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章