Day 16 - 进行影像辨识训练

Day 16 - 进行影像辨识训练

在进行训练的过程中,我们可能因为某些关系而中断训练,可能是网路断线或是电脑断电等问题,这时候我们可以用以下指令重新开始训练,简单来说就是把原先 darknet53.conv.74 的权重,换成最新一个训练权重结果,而後面是记录整个训练过程的纪录档,因为是用 -a 选项,所以也是会继续附加上去。

cd /home/ec2-user/fishRecognition/fishsite/FishRecognition
../darknet/darknet detector train cfg/obj.data cfg/yolov3.cfg weights/yolov3.backup | tee -a trainRecord.txt

最终,我们训练了 6 千多次,大约花了 5 个小时,因为晚上训练了一段时间,隔天早上又接着训练,所以没有记录确切时间。最终平均损失值约为 0.26 左右,已经是已经是官方允可的范围 (0.05 ~ 3)内。接着要进行测试,看看训练结果如何,测试图片时需要有 data 这个目录,似乎是因为辨识完成後画图时需要有些图片在这个目录内,所以需要把这个目录建立一个链结到目前的目录里

ln -s ../darknet/data .
# 利用训练後的权重来进行模型测试
../darknet/darknet detector test cfg/obj.data cfg/yolov3.cfg weights/yolov3.backup ./labels/02-frame-608x608-0090.jpg
../darknet/darknet detector test cfg/obj.data cfg/yolov3.cfg weights/yolov3.backup ./labels/00-frame-608x608-0030.jpg
../darknet/darknet detector test cfg/obj.data cfg/yolov3.cfg weights/yolov3.backup ./labels/01-frame-608x608-0030.jpg

https://ithelp.ithome.com.tw/upload/images/20210916/20129510Mb2srWPl2q.png
图 1、辨识鱼类目录的结构

测试後的输出结果,结果非常准确,照片中所有的鱼都有找到,且置信度很高。

https://ithelp.ithome.com.tw/upload/images/20210916/20129510l98bM8etj5.png
图 2、测试的输出结果

下图是针对 3 种观赏鱼来进行辨识的结果,辨识时间很短,也都能准确找出来。

https://ithelp.ithome.com.tw/upload/images/20210916/20129510gm4A9H5zxC.png
图 3、针对 3 种观赏鱼分别测试的结果

对於这样的结果很满意,但是主要的原因是样本数太少,且太相近,因为是从同一个影片撷取出来的,但只能说本次专案的目标本来就不在提供一个精准的结果,而是展示一个过程,以及展示一个全端架构,每一个部分都可以进行修改跟优化。以下内容是观察整个训练过程,观察平均损失的变化以及 IoU (交集与联集比,Intersection over Union),简单来说平均损失可以视为猜错的量,数值越大表示模型越不准;IoU 是指模型所找出的方块框,与物件所在的方块框,如果等於 1,那就表示模型找到的方块框与物件所在的方块框完全重叠,就算是没有,也希望越大越好,当然,范围就是介於 0-1 之间,下图就是 IoU 的示意图,可以想像 A 方块框就是物件所在方块,B 方块框是模型猜测方块。

https://ithelp.ithome.com.tw/upload/images/20210916/20129510NsLBG9MQTp.png
图 4、IoU 的示意图

以下三只程序的目的是要分析训验记录档,并将结果以图形方式呈现:

  • extract_log.py:将 trainRecord.txt 的文字内容进行转换处理,并分别存成:train_log_loss.txt 和 train_log_iou.txt。
  • train_iou_visualization.py:分析 train_log_loss.txt ,将平均损失的优化过程视觉化。
  • train_loss_visualization.py:分析 train_log_iou.txt ,将交集与联集比 (IoU )的优化过程视觉化。

extract_log.py

#!/usr/bin/python
#coding=utf-8
import inspect
import os
import random
import sys
def extract_log(log_file, new_log_file, key_word):
    with open(log_file, 'r') as f:
        with open(new_log_file, 'w') as train_log:
            for line in f:
                #去除多 GPU 的同步记录;去除除零错误的记录
                if ('Syncing' in line) or ('nan' in line):
                    continue
                if key_word in line:
                    train_log.write(line)
    f.close()
    train_log.close()
 
extract_log('trainRecord.txt', 'train_log_loss.txt', 'images')
extract_log('trainRecord.txt', 'train_log_iou.txt', 'IOU')

下图就是 YOLOV3 训练时的纪录档 (trainRecord.txt),上面的程序就是依照关键字 images 来形成 train_log_loss.txt 文档; IOU 来形成 train_log_iou.txt

https://ithelp.ithome.com.tw/upload/images/20210916/20129510kIQXrxhqj0.png
图 5、YOLOV3 训练时的纪录档

下图是每次叠代损失的文字记录档 train_log_loss.txt,共 6298 行。

https://ithelp.ithome.com.tw/upload/images/20210916/20129510yHEPqAHzTH.png
图 6、每次叠代损失的文字记录档

下图是优化 IoU 的文字记录档 train_log_iou.txt ,共 106451 行。

https://ithelp.ithome.com.tw/upload/images/20210916/20129510mxjTaTFoUi.png
图 7、优化 IoU 的文字记录档

train_iou_visualization.py

#!/usr/bin/python
#coding=utf-8
 
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
 
#根据自己的 log_loss.txt 中的行数修改 lines, 修改训练时的叠代起始次数 (start_ite) 和结束次数 (end_ite)。
lines = 6331
start_ite = 1 #log_loss.txt 里面的最小叠代次数
end_ite = 6298 #log_loss.txt里面的最大叠代次数
step = 30 # 跳行数,决定画图的稠密程度
igore = 0 # 当开始的 loss 较大时,你需要忽略前 igore 次叠代,注意这里是叠代次数
  
y_ticks = [1, 100, 200, 300, 500, 800] #纵坐标的值,可以自己设置。
data_path =  'train_log_loss.txt' #log_loss的路径。
 
####-只需要改上面的,下面的可以不改动
names = ['loss', 'avg', 'rate', 'seconds', 'images']
result = pd.read_csv(data_path, skiprows=[x for x in range(lines) if (x<lines*1.0/((end_ite - start_ite)*1.0)*igore or x%step!=9)], error_bad_lines=\
False, names=names)
result.head()
for name in names:
    result[name] = result[name].str.split(' ').str.get(1)
 
result.head()
result.tail()
 
for name in names:
    result[name] = pd.to_numeric(result[name])
result.dtypes
print(result['loss'].values)
 
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
 
x_num = len(result['loss'].values)
tmp = (end_ite-start_ite - igore)/(x_num*1.0)
x = []
for i in range(x_num):
    x.append(i*tmp + start_ite + igore)
#print(x)
print('total = %d\n' %x_num)
print('start = %d, end = %d\n' %(x[0], x[-1]))
 
ax.plot(x, result['loss'].values, label='avg_loss')
#ax.plot(result['loss'].values, label='loss')
plt.yticks(y_ticks)
plt.grid()
ax.legend(loc = 'best')
ax.set_title('The loss curves')
ax.set_xlabel('batches')
fig.savefig('loss')

下图中显示平均损失数量收敛的很快,在前200多次的叠代中就收敛 1 左右。

https://ithelp.ithome.com.tw/upload/images/20210916/201295102H1DVWL7Bq.png
图 8、训练过程的平均损失变化

当我们忽略前 1000 次的叠代时,得到下图,可以发现训练过程中是有发生震荡的

igore = 1000 # 当开始的 loss 较大时,你需要忽略前 igore 次叠代,注意这里是叠代次数

https://ithelp.ithome.com.tw/upload/images/20210916/20129510nnncw6CEJX.png
图 9、训练过程2000次後的平均损失变化

train_loss_visualization.py

#!/usr/bin/python
#coding=utf-8
 
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
 
#根据log_iou修改行数
lines = 106451
step = 5000
start_ite = 100
end_ite = 10000
igore = 100
data_path =  'train_log_iou.txt' #log_loss的路径。
 
names = ['Region Avg IOU', 'Class', 'Obj', 'No Obj', '.5_Recall', '.7_Recall', 'count']
#result = pd.read_csv('log_iou.txt', skiprows=[x for x in range(lines) if (x%10==0 or x%10==9)]\
result = pd.read_csv(data_path, skiprows=[x for x in range(lines) if (x<lines*1.0/((end_ite - start_ite)*1.0)*igore or x%step!=0)]\
, error_bad_lines=False, names=names)
result.head()
 
for name in names:
    result[name] = result[name].str.split(': ').str.get(1)
result.head()
result.tail()
for name in names:
    result[name] = pd.to_numeric(result[name])
result.dtypes
 
 
####--------------
x_num = len(result['Region Avg IOU'].values)
tmp = (end_ite-start_ite - igore)/(x_num*1.0)
x = []
for i in range(x_num):
	x.append(i*tmp + start_ite + igore)
#print(x)
print('total = %d\n' %x_num)
print('start = %d, end = %d\n' %(x[0], x[-1]))
####-------------
 
 
fig = plt.figure()
ax = fig.add_subplot(1,1,1)
ax.plot(x, result['Region Avg IOU'].values, label='Region Avg IOU')
#ax.plot(result['Avg Recall'].values, label='Avg Recall')
plt.grid()
ax.legend(loc='best')
ax.set_title('The Region Avg IOU curves')
ax.set_xlabel('batches')
fig.savefig('iou')

下图显示的是 iou 的变化情形

https://ithelp.ithome.com.tw/upload/images/20210916/20129510n6697WPZ5n.png
图 10、训练过程中 IoU 的变化

参考资料


<<:  [Day 11] 来自未来的资料 - 数据泄露(Data leakage)

>>:  【Day 01】认识资料结构 Data Structure ( 使用 JavaScript )

Day 17. 来摸摸Unreal Engine吧!

决定来摸Unreal Engine(UE)怎麽使用,经过Unity的下载後,其实Unreal的下载也...

Day15-Overloading

函式多载(overloading),今天顺着蚂蚁书的顺序先讨论函式多载(overloading)与样...

xampp 多个网站 必须重启I-040GW 才可连上 浮动IP no-ip

各位前辈好 这个问题困扰我一年多了,真的找不到问题点所以提出 我的问题跟这位很像 我的原先设定是 使...

Day29- 这是替身攻击!! 替换你的pod Telepresence

在前面我们介绍到了各种建立以及产生pod的方式,但是当你已经建构好一个系统後,写好的程序要更新以及测...

[Day 08] Kotlin DAO 其他和资料库互动的方式

昨天我们看过了使用 Kotlin DAO 进行资料库 CRUD 的方式。 今天我们来看看,除了基本的...