tensorflow如何将batchnorm合并到卷积中以进行更快的推断

K.W*_*ter 2 tensorflow

有没有一种方法(代码脚本)将Tensorflow Batchnorm和Dropout层合并到卷积层中以进行推理以加快计算速度?

我搜索了一段时间,但没有得到相关的答案。

BiB*_*iBi 5

据我所知,TensorFlow中没有内置功能可用于折叠批处理规范化。话虽这么说,手动操作并不难。值得注意的是,不存在折叠退出的问题,因为在推断时仅将退出激活即可。

要折叠批标准化,基本上有三个步骤:

  1. 给定一个TensorFlow图,过滤需要折叠的变量,
  2. 折叠变量,
  3. 使用折叠的变量创建一个新图。

我们需要过滤需要折叠的变量。使用批处理规范化时,它将创建名称包含moving_mean和的变量moving_variance。您可以使用它很容易地从使用批处理规范的图层中提取变量。

现在,你知道哪些图层使用批量规范,对每一个这样的层,可以提取其权重W,偏差b,一批标准方差v,平均值mgammabeta参数。您需要创建一个新变量来存储折叠后的权重和偏差,如下所示:

W_new = gamma * W / var
b_new = gamma * (b - mean) / var + beta
Run Code Online (Sandbox Code Playgroud)

最后一步是创建一个新图,在该图中我们停用批处理规范并bias在必要时添加变量-每个可折叠层都应如此,因为对批处理规范使用偏差是毫无意义的。

整个代码应如下所示。根据用于批处理规范的参数,您的图形可能没有gammabeta

# ****** (1) Get variables ******
variables = {v.name: session.run(v) for v in tf.global_variables()}

# ****** (2) Fold variables ******
folded_variables = {}
for v in variables.keys():
    if not v.endswith('moving_variance:0'):
        continue

    n = get_layer_name(v) # 'model/conv1/moving_variance:0' --> 'model/conv1'

    W = variable[n + '/weights:0'] # or "/kernel:0", etc.
    b = variable[n + '/bias:0'] # if a bias existed before
    gamma = variable[n + '/gamma:0']
    beta = variable[n + '/beta:0']
    m = variable[n + '/moving_mean:0']
    var = variable[n + '/moving_variance:0']

    # folding batch norm
    W_new = gamma * W / var
    b_new = gamma * (b - mean) / var + beta # remove `b` if no bias
    folded_variables[n + '/weights:0'] = W_new        
    folded_variables[n + '/bias:0'] = b_new   

    # ****** (3) Create new graph ******
    new_graph = tf.Graph()
    new_session = tf.Session(graph=new_graph) 
    network = ... # instance batch-norm free graph with bias added.
                  # Careful, the names should match the original model

    for v in tf.global_variables():
        try:
            new_session.run(v.assign(folded_variables[v.name]))
        except:
            new_session.run(v.assign(variables[v.name]))
Run Code Online (Sandbox Code Playgroud)

  • 嘿,我正在这里做同样的事情,并偶然发现了这一点。我试图在折叠之前和之后获得相同的结果,并意识到结果与您的公式不匹配。看看batchnorm是如何计算的(https://medium.com/deeplearningmadeeasy/everything-you-wish-to-know-about-batchnorm-6055e07fdce2)我意识到你错过了sqrt和epsilon。``w_new = gamma * w / np.sqrt(var + epsilon); b_new = gamma * (b - 均值) / np.sqrt(var + epsilon) + beta)`` (2认同)