Gündem açıklandı! 19 Ekim tarihinde ML Sempozyumu Kadınlar bir noktaya kaydet şimdi Register

Budama koruyarak nicemleme farkında eğitim (PQAT) Keras örneği

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın GitHub'da görüntüle Not defterini indir

genel bakış

Bu budama koruyarak nicemleme farkında eğitimi (PQAT) API, TensorFlow Modeli Optimizasyon Toolkit'in işbirlikçi optimizasyon boru hattının bir kısmının kullanımını gösteren uç örnek bir sonudur.

Diğer sayfalar

Boru hattı ve mevcut diğer tekniklere bir giriş için bkz işbirlikçi optimizasyon genel bakış sayfası .

İçindekiler

Eğitimde şunları yapacaksınız:

  1. Bir Tren tf.keras sıfırdan MNIST veri kümesi için bir model.
  2. Seyreklik API'sini kullanarak budama ile modelde ince ayar yapın ve doğruluğu görün.
  3. QAT uygulayın ve seyreklik kaybını gözlemleyin.
  4. PQAT uygulayın ve daha önce uygulanan seyrekliğin korunduğunu gözlemleyin.
  5. Bir TFLite modeli oluşturun ve üzerinde PQAT uygulamasının etkilerini gözlemleyin.
  6. Elde edilen PQAT model doğruluğunu, eğitim sonrası niceleme kullanılarak nicelenen bir modelle karşılaştırın.

Kurmak

Eğer yerel Bu Jupyter Notebook çalıştırabilir virtualenv veya CoLab . Bağımlılıklarını kurma ayrıntılar için bakınız kurulum kılavuzu .

 pip install -q tensorflow-model-optimization
import tensorflow as tf

import numpy as np
import tempfile
import zipfile
import os

MNIST için bir tf.keras modelini budamadan eğitin

# Load MNIST dataset
mnist = tf.keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# Normalize the input image so that each pixel value is between 0 to 1.
train_images = train_images / 255.0
test_images  = test_images / 255.0

model = tf.keras.Sequential([
  tf.keras.layers.InputLayer(input_shape=(28, 28)),
  tf.keras.layers.Reshape(target_shape=(28, 28, 1)),
  tf.keras.layers.Conv2D(filters=12, kernel_size=(3, 3),
                         activation=tf.nn.relu),
  tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),
  tf.keras.layers.Flatten(),
  tf.keras.layers.Dense(10)
])

# Train the digit classification model
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

model.fit(
    train_images,
    train_labels,
    validation_split=0.1,
    epochs=10
)
Epoch 1/10
1688/1688 [==============================] - 8s 4ms/step - loss: 0.2940 - accuracy: 0.9172 - val_loss: 0.1183 - val_accuracy: 0.9693
Epoch 2/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.1150 - accuracy: 0.9674 - val_loss: 0.0863 - val_accuracy: 0.9770
Epoch 3/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0821 - accuracy: 0.9760 - val_loss: 0.0738 - val_accuracy: 0.9797
Epoch 4/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0673 - accuracy: 0.9806 - val_loss: 0.0661 - val_accuracy: 0.9837
Epoch 5/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0583 - accuracy: 0.9826 - val_loss: 0.0632 - val_accuracy: 0.9835
Epoch 6/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0520 - accuracy: 0.9845 - val_loss: 0.0635 - val_accuracy: 0.9820
Epoch 7/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0460 - accuracy: 0.9857 - val_loss: 0.0746 - val_accuracy: 0.9815
Epoch 8/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0423 - accuracy: 0.9875 - val_loss: 0.0601 - val_accuracy: 0.9848
Epoch 9/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0384 - accuracy: 0.9885 - val_loss: 0.0604 - val_accuracy: 0.9855
Epoch 10/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0347 - accuracy: 0.9894 - val_loss: 0.0648 - val_accuracy: 0.9835
<tensorflow.python.keras.callbacks.History at 0x7fb08657b5d0>

Temel modeli değerlendirin ve daha sonra kullanmak üzere saklayın

_, baseline_model_accuracy = model.evaluate(
    test_images, test_labels, verbose=0)

print('Baseline test accuracy:', baseline_model_accuracy)

_, keras_file = tempfile.mkstemp('.h5')
print('Saving model to: ', keras_file)
tf.keras.models.save_model(model, keras_file, include_optimizer=False)
Baseline test accuracy: 0.9810000061988831
Saving model to:  /tmp/tmp0akp2126.h5

Modeli budayın ve %50 seyrekliğe ayarlayın

Uygulama prune_low_magnitude() göstermek ve doğruluğunu korurken, zip uygulanırken modeli azaltılmasında etkinliğini gözlemlemek için bütün ön eğitimli bir model budamak için API. En iyi hedef doğruluğunu koruyarak en iyi sıkıştırma oranı elde etmek için API nasıl kullanılacağı için, bakınız budama kapsamlı bir rehber .

Modeli tanımlayın ve seyreklik API'sini uygulayın

Seyreklik API'sini kullanmadan önce modelin önceden eğitilmesi gerekir.

import tensorflow_model_optimization as tfmot

prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude

pruning_params = {
      'pruning_schedule': tfmot.sparsity.keras.ConstantSparsity(0.5, begin_step=0, frequency=100)
  }

callbacks = [
  tfmot.sparsity.keras.UpdatePruningStep()
]

pruned_model = prune_low_magnitude(model, **pruning_params)

# Use smaller learning rate for fine-tuning
opt = tf.keras.optimizers.Adam(learning_rate=1e-5)

pruned_model.compile(
  loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
  optimizer=opt,
  metrics=['accuracy'])

pruned_model.summary()
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py:2191: UserWarning: `layer.add_variable` is deprecated and will be removed in a future version. Please use `layer.add_weight` method instead.
  warnings.warn('`layer.add_variable` is deprecated and '
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
prune_low_magnitude_reshape  (None, 28, 28, 1)         1         
_________________________________________________________________
prune_low_magnitude_conv2d ( (None, 26, 26, 12)        230       
_________________________________________________________________
prune_low_magnitude_max_pool (None, 13, 13, 12)        1         
_________________________________________________________________
prune_low_magnitude_flatten  (None, 2028)              1         
_________________________________________________________________
prune_low_magnitude_dense (P (None, 10)                40572     
=================================================================
Total params: 40,805
Trainable params: 20,410
Non-trainable params: 20,395
_________________________________________________________________

Modelde ince ayar yapın ve temel çizgiye göre doğruluğu değerlendirin

3 dönem için budama ile modele ince ayar yapın.

# Fine-tune model
pruned_model.fit(
  train_images,
  train_labels,
  epochs=3,
  validation_split=0.1,
  callbacks=callbacks)
Epoch 1/3
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/array_ops.py:5049: calling gather (from tensorflow.python.ops.array_ops) with validate_indices is deprecated and will be removed in a future version.
Instructions for updating:
The `validate_indices` argument has no effect. Indices are always validated on CPU and never validated on GPU.
1688/1688 [==============================] - 9s 5ms/step - loss: 0.1243 - accuracy: 0.9580 - val_loss: 0.1146 - val_accuracy: 0.9650
Epoch 2/3
1688/1688 [==============================] - 8s 4ms/step - loss: 0.0883 - accuracy: 0.9713 - val_loss: 0.0945 - val_accuracy: 0.9720
Epoch 3/3
1688/1688 [==============================] - 8s 4ms/step - loss: 0.0722 - accuracy: 0.9774 - val_loss: 0.0858 - val_accuracy: 0.9753
<tensorflow.python.keras.callbacks.History at 0x7fafb6c80310>

Modelin seyrekliğini hesaplamak ve yazdırmak için yardımcı işlevleri tanımlayın.

def print_model_weights_sparsity(model):

    for layer in model.layers:
        if isinstance(layer, tf.keras.layers.Wrapper):
            weights = layer.trainable_weights
        else:
            weights = layer.weights
        for weight in weights:
            # ignore auxiliary quantization weights
            if "quantize_layer" in weight.name:
                continue
            weight_size = weight.numpy().size
            zero_num = np.count_nonzero(weight == 0)
            print(
                f"{weight.name}: {zero_num/weight_size:.2%} sparsity ",
                f"({zero_num}/{weight_size})",
            )

Modelin doğru şekilde budandığını kontrol edin. Önce budama sargısını soymamız gerekiyor.

stripped_pruned_model = tfmot.sparsity.keras.strip_pruning(pruned_model)

print_model_weights_sparsity(stripped_pruned_model)
conv2d/kernel:0: 50.00% sparsity  (54/108)
conv2d/bias:0: 0.00% sparsity  (0/12)
dense/kernel:0: 50.00% sparsity  (10140/20280)
dense/bias:0: 0.00% sparsity  (0/10)

Bu örnek için, budamadan sonra test doğruluğunda taban çizgisine kıyasla minimum kayıp vardır.

_, pruned_model_accuracy = pruned_model.evaluate(
  test_images, test_labels, verbose=0)

print('Baseline test accuracy:', baseline_model_accuracy)
print('Pruned test accuracy:', pruned_model_accuracy)
Baseline test accuracy: 0.9810000061988831
Pruned test accuracy: 0.973800003528595

QAT ve PQAT uygulayın ve her iki durumda da model seyrekliği üzerindeki etkisini kontrol edin

Daha sonra, budanmış modele hem QAT hem de budamayı koruyan QAT (PQAT) uygularız ve PQAT'ın budanmış modelinizde seyrekliği koruduğunu gözlemleriz. Biz sizin budanmış modelden budama sarmalayıcılarını elimden geldiğini hatırlatırız tfmot.sparsity.keras.strip_pruning PQAT API uygulamadan önce.

# QAT
qat_model = tfmot.quantization.keras.quantize_model(stripped_pruned_model)

qat_model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
print('Train qat model:')
qat_model.fit(train_images, train_labels, batch_size=128, epochs=1, validation_split=0.1)

# PQAT
quant_aware_annotate_model = tfmot.quantization.keras.quantize_annotate_model(
              stripped_pruned_model)
pqat_model = tfmot.quantization.keras.quantize_apply(
              quant_aware_annotate_model,
              tfmot.experimental.combine.Default8BitPrunePreserveQuantizeScheme())

pqat_model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
print('Train pqat model:')
pqat_model.fit(train_images, train_labels, batch_size=128, epochs=1, validation_split=0.1)
Train qat model:
422/422 [==============================] - 4s 8ms/step - loss: 0.0386 - accuracy: 0.9891 - val_loss: 0.0607 - val_accuracy: 0.9832
Train pqat model:
422/422 [==============================] - 4s 8ms/step - loss: 0.0416 - accuracy: 0.9881 - val_loss: 0.0590 - val_accuracy: 0.9832
<tensorflow.python.keras.callbacks.History at 0x7fafb5e48f50>
print("QAT Model sparsity:")
print_model_weights_sparsity(qat_model)
print("PQAT Model sparsity:")
print_model_weights_sparsity(pqat_model)
QAT Model sparsity:
conv2d/bias:0: 0.00% sparsity  (0/12)
conv2d/kernel:0: 6.48% sparsity  (7/108)
dense/bias:0: 0.00% sparsity  (0/10)
dense/kernel:0: 5.67% sparsity  (1149/20280)
PQAT Model sparsity:
conv2d/bias:0: 0.00% sparsity  (0/12)
conv2d/kernel:0: 50.00% sparsity  (54/108)
dense/bias:0: 0.00% sparsity  (0/10)
dense/kernel:0: 50.00% sparsity  (10140/20280)

PQAT modelinin sıkıştırma avantajlarını görün

Sıkıştırılmış model dosyasını almak için yardımcı işlevi tanımlayın.

def get_gzipped_model_size(file):
  # It returns the size of the gzipped model in kilobytes.

  _, zipped_file = tempfile.mkstemp('.zip')
  with zipfile.ZipFile(zipped_file, 'w', compression=zipfile.ZIP_DEFLATED) as f:
    f.write(file)

  return os.path.getsize(zipped_file)/1000

Bu küçük bir model olduğu için iki model arasındaki fark çok belirgin değil. Budama ve PQAT'yi daha büyük bir üretim modeline uygulamak, daha önemli bir sıkıştırma sağlar.

# QAT model
converter = tf.lite.TFLiteConverter.from_keras_model(qat_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
qat_tflite_model = converter.convert()
qat_model_file = 'qat_model.tflite'
# Save the model.
with open(qat_model_file, 'wb') as f:
    f.write(qat_tflite_model)

# PQAT model
converter = tf.lite.TFLiteConverter.from_keras_model(pqat_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
pqat_tflite_model = converter.convert()
pqat_model_file = 'pqat_model.tflite'
# Save the model.
with open(pqat_model_file, 'wb') as f:
    f.write(pqat_tflite_model)

print("QAT model size: ", get_gzipped_model_size(qat_model_file), ' KB')
print("PQAT model size: ", get_gzipped_model_size(pqat_model_file), ' KB')
WARNING:absl:Found untraced functions such as reshape_layer_call_fn, reshape_layer_call_and_return_conditional_losses, conv2d_layer_call_fn, conv2d_layer_call_and_return_conditional_losses, flatten_layer_call_fn while saving (showing 5 of 20). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmpurndy6nz/assets
INFO:tensorflow:Assets written to: /tmp/tmpurndy6nz/assets
WARNING:absl:Found untraced functions such as reshape_layer_call_fn, reshape_layer_call_and_return_conditional_losses, conv2d_layer_call_fn, conv2d_layer_call_and_return_conditional_losses, flatten_layer_call_fn while saving (showing 5 of 20). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmpgsy8_zld/assets
INFO:tensorflow:Assets written to: /tmp/tmpgsy8_zld/assets
QAT model size:  16.326  KB
PQAT model size:  14.022  KB

TF'den TFLite'a doğruluğun kalıcılığını görün

Test veri kümesinde TFLite modelini değerlendirmek için bir yardımcı işlev tanımlayın.

def eval_model(interpreter):
  input_index = interpreter.get_input_details()[0]["index"]
  output_index = interpreter.get_output_details()[0]["index"]

  # Run predictions on every image in the "test" dataset.
  prediction_digits = []
  for i, test_image in enumerate(test_images):
    if i % 1000 == 0:
      print(f"Evaluated on {i} results so far.")
    # Pre-processing: add batch dimension and convert to float32 to match with
    # the model's input data format.
    test_image = np.expand_dims(test_image, axis=0).astype(np.float32)
    interpreter.set_tensor(input_index, test_image)

    # Run inference.
    interpreter.invoke()

    # Post-processing: remove batch dimension and find the digit with highest
    # probability.
    output = interpreter.tensor(output_index)
    digit = np.argmax(output()[0])
    prediction_digits.append(digit)

  print('\n')
  # Compare prediction results with ground truth labels to calculate accuracy.
  prediction_digits = np.array(prediction_digits)
  accuracy = (prediction_digits == test_labels).mean()
  return accuracy

Budanmış ve nicelenmiş modeli değerlendirirsiniz ve ardından TensorFlow'un doğruluğunun TFLite arka ucunda devam ettiğini görürsünüz.

interpreter = tf.lite.Interpreter(pqat_model_file)
interpreter.allocate_tensors()

pqat_test_accuracy = eval_model(interpreter)

print('Pruned and quantized TFLite test_accuracy:', pqat_test_accuracy)
print('Pruned TF test accuracy:', pruned_model_accuracy)
Evaluated on 0 results so far.
Evaluated on 1000 results so far.
Evaluated on 2000 results so far.
Evaluated on 3000 results so far.
Evaluated on 4000 results so far.
Evaluated on 5000 results so far.
Evaluated on 6000 results so far.
Evaluated on 7000 results so far.
Evaluated on 8000 results so far.
Evaluated on 9000 results so far.


Pruned and quantized TFLite test_accuracy: 0.9815
Pruned TF test accuracy: 0.973800003528595

Eğitim sonrası nicelemeyi uygulayın ve PQAT modeliyle karşılaştırın

Daha sonra, budanmış modelde normal eğitim sonrası niceleme (ince ayar yok) kullanıyoruz ve doğruluğunu PQAT modeline göre kontrol ediyoruz. Bu, nicelenmiş modelin doğruluğunu artırmak için neden PQAT kullanmanız gerektiğini gösterir.

İlk olarak, ilk 1000 eğitim görüntüsünden kalibrasyon veri kümesi için bir oluşturucu tanımlayın.

def mnist_representative_data_gen():
  for image in train_images[:1000]:  
    image = np.expand_dims(image, axis=0).astype(np.float32)
    yield [image]

Modeli nicelleştirin ve doğruluğu önceden edinilmiş PQAT modeliyle karşılaştırın. İnce ayar ile nicelenen modelin daha yüksek doğruluk elde ettiğini unutmayın.

converter = tf.lite.TFLiteConverter.from_keras_model(stripped_pruned_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = mnist_representative_data_gen
post_training_tflite_model = converter.convert()
post_training_model_file = 'post_training_model.tflite'
# Save the model.
with open(post_training_model_file, 'wb') as f:
    f.write(post_training_tflite_model)

# Compare accuracy
interpreter = tf.lite.Interpreter(post_training_model_file)
interpreter.allocate_tensors()

post_training_test_accuracy = eval_model(interpreter)

print('PQAT TFLite test_accuracy:', pqat_test_accuracy)
print('Post-training (no fine-tuning) TF test accuracy:', post_training_test_accuracy)
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
WARNING:tensorflow:Compiled the loaded model, but the compiled metrics have yet to be built. `model.compile_metrics` will be empty until you train or evaluate the model.
INFO:tensorflow:Assets written to: /tmp/tmpk4ymv7ej/assets
INFO:tensorflow:Assets written to: /tmp/tmpk4ymv7ej/assets
Evaluated on 0 results so far.
Evaluated on 1000 results so far.
Evaluated on 2000 results so far.
Evaluated on 3000 results so far.
Evaluated on 4000 results so far.
Evaluated on 5000 results so far.
Evaluated on 6000 results so far.
Evaluated on 7000 results so far.
Evaluated on 8000 results so far.
Evaluated on 9000 results so far.


PQAT TFLite test_accuracy: 0.9815
Post-training (no fine-tuning) TF test accuracy: 0.9734

Çözüm

Bu öğreticide, bir model oluşturmayı, seyreklik API'sini kullanarak budamayı ve QAT kullanırken seyrekliği korumak için seyrekliği koruyan nicemleme farkında eğitimi (PQAT) uygulamayı öğrendiniz. Son PQAT modeli, seyrekliğin ilkinde korunduğunu ve ikincisinde kaybolduğunu göstermek için QAT modeliyle karşılaştırıldı. Ardından, zincirleme budama ve PQAT model optimizasyon tekniklerinin sıkıştırma faydalarını göstermek için modeller TFLite'a dönüştürüldü ve doğruluğun TFLite arka ucunda devam etmesini sağlamak için TFLite modeli değerlendirildi. Son olarak, PQAT modeli, normal nicelemeden doğruluk kaybını geri kazanmada PQAT'ın avantajını göstermek için eğitim sonrası niceleme API'si kullanılarak elde edilen nicelenmiş budanmış bir modelle karşılaştırıldı.