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]一起讨论。

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