稀疏性中的初始_稀疏性参数。多项式decay()TensorFlow 2.0基于幅值的权重修剪

2024-06-02 06:58:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我在试教程TensorFlow 2.0 Magnitude-based weight pruning with Keras 遇到了参数初始稀疏度

import tensorflow_model_optimization as tfmot
from tensorflow_model_optimization.sparsity import keras as sparsity
import numpy as np

epochs = 12
num_train_samples = x_train.shape[0]
end_step = np.ceil(1.0 * num_train_samples / batch_size).astype(np.int32) * epochs
print('End step: ' + str(end_step))

pruning_params = {
      'pruning_schedule': sparsity.PolynomialDecay(initial_sparsity=0.50,
                                                   final_sparsity=0.90,
                                                   begin_step=2000,
                                                   end_step=end_step,
                                                   frequency=100)
}

教程说:

The parameter used here means:

Sparsity PolynomialDecay is used across the whole training process. We start at the sparsity level 50% and gradually train the model to reach 90% sparsity. X% sparsity means that X% of the weight tensor is going to be pruned away.

我的问题是,你不应该从0%的初始稀疏度开始,然后删掉90%的权重吗

以50%的初始稀疏度开始意味着什么?这是否意味着从开始修剪50%的权重,然后达到90%的稀疏修剪

此外,对于tfmot.sparsity.keras.ConstantSparsity,API如下所示:

pruning_params_unpruned = {
    'pruning_schedule': sparsity.ConstantSparsity(
        target_sparsity=0.0, begin_step=0,
        end_step = 0, frequency=100
    )
}

Initializes a Pruning schedule with constant sparsity.

Sparsity is applied in the interval [begin_step, end_step] every frequency steps. At each applicable step, the sparsity(%) is constant.

这是否意味着,如果一个神经网络模型已经处于50%的稀疏水平,但目标_稀疏度=0.5,那么修剪计划将执行以下操作:

  1. 无修剪,因为模型已处于50%的修剪级别
  2. 它进一步删减已删减(50%删减)模型的50%权重

你可以在PolynomialDecayConstantSparsity中读到它

谢谢


Tags: theimportmodelisasstepnptrain
1条回答
网友
1楼 · 发布于 2024-06-02 06:58:24

因此,我还发现关于权重修剪的Tensorflow文档非常稀疏,因此我花了一些时间与调试器一起研究如何工作。

修剪时间表是如何工作的

在最基本的层次上,修剪计划只是一个函数,它将该步骤作为输入并生成稀疏百分比。然后使用该稀疏值生成掩码,该掩码用于修剪绝对值小于绝对值权重分布和稀疏百分比给出的k-1值的权重

多项式

类定义:Github Link
上面的类定义中包含的注释帮助我理解了PolynomialDecay调度程序是如何工作的

Pruning rate grows rapidly in the beginning from initial_sparsity, but then plateaus slowly to the target sparsity.

The function applied is

current_sparsity = final_sparsity + (initial_sparsity - final_sparsity) * (1 - (step - begin_step)/(end_step - begin_step)) ^ exponent

根据上述等式,当step == begin_step时,则current_sparsity = initial_sparsity。因此,在begin_step参数指定的步长上,权重将被修剪为initial_sparsity

我同意你的评估,因为你通常希望在低于50%的稀疏度下开始修剪,但我没有任何发表的研究可以引用来支持这一说法。您可以在多项式decay类定义中引用的paper中找到更多信息,尽管我自己还没有机会阅读它

恒常性

类定义:Github Link
这个调度程序的用途似乎非常有限。对于每个有效的修剪步骤,都会返回target_sparsity。因此,多个修剪步骤是非常冗余的。此调度器的用例似乎是在培训期间进行一次性修剪。使用此调度器进行多次修剪的能力是将其与其父抽象类和其他修剪调度器对齐

创建自己的修剪计划程序

如果上面的两个调度器不能使您的船浮起来,那么抽象类PruningSchedule将公开一个端点,这使得创建您自己的修剪调度器非常容易,尽管它可能很复杂。下面是我自己创建的一个示例。

免责声明:此调度器是一名19岁大学生想象力的产物,在任何已发表的文献中都没有依据

PruningSchedule = tfmot.sparsity.keras.PruningSchedule

class ExponentialPruning(PruningSchedule):
def __init__(self, rate=0.01, begin_step=0, frequency=100, max_sparsity=0.9):
    self.rate = rate
    self.begin_step = begin_step
    self.frequency = frequency
    self.max_sparsity = max_sparsity

    # Validation functions provided by the parent class
    # The -1 parameter is for the end_step
    # as this pruning schedule does not have one
    # The last true value is a boolean flag which says it is okay
    # to have no end_step
    self._validate_step(self.begin_step, -1, self.frequency, True)
    self._validate_sparsity(self.max_sparsity, 'Max Sparsity')

def __call__(self, step):
    # Sparsity calculation endpoint

    # step is a integer tensor

    # The sparsity returned by __call__ must be a tensor
    # of dtype=tf.float32, so tf.math is required.

    # In the logic below, you can assume that a valid
    # pruning step is passed.

    p = tf.math.divide(
        tf.cast(step - self.begin_step, tf.float32),
        tf.constant(self.frequency, dtype=tf.float32)
    )
    sparsity = tf.math.subtract(
        tf.constant(1, dtype=tf.float32),
        tf.math.pow(
            tf.constant(1 - self.rate, dtype=tf.float32),
            p
        )
    )

    sparsity = tf.cond(
        tf.math.greater(sparsity, tf.constant(self.max_sparsity, dtype=tf.float32)),
        lambda: tf.constant(self.max_sparsity, dtype=tf.float32),
        lambda: sparsity
    )

    # This function returns a tuple of length 2
    # The first value determines if pruning should occur on this step
    # I recommend using the parent class function below for this purpose
    # The negative one value denotes no end_step
    # The second value is the sparsity to prune to
    return (self._should_prune_in_step(step, self.begin_step, -1, self.frequency),
            sparsity)

def get_config(self):
    # A function required by the parent class
    # return the class_name and the input parameters as
    # done below
    return {
        'class_name': self.__class__.__name__,
        'config': {
            'rate': self.rate,
            'begin_step': self.begin_step,
            'frequency': self.frequency,
            'max_sparsity': self.max_sparsity
        }
    }

使用修剪调度器

如果您只希望修剪某些层,而不是所有可修剪的层,则可以对要添加到模型中的层调用prune_low_magnitude函数

prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude
model = keras.models.Sequential()
...
model.add(prune_low_magnitude(keras.layers.Dense(8, activation='relu', kernel_regularizer=keras.regularizers.l1(0.0001)),
  ExponentialPruning(rate=1/8)))

还要确保将UpdatePruningStep实例传递给培训回调:

m.fit(train_input, train_labels, epochs=epochs, validation_data=[test_input, test_labels],
  callbacks=[UpdatePruningStep()])

相关问题 更多 >