Umfassende Anleitung zum Gewicht-Clustering

Auf TensorFlow.org ansehen In Google Colab ausführen Quelle auf GitHub anzeigen Notizbuch herunterladen

Willkommen in die umfassenden Leitfaden für das Gewicht Clustering Teil der TensorFlow Modell Optimization Toolkit.

Diese Seite dokumentiert verschiedene Anwendungsfälle und zeigt, wie Sie die API für jeden verwenden. Sobald Sie wissen , welche APIs Sie benötigen, finden die Parameter und die Low-Level - Details in der API - Dokumentation :

  • Wenn Sie die Vorteile der Gewichts Clustering sehen wollen und was unterstützt wird , überprüfen Sie den Überblick .
  • Für ein einzelnes End-to-End - Beispiel finden Sie in das Gewicht Clustering Beispiel .

In diesem Handbuch werden die folgenden Anwendungsfälle behandelt:

  • Definieren Sie ein Clustermodell.
  • Checkpoint und Deserialisieren eines geclusterten Modells.
  • Verbessern Sie die Genauigkeit des geclusterten Modells.
  • Nur für die Bereitstellung müssen Sie Schritte unternehmen, um die Vorteile der Komprimierung zu sehen.

Aufstellen

! pip install -q tensorflow-model-optimization

import tensorflow as tf
import numpy as np
import tempfile
import os
import tensorflow_model_optimization as tfmot

input_dim = 20
output_dim = 20
x_train = np.random.randn(1, input_dim).astype(np.float32)
y_train = tf.keras.utils.to_categorical(np.random.randn(1), num_classes=output_dim)

def setup_model():
  model = tf.keras.Sequential([
      tf.keras.layers.Dense(input_dim, input_shape=[input_dim]),
      tf.keras.layers.Flatten()
  ])
  return model

def train_model(model):
  model.compile(
      loss=tf.keras.losses.categorical_crossentropy,
      optimizer='adam',
      metrics=['accuracy']
  )
  model.summary()
  model.fit(x_train, y_train)
  return model

def save_model_weights(model):
  _, pretrained_weights = tempfile.mkstemp('.h5')
  model.save_weights(pretrained_weights)
  return pretrained_weights

def setup_pretrained_weights():
  model= setup_model()
  model = train_model(model)
  pretrained_weights = save_model_weights(model)
  return pretrained_weights

def setup_pretrained_model():
  model = setup_model()
  pretrained_weights = setup_pretrained_weights()
  model.load_weights(pretrained_weights)
  return model

def save_model_file(model):
  _, keras_file = tempfile.mkstemp('.h5') 
  model.save(keras_file, include_optimizer=False)
  return keras_file

def get_gzipped_model_size(model):
  # It returns the size of the gzipped model in bytes.
  import os
  import zipfile

  keras_file = save_model_file(model)

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

Definieren Sie ein geclustertes Modell

Ein ganzes Modell gruppieren (sequentiell und funktional)

Tipps für eine bessere Modellgenauigkeit:

  • Sie müssen ein vortrainiertes Modell mit akzeptabler Genauigkeit an diese API übergeben. Das Training von Modellen von Grund auf mit Clustering führt zu einer unterdurchschnittlichen Genauigkeit.
  • In einigen Fällen wirkt sich das Clustern bestimmter Layer nachteilig auf die Modellgenauigkeit aus. Aktivieren Sie "Cluster einiger Ebenen", um zu sehen, wie Sie das Clustern der Ebenen überspringen können, die die Genauigkeit am meisten beeinträchtigen.

Um alle Schichten Cluster gelten tfmot.clustering.keras.cluster_weights zum Modell.

import tensorflow_model_optimization as tfmot

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

clustering_params = {
  'number_of_clusters': 3,
  'cluster_centroids_init': CentroidInitialization.KMEANS_PLUS_PLUS
}

model = setup_model()
model.load_weights(pretrained_weights)

clustered_model = cluster_weights(model, **clustering_params)

clustered_model.summary()
Model: "sequential_2"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
cluster_dense_2 (ClusterWeig (None, 20)                823       
_________________________________________________________________
cluster_flatten_2 (ClusterWe (None, 20)                0         
=================================================================
Total params: 823
Trainable params: 423
Non-trainable params: 400
_________________________________________________________________

Clustern Sie einige Schichten (sequentielle und funktionale Modelle)

Tipps für eine bessere Modellgenauigkeit:

  • Sie müssen ein vortrainiertes Modell mit akzeptabler Genauigkeit an diese API übergeben. Das Training von Modellen von Grund auf mit Clustering führt zu einer unterdurchschnittlichen Genauigkeit.
  • Cluster späteren Schichten mit mehreren redundanten Parameter (zB tf.keras.layers.Dense , tf.keras.layers.Conv2D ), wie zu Anfang der Schichten gegenüberliegen.
  • Frieren Sie frühe Layer vor den Cluster-Layern während der Feinabstimmung ein. Behandeln Sie die Anzahl der eingefrorenen Layer als Hyperparameter. Empirisch ist das Einfrieren der meisten frühen Schichten ideal für die aktuelle Clustering-API.
  • Vermeiden Sie die Anhäufung kritischer Schichten (zB Aufmerksamkeitsmechanismus).

Mehr: die tfmot.clustering.keras.cluster_weights API - Dokumentation detaillierte Angaben darüber , wie die Cluster - Konfiguration pro Schicht zu variieren.

# Create a base model
base_model = setup_model()
base_model.load_weights(pretrained_weights)

# Helper function uses `cluster_weights` to make only 
# the Dense layers train with clustering
def apply_clustering_to_dense(layer):
  if isinstance(layer, tf.keras.layers.Dense):
    return cluster_weights(layer, **clustering_params)
  return layer

# Use `tf.keras.models.clone_model` to apply `apply_clustering_to_dense` 
# to the layers of the model.
clustered_model = tf.keras.models.clone_model(
    base_model,
    clone_function=apply_clustering_to_dense,
)

clustered_model.summary()
Model: "sequential_3"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
cluster_dense_3 (ClusterWeig (None, 20)                823       
_________________________________________________________________
flatten_3 (Flatten)          (None, 20)                0         
=================================================================
Total params: 823
Trainable params: 423
Non-trainable params: 400
_________________________________________________________________

Clustern Sie eine benutzerdefinierte Keras-Ebene oder geben Sie an, welche Gewichtungen der Ebene geclustert werden sollen

tfmot.clustering.keras.ClusterableLayer dient zwei Anwendungsfälle:

  1. Clustern Sie jeden Layer, der nicht nativ unterstützt wird, einschließlich eines benutzerdefinierten Keras-Layers.
  2. Geben Sie an, welche Gewichtungen einer unterstützten Schicht geclustert werden sollen.

Ein Beispiel der API Standardwerte Clustering nur den Kern der Dense Schicht. Das folgende Beispiel zeigt, wie Sie es ändern, um auch den Bias zu gruppieren. Beachten Sie, dass , wenn von der keras Schicht abzuleiten, müssen Sie die Funktion außer Kraft setzen get_clusterable_weights , in dem Sie den Namen der trainierbar Variable angeben geclustert werden und die trainierbar Variable selbst. Wenn Sie beispielsweise eine leere Liste [] zurückgeben, können keine Gewichtungen geclustert werden.

Häufiger Fehler: Clustering die Vorspannung in der Regel schadet Modellgenauigkeit zu viel.

class MyDenseLayer(tf.keras.layers.Dense, tfmot.clustering.keras.ClusterableLayer):

  def get_clusterable_weights(self):
   # Cluster kernel and bias. This is just an example, clustering
   # bias usually hurts model accuracy.
   return [('kernel', self.kernel), ('bias', self.bias)]

# Use `cluster_weights` to make the `MyDenseLayer` layer train with clustering as usual.
model_for_clustering = tf.keras.Sequential([
  tfmot.clustering.keras.cluster_weights(MyDenseLayer(20, input_shape=[input_dim]), **clustering_params),
  tf.keras.layers.Flatten()
])

model_for_clustering.summary()
Model: "sequential_4"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
cluster_my_dense_layer (Clus (None, 20)                846       
_________________________________________________________________
flatten_4 (Flatten)          (None, 20)                0         
=================================================================
Total params: 846
Trainable params: 426
Non-trainable params: 420
_________________________________________________________________

Sie dürfen auch tfmot.clustering.keras.ClusterableLayer eine keras benutzerdefinierte Schicht gruppieren. Dazu erweitern Sie tf.keras.Layer wie gewohnt und implementieren die __init__ , call und build - Funktionen, aber Sie haben auch die erweitern müssen clusterable_layer.ClusterableLayer Klasse und implementieren:

  1. get_clusterable_weights , wo Sie das Gewicht Kernel angeben , geclustert werden, wie oben gezeigt.
  2. get_clusterable_algorithm , in dem Sie den Cluster - Algorithmus für das Gewicht Tensor angeben. Dies liegt daran, dass Sie angeben müssen, wie die benutzerdefinierten Layer-Gewichtungen für das Clustering geformt werden. Der zurück Clusterungsalgorithmus Klasse sollte aus der abgeleitet werden clustering_algorithm.ClusteringAlgorithm Klasse und die Funktion get_pulling_indices sollte überschrieben. Ein Beispiel für diese Funktion, die Gewichte von Reihen 1D, 2D unterstützt und 3D können gefunden werden hier .

Ein Beispiel für diesen Anwendungsfall kann gefunden werden hier .

Checkpoint und Deserialisieren eines geclusterten Modells

Ihr Anwendungsfall: Dieser Code wird nur für das HDF5 Modellformat (nicht HDF5 Gewichte oder andere Formate) benötigt.

# Define the model.
base_model = setup_model()
base_model.load_weights(pretrained_weights)
clustered_model = cluster_weights(base_model, **clustering_params)

# Save or checkpoint the model.
_, keras_model_file = tempfile.mkstemp('.h5')
clustered_model.save(keras_model_file, include_optimizer=True)

# `cluster_scope` is needed for deserializing HDF5 models.
with tfmot.clustering.keras.cluster_scope():
  loaded_model = tf.keras.models.load_model(keras_model_file)

loaded_model.summary()
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:No training configuration found in the save file, so the model was *not* compiled. Compile it manually.
Model: "sequential_5"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
cluster_dense_4 (ClusterWeig (None, 20)                823       
_________________________________________________________________
cluster_flatten_5 (ClusterWe (None, 20)                0         
=================================================================
Total params: 823
Trainable params: 423
Non-trainable params: 400
_________________________________________________________________

Verbessern Sie die Genauigkeit des geclusterten Modells

Für Ihren speziellen Anwendungsfall gibt es Tipps, die Sie berücksichtigen können:

  • Die Schwerpunktinitialisierung spielt eine Schlüsselrolle bei der endgültigen optimierten Modellgenauigkeit. Im Allgemeinen übertrifft die kmeans++-Initialisierung die Linear-, Dichte- und Zufallsinitialisierung. Wenn kmeans++ nicht verwendet wird, tendiert die lineare Initialisierung dazu, die Dichte und die zufällige Initialisierung zu übertreffen, da sie keine großen Gewichte übersieht. Es wurde jedoch beobachtet, dass die Dichteinitialisierung eine bessere Genauigkeit für den Fall ergibt, dass sehr wenige Cluster auf Gewichten mit bimodalen Verteilungen verwendet werden.

  • Legen Sie bei der Feinabstimmung des Clustermodells eine niedrigere Lernrate als die beim Training verwendete fest.

  • Allgemeine Ideen zur Verbesserung der Modellgenauigkeit finden Sie unter "Definieren eines geclusterten Modells".

Einsatz

Modell mit Größenkomprimierung exportieren

Häufiger Fehler: beide strip_clustering und ein Standard - Kompressionsalgorithmus Anwendung (zB über gzip) sind notwendig , um die Kompression Vorteile von Clustern zu sehen.

model = setup_model()
clustered_model = cluster_weights(model, **clustering_params)

clustered_model.compile(
    loss=tf.keras.losses.categorical_crossentropy,
    optimizer='adam',
    metrics=['accuracy']
)

clustered_model.fit(
    x_train,
    y_train
)

final_model = tfmot.clustering.keras.strip_clustering(clustered_model)

print("final model")
final_model.summary()

print("\n")
print("Size of gzipped clustered model without stripping: %.2f bytes" 
      % (get_gzipped_model_size(clustered_model)))
print("Size of gzipped clustered model with stripping: %.2f bytes" 
      % (get_gzipped_model_size(final_model)))
1/1 [==============================] - 0s 343ms/step - loss: 16.1181 - accuracy: 0.0000e+00
final model
Model: "sequential_6"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_5 (Dense)              (None, 20)                420       
_________________________________________________________________
flatten_6 (Flatten)          (None, 20)                0         
=================================================================
Total params: 420
Trainable params: 420
Non-trainable params: 0
_________________________________________________________________


Size of gzipped clustered model without stripping: 3447.00 bytes
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.
Size of gzipped clustered model with stripping: 1433.00 bytes