Windows下FCN保存训练日志并画loss曲线图
前言
网上有很多教程画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.txt是乱码,可以删除。训练结束后,所有训练日志记录将会保存在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]一起讨论。