Faster-Rcnn的loss曲线可视化

 

http://blog.csdn.net/wxplol/article/details/73694657

http://www.cnblogs.com/ymjyqsx/p/7059280.html

  由于要写论文需要画loss曲线,查找网上的loss曲线可视化的方法发现大多数是基于Imagenat的一些方法,在运用到Faster-Rcnn上时没法用,本人不怎么会编写代码,所以想到能否用python直接写一个代码,读取txt然后画出来,参考大神们的博客,然后总和总算一下午时间,搞出来了,大牛们不要见笑。

        首先,在训练Faster-Rcnn时会自己生成log文件,大概在/py-faster-rcnn/experiments/logs文件下,把他直接拿出来,放在任意位置即可,因为是txt格式,可以直接用,如果嫌麻烦重命名1.txt.接下来就是编写程序了

一下为log基本的格式

I0530 08:54:19.183091 10143 solver.cpp:229] Iteration 22000, loss = 0.173712
I0530 08:54:19.183137 10143 solver.cpp:245]     Train net output #0: rpn_cls_loss = 0.101713 (* 1 = 0.101713 loss)
I0530 08:54:19.183145 10143 solver.cpp:245]     Train net output #1: rpn_loss_bbox = 0.071999 (* 1 = 0.071999 loss)
I0530 08:54:19.183148 10143 sgd_solver.cpp:106] Iteration 22000, lr = 0.001

通过发现,我们只需获得 Iteration 和loss就行

 

[python] view plain copy
 
  1. #!/usr/bin/env python  
  2. import os  
  3. import sys  
  4. import numpy as np  
  5. import matplotlib.pyplot as plt  
  6. import math  
  7. import re  
  8. import pylab  
  9. from pylab import figure, show, legend  
  10. from mpl_toolkits.axes_grid1 import host_subplot  
  11.   
  12. # read the log file  
  13. fp = open('2.txt', 'r')  
  14.   
  15. train_iterations = []  
  16. train_loss = []  
  17. test_iterations = []  
  18. #test_accuracy = []  
  19.   
  20. for ln in fp:  
  21.   # get train_iterations and train_loss  
  22.   if '] Iteration ' in ln and 'loss = ' in ln:  
  23.     arr = re.findall(r'ion \b\d+\b,',ln)  
  24.     train_iterations.append(int(arr[0].strip(',')[4:]))  
  25.     train_loss.append(float(ln.strip().split(' = ')[-1]))  
  26.       
  27. fp.close()  
  28.   
  29. host = host_subplot(111)  
  30. plt.subplots_adjust(right=0.8) # ajust the right boundary of the plot window  
  31. #par1 = host.twinx()  
  32. # set labels  
  33. host.set_xlabel("iterations")  
  34. host.set_ylabel("RPN loss")  
  35. #par1.set_ylabel("validation accuracy")  
  36.   
  37. # plot curves  
  38. p1, = host.plot(train_iterations, train_loss, label="train RPN loss")  
  39. #p2, = par1.plot(test_iterations, test_accuracy, label="validation accuracy")  
  40.   
  41. # set location of the legend,   
  42. # 1->rightup corner, 2->leftup corner, 3->leftdown corner  
  43. # 4->rightdown corner, 5->rightmid ...  
  44. host.legend(loc=1)  
  45.   
  46. # set label color  
  47. host.axis["left"].label.set_color(p1.get_color())  
  48. #par1.axis["right"].label.set_color(p2.get_color())  
  49. # set the range of x axis of host and y axis of par1  
  50. host.set_xlim([-1500,60000])  
  51. host.set_ylim([0., 1.6])  
  52.   
  53. plt.draw()  
  54. plt.show()  
绘图结果

参考博客地址:

http://blog.csdn.net/YhL_Leo/article/details/51774966

 

 
 

解决caffe绘制训练过程的loss和accuracy曲线时候报错:paste: aux4.txt: 没有那个文件或目录 rm: 无法删除"aux4.txt": 没有那个文件或目录https://www.yuanmas.com/info/okzVl6WGyv.html

我用的是faster-rcnn,在绘制训练过程的loss和accuracy曲线时候,抛出如下错误,在网上查找无数大牛博客后无果,自己稍微看了下代码,发现,extract_seconds.py文件的

get_start_time()函数在获取时间时候获取失败,因为if line.find(‘Solving‘) != -1:这个语句判断错误导致,具体解决办法:

将该函数改造成:

def get_start_time(line_iterable, year):
    """Find start time from group of lines
    """

start_datetime = None
    for line in line_iterable:
        line = line.strip()
        #if line.find(‘Solving‘) != -1:
        start_datetime = extract_datetime_from_line(line, year)
        break
    return start_datetime

没错,就是把这个判断注释掉就ok了!

但是还有一个问题:解析出来的两个文件,分别是:mylog.train和mylog.test,其中mylog.test是个空文件,很是无语,暂时不想去深探原因,求各位看客帮

=======================================================================================================================================================

绘制loss曲线

 

第一步保存日志文件,用重定向即可:

$TOOLS/caffe train --solver=$SOLVERFILE 2>&1 |tee out.log

第二步直接绘制:

python plot_training_log.py 2 testloss.png out.log

这个plot_training_log.py在这个目录下caffe-fast-rcnn/tools/extra

2是选择画哪种类型的图片,具体数字是代表哪个类型可以查看帮助信息看到:

0: Test accuracy vs. Iters

1: Test accuracy vs. Seconds

2: Test loss vs. Iters

3: Test loss vs. Seconds

4: Train learning rate vs. Iters

5: Train learning rate vs. Seconds

6: Train loss vs. Iters

7: Train loss vs. Seconds

testloss.png是生成图片的名字,要求必须是png类型的文件

out.log是之前生成的日志文件

 

有个教程让你先生成解析日志文件:用:./parse_log.sh xxxxxxx.log

python parse_log.py out.log ./

注意最后一个是./,是保存的路径,最后会生成.train和.test两个文件。

实际上我觉得没有必要执行这一步,直接绘制曲线就好,绘制曲线中间也会生成这两个文件,因为plot_training_log.py本身要调用parse_log.py的shell脚本。并且生成的文件第一行是自带'#',但是用这个解析生成的反而是不带的。

 

跑项目代码时,生成的日志文件有一点问题,一个正常的日志文件应该是这样:

而我的日志文件是这样;

即在Iteration前我的日志文件没有I0619 10:29:45.757735  8944 solver.cpp:280] Solving deeplab_largeFOV 这句话,在parse_log.sh里有这样一句:grep '] Solving ' $1 > aux3.txt,要寻找 '] Solving ',如果没有,生成的aux3.txt就为空,

因为aux4.txt是由aux3.txt来的,这样就无法生成aux4.txt,也就报错说不能paste和rm aux4.txt。在extract_seconds.py中也是通过寻找sovling来确定开始时间的。如果单独用parse_log.py生成日志文件,不会报aux4.txt的错误,但会报extract_seconds.py

的错误。所以在Iteration 0前面一行加上没有这句话,就能解决问题。

 

在parse_log.sh中两行代码:

grep '] Solving ' $1 > aux3.txt
# grep 'Testing net' $1 >> aux3.txt
grep 'Train net' $1 >> aux3.txt

这两行代码都是搜索含有字符串的行然后写入aux3.txt。因为我的日志中没有] Solving,并且我的是训练日志,也没有Testing net,所以在没有添加] Solving的时候去运行脚本就报了:无法paste,rm aux4.txt的错误。实际上是因为没有任何东西写进aux3.txt,

aux3.txt是空的,所以运行$DIR/extract_seconds.py aux3.txt aux4.txt就不会生成aux4.txt。当然也就没办法paste,rm。修改的方法可以把Testing net改成Train net,这样可以在日志文件中找到行写入aux3.txt。或者在日志中添加] Solving让能有东西写进

aux3.txt。其实两种改法都可以,反正这个脚本之后要删除这些临时文件,然后再取生成.train的东西,这样改只是为了让程序不报错,能正常运行。

 

 

plot_training_log.py.example里的load_data函数也需要改一下,原本的代码是:

复制代码
def load_data(data_file, field_idx0, field_idx1):
    data = [[], []]
    with open(data_file, 'r') as f:
        for line in f:
            line = line.strip()
            if line[0] != '#':
                fields = line.split()
                data[0].append(float(fields[field_idx0].strip()))
                data[1].append(float(fields[field_idx1].strip()))
return data
复制代码

这段代码是从中间生成的日志文件读取你需要项的数据,!= '#'其实就是不读取第一行的项信息,这是中间文件:

直接用会报字符串无法转换成float的错误,原代码里对每一行split空格后生成的list,不是只含这4个数字的list,而是含有许多空格的list,所以当然float无法转换空格字符。需要做的就是split掉所有的空格,生成一个大小为4只包含4个数字的list。

这里需要注意个问题,日志文件中两个数字间的间隔的空格数是不一样的,有的是4个,有的是5个,代码需要实现无论多少个空格,都split掉。

修改代码:

复制代码
def load_data(data_file, field_idx0, field_idx1):
    data = [[], []]
    with open(data_file, 'r') as f:
        for line in f:
            line = line.strip()
            if line[0] != '#':
                line=','.join(filter(lambda x: x, line.split(' ')))
                print line
                fields = line.split(',')
                print fields
                data[0].append(float(fields[field_idx0].strip()))
                data[1].append(float(fields[field_idx1].strip()))
    return data
复制代码

这个的filter实现了功能。filter先split生成了一个每个空格占一个位置的list。

以下这张图大概模拟了一下过程:

可以看到split之后一个空格占一个位置。实际上我发现,这个filter函数,要想完成我需要的功能,只能处理list中任何带空格的位置都只能有一个空格,如果包含两个或其他多个,就不能实现过滤掉空格的功能,下图做了演示:

实际上,这样做很麻烦,split函数里面什么都不加,就会处理掉所有空格,无论空格多少个,即split(),如下图:

 

 

我最初绘制的loss曲线是将日志中每个loss都显示,但曲线误差大,不平滑,不便于分析:

造成这种原因是,在项目中,batch_size大小是2,即每次处理两张图片,在终端每20个迭代期显示一次loss,也就是每个loss是40张图片的,有可能某几张图片的loss比较大,就造成这一段迭代期的误差大。基于此,我将图像显示换成连续10个loss的平均,相当于200个迭代期的平均loss,这样下来波动就小了很多,方便分析:

 

生成的日志文件,无论是40000迭代期,还是80000,在20000时都要进入ipython,造成日志的格式不对,导致画不出图像,在后面的迭代期也会显示一些奇怪的东西,反正都需要删除掉,之后就能正常显示图像:

 

 
 ==========================================================================================================================================================
http://f.dataguru.cn/thread-729756-1-1.html
affe中提供了一个很好用的绘图工具,直接绘制出训练的log文件曲线,但是之前在绘制过程中,却出现了不寻常的问题。个人通过逐行读取代码,发现代码中是有一些小的问题的,不满足自己的要求。为了满足个人的需要,对代码做了两处简单的修正。
1 tools/extra/parse_log.sh中
   第17行第48列
     源程序:sed -n '/Iteration .* Testing net/,/Iteration *. loss/p' $1 > aux.txt
     修正为:sed -n '/Iteration .* Testing net/,/Iteration .* loss/p' $1 > aux.txt

2 由于自己想在同一个窗口画多个log文件形成对比,所以希望每条曲线的label不同,本代码所有曲线上label都是‘x’,我修正成了随机,源代码已经写了随机的部分,但是最后用的时候却有点匪夷所思,个人觉得可能是作者的疏忽,而且之前也没见人提出这个问题。个人愚见,有不同意的还请勿喷。
  tools/extra/plot_training_log.py.example
  第95行第20列
    源程序:return markers.values()[idx]
    修改为:return markers.keys()[idx]


修改完毕后,达到了我自己想要的效果。大家可以借鉴。
========================================================================================================================================================

注意1:如果有Invalid DISPLAY variable的报错,就在plot_training_log.py.example中修改。我按照下图该就ok了。

注意2:如果生成train loss相关图像时报错,可能是日志解析有问题,查看caffe.log.train是否正确,如果错误,需要更改parse_log.sh。我按照以下这样改就ok了。

 

posted on 2017-11-19 18:23  塔上的樹  阅读(1532)  评论(0编辑  收藏  举报