ML 커뮤니티 데이는 11월 9일입니다! TensorFlow, JAX에서 업데이트를 우리와 함께, 더 자세히 알아보기

희소성 및 클러스터 보존 양자화 인식 훈련(PCQAT) Keras 예제

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 보기 노트북 다운로드

개요

이것은 희소성의 사용을 보여주는 최종 예와 양자화 인식 교육 (PCQAT) API의 TensorFlow 모델 최적화 툴킷의 공동 최적화 파이프 라인의 일부를 보존 클러스터 끝입니다.

다른 페이지

파이프 라인 및 사용 가능한 다른 기술에 대한 소개를 들어, 참조 협업 최적화 개요 페이지를 .

내용물

이 자습서에서는 다음을 수행합니다.

  1. 기차 tf.keras 처음부터 MNIST 데이터 세트에 대한 모델을.
  2. 가지치기로 모델을 미세 조정하고 정확도를 확인하고 모델이 성공적으로 정리되었는지 관찰합니다.
  3. 제거된 모델에 희소성 보존 클러스터링을 적용하고 이전에 적용된 희소성이 보존되었는지 관찰합니다.
  4. QAT를 적용하고 희소성과 클러스터의 손실을 관찰합니다.
  5. PCQAT를 적용하고 이전에 적용된 희소성과 클러스터링이 모두 보존되었음을 관찰합니다.
  6. TFLite 모델을 생성하고 여기에 PCQAT를 적용한 효과를 관찰합니다.
  7. 서로 다른 모델의 크기를 비교하여 희소성을 유지하는 클러스터링 및 PCQAT의 협업 최적화 기술에 이어 희소성을 적용할 때의 압축 이점을 관찰합니다.
  8. 완전히 최적화된 모델의 정확도와 최적화되지 않은 기본 모델 정확도를 비교합니다.

설정

당신은 당신의 지역이 Jupyter 노트북을 실행할 수 있습니다 VIRTUALENV 또는 colab . 종속성을 설정하는 자세한 내용을 참조하시기 바랍니다 설치 가이드 .

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

import numpy as np
import tempfile
import zipfile
import os

MNIST가 가지치기 및 클러스터링되도록 tf.keras 모델 훈련

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

opt = tf.keras.optimizers.Adam(learning_rate=1e-3)

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

model.fit(
    train_images,
    train_labels,
    validation_split=0.1,
    epochs=10
)
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
11493376/11490434 [==============================] - 0s 0us/step
11501568/11490434 [==============================] - 0s 0us/step
2021-09-02 11:14:14.164834: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected
Epoch 1/10
1688/1688 [==============================] - 8s 5ms/step - loss: 0.2842 - accuracy: 0.9215 - val_loss: 0.1078 - val_accuracy: 0.9713
Epoch 2/10
1688/1688 [==============================] - 8s 5ms/step - loss: 0.1110 - accuracy: 0.9684 - val_loss: 0.0773 - val_accuracy: 0.9783
Epoch 3/10
1688/1688 [==============================] - 8s 4ms/step - loss: 0.0821 - accuracy: 0.9760 - val_loss: 0.0676 - val_accuracy: 0.9803
Epoch 4/10
1688/1688 [==============================] - 8s 4ms/step - loss: 0.0684 - accuracy: 0.9799 - val_loss: 0.0600 - val_accuracy: 0.9825
Epoch 5/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0590 - accuracy: 0.9828 - val_loss: 0.0601 - val_accuracy: 0.9838
Epoch 6/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0522 - accuracy: 0.9845 - val_loss: 0.0599 - val_accuracy: 0.9835
Epoch 7/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0472 - accuracy: 0.9863 - val_loss: 0.0544 - val_accuracy: 0.9862
Epoch 8/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0422 - accuracy: 0.9868 - val_loss: 0.0579 - val_accuracy: 0.9848
Epoch 9/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0384 - accuracy: 0.9884 - val_loss: 0.0569 - val_accuracy: 0.9847
Epoch 10/10
1688/1688 [==============================] - 7s 4ms/step - loss: 0.0347 - accuracy: 0.9892 - val_loss: 0.0559 - val_accuracy: 0.9840
<keras.callbacks.History at 0x7f6a8212c550>

기준 모델을 평가하고 나중에 사용할 수 있도록 저장합니다.

_, 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.9811000227928162
Saving model to:  /tmp/tmprlekfdwb.h5

모델을 50% 희소성으로 정리 및 미세 조정

적용 prune_low_magnitude() 다음 단계에서 클러스터 될 제거 된 모델을 달성하기 위해 API를. 참고하여주십시오 치기 포괄적 인 가이드 치기 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'])
/tmpfs/src/tf_docs_env/lib/python3.7/site-packages/keras/engine/base_layer.py:2223: 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 '

모델 미세 조정, 희소성 확인, 기준선에 대한 정확도 평가

3 Epoch 동안 가지치기로 모델을 미세 조정합니다.

# Fine-tune model
pruned_model.fit(
  train_images,
  train_labels,
  epochs=3,
  validation_split=0.1,
  callbacks=callbacks)
2021-09-02 11:15:31.836903: W tensorflow/python/util/util.cc:348] Sets are not currently considered sequences, but this may change in the future, so consider avoiding using them.
Epoch 1/3
1688/1688 [==============================] - 9s 5ms/step - loss: 0.2095 - accuracy: 0.9305 - val_loss: 0.1440 - val_accuracy: 0.9528
Epoch 2/3
1688/1688 [==============================] - 8s 4ms/step - loss: 0.1042 - accuracy: 0.9671 - val_loss: 0.0947 - val_accuracy: 0.9715
Epoch 3/3
1688/1688 [==============================] - 8s 4ms/step - loss: 0.0743 - accuracy: 0.9782 - val_loss: 0.0829 - val_accuracy: 0.9770
<keras.callbacks.History at 0x7f6a81f94250>

모델의 희소성과 클러스터를 계산하고 인쇄하는 도우미 함수를 정의합니다.

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:
            if "kernel" not in weight.name or "centroid" 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})",
            )

def print_model_weight_clusters(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
            if "kernel" in weight.name:
                unique_count = len(np.unique(weight))
                print(
                    f"{layer.name}/{weight.name}: {unique_count} clusters "
                )

먼저 가지치기 래퍼를 제거한 다음 모델 커널이 올바르게 정리되었는지 확인합니다.

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)
dense/kernel:0: 50.00% sparsity  (10140/20280)

희소성 보존 클러스터링을 적용하고 두 경우 모두 모델 희소성에 미치는 영향 확인

다음으로, 프루닝된 모델에 희소성 보존 군집화를 적용하고 군집의 수를 관찰하여 희소성이 유지되는지 확인한다.

import tensorflow_model_optimization as tfmot
from tensorflow_model_optimization.python.core.clustering.keras.experimental import (
    cluster,
)

cluster_weights = tfmot.clustering.keras.cluster_weights
CentroidInitialization = tfmot.clustering.keras.CentroidInitialization

cluster_weights = cluster.cluster_weights

clustering_params = {
  'number_of_clusters': 8,
  'cluster_centroids_init': CentroidInitialization.KMEANS_PLUS_PLUS,
  'preserve_sparsity': True
}

sparsity_clustered_model = cluster_weights(stripped_pruned_model, **clustering_params)

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

print('Train sparsity preserving clustering model:')
sparsity_clustered_model.fit(train_images, train_labels,epochs=3, validation_split=0.1)
Train sparsity preserving clustering model:
Epoch 1/3
1688/1688 [==============================] - 9s 5ms/step - loss: 0.0495 - accuracy: 0.9847 - val_loss: 0.0611 - val_accuracy: 0.9843
Epoch 2/3
1688/1688 [==============================] - 8s 5ms/step - loss: 0.0472 - accuracy: 0.9855 - val_loss: 0.0705 - val_accuracy: 0.9812
Epoch 3/3
1688/1688 [==============================] - 8s 5ms/step - loss: 0.0463 - accuracy: 0.9846 - val_loss: 0.0796 - val_accuracy: 0.9780
<keras.callbacks.History at 0x7f6a81c10250>

먼저 클러스터링 래퍼를 제거한 다음 모델이 올바르게 정리되고 클러스터링되었는지 확인합니다.

stripped_clustered_model = tfmot.clustering.keras.strip_clustering(sparsity_clustered_model)

print("Model sparsity:\n")
print_model_weights_sparsity(stripped_clustered_model)

print("\nModel clusters:\n")
print_model_weight_clusters(stripped_clustered_model)
Model sparsity:

kernel:0: 51.85% sparsity  (56/108)
kernel:0: 60.83% sparsity  (12337/20280)

Model clusters:

conv2d/kernel:0: 8 clusters 
dense/kernel:0: 8 clusters

QAT 및 PCQAT 적용 및 모델 클러스터 및 희소성에 미치는 영향 확인

다음으로, 희소 클러스터 모델에 QAT와 PCQAT를 모두 적용하고 PCQAT가 모델의 가중치 희소성과 클러스터를 유지하는지 관찰합니다. 제거된 모델은 QAT 및 PCQAT API로 전달됩니다.

# QAT
qat_model = tfmot.quantization.keras.quantize_model(stripped_clustered_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)

# PCQAT
quant_aware_annotate_model = tfmot.quantization.keras.quantize_annotate_model(
              stripped_clustered_model)
pcqat_model = tfmot.quantization.keras.quantize_apply(
              quant_aware_annotate_model,
              tfmot.experimental.combine.Default8BitClusterPreserveQuantizeScheme(preserve_sparsity=True))

pcqat_model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])
print('Train pcqat model:')
pcqat_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.0343 - accuracy: 0.9892 - val_loss: 0.0600 - val_accuracy: 0.9858
Train pcqat model:
WARNING:tensorflow:Gradients do not exist for variables ['conv2d/kernel:0', 'dense/kernel:0'] when minimizing the loss.
WARNING:tensorflow:Gradients do not exist for variables ['conv2d/kernel:0', 'dense/kernel:0'] when minimizing the loss.
422/422 [==============================] - 4s 8ms/step - loss: 0.0371 - accuracy: 0.9880 - val_loss: 0.0664 - val_accuracy: 0.9832
<keras.callbacks.History at 0x7f6a81792910>
print("QAT Model clusters:")
print_model_weight_clusters(qat_model)
print("\nQAT Model sparsity:")
print_model_weights_sparsity(qat_model)
print("\nPCQAT Model clusters:")
print_model_weight_clusters(pcqat_model)
print("\nPCQAT Model sparsity:")
print_model_weights_sparsity(pcqat_model)
QAT Model clusters:
quant_conv2d/conv2d/kernel:0: 101 clusters 
quant_dense/dense/kernel:0: 18285 clusters 

QAT Model sparsity:
conv2d/kernel:0: 7.41% sparsity  (8/108)
dense/kernel:0: 7.64% sparsity  (1549/20280)

PCQAT Model clusters:
quant_conv2d/conv2d/kernel:0: 8 clusters 
quant_dense/dense/kernel:0: 8 clusters 

PCQAT Model sparsity:
conv2d/kernel:0: 51.85% sparsity  (56/108)
dense/kernel:0: 60.84% sparsity  (12338/20280)

PCQAT 모델의 압축 이점 보기

압축된 모델 파일을 가져오는 도우미 함수를 정의합니다.

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

희소성, 클러스터링 및 PCQAT를 모델에 적용하면 상당한 압축 이점을 얻을 수 있습니다.

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

# PCQAT model
converter = tf.lite.TFLiteConverter.from_keras_model(pcqat_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
pcqat_tflite_model = converter.convert()
pcqat_model_file = 'pcqat_model.tflite'
# Save the model.
with open(pcqat_model_file, 'wb') as f:
    f.write(pcqat_tflite_model)

print("QAT model size: ", get_gzipped_model_size(qat_model_file), ' KB')
print("PCQAT model size: ", get_gzipped_model_size(pcqat_model_file), ' KB')
WARNING:absl:Found untraced functions such as reshape_layer_call_and_return_conditional_losses, reshape_layer_call_fn, conv2d_layer_call_and_return_conditional_losses, conv2d_layer_call_fn, flatten_layer_call_and_return_conditional_losses while saving (showing 5 of 20). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmp6_obh00g/assets
INFO:tensorflow:Assets written to: /tmp/tmp6_obh00g/assets
2021-09-02 11:16:32.221664: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-02 11:16:32.221712: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.
WARNING:absl:Found untraced functions such as reshape_layer_call_and_return_conditional_losses, reshape_layer_call_fn, conv2d_layer_call_and_return_conditional_losses, conv2d_layer_call_fn, flatten_layer_call_and_return_conditional_losses while saving (showing 5 of 20). These functions will not be directly callable after loading.
INFO:tensorflow:Assets written to: /tmp/tmpuqqwyk0s/assets
INFO:tensorflow:Assets written to: /tmp/tmpuqqwyk0s/assets
QAT model size:  13.723  KB
PCQAT model size:  7.352  KB
2021-09-02 11:16:33.766310: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:351] Ignored output_format.
2021-09-02 11:16:33.766350: W tensorflow/compiler/mlir/lite/python/tf_tfl_flatbuffer_helpers.cc:354] Ignored drop_control_dependency.

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(pcqat_model_file)
interpreter.allocate_tensors()

pcqat_test_accuracy = eval_model(interpreter)

print('Pruned, clustered and quantized TFLite test_accuracy:', pcqat_test_accuracy)
print('Baseline TF test accuracy:', baseline_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, clustered and quantized TFLite test_accuracy: 0.9803
Baseline TF test accuracy: 0.9811000227928162

결론

이 튜토리얼에서는, 모델을 만들 사용하여 가지 치기하는 방법을 배웠습니다 prune_low_magnitude() API를하고, 사용 희소성 유지 클러스터링을 적용 cluster_weights() 가중치를 클러스터링 동안 희소성을 유지하기 위해 API를.

다음으로, QAT를 사용하는 동안 모델 희소성과 클러스터를 보존하기 위해 희소성 및 클러스터 보존 양자화 인식 훈련(PCQAT)이 적용되었습니다. 최종 PCQAT 모델을 QAT 모델과 비교하여 전자에서는 희소성과 클러스터가 유지되고 후자는 손실됨을 보여줍니다.

다음으로, 모델을 TFLite로 변환하여 연결 희소성, 클러스터링 및 PCQAT 모델 최적화 기술의 압축 이점을 보여주고 TFLite 모델은 TFLite 백엔드에서 정확도가 지속되는지 확인하기 위해 평가되었습니다.

마지막으로 PCQAT TFLite 모델 정확도를 사전 최적화 기준 모델 정확도와 비교하여 협업 최적화 기술이 원래 모델과 유사한 정확도를 유지하면서 압축 이점을 달성할 수 있음을 보여주었습니다.