【问题标题】:How to reduce the number of kernels/filters in a trained model in Tensorflow?如何减少 Tensorflow 中训练模型中的内核/过滤器数量?
【发布时间】:2020-02-07 07:34:46
【问题描述】:

如果我有一个经过训练的模型,我想重新训练相同的模型,并从现有模型中删除一些过滤器/内核。例如

conv1 = tf.get_variable('conv1_1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer()),

我想调整这个张量的大小,使其具有 (11, 11, 3, 20) 的形状,但名称和位置相同,意味着完全相同的变量。提前感谢您的帮助。

我已经尝试过tf.reshape,但它给了我不匹配 a 和 b 中的元素数量的错误 我也试过tf.assign(a,b, validate_shape=false)

self.weights = {
    'conv1_': tf.get_variable('conv1_l1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer()),
    'conv2_': tf.get_variable('conv2_l1', shape=(7, 7, 64, 128), initializer=tf.contrib.layers.xavier_initializer())
}

【问题讨论】:

  • 您是否尝试将预训练模型的权重转移到新模型。需要注意的是新模型的过滤器数量较少?
  • 不是新型号。我想继续用一组新的内核/过滤器训练相同的模型
  • 一旦你改变了过滤器的数量,它就不再是同一个模型了。架构发生了变化。你同意吗?
  • 我认为架构是通过变量数量及其相互联系来定义的。变量的数量和它们的相互联系保持不变,这里的情况是重塑一个变量。即 'conv1_': tf.get_variable('conv1_l1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer()) 是具有给定大小的单个变量,所以在保持这个的同时变量到位,以调整其形状。可能是我的观念不正确。对不起
  • 不。变量的数量不一样,因为过滤器来自维度:(11, 11, 3, 64) -> (11, 11, 3, 20)。假设前 2 个维度是您的图像大小。这意味着您的过滤器组从 64 个过滤器减少到 20 个过滤器。因此,网络的设计发生了变化。我会告诉你架构(连接)保持不变。

标签: tensorflow machine-learning image-processing computer-vision


【解决方案1】:

我知道Tensorflow只执行静态图,所以过滤器的数量不能改变(形状可以改变),这方面PyTorch很有帮助,它可以执行动态图。 我通过创建一个新图表并将所需过滤器的值复制到新图表中并丢弃选定的过滤器来解决此问题。

【讨论】:

    【解决方案2】:

    从根本上说,您正在更改模型的参数数量。当你离开时

    conv1 = tf.get_variable('conv1_1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer())
    

    conv2 = tf.get_variable('conv2_l1', shape=(11, 11, 3, 20), initializer=tf.contrib.layers.xavier_initializer())
    

    您的可学习参数从 {Kernel x 64} 变为 {Kernel x 20} 这将要求您重新训练网络并学习其新权重。

    但是,这是一个已演变为研究领域的常见问题。为此已经提出了许多方法,例如权重的低秩近似(Denton 等人,2014;Lebedev 等人,2014)、权重量化(Courbariaux 等人,2016;Rastegari 等人,2016)、知识蒸馏(Hinton et al., 2014; Romeroet al., 2015)和网络剪枝(Han et al., 2015; Li et al., 2017),其中网络剪枝因其具有竞争力的性能和兼容性而备受关注。

    参考探索:

    1. Emily L Denton、Wojciech Zaremba、Joan Bruna、Yann LeCun 和 Rob Fergus。利用卷积网络中的线性结构进行有效评估。 InNIPS,2014 年。
    2. Vadim Lebedev、Yaroslav Ganin、Maksim Rakhuba、Ivan Oseledets 和 Victor Lempitsky。使用微调的 cp-decomposition 加速卷积神经网络。ICLR,2014 年。
    3. Matthieu Courbariaux、Itay Hubara、Daniel Soudry、Ran El-Yaniv 和 Yoshua Bengio。二值化神经网络:训练深度神经网络,权重和激活限制为+ 1or-1.arXiv preprint arXiv:1602.02830, 2016
    4. Geoffrey Hinton、Oriol Vinyals 和 Jeff Dean。在神经网络中提取知识。NIPSWorkshop,2014 年。

    【讨论】:

    • 谢谢@Nav。我也在研究网络修剪。我已经建立了理论解决方案,但现在面临特定于 tensorflow 的问题。 这将需要你重新训练网络并学习它的新权重当然我必须训练,但我需要用相同的图表训练完全相同的模型但调整大小的变量。从技术上讲,它变成了一种新的架构,但从逻辑上讲,它保持不变。因为所有变量和图表都已到位,所以没有任何改变。变量内部结构刚刚改变。
    • 我明白了。如果清楚,您应该关闭 Q. SO 礼仪。
    • 不不,我不是那个意思。兄弟,我有一个技术问题,如何在 tensorflow 中调整经过训练的 CNN 模型的变量大小?如果我错误地造成了任何混乱,我深表歉意。
    【解决方案3】:

    你想做的事情是部分可以实现的。

    拥有一个与已经定义的变量同名的变量可能是不可能的。因为 TensorFlow 创建了一个数据流图,并且每个节点都需要是唯一可识别的(以避免歧义)。如果您想要相同的名称,您可以使用具有不同作用域的 variable scoping 来实现。

    但是要将变量的一部分分配给另一个变量,您可以使用以下代码。

    import tensorflow as tf
    import numpy as np
    
    tf.reset_default_graph()
    
    with tf.variable_scope('old'):
      conv1 = tf.get_variable('conv1_1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer())
    with tf.variable_scope('new'):
      conv_res_1 = tf.get_variable('conv1_1', shape=(11, 11, 3, 20), initializer=tf.contrib.layers.xavier_initializer())
    
    assign_op = tf.assign(conv_res_1,conv1[:,:,:,:20])
    
    with tf.Session() as sess:
      tf.global_variables_initializer().run()
      w_1, w_res_1 = sess.run([conv1, assign_op])
      assert np.all(w_1[:,:,:,:20] == w_res_1)
      print(w_1[0,0,0,0], w_res_1[0,0,0,0])  
    

    更新:如果您可以接受丢失较大的变量,您可以执行以下操作。这将采用 conv_1 并将变量替换为较小的变量。

    import tensorflow as tf
    
    tf.reset_default_graph()
    conv1 = tf.get_variable('conv1_1', shape=(11, 11, 3, 64), initializer=tf.contrib.layers.xavier_initializer())
    
    assign_op = tf.assign(conv1, conv1[:,:,:,:20], validate_shape=False)
    
    with tf.Session() as sess:
      tf.global_variables_initializer().run()
      sess.run(assign_op)
    

    【讨论】:

    • 谢谢@thushv89。实际上,我不想定义另一个变量,而是想减小现有变量的大小。
    • 此外,我需要在会话中执行此操作,并且我在 tf.reset_default_graph() 文档中看到它在会话中不起作用。
    • 唯一的选择是将权重部分复制到另一个变量。在 TensorFlow 中,一旦定义了变量,就无法修改形状。
    • 我不确定您所说的重置图在会话中不起作用是什么意思。关于会话和图表,当您定义变量时,除非指定了不同的图表,否则它们会转到默认图表(您可以尝试多个图表,但这会使问题复杂化)。然后会话将根据您在session.run 中想要的内容执行该图的部分内容。
    • 我想知道,他们是怎么决定的 :) 因为同时 tf.reshape 工作正常。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 2020-06-07
    • 1970-01-01
    • 1970-01-01
    • 2020-05-27
    相关资源
    最近更新 更多