Le crash course sur TensorFlow 2.0 de François Chollet @fchollet fondateur de Keras mérite quelques notes.

C’est l’objectif de ce 1er article qui couvre les parties 1, 2 et 3 de l’article.

Installation

Le code présenté est dans l’environnement de Google Colaboratory GCP.

On commence par l’installation de tf-nightly-gpu-2.0-preview. Il s’agit de l’installation pour GPU. Il y en a une pour CPU aussi.

!pip install tf-nightly-gpu-2.0-preview

Comme son nom l’indique, tf-nightly-gpu-2.0-preview est une version 2.0 pour GPU et « nightly build », c’est à dire que ce n’est pas une version stable.

Si vous voulez une autre version, il y a le choix :

– tensorflow —Latest stable release for CPU-only (Ubuntu and Windows)
– tensorflow-gpu —Latest stable release with GPU support (Ubuntu and Windows)
– tf-nightly —Preview nightly build for CPU-only (unstable)
– tf-nightly-gpu —Preview nightly build with GPU support (unstable, Ubuntu and Windows)

https://www.tensorflow.org/install/pip

L’installation de TensorFlow se fait de la façon suivante :

# Current stable release for CPU-only
pip install tensorflow

# Preview nightly build for CPU-only (unstable)
pip install tf-nightly

# Install TensorFlow 2.0 Alpha
pip install tensorflow==2.0.0-alpha0

import

Il est d’usage que TensorFlow soit importé de cette façon.

import tensorflow as tf

La version de travail de tf est la : 2.0.0-dev20190311

Layer

from tensorflow.keras.layers import Layer

class Linear(Layer):
  """y = w.x + b"""

  def __init__(self, units=32, input_dim=32):
      super(Linear, self).__init__()
      w_init = tf.random_normal_initializer()
      self.w = tf.Variable(
          initial_value=w_init(shape=(input_dim, units), dtype='float32'),
          trainable=True)
      b_init = tf.zeros_initializer()
      self.b = tf.Variable(
          initial_value=b_init(shape=(units,), dtype='float32'),
          trainable=True)

  def call(self, inputs):
      return tf.matmul(inputs, self.w) + self.b

# Instantiate our layer.
linear_layer = Linear(4, 2)

# The layer can be treated as a function.
# Here we call it on some data.
y = linear_layer(tf.ones((2, 2)))
assert y.shape == (2, 4)

# Weights are automatically tracked under the `weights` property.
assert linear_layer.weights == [linear_layer.w, linear_layer.b]

On définit ici une classe Linear qui hérite de Layer. Cette définition n’est pas simple pour ceux qui ne sont pas des gurus en Python 3.

super

Pour bien comprendre le fonctionnement de super(), référez-vous à cet article.

super() est un outil puissant permettant d’accéder aux parents directs lors d’héritage et de régler différents problèmes dus à l’héritage multiple.

https://he-arc.github.io/livre-python/super/index.html

On aurait pu remplacer la ligne

super(Linear, self).__init__()

par :

Layer.__init__(self).__init__()

puisque Layer est la classe parente de Linear.

tf.random_normal_initializer

Initializer that generates tensors with a normal distribution

https://www.tensorflow.org/api_docs/python/tf/initializers/random_normal

L’initialisation se fait selon une distribution normale, de moyenne 0 et d’écart-type 1.

tf.Variable

A variable maintains state in the graph across calls to run(). You add a variable to the graph by constructing an instance of the class Variable.
The Variable() constructor requires an initial value for the variable, which can be a Tensor of any type and shape. The initial value defines the type and shape of the variable. After construction, the type and shape of the variable are fixed. The value can be changed using one of the assign methods.

https://www.tensorflow.org/api_docs/python/tf/Variable
self.w = tf.Variable(
          initial_value=w_init(shape=(input_dim, units),
          dtype='float32'),
          trainable=True)

initial_value: A Tensor, or Python object convertible to a Tensor, which is the initial value for the Variable. The initial value must have a shape specified unless validate_shape is set to False. Can also be a callable with no argument that returns the initial value when called. In that case, dtype must be specified. (Note that initializer functions from init_ops.py must first be bound to a shape before being used here.)

dtype: If set, initial_value will be converted to the given type. If None, either the datatype will be kept (if initial_value is a Tensor), or convert_to_tensor will decide.

trainable: If True, the default, also adds the variable to the graph collection

https://www.tensorflow.org/api_docs/python/tf/Variable

Cette manière de faire en 2 temps : définition d’un initializer suivi de la création des poids n’est pas optimum.

La suite du code présente une solution plus simple :

self.w = self.add_weight(shape=(input_shape[-1], self.units),
                               initializer='random_normal',
                               trainable=True)

C’est beaucoup plus explicite.

tf.ones()

y = linear_layer(tf.ones((2, 2)))

Attention : tf.ones(2, 2) n’est pas équivalent à tf.ones((2, 2))

Le premier paramètre (et ici le seul), définit shape (la forme du tenseur)

Pour un tenseur donné, on a le nombre d’axes (le rang) (par exemple : une matrice a 2 axes) et shape : le nombre de dimensions sur chaque axe.

Par exemple :

one=tf.ones(2, 2)
one

donne :

<tf.Tensor: id=754, shape=(2,), dtype=float64, numpy=array([1., 1.])>

tandis-que :

one=tf.ones((2, 2))
one

donne :

<tf.Tensor: id=758, shape=(2, 2), dtype=float32, numpy=
array([[1., 1.],
       [1., 1.]], dtype=float32)>

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *