Google I/O est terminé ! Suivez les sessions TensorFlow Afficher les sessions

Guide complet de regroupement de poids

Voir sur TensorFlow.org Exécuter dans Google Colab Voir la source sur GitHub Télécharger le cahier

Bienvenue au guide complet pour la classification du poids, une partie de la boîte à outils modèle d' optimisation tensorflow.

Cette page documente divers cas d'utilisation et montre comment utiliser l'API pour chacun. Une fois que vous savez que les API dont vous avez besoin, trouver les paramètres et les détails de bas niveau dans les API docs :

Dans ce guide, les cas d'utilisation suivants sont couverts :

  • Définir un modèle en cluster.
  • Point de contrôle et désérialisation d'un modèle en cluster.
  • Améliorez la précision du modèle en cluster.
  • Pour le déploiement uniquement, vous devez prendre des mesures pour voir les avantages de la compression.

Installer

! 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()
2021-08-31 11:04:26.070553: E tensorflow/stream_executor/cuda/cuda_driver.cc:271] failed call to cuInit: CUDA_ERROR_NO_DEVICE: no CUDA-capable device is detected

Définir un modèle en cluster

Regrouper un modèle entier (séquentiel et fonctionnel)

Conseils pour une meilleure précision du modèle:

  • Vous devez transmettre un modèle pré-entraîné avec une précision acceptable à cette API. L'entraînement de modèles à partir de zéro avec le clustering donne une précision inférieure à la moyenne.
  • Dans certains cas, le regroupement de certaines couches a un effet néfaste sur la précision du modèle. Cochez « Cluster quelques couches » pour savoir comment ignorer le regroupement des couches qui affectent le plus la précision.

Pour regrouper toutes les couches, appliquez tfmot.clustering.keras.cluster_weights au modèle.

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
_________________________________________________________________

Regrouper quelques couches (modèles séquentiels et fonctionnels)

Conseils pour une meilleure précision du modèle:

  • Vous devez transmettre un modèle pré-entraîné avec une précision acceptable à cette API. L'entraînement de modèles à partir de zéro avec le clustering donne une précision inférieure à la moyenne.
  • Cluster couches ultérieures avec des paramètres plus redondants (par exemple tf.keras.layers.Dense , tf.keras.layers.Conv2D ), par opposition aux premières couches.
  • Gelez les premières couches avant les couches groupées pendant le réglage fin. Traitez le nombre de couches gelées comme un hyperparamètre. Empiriquement, le gel de la plupart des premières couches est idéal pour l'API de clustering actuelle.
  • Évitez de regrouper les couches critiques (par exemple, mécanisme d'attention).

En savoir plus: les tfmot.clustering.keras.cluster_weights API docs fournissent des détails sur la façon de modifier la configuration de clusters par couche.

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

Regroupez la couche Keras personnalisée ou spécifiez les poids de couche à regrouper

tfmot.clustering.keras.ClusterableLayer a deux cas d'utilisation:

  1. Regroupez toute couche qui n'est pas prise en charge nativement, y compris une couche Keras personnalisée.
  2. Spécifiez les poids d'une couche prise en charge à regrouper.

Pour un exemple, les paramètres par défaut de l' API pour la classification que le noyau de la Dense couche. L'exemple ci-dessous montre comment le modifier pour regrouper également le biais. Notez que lors du calcul de la couche keras, vous devez remplacer la fonction get_clusterable_weights , où vous spécifiez le nom de la variable trainable à être regroupées et la variable trainable elle - même. Par exemple, si vous retournez une liste vide [], aucun poids ne pourra être regroupé.

Erreur commune: le regroupement le biais nuit généralement trop précision du modèle.

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
_________________________________________________________________

Vous pouvez également utiliser tfmot.clustering.keras.ClusterableLayer pour regrouper une couche keras personnalisée. Pour ce faire, vous étendez tf.keras.Layer comme d' habitude et à mettre en œuvre l' __init__ , call et build des fonctions, mais vous avez également besoin d'étendre la clusterable_layer.ClusterableLayer classe et mettre en œuvre:

  1. get_clusterable_weights , où vous spécifiez le noyau de poids à être regroupés, comme indiqué ci - dessus.
  2. get_clusterable_algorithm , où vous spécifiez l'algorithme de clustering pour le tenseur de poids. En effet, vous devez spécifier la façon dont les pondérations de couche personnalisées sont mises en forme pour le clustering. La classe algorithme de classification retour doit être dérivé de la clustering_algorithm.ClusteringAlgorithm classe et la fonction get_pulling_indices doit être remplacée. Un exemple de cette fonction, qui prend en charge le poids des rangs 1D, 2D et 3D, se trouve ici .

Un exemple de ce cas d'utilisation se trouve ici .

Point de contrôle et désérialisation d'un modèle en cluster

Votre cas d'utilisation: ce code est nécessaire uniquement pour le format de modèle HDF5 (pas HDF5 de poids ou d' autres formats).

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

Améliorer la précision du modèle en cluster

Pour votre cas d'utilisation spécifique, voici quelques conseils que vous pouvez prendre en compte :

  • L'initialisation du centroïde joue un rôle clé dans la précision finale optimisée du modèle. En général, l'initialisation kmeans++ surpasse l'initialisation linéaire, de densité et aléatoire. Lorsque vous n'utilisez pas kmeans++, l'initialisation linéaire a tendance à surpasser la densité et l'initialisation aléatoire, car elle n'a pas tendance à manquer des poids importants. Cependant, l'initialisation de la densité a été observée pour donner une meilleure précision dans le cas de l'utilisation de très peu de clusters sur des poids avec des distributions bimodales.

  • Définissez un taux d'apprentissage inférieur à celui utilisé dans la formation lors du réglage fin du modèle en cluster.

  • Pour des idées générales pour améliorer la précision du modèle, recherchez des conseils pour votre ou vos cas d'utilisation sous "Définir un modèle en cluster".

Déploiement

Modèle d'exportation avec compression de taille

Erreur commune: les deux strip_clustering et l' application d' un algorithme standard de compression (par exemple via gzip) sont nécessaires pour voir les avantages de la compression du regroupement.

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