مساعدة في حماية الحاجز المرجاني العظيم مع TensorFlow على Kaggle تاريخ التحدي

التقليم الحفاظ على الوعي الكمي التدريب (PQAT) مثال Keras

عرض على TensorFlow.org تشغيل في Google Colab عرض على جيثب تحميل دفتر

ملخص

هذا هو وضع حد لمثل نهاية تبين استخدام والحفاظ على تكميم التدريب علم (PQAT) API تشذيب، وهي جزء من خط أنابيب الأمثل التعاوني للTensorFlow نموذج الأمثل أدوات و.

صفحات أخرى

للحصول على مقدمة إلى خط أنابيب وغيرها من التقنيات المتاحة، راجع صفحة نظرة عامة الأمثل التعاونية .

محتويات

في البرنامج التعليمي ، سوف:

  1. تدريب tf.keras نموذج للبيانات MNIST من الصفر.
  2. اضبط النموذج باستخدام التقليم ، باستخدام واجهة برمجة التطبيقات (API) المتناثرة ، وشاهد الدقة.
  3. تطبيق QAT ولاحظ فقدان النثر.
  4. قم بتطبيق PQAT ولاحظ أنه تم الحفاظ على التباعد المطبق مسبقًا.
  5. قم بإنشاء نموذج TFLite ولاحظ تأثيرات تطبيق PQAT عليه.
  6. قارن دقة نموذج PQAT المحققة مع نموذج كمي باستخدام تكميم ما بعد التدريب.

اقامة

يمكنك تشغيل هذا الكمبيوتر الدفتري Jupyter في منطقتك virtualenv أو colab . للحصول على تفاصيل إنشاء التبعيات، يرجى الرجوع إلى دليل التثبيت .

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

import numpy as np
import tempfile
import zipfile
import os

تدريب نموذج tf.keras لـ MNIST بدون تقليم

# 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>

قم بتقييم النموذج الأساسي وحفظه لاستخدامه لاحقًا

_, 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

قم بتقليم النموذج وضبطه بدقة حتى يصل إلى 50٪ من التباين

تطبيق prune_low_magnitude() API لتقليم نموذج المدربين قبل كله لإثبات ومراقبة فعاليتها في الحد من حجم النموذج عند تطبيق البريدي، مع الحفاظ على دقة. لأفضل السبل لاستخدام API لتحقيق أفضل معدل ضغط مع الحفاظ على دقة الهدف الخاص بك، يرجى الرجوع إلى دليل شامل التقليم .

حدد النموذج وطبق واجهة برمجة التطبيقات المتناثرة

يحتاج النموذج إلى تدريب مسبق قبل استخدام واجهة برمجة التطبيقات المتناثرة.

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
_________________________________________________________________

صقل النموذج وتقييم الدقة مقابل خط الأساس

صقل النموذج بالتقليم لمدة 3 فترات.

# 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>

تحديد وظائف المساعد لحساب وطباعة تناثر النموذج.

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})",
            )

تحقق من أن النموذج تم تقليمه بشكل صحيح. نحتاج إلى تجريد غلاف التقليم أولاً.

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)

في هذا المثال ، يوجد قدر ضئيل من الخسارة في دقة الاختبار بعد التقليم ، مقارنة بخط الأساس.

_, 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 و PQAT وتحقق من التأثير على تباين النموذج في كلتا الحالتين

بعد ذلك ، نطبق كلاً من QAT والمحافظة على التقليم QAT (PQAT) على النموذج المشذب ونلاحظ أن PQAT يحافظ على التباين في نموذجك المشذب. ملاحظة أننا جردت تقليم مغلفة من النموذج الخاص بك مجردة مع tfmot.sparsity.keras.strip_pruning قبل تطبيق API PQAT.

# 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

تحديد وظيفة المساعد للحصول على ملف نموذج مضغوط.

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

نظرًا لأن هذا نموذج صغير ، فإن الاختلاف بين النموذجين ليس ملحوظًا جدًا. سيؤدي تطبيق التقليم و PQAT على نموذج إنتاج أكبر إلى ضغط أكثر أهمية.

# 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 إلى TFLite

حدد وظيفة مساعد لتقييم نموذج TFLite في مجموعة بيانات الاختبار.

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

تقوم بتقييم النموذج ، الذي تم تقليمه وتقويته ، ثم ترى الدقة من TensorFlow مستمرة في الواجهة الخلفية لـ TFLite.

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

تطبيق التكميم بعد التدريب ومقارنتها بنموذج PQAT

بعد ذلك ، نستخدم التكميم العادي بعد التدريب (بدون ضبط دقيق) على النموذج المشذب والتحقق من دقته مقابل نموذج PQAT. يوضح هذا سبب حاجتك إلى استخدام PQAT لتحسين دقة النموذج الكمي.

أولاً ، حدد مولدًا لمجموعة بيانات الاستدعاء من أول 1000 صورة تدريب.

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

حدد النموذج وقارن الدقة بنموذج PQAT الذي تم الحصول عليه مسبقًا. لاحظ أن النموذج الكمي مع الضبط الدقيق يحقق دقة أعلى.

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

استنتاج

في هذا البرنامج التعليمي ، تعلمت كيفية إنشاء نموذج ، وتقليمه باستخدام واجهة برمجة التطبيقات (API) المتناثرة ، وتطبيق التدريب القائم على الحفاظ على التباين (PQAT) للحفاظ على التباين أثناء استخدام QAT. تمت مقارنة نموذج PQAT النهائي بنموذج QAT لإظهار أن التباين محفوظ في الأول وفقد في الأخير. بعد ذلك ، تم تحويل النماذج إلى TFLite لإظهار فوائد الضغط لتقنيات التقليم المتسلسل وتقنيات تحسين نموذج PQAT وتم تقييم نموذج TFLite لضمان استمرار الدقة في الواجهة الخلفية لـ TFLite. أخيرًا ، تمت مقارنة نموذج PQAT بنموذج تقليم كمي تم تحقيقه باستخدام واجهة برمجة تطبيقات تكميم ما بعد التدريب لإثبات ميزة PQAT في استرداد فقدان الدقة من التكميم الطبيعي.