caffe框架 结构及其运行流程时序图

1.caffe文件目录结构

caffe文件目录结构如下图:
caffe文件目录结构
caffe源码目录结构

  • 如使用make编译,通过更改Makefile.config来更改编译配置。
  • 如使用cmake编译,通过更改CMakeLists.txt来更改编译配置。
  • 可以直接使用docker文件夹下的Dockerfile来快速构建包含caffe所需依赖环境的系统容器。
  • 可以使用gtest快速测试caffe工程。
  • caffe工程使用Protocol Buffers来实现结构化数据的序列号与反序列化。需要使用protoc编译器编译数据存储格式描述文件。
  • model文件夹提供了几种常见模型的网络结构及配置文件。更多模型可以参考Caffe的model zoo

2.caffe 结构

Caffe中的四大基本组件。Blob,Layer,NetSolver。分别对应数据,层,网络求解器。这几个组件之间的关系如下:
caffe 类结构

  • Blob
  1. (blob.hpp)为数据载体。是其他几个组件间交互的基本单元。
  2. 输入数据,层间传递数据,层中参数均由Blob封装。
  3. 其中数据成员由SyncedMemory封装,负责CPU,GPU内存管理及同步。在存储格式上通常以NCHW方式。
  4. Blob主要成员如下:

    data_ -->数据
    diff_ -->梯度
    shape_data_ -->GPU维度信息
    shape_ --> 维度信息
    count -->元素个数
    capacity_ -->当前分配的内存容量

  • Layer
  1. (layer.hpp)为为网络中的层。负责层的初始化及前向/后向传递。
  2. Layer初始化会校验底层和顶层网络个数,初始化层中参数,计算并设置本层的输出大小。
  3. 会根据当前mode选择CPU/GPU实现来进行前向/后向传递。若没有GPU实现会默认使用CPU实现。每次执行前向传递前都会重新计算并设置本层的输出大小。
  4. 各layer官方详细介绍
  5. Layer主要成员如下:

    blobs_ -->层中参数
    layer_propagate_ -->是否需要计算梯度
    phase_ -->训练/测试阶段

  6. 自定义layer主要过程

    向caffe.proto添加自定义层的参数描述。
    实现LayerSetUp() -->层的初始化
    实现Reshape() -->计算并设置本层的输出大小
    实现Forward_cpu/gpu() -->前向传递的cpu/gpu实现
    实现Backward_cpu/gpu() -->后向传递的cpu/gpu实现
    实例化并注册该自定义层

  • Net
  1. (net.hpp)为网络。负责构建整个网络,前向/后向传递。
  2. 调用Forward()和Backward()实现整个网络的一次前向和后向传递。
  3. Update()负责更新layer中的学习参数。
  4. Net主要成员如下:

layers_ -->网络层列表
blobs_ -->网络层输出结果列表
params_ -->参数列表
learnable_params_ -->需要学习的参数列表

  • Solver
  1. (solver.hpp)为求解器。负责模型参数优化。
  2. 调用ComputeUpdateValue()根据后向传递计算的梯度计算参数更新量。
  3. Solver主要成员如下:

    net_ -->网络
    test_nets_ -->测试网络
    losses_ -->损失值
    iter_ -->迭代次数
    smoothed_loss_ -->平滑损失值

3. 运行流程时序图

caffe源代码的入口在./tools/caffe.cpp,caffe训练的主要流程如下:

  • 初始化
    在这里插入图片描述
    主要步骤:

    1. 使用RegisterBrewFunction宏在程序载入时通过类的实例化来将函数注册到g_brew_map这个查找表中。包括device_query(), train(), test()和time()。
    2. 初始化命令行解析及日志功能。
    3. GetBrewFunction() 通过命令行的输入参数在g_brew_map中查找并执行对应的函数。
    4. 执行训练过程。
      4.1 通过ReadSolverParamsFromTextFileOrDie()函数从solver配置文件中把数据读入并填入SolverParameter结构。
      4.2 配置GPU,设置计算模式。
      4.3 新建一个信号处理实例。
      4.4 通过工厂模式新建一个solver求解器。初始化solver求解器。
      4.5 配置signal处理。例如收到Ctrl+C命令先执行Snapshot保存参数后再退出程序。
      4.6 若果是继续训练,通过Restore()函数进行恢复再继续训练。网络初始化会通过LoadNetWeights()函数恢复权重参数值。
      4.7 调用Solve()开始训练。
  • Solver初始化
    在这里插入图片描述
    主要步骤:
    1.Solver初始化。
    2.设置随机数种子。
    3.初始化训练网络。
    4.读取网络配置参数。
    5.新建网络。

    网络初始化。
    1.处理过滤规则及多路输出的网络。
    2.根据网络配置参数为每一层网络实例化

    12.对于该层的所有bottom blob,调用AppendBottom()进行进行处理。添加一个下层到网络中。
    13.对于该层所有的top blob,调用AppendTop()函数进行处理。添加一个上层到网络中。
    15.调用当前层的SetUp()函数。包括校验底层/顶层数量,初始化网络层,计算并设置输出大小。
    22.对于该层中所有的param blob,调用AppendParam()函数来处理。记录名字和blob对应的index。
    24.载入权值。
    25.初始化测试网络。与初始化训练网络相似。

  • 训练过程
    在这里插入图片描述
    主要步骤:
    2.调用Step()函数进行训练,参数为需要迭代的次数。该函数为训练的主循环。循环的index从iter_到iter_+iters。循环次数由参数iters指定。
    3.调用Net的ClearParamDiffs()函数初始化参数的梯度信息。
    4.读取网络配置参数。
    5.ForwardBackward()函数完成一次前向和后向传递。
    15.UpdateSmoothedLoss()函数计算平滑后的loss值。
    16.ApplyUpdate()函数应用更新权值参数值。

    通过GetLearningRate()函数计算学习率
    通过ClipGradients()函数来clip梯度
    调用Normalize(),Regularize()和ComputeUpdateValue()三个函数,使用优化方法计算权值参数更新量。
    21.更新权值参数。
    23.保存权值文件(如果需要保存)。

  • 小结
    通过分析caffe的框架结构以及训练过程,可以增强对源码的理解。对于加深理解深度学的整个流程有很大的帮助。

猜你喜欢

转载自blog.csdn.net/u014292358/article/details/87884863