Brew 简介
brew
是 Caffe2 里面的一个新的 API, 该 API 和过去的 CNNModelHelper
的作用是相似的, 但是由于 Caffe2 现在不仅仅支持 CNN, 因此将 CNNModelHelper
替换为 ModelHelper
显得更加合理. brew
封装了 ModelHelper
, 是的搭建模型更加简单.
Model Building and Brew’s Helper Functions
在本小节中, 我们将会介绍一个由 helper functions 组成的轻量级的集合, 这些函数可以帮助我们更轻易的搭建模型. 下面我们会先介绍关于 Ops 和 Helper Functions 的相关概念. 接下来我们将会展示如何使用 brew
以及引入 brew
的动机.
Concepts: Ops vs Helper Functions
在介绍 brew
之前, 我们首先应该回顾一下 Caffe2 中的一些常规概念, 以及在一个神经网络中, 一个网络层是如何表示的. 在 Caffe2 中, 深度学习框架是建立在 operators 之上的. 通常这些 operators 使用 C++ 实现, 同时 Caffe2 会提供封装了 C++ 代码的 Python API. 在 Caffe2 中, operators 的命名方式采用驼峰风格, 而对应的 helper functions 则采用相似的小写名称.
Ops
通常我们将 operators 缩写为 Op, 将一系列 operators 的集合缩写为 Ops. 例如, 一个 FC Op 代表了一个 Fully-Connected operator. 下面的代码创建了一个 FC 网络层.
1 | model.net.FC([blob_in, weights, bias], blob_out) |
下面的代码创建了一个 Copy Op:
1 | model.net.Copy(blob_in, blob_out) |
也可以省略.net
, 含义等价, 如下所示:1
model.Copy(blob_in, blob_out)
ModelHelper 包含了29个最常用的 Ops. 其持有的 Ops 是 Caffe2 中400+ Ops 的一个子集
Helper Functions
如果使用单一的 operators 来创建网络或模型, 则在参数初始化的时候会非常麻烦, 并且还需要自己选择 device/engine (这也是为什么 Caffe2 很快!). 利用, 创建一个 FC 层的时候, 我们需要自己写代码来准备 weights
和 bias
, 然后将其送入到 Op 中, 如下所示:
1 | # This is the longer, manual way: |
可以看出, 上面的代码十分麻烦, 因此, 我们可以利用 Caffe2 helper functions 来帮助我们. helper function 会自动处理参数的初始化, operator 的定义, 以及 engine 的选择. Caffe2 中默认的 helper functions 采用的是 Python PEP8 的命名规范. 例如, 它会使用 fc
来实现 FC Op. 下面的代码和上面的代码相同, 可以明显看出更加简洁:
1 | fcLayer = fc(model, blob_in, blob_out, **kwargs) |
brew
既然我们已经了解的 Ops 和 Helper Functions, 下面就来介绍一下如何利用 brew
更简单的搭建模型. brew
更像是一个智能的集合, 你可以利用它调用所有的 Caffe2 helper functions, 如下所示, 调用了一个 fc 辅助函数.
1 | from caffe2.python import brew |
当模型变的复杂度, brew
就会显得十分有用, 下面的代码定义了一个经典的 LeNet.
1 | def AddLeNetModel(model, data): |
上面的代码使用 brew
来定义网络, 代码变的十分整洁.
arg_scope
arg_scope
更像是一种语法糖, 它可以让你在当前上下文环境中设置默认的 helper function 的参数. 举个例子, 如果你想要在 ResNet-150 的训练脚本中尝试使用不同的权重初始化, 你首先会想到这么做:
1 | # 改变所有的 weight_init 参数 |
而如果使用 arg_scope
, 我们只需要更改一处地方即可:1
2
3
4with brew.arg_scope([brew.conv], weight_init=("XavierFill", {})):
brew.conv(model, ...) # 这里不用指定 weight_init 参数
brew.conv(model, ...)
...
自定义 Helper Function
如果你经常使用 brew
, 而某个你希望的 Op 没有默认的实现, 那么你可以自定义使用一个 helper function.
创建自定义的 new_helper_function
, 首先利用 brew.Register
进行注册, 然后就可以使用 brew.new_helper_function
进行调用, 如下所示:
1 | def my_super_layer(model, blob_in, blob_out, **kwargs): |
Caffe2 Default Helper Functions
下面是 Caffe2 中默认的29个最常用的 Ops, 点击这里可以查看详细信息.
引入 brew 的动机.
长话短说: Caffe2 的开发者希望将模型的创建过程和模型的存储分离开. 在开发者的想法中, ModelHelper
类应该只包含网络的定义和网络参数信息. 而 brew
会包含用于创建网络的初始化参数的函数.
旧版的 CNNModelHelper
同时包含模型存储和模型搭建, 与之相比, ModelHelper
+ brew
的模型创建方式更加模块化且易于扩展. 并且避免了命名方面造成的疑惑(因为 Caffe2
不仅仅有CNN, 还有 RNN 和 MLP 等).
关于 brew 的一个详细示例
https://github.com/pytorch/pytorch/blob/master/caffe2/python/brew_test.py