win11+tensorflow+Faster-RCNN爬坑记录(三)

对于检测出来的结果,虽然没有漏检虚检,但是几乎所有目标置信度都为1…所有结果都对,那八成就是检错了…
具体原因我现在也没搞清楚,刚开始以为是训练集和验证集有重叠部分导致的,后来仔细研读了代码之后发现并没有,人家是在所有数据集中选取了66%作为训练集和验证集的总和,又在这些图片中选取了50%作为训练集,其余的16%作为验证集,所以训练集、验证集、测试集之间根本没有重叠…而且计算所得到的mAP值也不太理想,只有0.6左右。
由于当时时间有些匆忙,只能做到这一步。后来寒假时间充裕了一些,又做了一些小小的调整。这里先记录一下过程。

重建数据集

由于之前时间原因,图片只用了1500张,这次就将两个文件夹中的4500张图片全部用来做数据集,首先随机抽取数据集的80%共3600张图片作为训练集和验证集,剩下的20%共900张图片用作测试集,再从训练集和验证集中随机抽取75%共2700张图片作为训练集,剩下的25%共900张图片作为验证集。即训练集、验证集、测试集的比例为6:2:2。
其次,由于训练时间过长,这次将迭代次数改为4000次,每500次保存一个模型。修改过后,每训练一次大概1小时左右。测试结果置信度也没有再出现1的情况,基本都在0.95左右,且最后算得的mAP值在0.8左右。

获取mAP值,precision,recall

详情请见这位大佬帖子的评论区,大佬后来又给出了一个计算mAP值,precision,recall的代码链接如下:

https://github.com/Cartucho/mAP

这套代码我没有用过,我是直接参照了这位博主的帖子,步骤如下:

1.添加可视化loss

注意在她的第8步(训练模型之前)中,添加了可视化loss,方便训练结束后在根路径下得到一个write_loss.txt,保存每迭代10次对应的损失值。可视化即在train.py中做如下更改;
在这里插入图片描述
(图片来自原博主)
添加代码如下图所示:

        filename = './write_loss.txt'  # 添加的代码(保存loss的文件)
                # 添加的代码(可视化loss)
                fw = open(filename, 'a')
                fw.write(str(int(iter))+' '+str(float('%.4f' % total_loss))+"\n")
                fw.close()
                # 添加结束

2.绘制loss曲线图

训练结束后,在根路径下得到一个write_loss.txt,保存着每迭代10次对应的损失值。在根路径下新建一个Python文件visual_loss.py,代码如下,运行后可以在根目录下得到一张loss曲线图。

import numpy as np
import matplotlib.pyplot as plt

y_ticks = [0, 0, 0.5, 1.0, 2.0, 3.0, 4.0, 5.0]  # 纵坐标的值,可以自己设置。
data_path = 'E:/Remote Sensing/Faster-RCNN-TensorFlow-Python3-master/write_loss.txt'  # log_loss的路径
result_path = 'E:/Remote Sensing/Faster-RCNN-TensorFlow-Python3-master/total_loss'  # 保存结果的路径

data1_loss = np.loadtxt(data_path)
x = data1_loss[:, 0]  # 冒号左边是行范围,冒号右边列范围,取第一列
y = data1_loss[:, 1]  # 取第2列

# 开始画图
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(x, y, label='total_loss')
plt.yticks(y_ticks)  # 如果不想自己设置纵坐标,可以注释掉
ax.legend(loc='best')
ax.set_title('The loss curves')
ax.set_xlabel('batches')
fig.savefig(result_path)

直接运行即可出图。
在这里插入图片描述

3.输出PR曲线并计算AP值

在.\lib\datasets路径下打开pascal_voc.py文件,做如下修改:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
修改和添加的代码如下所示:

# 添加的代码(输出PR曲线并计算AP值)
import matplotlib.pyplot as plt
import pylab as pl
# 添加结束
        # filename = self._get_comp_id() + '_det_' + self._image_set + '_{:s}.txt'  # 修改这行代码为下面这行
        filename = self._image_set + '_{:s}'  # 添加的代码(输出PR曲线并计算AP值)
    def _do_python_eval(self, output_dir='output'):
        annopath = self._devkit_path + '\\VOC' + self._year + '\\Annotations\\' + '{:s}.xml'
        imagesetfile = os.path.join(
            self._devkit_path,
            'VOC' + self._year,
            'ImageSets',
            'Main',
            self._image_set + '.txt')
        cachedir = os.path.join(self._devkit_path, 'annotations_cache')
        aps = []
        # The PASCAL VOC metric changed in 2010
        use_07_metric = True if int(self._year) < 2010 else False
        print('VOC07 metric? ' + ('Yes' if use_07_metric else 'No'))
        if not os.path.isdir(output_dir):
            os.mkdir(output_dir)
        for i, cls in enumerate(self._classes):
            if cls == '__background__':
                continue
            filename = self._get_voc_results_file_template().format(cls)
            rec, prec, ap = voc_eval(
                filename, annopath, imagesetfile, cls, cachedir, ovthresh=0.5,
                use_07_metric=use_07_metric)
            aps += [ap]
            # 添加的代码(输出PR曲线并计算AP值)
            recs = []
            precs = []
            recs += [rec[-1]]
            precs += [prec[-1]]
            print('recall for {} = {:.4f}'.format(cls, rec[-1]))
            print('precision for {} = {:.4f}'.format(cls, prec[-1]))
            pl.plot(rec, prec, lw=2,
                    label='Precision-recall curve of class {} (area = {:.4f})'
                          ''.format(cls, ap))
            # 添加结束
            print(('AP for {} = {:.4f}'.format(cls, ap)))
            with open(os.path.join(output_dir, cls + '_pr.pkl'), 'wb') as f:
                pickle.dump({'rec': rec, 'prec': prec, 'ap': ap}, f)
        # 添加的代码(输出PR曲线并计算AP值)
        pl.xlabel('Recall')
        pl.ylabel('Precision')
        plt.grid(True)
        pl.ylim([0.0, 1.05])
        pl.xlim([0.0, 1.05])
        pl.title('Precision-Recall')
        pl.legend(loc="upper right")
        plt.savefig('./PR.jpg')
        plt.show()
        # 添加结束
        print(('Mean AP = {:.4f}'.format(np.mean(aps))))
        print('~~~~~~~~')
        print('Results:')
        for ap in aps:
            print(('{:.3f}'.format(ap)))
        print(('{:.3f}'.format(np.mean(aps))))
        print('~~~~~~~~')
        print('')
        print('--------------------------------------------------------------')
        print('Results computed with the **unofficial** Python eval code.')
        print('Results should be very close to the official MATLAB eval code.')
        print('Recompute with `./tools/reval.py --matlab ...` for your paper.')
        print('-- Thanks, The Management')
        print('--------------------------------------------------------------')

然后在.\lib\datasets路径下打开voc_eval.py文件,做如下修改:
在这里插入图片描述
修改的代码如下所示:

    # tree = ET.parse(filename)  # 修改这行代码为下面这行
    tree = ET.parse('' + filename)  # 添加的代码(输入PR曲线并计算AP值)

最后在根路径下新建test_net.py文件,代码如下所示:

""""
Demo script showing detections in sample images.
See README.md for installation instructions before running.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import os

import tensorflow as tf
from lib.nets.vgg16 import vgg16
from lib.datasets.factory import get_imdb
from lib.utils.test import test_net

NETS = {'vgg16': ('vgg16.ckpt',)}  # 自己需要修改:训练输出模型
DATASETS = {'pascal_voc': ('voc_2007_trainval',), 'pascal_voc_0712': ('voc_2007_trainval+voc_2012_trainval',)}


def parse_args():
    """Parse input arguments."""
    parser = argparse.ArgumentParser(description='Tensorflow Faster R-CNN test')
    parser.add_argument('--net', dest='demo_net', help='Network to use [vgg16 res101]',
                        choices=NETS.keys(), default='vgg16')
    parser.add_argument('--dataset', dest='dataset', help='Trained dataset [pascal_voc pascal_voc_0712]',
                        choices=DATASETS.keys(), default='pascal_voc')
    args = parser.parse_args()
    return args


if __name__ == '__main__':
    args = parse_args()
    # model path
    demonet = args.demo_net
    dataset = args.dataset
    tfmodel = os.path.join('output', demonet, DATASETS[dataset][0], 'default', NETS[demonet][0])  # 模型路径
    # 获得模型文件名称
    filename = (os.path.splitext(tfmodel)[0]).split('\\')[-1]
    filename = 'default' + '/' + filename
    imdb = get_imdb("voc_2007_test")  # 得到
    imdb.competition_mode('competition mode')
    if not os.path.isfile(tfmodel + '.meta'):
        print(tfmodel)
        raise IOError(('{:s} not found.\nDid you download the proper networks from '
                       'our server and place them properly?').format(tfmodel + '.meta'))
    # set config
    tfconfig = tf.ConfigProto(allow_soft_placement=True)
    tfconfig.gpu_options.allow_growth = True
    # init session
    sess = tf.Session(config=tfconfig)
    # load network
    if demonet == 'vgg16':
        net = vgg16(batch_size=1)
    # elif demonet == 'res101':
    #     net = resnetv1(batch_size=1, num_layers=101)
    else:
        raise NotImplementedError
    net.create_architecture(sess, "TEST", 21,  # 自己需要修改:类别数量+1
                            tag='default', anchor_scales=[8, 16, 32])
    saver = tf.train.Saver()
    saver.restore(sess, tfmodel)
    print('Loaded network {:s}'.format(tfmodel))
    print(filename)
    test_net(sess, net, imdb, filename, max_per_image=100)
    sess.close()

运行结束后,即可得到各类AP值以及mAP值和PR曲线。
注意:每次测试前都要清空./data/VOCdevkit2007/annotation_cache文件夹里面的文件。

由于我的目标只有一类,故mAP值等于AP值:
在这里插入图片描述
在这里插入图片描述

修改学习率

1.增大学习率

将学习率调整为0.01,一开始loss就为nan,显然学习率过大;将学习率调为0.005,虽然loss值最后是收敛的,但测试的图片却没有显示结果。分析猜想,可能是检测出的置信度比设置的置信度小,也就是网络模型没有学习到需要的特征信息,将阈值置信度调到更小之后,训练过程中loss又变为nan了。

2.减小学习率

将学习率减小到0.0005,测试时虽然还是没有虚检漏检,但有个别目标置信度为0.1左右,很低。
其余结果如下所示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

另外,训练所得loss值其实并不是图上所画的样子(为了写报告好看被我改掉了,【捂脸】),每次训练都有几个跳变值,有的甚至跳到了几百上千…
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
也不知道原因。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值