您当前的位置:首页 > IT编程 > 深度学习
| C语言 | Java | VB | VC | python | Android | TensorFlow | C++ | oracle | 学术与代码 | cnn卷积神经网络 | gnn | 图像修复 | Keras | 数据集 | Neo4j | 自然语言处理 | 深度学习 | 医学CAD | 医学影像 | 超参数 | pointnet | pytorch |

自学教程:FPN-从原理到模型的训练与测试

51自学网 2020-11-01 08:56:12
  深度学习
这篇教程FPN-从原理到模型的训练与测试写得很实用,希望能帮到您。

原文https://blog.csdn.net/gusui7202/article/details/101875703?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
原理简介

-------------------------------

【FPN】

特征金字塔网络,是众多卷积神经网络结构中的一种。

【创新点】

特征的构建和对特征的应用呈现出一种金字塔状的多尺度方式。这里的多尺度有两个层次,一个是特征的多尺度:构建了不同分辨率的融合特征;另一个是多尺度是应用的多尺度,在多个不同尺度的特征上分别做分类和回归。

【动机】

1.针对深度网络中语义不能兼顾的问题,设计一种能够兼顾底层和高层特征的卷积神经网络结构

2.附带针对:小目标。

【有效性分析】

1.特征融合是一个被证明有效的,通过增加计算量来提高模型性能的方式,FPN提供的,是一种更充分的特征融合,因为每一种分辨率的特征,都被用于融合,而融合结果也不是局限于单一的一个特征,而是同样融合出多种分辨率的特征,并且融合的特征之间还有递进关系,更后面的特征融合将会用到前面的融合特征。在这么一个不同层之间构建了丰富的信息交互,保证了从头到尾有效信息的传播。

2.关于小目标的检测,是其主打卖点。有用的原因主要有三个,第一个是更充分的利用了底层特征,而小目标正是因为小,所以在底层的信息才是最多的,所以对于小目标的特征是被优化了的。第二,就是在不同尺度的特征上都做预测,本质就是加大了搜索粒度,因为每个尺度的Feature上都会产生anchor,那么三个尺度的特征上都做预测,本质上,anchor boxes会更多更充分更准确的包含到小目标,也就是能更好的将小目标检索出来。第三,是原因1和原因2的共同作用,特征优化了,搜索更细了,这才是效果直接提升的必要因素,也就是我能框出更多的框,并且小框的特征还更有效。

3.模型结构:这些其他博客都很多了,不必赘述。

4.关于FPNFaster R-CNN等模型的关系。其实FPN不是一个单独的网络,其提出的是一种主干网络以及对应该主干网络的一种检测方式。也就相当于把Faster R-CNN中的Backbone从ResNet-101的连接结构变成FPN结构,然后将Faster R-CNN的RPN输入从原来的最后一个特征层变为多个特征层(不同尺度的融合特征),也可以理解为将RPN复制多次。所以大家看源代码的时候,就当成Faster R-CNN的一种改进看就可以了。其他部分都一样的。

-------------------------------

模型搭建

-------------------------------

1.环境搭建

ubuntu + python2 + tensorflow1.2 + cv2 + cuda8.0 (+ GeForce GTX 1080)

作者将自己的环境用Docker打包了一份,So,
You can also use docker environment, command:

docker pull yangxue2docker/tensorflow3_gpu_cv2_sshd:v1.0

2.下载源代码

git clone https://github.com/yangxue0827/FPN_Tensorflow.git   

3.跑一下Demo测试一下模型

1、解压基于res101训练好的demo模型:

  文件在 FPN根目录/output/res101_trained_weights/(一个飞机检测的模型)


2、在测试图像文件夹里面丢一些包含目标(飞机)的图片。本身就有几张,故可不放。

      文件夹为:FPN根目录/tools/inference_image


3、修改模型的绝对路径。因为内部的调用都需要基于一个路径,这里作者集成到配置文件cfgs.py中了。在里面直接改就行,然后其他的路径就都会根据这个来。

在这里面修改:FPN根目录/libs/configs/cfgs.py 

 
  1.  
    # 找到这一句,将后面的路径改为自己FPN的文件夹位置
  2.  
    ROOT_PATH = os.path.abspath(r'C:\Users\yangxue\Documents\GitHub\FPN_Tensorflow')

4、运行代码测试:

这里作者提供两种代码,一种是用于跑小图片的(作者所用数据集中的.jpg为小分辨率图像),一种是用于跑大图的,.tif结尾的是分辨率大的大图。


 
  1.  
    ###跑小图
  2.  
     
  3.  
    cd FPN根目录/tools
  4.  
    python inference.py
  5.  
     
  6.  
    (注:大图小图都可以跑,大图就用最小边压缩了一下)
  7.  
     
  8.  
    ###跑大图
  9.  
     
  10.  
    cd FPN根目录/tools
  11.  
    python demo.py --src_folder=.\demo_src --des_folder=.\demo_des
  12.  
     
  13.  
     
  14.  
    (注:这个demo只处理.tif结尾的大图,src_folder和des_folder后面修改为测试图片和保存测试结果的文件夹位置。)

一般就用第一个就行了。后面那个也就相当换了一种方式处理格式问题,然后还是用最小边缩小大图。

【测试结果】

到此,模型搭建完成,测试通过。

-------------------------------

训练自己的数据

-------------------------------

1.数据准备

将自己的PASCAL_VOC数据集拆分为训练集、测试集合。适用/data/io/divide_data.py

具体的拆分比例,调节divide_data.py中的divide_rate = 0.8。

python /data/io/divide_data.py

在根目录下,将会生成两个文件夹:VOCdevkit_train 和 VOCdevkit_test

下一步,需要分别将训练和测试数据转换成 TFrecord 格式。该格式是TensorFlow的高效存储格式,连续的内存二进制存储能够有效的加快数据的读取和写入。而像原始文件夹那样每个数据独立存储。

转换的代码为 /data/io/convert_data_to_tfrecord.py

python convert_data_to_tfrecord.py --VOC_dir='***/VOCdevkit/VOCdevkit_train/' --save_name='train' --img_format='.jpg' --dataset='ship'

在使用的时候,训练和测试数据分别使用。.py后面的参数需要根据自己的路径和数据集进行修改。参数说明如下:


 
  1.  
    # 上一步训练、测试数据分离后的文件夹路径。
  2.  
    --VOC_dir='你的FPN路径/VOCdevkit/VOCdevkit_train/'
  3.  
    #tfrecord名字。训练数据用'train' ,测试数据用'test'
  4.  
    --save_name='train'
  5.  
    #你的图片格式。有Png\tif\jpeg
  6.  
    --img_format='.jpg'
  7.  
    #你的数据集名字。这个需要在/libs/label_name_dict/label_dict.py中添加自己的数据集
  8.  
    --dataset='mydataset'

上面的参数前三个都Ok,第四个需要添加自己数据集的类别字典,所以你无法直接运行上面的代码。需要修改以下:

在/libs/label_name_dict/label_dict.py中添加自己的数据集标签类别。具体如下:


 
  1.  
    # -*- coding: utf-8 -*-
  2.  
    from __future__ import division, print_function, absolute_import
  3.  
     
  4.  
    from libs.configs import cfgs
  5.  
     
  6.  
    if cfgs.DATASET_NAME == 'ship':
  7.  
    NAME_LABEL_MAP = {
  8.  
    'back_ground': 0,
  9.  
    "ship": 1
  10.  
    }
  11.  
    ##########################
  12.  
    ###插入以下:--dataset='mydataset'中的名字一致就是调用到这个字典的。
  13.  
    别人我为什么需要自己数据集训练数据类别的字典- -
  14.  
    因为字典不同训练的模型后面的softmax层大小不一样。2类就2个。
  15.  
    4类的话softmax就有4个节点。这个需要训练师自己确认。
  16.  
    (而不是因为无法从你的dataset自动的统计你的类别名字及其数量。)
  17.  
    ##########################
  18.  
    elif cfgs.DATASET_NAME == 'mydataset':#这个名字就是你数据集类别字典的名字了。
  19.  
    NAME_LABEL_MAP = {
  20.  
    'back_ground': 0,
  21.  
    "你的类1": 1
  22.  
    "你的类2": 2
  23.  
    "你的类3": 3
  24.  
    ......
  25.  
    }
  26.  
     
  27.  
    ##########################
  28.  
    ###实际上和下面的格式都一样。
  29.  
    ##########################
  30.  
    elif cfgs.DATASET_NAME == 'SSDD':
  31.  
    NAME_LABEL_MAP = {
  32.  
    'back_ground': 0,
  33.  
    "ship": 1
  34.  
    }
  35.  
    elif cfgs.DATASET_NAME == 'airplane':
  36.  
    NAME_LABEL_MAP = {
  37.  
    'back_ground': 0,
  38.  
    "airplane": 1
  39.  
    }
  40.  
    elif cfgs.DATASET_NAME == 'nwpu':
  41.  
    NAME_LABEL_MAP = {
  42.  
    'back_ground': 0,
  43.  
    'airplane': 1,
  44.  
    'ship': 2,
  45.  
    'storage tank': 3,
  46.  
    'baseball diamond': 4,
  47.  
    'tennis court': 5,
  48.  
    'basketball court': 6,
  49.  
    'ground track field': 7,
  50.  
    'harbor': 8,
  51.  
    'bridge': 9,
  52.  
    'vehicle': 10,
  53.  
    }
  54.  
     
  55.  
    ....
  56.  
    .....
  57.  
    ......
  58.  
    .......

然后就可以运行convert_data_to_tfrecord.py了。别忘了填上四个参数。

python convert_data_to_tfrecord.py --VOC_dir='***/VOCdevkit/VOCdevkit_train/' --save_name='train' --img_format='.jpg' --dataset='ship'

运行结果就是得到训练、测试数据的tfrecord格式数据,在 /data/tfrecords/ 里面。你可以自己检查一下。

2.参数设置

数据准备好了,那么训练就要调参和调一些路径啦。打开/libs/configs/cfgs.py,按我的注释来。

对应里面的model,应先下载好预训练模型,放在 /data/pretrained_weights/ 中。

预训练模型的下载地址:

 Res101: http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz

Res50: http://download.tensorflow.org/models/resnet_v1_50_2016_08_28.tar.gz


 
  1.  
    # -*- coding: utf-8 -*-
  2.  
    from __future__ import division, print_function, absolute_import
  3.  
    import os
  4.  
     
  5.  
    #####
  6.  
    初始化设置
  7.  
    #####
  8.  
     
  9.  
    # 你的FPN目录地址
  10.  
    ROOT_PATH = os.path.abspath(r'C:\Users\yangxue\Documents\GitHub\FPN_Tensorflow')
  11.  
     
  12.  
    # pretrain weights path
  13.  
    #测试结果保存路径,上面我们已经测试过了 不用改。
  14.  
    TEST_SAVE_PATH = ROOT_PATH + '/tools/test_result'
  15.  
    INFERENCE_IMAGE_PATH = ROOT_PATH + '/tools/inference_image'
  16.  
    INFERENCE_SAVE_PATH = ROOT_PATH + '/tools/inference_result'
  17.  
    #使用的model。
  18.  
    NET_NAME = 'resnet_v1_101'
  19.  
    #你的本次训练项目名字。每当重新训练一次,最好在后面加一个01\02区别。名字重复了就会训乱。按这个名字会有output里面生成对应名字的文件夹,保存训练的Net
  20.  
    VERSION = 'v1_mydataset'
  21.  
    #你的类别数,是几类就写几。
  22.  
    CLASS_NUM = 1
  23.  
     
  24.  
     
  25.  
     
  26.  
     
  27.  
    BASE_ANCHOR_SIZE_LIST = [15, 25, 40, 60, 80]
  28.  
    LEVEL = ['P2', 'P3', 'P4', 'P5', "P6"]
  29.  
    STRIDE = [4, 8, 16, 32, 64]
  30.  
    ANCHOR_SCALES = [1.]
  31.  
    ANCHOR_RATIOS = [1, 0.5, 2, 1 / 3., 3., 1.5, 1 / 1.5]
  32.  
    SCALE_FACTORS = [10., 10., 5., 5.]
  33.  
    OUTPUT_STRIDE = 16
  34.  
    SHORT_SIDE_LEN = 600
  35.  
    ####改成自己数据集字典的名字
  36.  
    DATASET_NAME = 'mydataset'
  37.  
    ####
  38.  
    BATCH_SIZE = 1
  39.  
    WEIGHT_DECAY = {'resnet_v1_50': 0.0001, 'resnet_v1_101': 0.0001}
  40.  
    EPSILON = 1e-5
  41.  
    MOMENTUM = 0.9
  42.  
    MAX_ITERATION = 50000
  43.  
    GPU_GROUP = "1"
  44.  
    LR = 0.001
  45.  
     
  46.  
    # rpn
  47.  
    SHARE_HEAD = True
  48.  
    RPN_NMS_IOU_THRESHOLD = 0.5
  49.  
    MAX_PROPOSAL_NUM = 2000
  50.  
    RPN_IOU_POSITIVE_THRESHOLD = 0.5
  51.  
    RPN_IOU_NEGATIVE_THRESHOLD = 0.2
  52.  
    RPN_MINIBATCH_SIZE = 512
  53.  
    RPN_POSITIVE_RATE = 0.5
  54.  
    IS_FILTER_OUTSIDE_BOXES = True
  55.  
    RPN_TOP_K_NMS = 12000
  56.  
     
  57.  
    # fast rcnn
  58.  
    ROI_SIZE = 14
  59.  
    ROI_POOL_KERNEL_SIZE = 2
  60.  
    USE_DROPOUT = False
  61.  
    KEEP_PROB = 0.5
  62.  
    FAST_RCNN_NMS_IOU_THRESHOLD = 0.2
  63.  
    FAST_RCNN_NMS_MAX_BOXES_PER_CLASS = 100
  64.  
    FINAL_SCORE_THRESHOLD = 0.5
  65.  
    FAST_RCNN_IOU_POSITIVE_THRESHOLD = 0.45
  66.  
    FAST_RCNN_MINIBATCH_SIZE = 256
  67.  
    FAST_RCNN_POSITIVE_RATE = 0.5

 

3.跑起来

在根目录下打开终端。运行以下:

python /tools/train.py 

等着训练完成吧。

-------------------------------

测试自己的数据

-------------------------------

1.参数设置

测试实际上包括指标验证和保存测试结果。如果只是像将测试集跑一边然后将结果保存下来,就用/tools/test.py

如果是想验证,就用/tools/eval.py

在test.py或eval.py里面有对应的测试参数可以改,比如正样本阈值等。

2.验证测试

运行代码。


 
  1.  
    python /tools/test.py
  2.  
    或者
  3.  
    python /tools/eval.py

运行test.py的话你会在./tools/test_result里获得测试集的图片检测结果。

运行eval.py则得到 AP、Recall 和mAP。

以上。

------------------------

作者优化的FPN版本:https://github.com/DetectionTeamUCAS/FPN_Tensorflow

作者给出了一个优化版本。因为原来的版本在训练的过程中因为summary的可视化原因,会终止训练。

比如tensorboard显示proposals图像结果的时候,画了超出图像的框等。就会终止训练。如果不想换模型,把对应的地方注释掉就可以,一般大家可能也用不到tensorboard。另一个就是使用方面的优化。优化版的代码用eval.py就可以直接获取指标验证结果以及测试结果,只需要调节一个参数。

以上是我使用时发现的主要两点感受。

两个使用方法大同,不赘述。


SSD网络原理解析
FPN(Feature Pyramid Networks)网络原理解析
51自学网,即我要自学网,自学EXCEL、自学PS、自学CAD、自学C语言、自学css3实例,是一个通过网络自主学习工作技能的自学平台,网友喜欢的软件自学网站。
京ICP备13026421号-1