Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
tensorflow
GitHub Repository: tensorflow/docs-l10n
Path: blob/master/site/pt-br/model_optimization/guide/pruning/comprehensive_guide.ipynb
25118 views
Kernel: Python 3
#@title Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # https://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License.

Guia completo de pruning

Bem-vindo ao guia completo sobre pruning de peso do Keras.

Esta página documenta vários casos de uso e mostra como usar a API para cada um. Depois de saber quais APIs são necessárias, encontre os parâmetros e os detalhes de nível inferior na documentação da API.

  • Se quiser ver os benefícios do pruning e saber o que é compatível, confira a visão geral.

  • Para um único exemplo completo, veja o exemplo de pruning.

São abordados os seguintes casos de uso:

  • Defina e treine um modelo após o pruning.

    • Sequencial e funcional.

    • Model.fit do Keras e loops de treinamento personalizados.

  • Faça o checkpoint e desserialize um modelo podado.

  • Implante um modelo podado e veja os benefícios da compressão.

Para a configuração do algoritmo de pruning, consulte a documentação da API tfmot.sparsity.keras.prune_low_magnitude.

Configuração

Para encontrar as APIs de que você precisa e para fins de compreensão, você pode executar mas pular a leitura desta seção.

! pip install -q tensorflow-model-optimization import tensorflow as tf import numpy as np import tensorflow_model_optimization as tfmot %load_ext tensorboard import tempfile input_shape = [20] x_train = np.random.randn(1, 20).astype(np.float32) y_train = tf.keras.utils.to_categorical(np.random.randn(1), num_classes=20) def setup_model(): model = tf.keras.Sequential([ tf.keras.layers.Dense(20, input_shape=input_shape), tf.keras.layers.Flatten() ]) return model def setup_pretrained_weights(): model = setup_model() model.compile( loss=tf.keras.losses.categorical_crossentropy, optimizer='adam', metrics=['accuracy'] ) model.fit(x_train, y_train) _, pretrained_weights = tempfile.mkstemp('.tf') model.save_weights(pretrained_weights) return pretrained_weights def get_gzipped_model_size(model): # Returns size of gzipped model, in bytes. import os import zipfile _, keras_file = tempfile.mkstemp('.h5') model.save(keras_file, include_optimizer=False) _, zipped_file = tempfile.mkstemp('.zip') with zipfile.ZipFile(zipped_file, 'w', compression=zipfile.ZIP_DEFLATED) as f: f.write(keras_file) return os.path.getsize(zipped_file) setup_model() pretrained_weights = setup_pretrained_weights()

Defina o modelo

Faça o pruning do modelo inteiro (sequencial e funcional)

Dicas para melhor exatidão do modelo:

  • Tente "podar algumas camadas" para pular o pruning das camadas que mais reduzem a exatidão.

  • Geralmente, é melhor fazer ajustes com o pruning, em vez de treinar do zero.

Para fazer o modelo inteiro treinar com o pruning, aplique tfmot.sparsity.keras.prune_low_magnitude a ele.

base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended. model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model) model_for_pruning.summary()

Faça o pruning de algumas camadas (sequencial e funcional)

O pruning de um modelo pode ter um efeito negativo na exatidão. Você pode fazer o pruning de camadas selecionadas de um modelo para explorar o trade-off entre exatidão, velocidade e tamanho do modelo.

Dicas para melhor exatidão do modelo:

  • Geralmente, é melhor fazer ajustes com o pruning, em vez de treinar do zero.

  • Tente fazer o pruning das camadas finais, em vez das iniciais.

  • Evite o pruning de camadas críticas (por exemplo, mecanismo de atenção).

Mais:

  • A documentação da API tfmot.sparsity.keras.prune_low_magnitude fornece detalhes sobre como variar a configuração do pruning por camada.

No exemplo abaixo, faça o pruning apenas das camadas Dense.

# Create a base model base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy # Helper function uses `prune_low_magnitude` to make only the # Dense layers train with pruning. def apply_pruning_to_dense(layer): if isinstance(layer, tf.keras.layers.Dense): return tfmot.sparsity.keras.prune_low_magnitude(layer) return layer # Use `tf.keras.models.clone_model` to apply `apply_pruning_to_dense` # to the layers of the model. model_for_pruning = tf.keras.models.clone_model( base_model, clone_function=apply_pruning_to_dense, ) model_for_pruning.summary()

Enquanto esse exemplo usa o tipo de camada para decidir o que podar, a maneira mais fácil de fazer o pruning de uma camada específica é definir sua propriedade name e procurar esse nome na clone_function.

print(base_model.layers[0].name)

Exatidão do modelo mais legível, mas possivelmente mais baixa

Os ajustes com o pruning não são compatíveis. Por isso, pode apresentar menos exatidão do que os exemplos acima, que oferecem suporte aos ajustes.

Enquanto prune_low_magnitude pode ser aplicado ao definir o modelo inicial, o carregamento de pesos posterior não funciona nos exemplos abaixo.

Exemplo funcional

# Use `prune_low_magnitude` to make the `Dense` layer train with pruning. i = tf.keras.Input(shape=(20,)) x = tfmot.sparsity.keras.prune_low_magnitude(tf.keras.layers.Dense(10))(i) o = tf.keras.layers.Flatten()(x) model_for_pruning = tf.keras.Model(inputs=i, outputs=o) model_for_pruning.summary()

Exemplo sequencial

# Use `prune_low_magnitude` to make the `Dense` layer train with pruning. model_for_pruning = tf.keras.Sequential([ tfmot.sparsity.keras.prune_low_magnitude(tf.keras.layers.Dense(20, input_shape=input_shape)), tf.keras.layers.Flatten() ]) model_for_pruning.summary()

Faça o pruning da camada do Keras personalizada ou modifique partes da camada para podar

Erro comum: o pruning do bias geralmente prejudica muito a exatidão do modelo.

tfmot.sparsity.keras.PrunableLayer atende dois casos de uso:

  1. Fazer o pruning de uma camada do Keras personalizada

  2. Modificar partes de uma camada do Keras integrada para fazer o pruning.

Por exemplo, o padrão da API é só fazer o pruning do kernel da camada Dense. O exemplo abaixo também faz o pruning do bias.

class MyDenseLayer(tf.keras.layers.Dense, tfmot.sparsity.keras.PrunableLayer): def get_prunable_weights(self): # Prune bias also, though that usually harms model accuracy too much. return [self.kernel, self.bias] # Use `prune_low_magnitude` to make the `MyDenseLayer` layer train with pruning. model_for_pruning = tf.keras.Sequential([ tfmot.sparsity.keras.prune_low_magnitude(MyDenseLayer(20, input_shape=input_shape)), tf.keras.layers.Flatten() ]) model_for_pruning.summary()

Treine o modelo

Model.fit

Chame a callback tfmot.sparsity.keras.UpdatePruningStep durante o treinamento.

Para ajudar a depurar o treinamento, use a callback tfmot.sparsity.keras.PruningSummaries.

# Define the model. base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model) log_dir = tempfile.mkdtemp() callbacks = [ tfmot.sparsity.keras.UpdatePruningStep(), # Log sparsity and other metrics in Tensorboard. tfmot.sparsity.keras.PruningSummaries(log_dir=log_dir) ] model_for_pruning.compile( loss=tf.keras.losses.categorical_crossentropy, optimizer='adam', metrics=['accuracy'] ) model_for_pruning.fit( x_train, y_train, callbacks=callbacks, epochs=2, ) #docs_infra: no_execute %tensorboard --logdir={log_dir}

Para usuários fora do Colab, é possível ver os resultados de uma execução anterior desse bloco de código no TensorBoard.dev.

Loop de treinamento personalizado

Chame a callback tfmot.sparsity.keras.UpdatePruningStep durante o treinamento.

Para ajudar a depurar o treinamento, use a callback tfmot.sparsity.keras.PruningSummaries.

# Define the model. base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model) # Boilerplate loss = tf.keras.losses.categorical_crossentropy optimizer = tf.keras.optimizers.Adam() log_dir = tempfile.mkdtemp() unused_arg = -1 epochs = 2 batches = 1 # example is hardcoded so that the number of batches cannot change. # Non-boilerplate. model_for_pruning.optimizer = optimizer step_callback = tfmot.sparsity.keras.UpdatePruningStep() step_callback.set_model(model_for_pruning) log_callback = tfmot.sparsity.keras.PruningSummaries(log_dir=log_dir) # Log sparsity and other metrics in Tensorboard. log_callback.set_model(model_for_pruning) step_callback.on_train_begin() # run pruning callback for _ in range(epochs): log_callback.on_epoch_begin(epoch=unused_arg) # run pruning callback for _ in range(batches): step_callback.on_train_batch_begin(batch=unused_arg) # run pruning callback with tf.GradientTape() as tape: logits = model_for_pruning(x_train, training=True) loss_value = loss(y_train, logits) grads = tape.gradient(loss_value, model_for_pruning.trainable_variables) optimizer.apply_gradients(zip(grads, model_for_pruning.trainable_variables)) step_callback.on_epoch_end(batch=unused_arg) # run pruning callback #docs_infra: no_execute %tensorboard --logdir={log_dir}

Para usuários fora do Colab, é possível ver os resultados de uma execução anterior desse bloco de código no TensorBoard.dev.

Melhore a exatidão do modelo após o pruning

Primeiro, confira a documentação da API tfmot.sparsity.keras.prune_low_magnitude para entender o que é um cronograma de pruning e a matemática de cada tipo de cronograma de pruning.

Dicas:

  • Não tenha uma taxa de aprendizado muito alta ou muito baixa durante o pruning do modelo. Considere o cronograma de pruning como um hiperparâmetro.

  • Como teste rápido, experimente com o pruning de um modelo para a esparsidade final no início do treinamento ao definir begin_step como 0 com um cronograma tfmot.sparsity.keras.ConstantSparsity. Talvez você tenha a sorte de conseguir bons resultados.

  • Não faça o pruning com muita frequência, dando tempo para o modelo se recuperar. O cronograma de pruning oferece uma frequência padrão apropriada.

  • Para ideias gerais sobre como melhorar a exatidão do modelo, procure dicas para seu caso de uso em "Defina um modelo".

Faça o checkpoint e desserialize

Você precisa preservar a etapa do otimizador durante o checkpoint. Isso significa que, embora você possa usar os modelos HDF5 do Keras para o checkpoint, não é possível usar os pesos HDF5 do Keras.

# Define the model. base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model) _, keras_model_file = tempfile.mkstemp('.h5') # Checkpoint: saving the optimizer is necessary (include_optimizer=True is the default). model_for_pruning.save(keras_model_file, include_optimizer=True)

A regra acima se aplica de forma geral. O código abaixo só é necessário para o formato de modelo HDF5 (e não pesos HDF5 e outros formatos).

# Deserialize model. with tfmot.sparsity.keras.prune_scope(): loaded_model = tf.keras.models.load_model(keras_model_file) loaded_model.summary()

Implante o modelo após o pruning

Exporte o modelo com a compressão do tamanho

Erro comum: o strip_pruning e a aplicação de um algoritmo de compressão padrão (por exemplo, por gzip) são necessários para ver os benefícios de compressão do pruning.

# Define the model. base_model = setup_model() base_model.load_weights(pretrained_weights) # optional but recommended for model accuracy model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model) # Typically you train the model here. model_for_export = tfmot.sparsity.keras.strip_pruning(model_for_pruning) print("final model") model_for_export.summary() print("\n") print("Size of gzipped pruned model without stripping: %.2f bytes" % (get_gzipped_model_size(model_for_pruning))) print("Size of gzipped pruned model with stripping: %.2f bytes" % (get_gzipped_model_size(model_for_export)))

Otimizações de hardware específico

Depois que back-ends diferentes ativarem o pruning para melhorar a latência, o uso da esparsidade de bloco pode melhorar a latência para hardware específico.

O aumento do tamanho do bloco diminuirá o pico de esparsidade possível para uma exatidão de modelo alvo. Apesar disso, a latência ainda pode melhorar.

Para mais detalhes sobre o que é compatível com a esparsidade de bloco, veja a documentação da API tfmot.sparsity.keras.prune_low_magnitude.

base_model = setup_model() # For using intrinsics on a CPU with 128-bit registers, together with 8-bit # quantized weights, a 1x16 block size is nice because the block perfectly # fits into the register. pruning_params = {'block_size': [1, 16]} model_for_pruning = tfmot.sparsity.keras.prune_low_magnitude(base_model, **pruning_params) model_for_pruning.summary()