التقليم للاستدلال على الجهاز مع XNNPACK

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

مرحبا بكم في دليل على الأوزان Keras تشذيب لتحسين الكمون للاستدلال على الجهاز عن طريق XNNPACK .

يعرض هذا دليل استخدام أدخلت حديثا tfmot.sparsity.keras.PruningPolicy API وتوضح كيف يمكن استخدامها لتسريع نماذج معظمهم التلافيف على وحدات المعالجة المركزية الحديثة باستخدام XNNPACK متناثر الاستدلال .

يغطي الدليل الخطوات التالية لعملية إنشاء النموذج:

  • بناء وتدريب خط الأساس الكثيف
  • نموذج دقيق مع التقليم
  • قم بالتحويل إلى TFLite
  • معيار على الجهاز

لا يغطي الدليل أفضل الممارسات للضبط الدقيق للتقليم. لمزيد من المعلومات التفصيلية حول هذا الموضوع، يرجى مراجعة موقعنا دليل شامل .

يثبت

 pip install -q tf-nightly
 pip install -q tensorflow-model-optimization==0.5.1.dev0
import tempfile

import tensorflow as tf
import numpy as np

from tensorflow import keras
import tensorflow_datasets as tfds
import tensorflow_model_optimization as tfmot

%load_ext tensorboard

بناء وتدريب النموذج الكثيف

نحن نبني وتدريب CNN بسيطة الأساس لمهمة التصنيف على CIFAR10 البيانات.

# Load CIFAR10 dataset.
(ds_train, ds_val, ds_test), ds_info = tfds.load(
    'cifar10',
    split=['train[:90%]', 'train[90%:]', 'test'],
    as_supervised=True,
    with_info=True,
)

# Normalize the input image so that each pixel value is between 0 and 1.
def normalize_img(image, label):
  """Normalizes images: `uint8` -> `float32`."""
  return tf.image.convert_image_dtype(image, tf.float32), label

# Load the data in batches of 128 images.
batch_size = 128
def prepare_dataset(ds, buffer_size=None):
  ds = ds.map(normalize_img, num_parallel_calls=tf.data.experimental.AUTOTUNE)
  ds = ds.cache()
  if buffer_size:
    ds = ds.shuffle(buffer_size)
  ds = ds.batch(batch_size)
  ds = ds.prefetch(tf.data.experimental.AUTOTUNE)
  return ds

ds_train = prepare_dataset(ds_train,
                           buffer_size=ds_info.splits['train'].num_examples)
ds_val = prepare_dataset(ds_val)
ds_test = prepare_dataset(ds_test)

# Build the dense baseline model.
dense_model = keras.Sequential([
    keras.layers.InputLayer(input_shape=(32, 32, 3)),
    keras.layers.ZeroPadding2D(padding=1),
    keras.layers.Conv2D(
        filters=8,
        kernel_size=(3, 3),
        strides=(2, 2),
        padding='valid'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.DepthwiseConv2D(kernel_size=(3, 3), padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.Conv2D(filters=16, kernel_size=(1, 1)),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.ZeroPadding2D(padding=1),
    keras.layers.DepthwiseConv2D(
        kernel_size=(3, 3), strides=(2, 2), padding='valid'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.Conv2D(filters=32, kernel_size=(1, 1)),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.GlobalAveragePooling2D(),
    keras.layers.Flatten(),
    keras.layers.Dense(10)
])

# Compile and train the dense model for 10 epochs.
dense_model.compile(
    loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
    optimizer='adam',
    metrics=['accuracy'])

dense_model.fit(
  ds_train,
  epochs=10,
  validation_data=ds_val)

# Evaluate the dense model.
_, dense_model_accuracy = dense_model.evaluate(ds_test, verbose=0)
Epoch 1/10
352/352 [==============================] - 16s 32ms/step - loss: 2.0021 - accuracy: 0.2716 - val_loss: 2.0871 - val_accuracy: 0.2106
Epoch 2/10
352/352 [==============================] - 9s 24ms/step - loss: 1.7056 - accuracy: 0.3779 - val_loss: 1.7434 - val_accuracy: 0.3364
Epoch 3/10
352/352 [==============================] - 8s 24ms/step - loss: 1.6049 - accuracy: 0.4144 - val_loss: 1.6463 - val_accuracy: 0.3834
Epoch 4/10
352/352 [==============================] - 8s 23ms/step - loss: 1.5485 - accuracy: 0.4359 - val_loss: 1.7435 - val_accuracy: 0.3808
Epoch 5/10
352/352 [==============================] - 8s 24ms/step - loss: 1.5099 - accuracy: 0.4516 - val_loss: 1.5217 - val_accuracy: 0.4300
Epoch 6/10
352/352 [==============================] - 9s 24ms/step - loss: 1.4806 - accuracy: 0.4632 - val_loss: 1.5367 - val_accuracy: 0.4404
Epoch 7/10
352/352 [==============================] - 8s 24ms/step - loss: 1.4548 - accuracy: 0.4724 - val_loss: 1.5238 - val_accuracy: 0.4470
Epoch 8/10
352/352 [==============================] - 8s 24ms/step - loss: 1.4401 - accuracy: 0.4782 - val_loss: 1.7590 - val_accuracy: 0.3754
Epoch 9/10
352/352 [==============================] - 8s 24ms/step - loss: 1.4255 - accuracy: 0.4859 - val_loss: 1.4854 - val_accuracy: 0.4598
Epoch 10/10
352/352 [==============================] - 8s 24ms/step - loss: 1.4127 - accuracy: 0.4889 - val_loss: 1.8831 - val_accuracy: 0.3708

بناء نموذج متفرق

باستخدام الإرشادات من دليل شامل ، ونحن نطبق tfmot.sparsity.keras.prune_low_magnitude وظيفة مع المعلمات هذا الهدف تسارع على الجهاز عن طريق تقليم أي tfmot.sparsity.keras.PruneForLatencyOnXNNPack السياسة.

prune_low_magnitude = tfmot.sparsity.keras.prune_low_magnitude

# Compute end step to finish pruning after after 5 epochs.
end_epoch = 5

num_iterations_per_epoch = len(ds_train)
end_step =  num_iterations_per_epoch * end_epoch

# Define parameters for pruning.
pruning_params = {
      'pruning_schedule': tfmot.sparsity.keras.PolynomialDecay(initial_sparsity=0.25,
                                                               final_sparsity=0.75,
                                                               begin_step=0,
                                                               end_step=end_step),
      'pruning_policy': tfmot.sparsity.keras.PruneForLatencyOnXNNPack()
}

# Try to apply pruning wrapper with pruning policy parameter.
try:
  model_for_pruning = prune_low_magnitude(dense_model, **pruning_params)
except ValueError as e:
  print(e)
Could not find a `GlobalAveragePooling2D` layer with `keepdims = True` in all output branches

الدعوة prune_low_magnitude النتائج في ValueError مع الرسالة Could not find a GlobalAveragePooling2D layer with keepdims = True in all output branches . وتشير الرسالة إلى أن النموذج لا يتم اعتماد لتشذيب مع سياسة tfmot.sparsity.keras.PruneForLatencyOnXNNPack وتحديدا الطبقة GlobalAveragePooling2D يتطلب المعلمة keepdims = True . الإصلاح دعونا أن وإعادة تطبيق prune_low_magnitude وظيفة.

fixed_dense_model = keras.Sequential([
    keras.layers.InputLayer(input_shape=(32, 32, 3)),
    keras.layers.ZeroPadding2D(padding=1),
    keras.layers.Conv2D(
        filters=8,
        kernel_size=(3, 3),
        strides=(2, 2),
        padding='valid'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.DepthwiseConv2D(kernel_size=(3, 3), padding='same'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.Conv2D(filters=16, kernel_size=(1, 1)),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.ZeroPadding2D(padding=1),
    keras.layers.DepthwiseConv2D(
        kernel_size=(3, 3), strides=(2, 2), padding='valid'),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.Conv2D(filters=32, kernel_size=(1, 1)),
    keras.layers.BatchNormalization(),
    keras.layers.ReLU(),
    keras.layers.GlobalAveragePooling2D(keepdims=True),
    keras.layers.Flatten(),
    keras.layers.Dense(10)
])

# Use the pretrained model for pruning instead of training from scratch.
fixed_dense_model.set_weights(dense_model.get_weights())

# Try to reapply pruning wrapper.
model_for_pruning = prune_low_magnitude(fixed_dense_model, **pruning_params)
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/keras/engine/base_layer.py:2233: 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 '

الاحتجاج prune_low_magnitude قد انتهت دون أي أخطاء وهذا يعني أن نموذج معتمد بشكل كامل ل tfmot.sparsity.keras.PruneForLatencyOnXNNPack سياسة ويمكن تسريع استخدام XNNPACK متناثر الاستدلال .

صقل النموذج المتناثر

وعقب سبيل المثال التقليم ، ونحن صقل نموذج متفرق باستخدام أوزان للنموذج كثيفة. نبدأ الضبط الدقيق للنموذج بتباين 25٪ (25٪ من الأوزان مضبوطة على الصفر) وننتهي بـ 75٪ من التباين.

logdir = tempfile.mkdtemp()

callbacks = [
  tfmot.sparsity.keras.UpdatePruningStep(),
  tfmot.sparsity.keras.PruningSummaries(log_dir=logdir),
]

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

model_for_pruning.fit(
  ds_train,
  epochs=15,
  validation_data=ds_val,
  callbacks=callbacks)

# Evaluate the dense model.
_, pruned_model_accuracy = model_for_pruning.evaluate(ds_test, verbose=0)

print('Dense model test accuracy:', dense_model_accuracy)
print('Pruned model test accuracy:', pruned_model_accuracy)
Epoch 1/15
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/array_ops.py:5065: 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.
WARNING:tensorflow:From /tmpfs/src/tf_docs_env/lib/python3.7/site-packages/tensorflow/python/ops/array_ops.py:5065: 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.
352/352 [==============================] - 10s 25ms/step - loss: 1.4274 - accuracy: 0.4850 - val_loss: 1.5313 - val_accuracy: 0.4336
Epoch 2/15
352/352 [==============================] - 8s 24ms/step - loss: 1.4519 - accuracy: 0.4756 - val_loss: 2.2348 - val_accuracy: 0.3022
Epoch 3/15
352/352 [==============================] - 8s 23ms/step - loss: 1.4864 - accuracy: 0.4622 - val_loss: 1.7750 - val_accuracy: 0.3752
Epoch 4/15
352/352 [==============================] - 8s 24ms/step - loss: 1.4758 - accuracy: 0.4634 - val_loss: 1.7347 - val_accuracy: 0.3742
Epoch 5/15
352/352 [==============================] - 9s 24ms/step - loss: 1.4509 - accuracy: 0.4736 - val_loss: 1.6406 - val_accuracy: 0.4166
Epoch 6/15
352/352 [==============================] - 8s 24ms/step - loss: 1.4345 - accuracy: 0.4788 - val_loss: 1.7445 - val_accuracy: 0.3804
Epoch 7/15
352/352 [==============================] - 9s 24ms/step - loss: 1.4196 - accuracy: 0.4865 - val_loss: 2.5808 - val_accuracy: 0.2624
Epoch 8/15
352/352 [==============================] - 9s 25ms/step - loss: 1.4093 - accuracy: 0.4900 - val_loss: 1.5336 - val_accuracy: 0.4498
Epoch 9/15
352/352 [==============================] - 9s 24ms/step - loss: 1.4023 - accuracy: 0.4940 - val_loss: 1.9210 - val_accuracy: 0.3654
Epoch 10/15
352/352 [==============================] - 9s 24ms/step - loss: 1.3968 - accuracy: 0.4960 - val_loss: 1.5129 - val_accuracy: 0.4406
Epoch 11/15
352/352 [==============================] - 9s 24ms/step - loss: 1.3882 - accuracy: 0.4983 - val_loss: 1.7009 - val_accuracy: 0.3896
Epoch 12/15
352/352 [==============================] - 9s 25ms/step - loss: 1.3807 - accuracy: 0.5020 - val_loss: 2.3179 - val_accuracy: 0.2984
Epoch 13/15
352/352 [==============================] - 8s 24ms/step - loss: 1.3781 - accuracy: 0.5034 - val_loss: 1.6146 - val_accuracy: 0.4324
Epoch 14/15
352/352 [==============================] - 9s 25ms/step - loss: 1.3735 - accuracy: 0.5054 - val_loss: 2.3618 - val_accuracy: 0.3062
Epoch 15/15
352/352 [==============================] - 8s 24ms/step - loss: 1.3748 - accuracy: 0.5040 - val_loss: 1.5962 - val_accuracy: 0.4312
Dense model test accuracy: 0.37400001287460327
Pruned model test accuracy: 0.4334000051021576

تظهر السجلات تطور التباين على أساس كل طبقة.

%tensorboard --logdir={logdir}

بعد الضبط الدقيق باستخدام التقليم ، تُظهر دقة الاختبار تحسنًا متواضعًا (43٪ إلى 44٪) مقارنة بالنموذج الكثيف. دعونا نقارن على جهاز الكمون باستخدام TFLite القياسي .

نموذج التحويل والقياس المعياري

لتحويل نموذج مجردة إلى TFLite، نحن بحاجة إلى استبدال PruneLowMagnitude مغلفة بطبقات الأصلية عبر strip_pruning وظيفة. أيضا، منذ أوزان نموذج مجردة ( model_for_pruning ) هي في معظمها الأصفار، ونحن قد تطبيق الأمثل tf.lite.Optimize.EXPERIMENTAL_SPARSITY لتخزين بكفاءة أدى نموذج TFLite. علامة التحسين هذه غير مطلوبة للنموذج الكثيف.

converter = tf.lite.TFLiteConverter.from_keras_model(dense_model)
dense_tflite_model = converter.convert()

_, dense_tflite_file = tempfile.mkstemp('.tflite')
with open(dense_tflite_file, 'wb') as f:
  f.write(dense_tflite_model)

model_for_export = tfmot.sparsity.keras.strip_pruning(model_for_pruning)

converter = tf.lite.TFLiteConverter.from_keras_model(model_for_export)
converter.optimizations = [tf.lite.Optimize.EXPERIMENTAL_SPARSITY]
pruned_tflite_model = converter.convert()

_, pruned_tflite_file = tempfile.mkstemp('.tflite')
with open(pruned_tflite_file, 'wb') as f:
  f.write(pruned_tflite_model)
INFO:tensorflow:Assets written to: /tmp/tmp9is7dj3q/assets
INFO:tensorflow:Assets written to: /tmp/tmp9is7dj3q/assets
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/tmp9kw8dwue/assets
INFO:tensorflow:Assets written to: /tmp/tmp9kw8dwue/assets

اتباع التعليمات من TFLite نموذج أداة مرجعية ، ونحن نبني الأداة، تحميله على جهاز الروبوت مع كثافة ونماذج TFLite مجردة، وقياس كلا النموذجين على الجهاز.

! adb shell /data/local/tmp/benchmark_model \
    --graph=/data/local/tmp/dense_model.tflite \
    --use_xnnpack=true \
    --num_runs=100 \
    --num_threads=1
/bin/bash: adb: command not found
! adb shell /data/local/tmp/benchmark_model \
    --graph=/data/local/tmp/pruned_model.tflite \
    --use_xnnpack=true \
    --num_runs=100 \
    --num_threads=1
/bin/bash: adb: command not found

أسفرت المعايير على بكسل 4 في متوسط الوقت الاستدلال من 17us لنموذج كثيفة و12us لنموذج مجردة. المعايير على جهاز يبرهن على وجود 5us واضحة أو 30٪ من التحسينات في الكمون حتى لمثل هذه النماذج الصغيرة. في تجربتنا، ونماذج أكبر على أساس MobileNetV3 أو EfficientNet لايت تظهر تحسينات في الأداء مماثلة. يختلف التسريع بناءً على المساهمة النسبية للالتفافات 1 × 1 في النموذج الكلي.

استنتاج

في هذا البرنامج التعليمي ، نوضح كيف يمكن للمرء إنشاء نماذج متفرقة للحصول على أداء أسرع على الجهاز باستخدام الوظائف الجديدة التي قدمتها TF MOT API و XNNPack. هذه النماذج المتناثرة أصغر وأسرع من نظيراتها الكثيفة مع الاحتفاظ بجودتها أو حتى تجاوزها.

نحن نشجعك على تجربة هذه الإمكانية الجديدة التي يمكن أن تكون مهمة بشكل خاص لنشر النماذج الخاصة بك على الجهاز.